[PATCH] OSX: Mach-O object file output

  • From: Adam Strzelecki <ono@xxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Mon, 29 Oct 2012 23:34:13 +0100

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)


Other related posts: