diff options
Diffstat (limited to 'src/libmach_amd64/executable.c')
-rw-r--r-- | src/libmach_amd64/executable.c | 150 |
1 files changed, 149 insertions, 1 deletions
diff --git a/src/libmach_amd64/executable.c b/src/libmach_amd64/executable.c index d00dc2ffa..4f0356ebc 100644 --- a/src/libmach_amd64/executable.c +++ b/src/libmach_amd64/executable.c @@ -32,6 +32,7 @@ #include <bootexec.h> #include <mach_amd64.h> #include "elf.h" +#include "macho.h" /* * All a.out header types. The dummy entry allows canonical @@ -50,6 +51,7 @@ typedef struct { struct mips4kexec mipsk4; /* bootexec.h */ struct sparcexec sparc; /* bootexec.h */ struct nextexec next; /* bootexec.h */ + Machhdr machhdr; /* macho.h */ } e; long dummy; /* padding to ensure extra long */ } ExecHdr; @@ -62,6 +64,7 @@ static int common(int, Fhdr*, ExecHdr*); static int commonllp64(int, Fhdr*, ExecHdr*); static int adotout(int, Fhdr*, ExecHdr*); static int elfdotout(int, Fhdr*, ExecHdr*); +static int machdotout(int, Fhdr*, ExecHdr*); static int armdotout(int, Fhdr*, ExecHdr*); static void setsym(Fhdr*, long, long, long, vlong); static void setdata(Fhdr*, uvlong, long, vlong, long); @@ -256,6 +259,15 @@ ExecTable exectab[] = sizeof(Ehdr64), nil, elfdotout }, + { MACH_MAG, /* 64-bit MACH (apple mac) */ + "mach executable", + nil, + FAMD64, + 0, + &mi386, + sizeof(Ehdr64), + nil, + machdotout }, { E_MAGIC, /* Arm 5.out and boot image */ "arm plan 9 executable", "arm plan 9 dlm", @@ -652,7 +664,6 @@ elf64dotout(int fd, Fhdr *fp, ExecHdr *hp) ep->machine = swab(ep->machine); ep->version = swal(ep->version); ep->elfentry = swal(ep->elfentry); -print("entry: 0x%x\n", ep->elfentry); ep->phoff = swav(ep->phoff); ep->shoff = swav(ep->shoff); ep->flags = swav(ep->flags); @@ -945,6 +956,143 @@ elfdotout(int fd, Fhdr *fp, ExecHdr *hp) return 1; } +static int +machdotout(int fd, Fhdr *fp, ExecHdr *hp) +{ + uvlong (*swav)(uvlong); + ulong (*swal)(ulong); + ushort (*swab)(ushort); + Machhdr *mp; + MachCmd **cmd; + MachSeg64 *text; + MachSeg64 *data; + MachSymSeg *symtab; + MachSymSeg *pclntab; + MachSeg64 *seg; + MachSect64 *sect; + uvlong textsize, datasize, bsssize; + uchar *cmdbuf; + uchar *cmdp; + int i; + + /* bitswap the header according to the DATA format */ + mp = &hp->e.machhdr; + if (mp->cputype != leswal(MACH_CPU_TYPE_X86_64)) { + werrstr("bad MACH cpu type - not amd64"); + return 0; + } + swab = leswab; + swal = leswal; + swav = leswav; + + mp->magic = swal(mp->magic); + mp->cputype = swal(mp->cputype); + mp->cpusubtype = swal(mp->cpusubtype); + mp->filetype = swal(mp->filetype); + mp->ncmds = swal(mp->ncmds); + mp->sizeofcmds = swal(mp->sizeofcmds); + mp->flags = swal(mp->flags); + mp->reserved = swal(mp->reserved); + if (mp->cpusubtype != MACH_CPU_SUBTYPE_X86) { + werrstr("bad MACH cpu subtype - not amd64"); + return 0; + } + if (mp->filetype != MACH_EXECUTABLE_TYPE) { + werrstr("bad MACH cpu subtype - not amd64"); + return 0; + } + mach = &mamd64; + fp->type = FAMD64; + + cmdbuf = malloc(mp->sizeofcmds); + seek(fd, sizeof(Machhdr), 0); + if(read(fd, cmdbuf, mp->sizeofcmds) != mp->sizeofcmds) { + free(cmdbuf); + return 0; + } + cmd = malloc(mp->ncmds * sizeof(MachCmd*)); + cmdp = cmdbuf; + text = 0; + data = 0; + symtab = 0; + pclntab = 0; + textsize = datasize = bsssize = 0; + for (i = 0; i < mp->ncmds; i++) { + MachCmd *c; + + cmd[i] = (MachCmd*)cmdp; + c = cmd[i]; + c->type = swal(c->type); + c->size = swal(c->size); + switch(c->type) { + case MACH_SEGMENT_64: + seg = (MachSeg64*)c; + seg->vmaddr = swav(seg->vmaddr); + seg->vmsize = swav(seg->vmsize); + seg->fileoff = swav(seg->fileoff); + seg->filesize = swav(seg->filesize); + seg->maxprot = swal(seg->maxprot); + seg->initprot = swal(seg->initprot); + seg->nsects = swal(seg->nsects); + seg->flags = swal(seg->flags); + if (strcmp(seg->segname, "__TEXT") == 0) { + text = seg; + sect = (MachSect64*)(cmdp + sizeof(MachSeg64)); + if (strcmp(sect->sectname, "__text") == 0) { + textsize = swav(sect->size); + } else { + werrstr("no text section"); + goto bad; + } + } + if (strcmp(seg->segname, "__DATA") == 0) { + data = seg; + sect = (MachSect64*)(cmdp + sizeof(MachSeg64)); + if (strcmp(sect->sectname, "__data") == 0) { + datasize = swav(sect->size); + } else { + werrstr("no data section"); + goto bad; + } + sect++; + if (strcmp(sect->sectname, "__bss") == 0) { + bsssize = swav(sect->size); + } else { + werrstr("no bss section"); + goto bad; + } + } + break; + case MACH_UNIXTHREAD: + break; + case MACH_SYMSEG: + if (symtab == 0) + symtab = (MachSymSeg*)c; + else if (pclntab == 0) + pclntab = (MachSymSeg*)c; + break; + } + cmdp += c->size; + } + if (text == 0 || data == 0) { + free(cmd); + free(cmdbuf); + return 0; + } + /* compute entry by taking address after header - weird - BUG? */ + settext(fp, text->vmaddr+sizeof(Machhdr) + mp->sizeofcmds, text->vmaddr, textsize, text->fileoff); + setdata(fp, data->vmaddr, datasize, data->fileoff, bsssize); + if(symtab != 0) + setsym(fp, symtab->filesize, 0, pclntab? pclntab->filesize : 0, symtab->fileoff); + free(cmd); + free(cmdbuf); + return 1; +bad: + free(cmd); + free(cmdbuf); + return 0; +} + /* * (Free|Net)BSD ARM header. */ |