diff options
| author | Mike Pall <mike> | 2013-02-11 17:58:06 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2013-02-11 17:58:06 +0100 |
| commit | 339b77ee050389f0f28584d373c53bd3ed81e24a (patch) | |
| tree | 637bcb1d38a90babeacba09f53f5f7db56ce5d48 /src | |
| parent | 250b24f93728e04851385cce5665eeae26dc60a1 (diff) | |
| download | luajit-339b77ee050389f0f28584d373c53bd3ed81e24a.tar.gz luajit-339b77ee050389f0f28584d373c53bd3ed81e24a.tar.bz2 luajit-339b77ee050389f0f28584d373c53bd3ed81e24a.zip | |
OSX: Add support for Mach-O object files to -b option.
Thanks to Adam Strzelecki.
Diffstat (limited to 'src')
| -rw-r--r-- | src/jit/bcsave.lua | 160 |
1 files changed, 159 insertions, 1 deletions
diff --git a/src/jit/bcsave.lua b/src/jit/bcsave.lua index 08e54454..1c511112 100644 --- a/src/jit/bcsave.lua +++ b/src/jit/bcsave.lua | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | local jit = require("jit") | 13 | local jit = require("jit") |
| 14 | assert(jit.version_num == 20000, "LuaJIT core/library version mismatch") | 14 | assert(jit.version_num == 20000, "LuaJIT core/library version mismatch") |
| 15 | local bit = require("bit") | ||
| 15 | 16 | ||
| 16 | -- Symbol name prefix for LuaJIT bytecode. | 17 | -- Symbol name prefix for LuaJIT bytecode. |
| 17 | local LJBC_PREFIX = "luaJIT_BC_" | 18 | local LJBC_PREFIX = "luaJIT_BC_" |
| @@ -398,7 +399,164 @@ typedef struct { | |||
| 398 | end | 399 | end |
| 399 | 400 | ||
| 400 | local function bcsave_machobj(ctx, output, s, ffi) | 401 | local function bcsave_machobj(ctx, output, s, ffi) |
| 401 | check(false, "NYI: no support for writing OSX object files") | 402 | ffi.cdef[[ |
| 403 | typedef struct | ||
| 404 | { | ||
| 405 | uint32_t magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags; | ||
| 406 | } mach_header; | ||
| 407 | typedef struct | ||
| 408 | { | ||
| 409 | mach_header; uint32_t reserved; | ||
| 410 | } mach_header_64; | ||
| 411 | typedef struct { | ||
| 412 | uint32_t cmd, cmdsize; | ||
| 413 | char segname[16]; | ||
| 414 | uint32_t vmaddr, vmsize, fileoff, filesize; | ||
| 415 | uint32_t maxprot, initprot, nsects, flags; | ||
| 416 | } mach_segment_command; | ||
| 417 | typedef struct { | ||
| 418 | uint32_t cmd, cmdsize; | ||
| 419 | char segname[16]; | ||
| 420 | uint64_t vmaddr, vmsize, fileoff, filesize; | ||
| 421 | uint32_t maxprot, initprot, nsects, flags; | ||
| 422 | } mach_segment_command_64; | ||
| 423 | typedef struct { | ||
| 424 | char sectname[16], segname[16]; | ||
| 425 | uint32_t addr, size; | ||
| 426 | uint32_t offset, align, reloff, nreloc, flags; | ||
| 427 | uint32_t reserved1, reserved2; | ||
| 428 | } mach_section; | ||
| 429 | typedef struct { | ||
| 430 | char sectname[16], segname[16]; | ||
| 431 | uint64_t addr, size; | ||
| 432 | uint32_t offset, align, reloff, nreloc, flags; | ||
| 433 | uint32_t reserved1, reserved2, reserved3; | ||
| 434 | } mach_section_64; | ||
| 435 | typedef struct { | ||
| 436 | uint32_t cmd, cmdsize, symoff, nsyms, stroff, strsize; | ||
| 437 | } mach_symtab_command; | ||
| 438 | typedef struct { | ||
| 439 | int32_t strx; | ||
| 440 | uint8_t type, sect; | ||
| 441 | int16_t desc; | ||
| 442 | uint32_t value; | ||
| 443 | } mach_nlist; | ||
| 444 | typedef struct { | ||
| 445 | uint32_t strx; | ||
| 446 | uint8_t type, sect; | ||
| 447 | uint16_t desc; | ||
| 448 | uint64_t value; | ||
| 449 | } mach_nlist_64; | ||
| 450 | typedef struct | ||
| 451 | { | ||
| 452 | uint32_t magic, nfat_arch; | ||
| 453 | } mach_fat_header; | ||
| 454 | typedef struct | ||
| 455 | { | ||
| 456 | uint32_t cputype, cpusubtype, offset, size, align; | ||
| 457 | } mach_fat_arch; | ||
| 458 | typedef struct { | ||
| 459 | struct { | ||
| 460 | mach_header hdr; | ||
| 461 | mach_segment_command seg; | ||
| 462 | mach_section sec; | ||
| 463 | mach_symtab_command sym; | ||
| 464 | } arch[1]; | ||
| 465 | mach_nlist sym_entry; | ||
| 466 | uint8_t space[4096]; | ||
| 467 | } mach_obj; | ||
| 468 | typedef struct { | ||
| 469 | struct { | ||
| 470 | mach_header_64 hdr; | ||
| 471 | mach_segment_command_64 seg; | ||
| 472 | mach_section_64 sec; | ||
| 473 | mach_symtab_command sym; | ||
| 474 | } arch[1]; | ||
| 475 | mach_nlist_64 sym_entry; | ||
| 476 | uint8_t space[4096]; | ||
| 477 | } mach_obj_64; | ||
| 478 | typedef struct { | ||
| 479 | mach_fat_header fat; | ||
| 480 | mach_fat_arch fat_arch[4]; | ||
| 481 | struct { | ||
| 482 | mach_header hdr; | ||
| 483 | mach_segment_command seg; | ||
| 484 | mach_section sec; | ||
| 485 | mach_symtab_command sym; | ||
| 486 | } arch[4]; | ||
| 487 | mach_nlist sym_entry; | ||
| 488 | uint8_t space[4096]; | ||
| 489 | } mach_fat_obj; | ||
| 490 | ]] | ||
| 491 | local symname = '_'..LJBC_PREFIX..ctx.modname | ||
| 492 | local isfat, is64, align, mobj = false, false, 4, "mach_obj" | ||
| 493 | if ctx.arch == "x64" then | ||
| 494 | is64, align, mobj = true, 8, "mach_obj_64" | ||
| 495 | elseif ctx.arch == "arm" then | ||
| 496 | isfat, mobj = true, "mach_fat_obj" | ||
| 497 | else | ||
| 498 | check(ctx.arch == "x86", "unsupported architecture for OSX") | ||
| 499 | end | ||
| 500 | local function aligned(v, a) return bit.band(v+a-1, -a) end | ||
| 501 | local be32 = bit.bswap -- Mach-O FAT is BE, supported archs are LE. | ||
| 502 | |||
| 503 | -- Create Mach-O object and fill in header. | ||
| 504 | local o = ffi.new(mobj) | ||
| 505 | local mach_size = aligned(ffi.offsetof(o, "space")+#symname+2, align) | ||
| 506 | local cputype = ({ x86={7}, x64={0x01000007}, arm={7,12,12,12} })[ctx.arch] | ||
| 507 | local cpusubtype = ({ x86={3}, x64={3}, arm={3,6,9,11} })[ctx.arch] | ||
| 508 | if isfat then | ||
| 509 | o.fat.magic = be32(0xcafebabe) | ||
| 510 | o.fat.nfat_arch = be32(#cpusubtype) | ||
| 511 | end | ||
| 512 | |||
| 513 | -- Fill in sections and symbols. | ||
| 514 | for i=0,#cpusubtype-1 do | ||
| 515 | local ofs = 0 | ||
| 516 | if isfat then | ||
| 517 | local a = o.fat_arch[i] | ||
| 518 | a.cputype = be32(cputype[i+1]) | ||
| 519 | a.cpusubtype = be32(cpusubtype[i+1]) | ||
| 520 | -- Subsequent slices overlap each other to share data. | ||
| 521 | ofs = ffi.offsetof(o, "arch") + i*ffi.sizeof(o.arch[0]) | ||
| 522 | a.offset = be32(ofs) | ||
| 523 | a.size = be32(mach_size-ofs+#s) | ||
| 524 | end | ||
| 525 | local a = o.arch[i] | ||
| 526 | a.hdr.magic = is64 and 0xfeedfacf or 0xfeedface | ||
| 527 | a.hdr.cputype = cputype[i+1] | ||
| 528 | a.hdr.cpusubtype = cpusubtype[i+1] | ||
| 529 | a.hdr.filetype = 1 | ||
| 530 | a.hdr.ncmds = 2 | ||
| 531 | a.hdr.sizeofcmds = ffi.sizeof(a.seg)+ffi.sizeof(a.sec)+ffi.sizeof(a.sym) | ||
| 532 | a.seg.cmd = is64 and 0x19 or 0x1 | ||
| 533 | a.seg.cmdsize = ffi.sizeof(a.seg)+ffi.sizeof(a.sec) | ||
| 534 | a.seg.vmsize = #s | ||
| 535 | a.seg.fileoff = mach_size-ofs | ||
| 536 | a.seg.filesize = #s | ||
| 537 | a.seg.maxprot = 1 | ||
| 538 | a.seg.initprot = 1 | ||
| 539 | a.seg.nsects = 1 | ||
| 540 | ffi.copy(a.sec.sectname, "__data") | ||
| 541 | ffi.copy(a.sec.segname, "__DATA") | ||
| 542 | a.sec.size = #s | ||
| 543 | a.sec.offset = mach_size-ofs | ||
| 544 | a.sym.cmd = 2 | ||
| 545 | a.sym.cmdsize = ffi.sizeof(a.sym) | ||
| 546 | a.sym.symoff = ffi.offsetof(o, "sym_entry")-ofs | ||
| 547 | a.sym.nsyms = 1 | ||
| 548 | a.sym.stroff = ffi.offsetof(o, "sym_entry")+ffi.sizeof(o.sym_entry)-ofs | ||
| 549 | a.sym.strsize = aligned(#symname+2, align) | ||
| 550 | end | ||
| 551 | o.sym_entry.type = 0xf | ||
| 552 | o.sym_entry.sect = 1 | ||
| 553 | o.sym_entry.strx = 1 | ||
| 554 | ffi.copy(o.space+1, symname) | ||
| 555 | |||
| 556 | -- Write Macho-O object file. | ||
| 557 | local fp = savefile(output, "wb") | ||
| 558 | fp:write(ffi.string(o, mach_size)) | ||
| 559 | bcsave_tail(fp, output, s) | ||
| 402 | end | 560 | end |
| 403 | 561 | ||
| 404 | local function bcsave_obj(ctx, output, s) | 562 | local function bcsave_obj(ctx, output, s) |
