Non-FAT x86_64 & i386 only for now, iOS/ARM coming. --- src/jit/bcsave.lua | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/src/jit/bcsave.lua b/src/jit/bcsave.lua index bf69e00..0dca2bb 100644 --- a/src/jit/bcsave.lua +++ b/src/jit/bcsave.lua @@ -398,7 +398,113 @@ typedef struct { end local function bcsave_machobj(ctx, output, s, ffi) - check(false, "NYI: no support for writing OSX object files") + ffi.cdef[[ +typedef struct +{ + uint32_t magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags; +} mach_header; +typedef struct +{ + uint32_t magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags, reserved; +} mach_header_64; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint32_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command; +typedef struct { + uint32_t cmd, cmdsize; + char segname[16]; + uint64_t vmaddr, vmsize, fileoff, filesize; + uint32_t maxprot, initprot, nsects, flags; +} mach_segment_command_64; +typedef struct { + char sectname[16], segname[16]; + uint32_t addr, size; + uint32_t offset, align, reloff, nreloc, flags, reserved1, reserved2; +} mach_section; +typedef struct { + char sectname[16], segname[16]; + uint64_t addr, size; + uint32_t offset, align, reloff, nreloc, flags, reserved1, reserved2, reserved3; +} mach_section_64; +typedef struct { + uint32_t cmd, cmdsize, symoff, nsyms, stroff, strsize; +} mach_symtab_command; +typedef struct { + int32_t strx; + uint8_t type, sect; + int16_t desc; + uint32_t value; +} mach_nlist; +typedef struct { + uint32_t strx; + uint8_t type, sect; + uint16_t desc; + uint64_t value; +} mach_nlist_64; +typedef struct { + mach_header hdr; + mach_segment_command seg; + mach_section sec; + mach_symtab_command sym; + mach_nlist sym_entry; + uint8_t space[4096]; +} mach_obj; +typedef struct { + mach_header_64 hdr; + mach_segment_command_64 seg; + mach_section_64 sec; + mach_symtab_command sym; + mach_nlist_64 sym_entry; + uint8_t space[4096]; +} mach_obj_64; +]] + local symname = LJBC_PREFIX..ctx.modname + local is64, align = false, 4 + if ctx.arch == "x64" then + is64 = true + align = 8 + end + -- Create Mach-O object and fill in header. + local o = ffi.new(is64 and "mach_obj_64" or "mach_obj") + local mach_size = ffi.offsetof(o, "space")+#symname+2 + -- Align BC offset. + mach_size = mach_size + (align - (mach_size % align)) % align + o.hdr.magic = is64 and 0xfeedfacf or 0xfeedface + o.hdr.cputype = is64 and 0x01000007 or 7 -- Intel 32-bit or 64-bit + o.hdr.cpusubtype = 3 -- Intel all + o.hdr.filetype = 0x1 -- obj + o.hdr.ncmds = 2 + o.hdr.sizeofcmds = ffi.sizeof(o.seg)+ffi.sizeof(o.sec)+ffi.sizeof(o.sym) + o.seg.cmd = is64 and 0x19 or 0x1 -- segment + o.seg.cmdsize = ffi.sizeof(o.seg)+ffi.sizeof(o.sec) + o.seg.vmsize = #s + o.seg.fileoff = mach_size + o.seg.filesize = #s + o.seg.maxprot = 0x1 -- readonly + o.seg.initprot = 0x1 + o.seg.nsects = 1 + ffi.copy(o.sec.sectname, "__data") + ffi.copy(o.sec.segname, "__DATA") + o.sec.size = #s + o.sec.offset = mach_size + o.sym.cmd = 0x2 -- symbol table + o.sym.cmdsize = ffi.sizeof(o.sym) + o.sym.symoff = ffi.offsetof(o, "sym_entry") + o.sym.nsyms = 1 + o.sym.stroff = ffi.offsetof(o, "sym_entry")+ffi.sizeof(o.sym_entry) + o.sym.strsize = #symname+2 + o.sym_entry.type = 0xf + o.sym_entry.sect = 0 + o.sym_entry.strx = 1 + ffi.copy(o.space+1, symname) + + -- Write Macho-O object file. + local fp = savefile(output, "wb") + fp:write(ffi.string(o, mach_size)) + bcsave_tail(fp, output, s) end local function bcsave_obj(ctx, output, s) -- 1.7.10.2 (Apple Git-33)