Supported architectures: x86, x64, arm, armv6, armv7, armv7s Raises warning when using "arm" (with no subtype), as object files for all ARM CPU subtypes are depreciated by ld. --- src/jit/bcsave.lua | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 1 deletion(-) diff --git a/src/jit/bcsave.lua b/src/jit/bcsave.lua index bf69e00..b8cc672 100644 --- a/src/jit/bcsave.lua +++ b/src/jit/bcsave.lua @@ -64,6 +64,8 @@ local map_type = { local map_arch = { x86 = true, x64 = true, arm = true, ppc = true, ppcspe = true, mips = true, mipsel = true, + -- osx only: + armv6 = true, armv7 = true, armv7s = true, } local map_os = { @@ -398,7 +400,122 @@ typedef struct { end local function bcsave_machobj(ctx, output, s, ffi) - check(false, "NYI: no support for writing OSX object files") + check(({ x86=true, x64=true, arm=true, armv6=true, armv7=true, armv7s=true })[ctx.arch], "only x86, x64 and arm(v6,v7,v7s) architectures are allowed for osx") + 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 + local function aligned(v,a) return v + (a - (v % a)) % a end + + -- Create Mach-O object and fill in header. + local o = ffi.new(is64 and "mach_obj_64" or "mach_obj") + local mach_size = aligned(ffi.offsetof(o, "space")+#symname+2, align) + o.hdr.magic = is64 and 0xfeedfacf or 0xfeedface + if string.sub(ctx.arch, 1, 3) == "arm" then + o.hdr.cputype = 12 + o.hdr.cpusubtype = ({ arm=0, armv6=6, armv7=9, armv7s=11 })[ctx.arch] + if ctx.arch == "arm" then + io.stderr:write("luajit: warning: output for all ARM subtypes produces ld warnings\n") + end + else + o.hdr.cputype = is64 and 0x01000007 or 7 -- Intel 32-bit or 64-bit + o.hdr.cpusubtype = 3 -- Intel all + end + 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 = aligned(#symname+2, align) + o.sym_entry.type = 0xf + o.sym_entry.sect = 1 + 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) @@ -488,6 +605,9 @@ local function docmd(...) bclist(arg[1], arg[2] or "-") else if #arg ~= 2 then usage() end + if ctx.os ~= "osx" and string.sub(ctx.arch, 1, 3) == "arm" then + ctx.arch = "arm" + end bcsave(ctx, arg[1], arg[2]) end end -- 1.7.10.2 (Apple Git-33)