#include #include #include #include "macho.h" /* http://www.channelu.com/NeXT/NeXTStep/3.3/nd/DevTools/14_MachO/MachO.htmld/ */ Macho* machoopen(char *name) { int fd; Macho *m; if((fd = open(name, OREAD)) < 0) return nil; m = machoinit(fd); if(m == nil) close(fd); return m; } static int unpackseg(uchar *p, Macho *m, MachoCmd *c, uint type, uint sz) { u32int (*e4)(uchar*); e4 = m->e4; c->type = type; c->size = sz; switch(type){ default: return -1; case MachoCmdSegment: if(sz < 56) return -1; strecpy(c->seg.name, c->seg.name+sizeof c->seg.name, (char*)p+8); c->seg.vmaddr = e4(p+24); c->seg.vmsize = e4(p+28); c->seg.fileoff = e4(p+32); c->seg.filesz = e4(p+36); c->seg.maxprot = e4(p+40); c->seg.initprot = e4(p+44); c->seg.nsect = e4(p+48); c->seg.flags = e4(p+52); break; case MachoCmdSymtab: if(sz < 24) return -1; c->sym.symoff = e4(p+8); c->sym.nsyms = e4(p+12); c->sym.stroff = e4(p+16); c->sym.strsize = e4(p+20); break; } return 0; } Macho* machoinit(int fd) { int i; uchar hdr[7*4], *cmdp; u32int (*e4)(uchar*); ulong ncmd, cmdsz, ty, sz, off; Macho *m; if(seek(fd, 0, 0) < 0 || readn(fd, hdr, sizeof hdr) != sizeof hdr) return nil; if(beload4(hdr) == 0xFEEDFACE) e4 = beload4; else if(leload4(hdr) == 0xFEEDFACE) e4 = leload4; else{ werrstr("bad magic - not mach-o file"); return nil; } ncmd = e4(hdr+4*4); cmdsz = e4(hdr+5*4); if(ncmd > 0x10000 || cmdsz >= 0x01000000){ werrstr("implausible mach-o header ncmd=%lud cmdsz=%lud", ncmd, cmdsz); return nil; } m = mallocz(sizeof(*m)+ncmd*sizeof(MachoCmd)+cmdsz, 1); if(m == nil) return nil; m->fd = fd; m->e4 = e4; m->cputype = e4(hdr+1*4); m->subcputype = e4(hdr+2*4); m->filetype = e4(hdr+3*4); m->ncmd = ncmd; m->flags = e4(hdr+6*4); m->cmd = (MachoCmd*)(m+1); off = sizeof hdr; cmdp = (uchar*)(m->cmd+ncmd); if(readn(fd, cmdp, cmdsz) != cmdsz){ werrstr("reading cmds: %r"); free(m); return nil; } for(i=0; icmd[i].off = off; unpackseg(cmdp, m, &m->cmd[i], ty, sz); cmdp += sz; off += sz; } return m; } void machoclose(Macho *m) { close(m->fd); free(m); }