Skip to content

Instantly share code, notes, and snippets.

@moteus
Created January 9, 2014 07:08
Show Gist options
  • Save moteus/8330491 to your computer and use it in GitHub Desktop.
Save moteus/8330491 to your computer and use it in GitHub Desktop.
Create proxy dll library on Windows. This script use `dumpbin` to list all export symbols. Example: `mkforwardlib lua51 lua5.1 X86` create lua5.1.dll as proxy to lua51.dll
local reallib
local fakelib
local machine
local extrasymbols = {}
local args = {...}
local errmsg
if args[1] then reallib = args[1] end
if args[2] then fakelib = args[2] end
if args[3] then machine = args[3] end
for i=4,#args do
table.insert(extrasymbols, args[i])
end
if #args<3 then
errmsg = "not enough parameters"
elseif not ({X86=true, AMD64=true, IA64=true})[machine] then
errmsg = "'"..machine.."' is not a recognized machine architecture"
end
if errmsg then
if errmsg then io.stderr:write("Error: "..errmsg.."\n") end
io.stderr:write[[
Usage: mkforwardlib <reallib> <fakelib> <machine> [<extrasymbols>...]
reallib The name of the existing dll that you want to use.
fakelib The name of the fake dll that you want to create and that
will call the reallib instead.
machine The hardware architecture of your windows version among:
X86, AMD64, IA64
extrasymbols Additionnal symbols to export beyond standard Lua symbols
(if you have a very custom Lua dll).
Example: mkforwardlib lua51 lua5.1 X86
]]
-- :TODO: add support for AM33, ARM, CEE, EBC, M32R, MIPS, MIPS16, MIPSFPU, MIPSFPU16, MIPSR41XX, SH4, SH5, THUMB
os.exit(0)
end
local VisualC = os.getenv('VCPATH')
if not VisualC then
if machine=='AMD64' then
local PlatformSDK = assert(os.getenv"MSSDK", "MSSDK environment variable is not set, please set it to the path to your Platform SDK")
VisualC = PlatformSDK.."\\Bin\\win64\\x86\\AMD64"
elseif machine=='IA64' then
local PlatformSDK = assert(os.getenv"MSSDK", "MSSDK environment variable is not set, please set it to the path to your Platform SDK")
VisualC = PlatformSDK.."\\Bin\\win64"
else
-- local VisualCRoot = (os.getenv"PROGRAMFILES(X86)" or os.getenv"PROGRAMFILES").."\\Microsoft Visual Studio .NET 2003\\Vc7"
local VisualCRoot = (os.getenv"PROGRAMFILES(X86)" or os.getenv"PROGRAMFILES").."\\Microsoft Visual Studio 8\\VC"
VisualC = VisualCRoot.."\\bin"
end
end
function file_temp()
local res = os.tmpname()
res = os.getenv'TMP' .. res .. 'tmp'
return res
end
function execute (cmd)
local res1,res2,res2 = os.execute(cmd)
if not lua52 then
return res1==0,res1
else
return res1,res2
end
end
function execute_wrapper (cmd,callback)
local tmpfile = file_temp()
local ok,code = execute(cmd..' >"' .. tmpfile .. '" 2>&1')
local inf = io.open(tmpfile, 'r')
callback(ok,code,inf)
if inf then inf:close() end
os.remove(tmpfile)
end
function get_exports(fname)
local ret, err
local cmd = 'dumpbin /EXPORTS "' .. fname .. '"'
local fn_pat = "^%s+%d+%s+[0-9A-F]+%s+[0-9A-F]+%s+(%S+)%s*$"
execute_wrapper(cmd, function(status, code, f)
err = code
if not status then return end
ret = {}
for str in f:lines() do
local fn = string.match(str,fn_pat)
if fn then table.insert(ret, fn) end
end
end)
return ret, err
end
local symbols = assert(get_exports(reallib .. '.dll'), 'Can not load reallib: ' .. reallib .. '.dll')
local link = '"'..VisualC..'\\link.exe"'
local command = {
" -dll",
" -nologo",
" -noentry",
" -machine:"..machine,
" -incremental:no",
" -nodefaultlib",
" -out:"..fakelib..".dll",
" -implib:"..fakelib..".lib",
}
for _,symbol in ipairs(symbols) do
table.insert(command," /export:"..symbol.."="..reallib.."."..symbol)
end
for _,symbol in ipairs(extrasymbols) do
table.insert(command," /export:"..symbol.."="..reallib.."."..symbol)
end
local tmpName = os.tmpname()
local tmpFile = io.open(tmpName,'w')
tmpFile:write(table.concat(command))
tmpFile:close()
local ok,ret = pcall(os.execute, '"'..link.. ' @'.. tmpName ..'"')
os.remove(tmpName);
if ok then
os.exit(ret)
else
error(ret)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment