diff options
author | David Walter Seikel | 2012-01-23 23:36:30 +1000 |
---|---|---|
committer | David Walter Seikel | 2012-01-23 23:36:30 +1000 |
commit | 6523585c66c04cea54df50013df8886b589847d8 (patch) | |
tree | 0b22aee7064166d88595eda260ca2d17c0773da5 /libraries/luajit-2.0/lib/bcsave.lua | |
parent | Update the EFL to what I'm actually using, coz I'm using some stuff not yet r... (diff) | |
download | SledjHamr-6523585c66c04cea54df50013df8886b589847d8.zip SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.gz SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.bz2 SledjHamr-6523585c66c04cea54df50013df8886b589847d8.tar.xz |
Add luaproc and LuaJIT libraries.
Two versions of LuaJIT, the stable release, and the dev version. Try the dev version first, until ih fails badly.
Diffstat (limited to 'libraries/luajit-2.0/lib/bcsave.lua')
-rw-r--r-- | libraries/luajit-2.0/lib/bcsave.lua | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/libraries/luajit-2.0/lib/bcsave.lua b/libraries/luajit-2.0/lib/bcsave.lua new file mode 100644 index 0000000..1783014 --- /dev/null +++ b/libraries/luajit-2.0/lib/bcsave.lua | |||
@@ -0,0 +1,496 @@ | |||
1 | ---------------------------------------------------------------------------- | ||
2 | -- LuaJIT module to save/list bytecode. | ||
3 | -- | ||
4 | -- Copyright (C) 2005-2011 Mike Pall. All rights reserved. | ||
5 | -- Released under the MIT license. See Copyright Notice in luajit.h | ||
6 | ---------------------------------------------------------------------------- | ||
7 | -- | ||
8 | -- This module saves or lists the bytecode for an input file. | ||
9 | -- It's run by the -b command line option. | ||
10 | -- | ||
11 | ------------------------------------------------------------------------------ | ||
12 | |||
13 | local jit = require("jit") | ||
14 | assert(jit.version_num == 20000, "LuaJIT core/library version mismatch") | ||
15 | |||
16 | -- Symbol name prefix for LuaJIT bytecode. | ||
17 | local LJBC_PREFIX = "luaJIT_BC_" | ||
18 | |||
19 | ------------------------------------------------------------------------------ | ||
20 | |||
21 | local function usage() | ||
22 | io.stderr:write[[ | ||
23 | Save LuaJIT bytecode: luajit -b[options] input output | ||
24 | -l Only list bytecode. | ||
25 | -s Strip debug info (default). | ||
26 | -g Keep debug info. | ||
27 | -n name Set module name (default: auto-detect from input name). | ||
28 | -t type Set output file type (default: auto-detect from output name). | ||
29 | -a arch Override architecture for object files (default: native). | ||
30 | -o os Override OS for object files (default: native). | ||
31 | -e chunk Use chunk string as input. | ||
32 | -- Stop handling options. | ||
33 | - Use stdin as input and/or stdout as output. | ||
34 | |||
35 | File types: c h obj o raw (default) | ||
36 | ]] | ||
37 | os.exit(1) | ||
38 | end | ||
39 | |||
40 | local function check(ok, ...) | ||
41 | if ok then return ok, ... end | ||
42 | io.stderr:write("luajit: ", ...) | ||
43 | io.stderr:write("\n") | ||
44 | os.exit(1) | ||
45 | end | ||
46 | |||
47 | local function readfile(input) | ||
48 | if type(input) == "function" then return input end | ||
49 | if input == "-" then input = nil end | ||
50 | return check(loadfile(input)) | ||
51 | end | ||
52 | |||
53 | local function savefile(name, mode) | ||
54 | if name == "-" then return io.stdout end | ||
55 | return check(io.open(name, mode)) | ||
56 | end | ||
57 | |||
58 | ------------------------------------------------------------------------------ | ||
59 | |||
60 | local map_type = { | ||
61 | raw = "raw", c = "c", h = "h", o = "obj", obj = "obj", | ||
62 | } | ||
63 | |||
64 | local map_arch = { | ||
65 | x86 = true, x64 = true, arm = true, ppc = true, ppcspe = true, | ||
66 | } | ||
67 | |||
68 | local map_os = { | ||
69 | linux = true, windows = true, osx = true, freebsd = true, netbsd = true, | ||
70 | openbsd = true, solaris = true, | ||
71 | } | ||
72 | |||
73 | local function checkarg(str, map, err) | ||
74 | str = string.lower(str) | ||
75 | local s = check(map[str], "unknown ", err) | ||
76 | return s == true and str or s | ||
77 | end | ||
78 | |||
79 | local function detecttype(str) | ||
80 | local ext = string.match(string.lower(str), "%.(%a+)$") | ||
81 | return map_type[ext] or "raw" | ||
82 | end | ||
83 | |||
84 | local function checkmodname(str) | ||
85 | check(string.match(str, "^[%w_.%-]+$"), "bad module name") | ||
86 | return string.gsub(str, "[%.%-]", "_") | ||
87 | end | ||
88 | |||
89 | local function detectmodname(str) | ||
90 | if type(str) == "string" then | ||
91 | local tail = string.match(str, "[^/\\]+$") | ||
92 | if tail then str = tail end | ||
93 | local head = string.match(str, "^(.*)%.[^.]*$") | ||
94 | if head then str = head end | ||
95 | str = string.match(str, "^[%w_.%-]+") | ||
96 | else | ||
97 | str = nil | ||
98 | end | ||
99 | check(str, "cannot derive module name, use -n name") | ||
100 | return string.gsub(str, "[%.%-]", "_") | ||
101 | end | ||
102 | |||
103 | ------------------------------------------------------------------------------ | ||
104 | |||
105 | local function bcsave_tail(fp, output, s) | ||
106 | local ok, err = fp:write(s) | ||
107 | if ok and output ~= "-" then ok, err = fp:close() end | ||
108 | check(ok, "cannot write ", output, ": ", err) | ||
109 | end | ||
110 | |||
111 | local function bcsave_raw(output, s) | ||
112 | local fp = savefile(output, "wb") | ||
113 | bcsave_tail(fp, output, s) | ||
114 | end | ||
115 | |||
116 | local function bcsave_c(ctx, output, s) | ||
117 | local fp = savefile(output, "w") | ||
118 | if ctx.type == "c" then | ||
119 | fp:write(string.format([[ | ||
120 | #ifdef _cplusplus | ||
121 | extern "C" | ||
122 | #endif | ||
123 | #ifdef _WIN32 | ||
124 | __declspec(dllexport) | ||
125 | #endif | ||
126 | const char %s%s[] = { | ||
127 | ]], LJBC_PREFIX, ctx.modname)) | ||
128 | else | ||
129 | fp:write(string.format([[ | ||
130 | #define %s%s_SIZE %d | ||
131 | static const char %s%s[] = { | ||
132 | ]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname)) | ||
133 | end | ||
134 | local t, n, m = {}, 0, 0 | ||
135 | for i=1,#s do | ||
136 | local b = tostring(string.byte(s, i)) | ||
137 | m = m + #b + 1 | ||
138 | if m > 78 then | ||
139 | fp:write(table.concat(t, ",", 1, n), ",\n") | ||
140 | n, m = 0, #b + 1 | ||
141 | end | ||
142 | n = n + 1 | ||
143 | t[n] = b | ||
144 | end | ||
145 | bcsave_tail(fp, output, table.concat(t, ",", 1, n).."\n};\n") | ||
146 | end | ||
147 | |||
148 | local function bcsave_elfobj(ctx, output, s, ffi) | ||
149 | ffi.cdef[[ | ||
150 | typedef struct { | ||
151 | uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; | ||
152 | uint16_t type, machine; | ||
153 | uint32_t version; | ||
154 | uint32_t entry, phofs, shofs; | ||
155 | uint32_t flags; | ||
156 | uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; | ||
157 | } ELF32header; | ||
158 | typedef struct { | ||
159 | uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; | ||
160 | uint16_t type, machine; | ||
161 | uint32_t version; | ||
162 | uint64_t entry, phofs, shofs; | ||
163 | uint32_t flags; | ||
164 | uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; | ||
165 | } ELF64header; | ||
166 | typedef struct { | ||
167 | uint32_t name, type, flags, addr, ofs, size, link, info, align, entsize; | ||
168 | } ELF32sectheader; | ||
169 | typedef struct { | ||
170 | uint32_t name, type; | ||
171 | uint64_t flags, addr, ofs, size; | ||
172 | uint32_t link, info; | ||
173 | uint64_t align, entsize; | ||
174 | } ELF64sectheader; | ||
175 | typedef struct { | ||
176 | uint32_t name, value, size; | ||
177 | uint8_t info, other; | ||
178 | uint16_t sectidx; | ||
179 | } ELF32symbol; | ||
180 | typedef struct { | ||
181 | uint32_t name; | ||
182 | uint8_t info, other; | ||
183 | uint16_t sectidx; | ||
184 | uint64_t value, size; | ||
185 | } ELF64symbol; | ||
186 | typedef struct { | ||
187 | ELF32header hdr; | ||
188 | ELF32sectheader sect[6]; | ||
189 | ELF32symbol sym[2]; | ||
190 | uint8_t space[4096]; | ||
191 | } ELF32obj; | ||
192 | typedef struct { | ||
193 | ELF64header hdr; | ||
194 | ELF64sectheader sect[6]; | ||
195 | ELF64symbol sym[2]; | ||
196 | uint8_t space[4096]; | ||
197 | } ELF64obj; | ||
198 | ]] | ||
199 | local symname = LJBC_PREFIX..ctx.modname | ||
200 | local is64, isbe = false, false | ||
201 | if ctx.arch == "x64" then | ||
202 | is64 = true | ||
203 | elseif ctx.arch == "ppc" or ctx.arch == "ppcspe" then | ||
204 | isbe = true | ||
205 | end | ||
206 | |||
207 | -- Handle different host/target endianess. | ||
208 | local function f32(x) return x end | ||
209 | local f16, fofs = f32, f32 | ||
210 | if ffi.abi("be") ~= isbe then | ||
211 | f32 = bit.bswap | ||
212 | function f16(x) return bit.rshift(bit.bswap(x), 16) end | ||
213 | if is64 then | ||
214 | function fofs(x) return bit.bswap(x)*(2ll^32) end | ||
215 | else | ||
216 | fofs = f32 | ||
217 | end | ||
218 | end | ||
219 | |||
220 | -- Create ELF object and fill in header. | ||
221 | local o = ffi.new(is64 and "ELF64obj" or "ELF32obj") | ||
222 | local hdr = o.hdr | ||
223 | if ctx.os == "bsd" or ctx.os == "other" then -- Determine native hdr.eosabi. | ||
224 | local bf = assert(io.open("/bin/ls", "rb")) | ||
225 | local bs = bf:read(9) | ||
226 | bf:close() | ||
227 | ffi.copy(o, bs, 9) | ||
228 | check(hdr.emagic[0] == 127, "no support for writing native object files") | ||
229 | else | ||
230 | hdr.emagic = "\127ELF" | ||
231 | hdr.eosabi = ({ freebsd=9, netbsd=2, openbsd=12, solaris=6 })[ctx.os] or 0 | ||
232 | end | ||
233 | hdr.eclass = is64 and 2 or 1 | ||
234 | hdr.eendian = isbe and 2 or 1 | ||
235 | hdr.eversion = 1 | ||
236 | hdr.type = f16(1) | ||
237 | hdr.machine = f16(({ x86=3, x64=62, arm=40, ppc=20, ppcspe=20 })[ctx.arch]) | ||
238 | hdr.version = f32(1) | ||
239 | hdr.shofs = fofs(ffi.offsetof(o, "sect")) | ||
240 | hdr.ehsize = f16(ffi.sizeof(hdr)) | ||
241 | hdr.shentsize = f16(ffi.sizeof(o.sect[0])) | ||
242 | hdr.shnum = f16(6) | ||
243 | hdr.shstridx = f16(2) | ||
244 | |||
245 | -- Fill in sections and symbols. | ||
246 | local sofs, ofs = ffi.offsetof(o, "space"), 1 | ||
247 | for i,name in ipairs{ | ||
248 | ".symtab", ".shstrtab", ".strtab", ".rodata", ".note.GNU-stack", | ||
249 | } do | ||
250 | local sect = o.sect[i] | ||
251 | sect.align = fofs(1) | ||
252 | sect.name = f32(ofs) | ||
253 | ffi.copy(o.space+ofs, name) | ||
254 | ofs = ofs + #name+1 | ||
255 | end | ||
256 | o.sect[1].type = f32(2) -- .symtab | ||
257 | o.sect[1].link = f32(3) | ||
258 | o.sect[1].info = f32(1) | ||
259 | o.sect[1].align = fofs(8) | ||
260 | o.sect[1].ofs = fofs(ffi.offsetof(o, "sym")) | ||
261 | o.sect[1].entsize = fofs(ffi.sizeof(o.sym[0])) | ||
262 | o.sect[1].size = fofs(ffi.sizeof(o.sym)) | ||
263 | o.sym[1].name = f32(1) | ||
264 | o.sym[1].sectidx = f16(4) | ||
265 | o.sym[1].size = fofs(#s) | ||
266 | o.sym[1].info = 17 | ||
267 | o.sect[2].type = f32(3) -- .shstrtab | ||
268 | o.sect[2].ofs = fofs(sofs) | ||
269 | o.sect[2].size = fofs(ofs) | ||
270 | o.sect[3].type = f32(3) -- .strtab | ||
271 | o.sect[3].ofs = fofs(sofs + ofs) | ||
272 | o.sect[3].size = fofs(#symname+1) | ||
273 | ffi.copy(o.space+ofs+1, symname) | ||
274 | ofs = ofs + #symname + 2 | ||
275 | o.sect[4].type = f32(1) -- .rodata | ||
276 | o.sect[4].flags = fofs(2) | ||
277 | o.sect[4].ofs = fofs(sofs + ofs) | ||
278 | o.sect[4].size = fofs(#s) | ||
279 | o.sect[5].type = f32(1) -- .note.GNU-stack | ||
280 | o.sect[5].ofs = fofs(sofs + ofs + #s) | ||
281 | |||
282 | -- Write ELF object file. | ||
283 | local fp = savefile(output, "wb") | ||
284 | fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) | ||
285 | bcsave_tail(fp, output, s) | ||
286 | end | ||
287 | |||
288 | local function bcsave_peobj(ctx, output, s, ffi) | ||
289 | ffi.cdef[[ | ||
290 | typedef struct { | ||
291 | uint16_t arch, nsects; | ||
292 | uint32_t time, symtabofs, nsyms; | ||
293 | uint16_t opthdrsz, flags; | ||
294 | } PEheader; | ||
295 | typedef struct { | ||
296 | char name[8]; | ||
297 | uint32_t vsize, vaddr, size, ofs, relocofs, lineofs; | ||
298 | uint16_t nreloc, nline; | ||
299 | uint32_t flags; | ||
300 | } PEsection; | ||
301 | typedef struct __attribute((packed)) { | ||
302 | union { | ||
303 | char name[8]; | ||
304 | uint32_t nameref[2]; | ||
305 | }; | ||
306 | uint32_t value; | ||
307 | int16_t sect; | ||
308 | uint16_t type; | ||
309 | uint8_t scl, naux; | ||
310 | } PEsym; | ||
311 | typedef struct __attribute((packed)) { | ||
312 | uint32_t size; | ||
313 | uint16_t nreloc, nline; | ||
314 | uint32_t cksum; | ||
315 | uint16_t assoc; | ||
316 | uint8_t comdatsel, unused[3]; | ||
317 | } PEsymaux; | ||
318 | typedef struct { | ||
319 | PEheader hdr; | ||
320 | PEsection sect[2]; | ||
321 | // Must be an even number of symbol structs. | ||
322 | PEsym sym0; | ||
323 | PEsymaux sym0aux; | ||
324 | PEsym sym1; | ||
325 | PEsymaux sym1aux; | ||
326 | PEsym sym2; | ||
327 | PEsym sym3; | ||
328 | uint32_t strtabsize; | ||
329 | uint8_t space[4096]; | ||
330 | } PEobj; | ||
331 | ]] | ||
332 | local symname = LJBC_PREFIX..ctx.modname | ||
333 | local is64 = false | ||
334 | if ctx.arch == "x86" then | ||
335 | symname = "_"..symname | ||
336 | elseif ctx.arch == "x64" then | ||
337 | is64 = true | ||
338 | end | ||
339 | local symexport = " /EXPORT:"..symname..",DATA " | ||
340 | |||
341 | -- The file format is always little-endian. Swap if the host is big-endian. | ||
342 | local function f32(x) return x end | ||
343 | local f16 = f32 | ||
344 | if ffi.abi("be") then | ||
345 | f32 = bit.bswap | ||
346 | function f16(x) return bit.rshift(bit.bswap(x), 16) end | ||
347 | end | ||
348 | |||
349 | -- Create PE object and fill in header. | ||
350 | local o = ffi.new("PEobj") | ||
351 | local hdr = o.hdr | ||
352 | hdr.arch = f16(({ x86=0x14c, x64=0x8664, arm=0x1c0, ppc=0x1f2 })[ctx.arch]) | ||
353 | hdr.nsects = f16(2) | ||
354 | hdr.symtabofs = f32(ffi.offsetof(o, "sym0")) | ||
355 | hdr.nsyms = f32(6) | ||
356 | |||
357 | -- Fill in sections and symbols. | ||
358 | o.sect[0].name = ".drectve" | ||
359 | o.sect[0].size = f32(#symexport) | ||
360 | o.sect[0].flags = f32(0x00100a00) | ||
361 | o.sym0.sect = f16(1) | ||
362 | o.sym0.scl = 3 | ||
363 | o.sym0.name = ".drectve" | ||
364 | o.sym0.naux = 1 | ||
365 | o.sym0aux.size = f32(#symexport) | ||
366 | o.sect[1].name = ".rdata" | ||
367 | o.sect[1].size = f32(#s) | ||
368 | o.sect[1].flags = f32(0x40300040) | ||
369 | o.sym1.sect = f16(2) | ||
370 | o.sym1.scl = 3 | ||
371 | o.sym1.name = ".rdata" | ||
372 | o.sym1.naux = 1 | ||
373 | o.sym1aux.size = f32(#s) | ||
374 | o.sym2.sect = f16(2) | ||
375 | o.sym2.scl = 2 | ||
376 | o.sym2.nameref[1] = f32(4) | ||
377 | o.sym3.sect = f16(-1) | ||
378 | o.sym3.scl = 2 | ||
379 | o.sym3.value = f32(1) | ||
380 | o.sym3.name = "@feat.00" -- Mark as SafeSEH compliant. | ||
381 | ffi.copy(o.space, symname) | ||
382 | local ofs = #symname + 1 | ||
383 | o.strtabsize = f32(ofs + 4) | ||
384 | o.sect[0].ofs = f32(ffi.offsetof(o, "space") + ofs) | ||
385 | ffi.copy(o.space + ofs, symexport) | ||
386 | ofs = ofs + #symexport | ||
387 | o.sect[1].ofs = f32(ffi.offsetof(o, "space") + ofs) | ||
388 | |||
389 | -- Write PE object file. | ||
390 | local fp = savefile(output, "wb") | ||
391 | fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) | ||
392 | bcsave_tail(fp, output, s) | ||
393 | end | ||
394 | |||
395 | local function bcsave_machobj(ctx, output, s, ffi) | ||
396 | check(false, "NYI: no support for writing OSX object files") | ||
397 | end | ||
398 | |||
399 | local function bcsave_obj(ctx, output, s) | ||
400 | local ok, ffi = pcall(require, "ffi") | ||
401 | check(ok, "FFI library required to write this file type") | ||
402 | if ctx.os == "windows" then | ||
403 | return bcsave_peobj(ctx, output, s, ffi) | ||
404 | elseif ctx.os == "osx" then | ||
405 | return bcsave_machobj(ctx, output, s, ffi) | ||
406 | else | ||
407 | return bcsave_elfobj(ctx, output, s, ffi) | ||
408 | end | ||
409 | end | ||
410 | |||
411 | ------------------------------------------------------------------------------ | ||
412 | |||
413 | local function bclist(input, output) | ||
414 | local f = readfile(input) | ||
415 | require("jit.bc").dump(f, savefile(output, "w"), true) | ||
416 | end | ||
417 | |||
418 | local function bcsave(ctx, input, output) | ||
419 | local f = readfile(input) | ||
420 | local s = string.dump(f, ctx.strip) | ||
421 | local t = ctx.type | ||
422 | if not t then | ||
423 | t = detecttype(output) | ||
424 | ctx.type = t | ||
425 | end | ||
426 | if t == "raw" then | ||
427 | bcsave_raw(output, s) | ||
428 | else | ||
429 | if not ctx.modname then ctx.modname = detectmodname(input) end | ||
430 | if t == "obj" then | ||
431 | bcsave_obj(ctx, output, s) | ||
432 | else | ||
433 | bcsave_c(ctx, output, s) | ||
434 | end | ||
435 | end | ||
436 | end | ||
437 | |||
438 | local function docmd(...) | ||
439 | local arg = {...} | ||
440 | local n = 1 | ||
441 | local list = false | ||
442 | local ctx = { | ||
443 | strip = true, arch = jit.arch, os = string.lower(jit.os), | ||
444 | type = false, modname = false, | ||
445 | } | ||
446 | while n <= #arg do | ||
447 | local a = arg[n] | ||
448 | if type(a) == "string" and string.sub(a, 1, 1) == "-" and a ~= "-" then | ||
449 | table.remove(arg, n) | ||
450 | if a == "--" then break end | ||
451 | for m=2,#a do | ||
452 | local opt = string.sub(a, m, m) | ||
453 | if opt == "l" then | ||
454 | list = true | ||
455 | elseif opt == "s" then | ||
456 | ctx.strip = true | ||
457 | elseif opt == "g" then | ||
458 | ctx.strip = false | ||
459 | else | ||
460 | if arg[n] == nil or m ~= #a then usage() end | ||
461 | if opt == "e" then | ||
462 | if n ~= 1 then usage() end | ||
463 | arg[1] = check(loadstring(arg[1])) | ||
464 | elseif opt == "n" then | ||
465 | ctx.modname = checkmodname(table.remove(arg, n)) | ||
466 | elseif opt == "t" then | ||
467 | ctx.type = checkarg(table.remove(arg, n), map_type, "file type") | ||
468 | elseif opt == "a" then | ||
469 | ctx.arch = checkarg(table.remove(arg, n), map_arch, "architecture") | ||
470 | elseif opt == "o" then | ||
471 | ctx.os = checkarg(table.remove(arg, n), map_os, "OS name") | ||
472 | else | ||
473 | usage() | ||
474 | end | ||
475 | end | ||
476 | end | ||
477 | else | ||
478 | n = n + 1 | ||
479 | end | ||
480 | end | ||
481 | if list then | ||
482 | if #arg == 0 or #arg > 2 then usage() end | ||
483 | bclist(arg[1], arg[2] or "-") | ||
484 | else | ||
485 | if #arg ~= 2 then usage() end | ||
486 | bcsave(ctx, arg[1], arg[2]) | ||
487 | end | ||
488 | end | ||
489 | |||
490 | ------------------------------------------------------------------------------ | ||
491 | |||
492 | -- Public module functions. | ||
493 | module(...) | ||
494 | |||
495 | start = docmd -- Process -b command line option. | ||
496 | |||