7 http://www.channelu.com/NeXT/NeXTStep/3.3/nd/DevTools/14_MachO/MachO.htmld/
16 if((fd = open(name, OREAD)) < 0)
25 unpackcmd(uchar *p, Macho *m, MachoCmd *c, uint type, uint sz)
43 strecpy(c->seg.name, c->seg.name+sizeof c->seg.name, (char*)p+8);
44 c->seg.vmaddr = e4(p+24);
45 c->seg.vmsize = e4(p+28);
46 c->seg.fileoff = e4(p+32);
47 c->seg.filesz = e4(p+36);
48 c->seg.maxprot = e4(p+40);
49 c->seg.initprot = e4(p+44);
50 c->seg.nsect = e4(p+48);
51 c->seg.flags = e4(p+52);
52 c->seg.sect = mallocz(c->seg.nsect * sizeof c->seg.sect[0], 1);
53 if(c->seg.sect == nil)
55 if(sz < 56+c->seg.nsect*68)
58 for(i=0; i<c->seg.nsect; i++) {
60 strecpy(s->name, s->name+sizeof s->name, (char*)p+0);
61 strecpy(s->segname, s->segname+sizeof s->segname, (char*)p+16);
69 // p+60 and p+64 are reserved
73 case MachoCmdSegment64:
76 strecpy(c->seg.name, c->seg.name+sizeof c->seg.name, (char*)p+8);
77 c->seg.vmaddr = e8(p+24);
78 c->seg.vmsize = e8(p+32);
79 c->seg.fileoff = e8(p+40);
80 c->seg.filesz = e8(p+48);
81 c->seg.maxprot = e4(p+56);
82 c->seg.initprot = e4(p+60);
83 c->seg.nsect = e4(p+64);
84 c->seg.flags = e4(p+68);
85 c->seg.sect = mallocz(c->seg.nsect * sizeof c->seg.sect[0], 1);
86 if(c->seg.sect == nil)
88 if(sz < 72+c->seg.nsect*80)
91 for(i=0; i<c->seg.nsect; i++) {
93 strecpy(s->name, s->name+sizeof s->name, (char*)p+0);
94 strecpy(s->segname, s->segname+sizeof s->segname, (char*)p+16);
100 s->nreloc = e4(p+60);
102 // p+68, p+72, and p+76 are reserved
109 c->sym.symoff = e4(p+8);
110 c->sym.nsym = e4(p+12);
111 c->sym.stroff = e4(p+16);
112 c->sym.strsize = e4(p+20);
114 case MachoCmdDysymtab:
117 c->dsym.ilocalsym = e4(p+8);
118 c->dsym.nlocalsym = e4(p+12);
119 c->dsym.iextdefsym = e4(p+16);
120 c->dsym.nextdefsym = e4(p+20);
121 c->dsym.iundefsym = e4(p+24);
122 c->dsym.nundefsym = e4(p+28);
123 c->dsym.tocoff = e4(p+32);
124 c->dsym.ntoc = e4(p+36);
125 c->dsym.modtaboff = e4(p+40);
126 c->dsym.nmodtab = e4(p+44);
127 c->dsym.extrefsymoff = e4(p+48);
128 c->dsym.nextrefsyms = e4(p+52);
129 c->dsym.indirectsymoff = e4(p+56);
130 c->dsym.nindirectsyms = e4(p+60);
131 c->dsym.extreloff = e4(p+64);
132 c->dsym.nextrel = e4(p+68);
133 c->dsym.locreloff = e4(p+72);
134 c->dsym.nlocrel = e4(p+76);
141 macholoadrel(Macho *m, MachoSect *sect)
148 if(sect->rel != nil || sect->nreloc == 0)
150 rel = mallocz(sect->nreloc * sizeof r[0], 1);
153 n = sect->nreloc * 8;
159 if(seek(m->fd, sect->reloff, 0) < 0 || readn(m->fd, buf, n) != n) {
164 for(i=0; i<sect->nreloc; i++) {
169 // TODO(rsc): Wrong interpretation for big-endian bitfields?
171 r->symnum = v & 0xFFFFFF;
175 r->length = 1<<(v&3);
187 macholoadsym(Macho *m, MachoSymtab *symtab)
195 if(symtab->sym != nil)
198 strbuf = mallocz(symtab->strsize, 1);
201 if(seek(m->fd, symtab->stroff, 0) < 0 || readn(m->fd, strbuf, symtab->strsize) != symtab->strsize) {
209 n = symtab->nsym * symsize;
210 symbuf = mallocz(n, 1);
215 if(seek(m->fd, symtab->symoff, 0) < 0 || readn(m->fd, symbuf, n) != n) {
220 sym = mallocz(symtab->nsym * sizeof sym[0], 1);
227 for(i=0; i<symtab->nsym; i++) {
230 if(v >= symtab->strsize) {
236 s->name = strbuf + v;
239 s->desc = m->e2(p+6);
241 s->value = m->e8(p+8);
243 s->value = m->e4(p+8);
246 symtab->str = strbuf;
256 uchar hdr[7*4], *cmdp;
258 uint16 (*e2)(uchar*);
259 uint32 (*e4)(uchar*);
260 uint64 (*e8)(uchar*);
261 ulong ncmd, cmdsz, ty, sz, off;
264 if(seek(fd, 0, 0) < 0 || readn(fd, hdr, sizeof hdr) != sizeof hdr)
267 if((beload4(hdr)&~1) == 0xFEEDFACE){
271 }else if((leload4(hdr)&~1) == 0xFEEDFACE){
276 werrstr("bad magic - not mach-o file");
279 is64 = e4(hdr) == 0xFEEDFACF;
282 if(ncmd > 0x10000 || cmdsz >= 0x01000000){
283 werrstr("implausible mach-o header ncmd=%lud cmdsz=%lud", ncmd, cmdsz);
287 readn(fd, tmp, 4); // skip reserved word in header
289 m = mallocz(sizeof(*m)+ncmd*sizeof(MachoCmd)+cmdsz, 1);
297 m->cputype = e4(hdr+1*4);
298 m->subcputype = e4(hdr+2*4);
299 m->filetype = e4(hdr+3*4);
301 m->flags = e4(hdr+6*4);
304 m->cmd = (MachoCmd*)(m+1);
306 cmdp = (uchar*)(m->cmd+ncmd);
307 if(readn(fd, cmdp, cmdsz) != cmdsz){
308 werrstr("reading cmds: %r");
313 for(i=0; i<ncmd; i++){
317 unpackcmd(cmdp, m, &m->cmd[i], ty, sz);