Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <mach.h>
4 #include "macho.h"
6 /*
7 http://www.channelu.com/NeXT/NeXTStep/3.3/nd/DevTools/14_MachO/MachO.htmld/
8 */
10 Macho*
11 machoopen(char *name)
12 {
13 int fd;
14 Macho *m;
16 if((fd = open(name, OREAD)) < 0)
17 return nil;
18 m = machoinit(fd);
19 if(m == nil)
20 close(fd);
21 return m;
22 }
24 static int
25 unpackseg(uchar *p, Macho *m, MachoCmd *c, uint type, uint sz)
26 {
27 u32int (*e4)(uchar*);
29 e4 = m->e4;
31 c->type = type;
32 c->size = sz;
33 switch(type){
34 default:
35 return -1;
36 case MachoCmdSegment:
37 if(sz < 56)
38 return -1;
39 strecpy(c->seg.name, c->seg.name+sizeof c->seg.name, (char*)p+8);
40 c->seg.vmaddr = e4(p+24);
41 c->seg.vmsize = e4(p+28);
42 c->seg.fileoff = e4(p+32);
43 c->seg.filesz = e4(p+36);
44 c->seg.maxprot = e4(p+40);
45 c->seg.initprot = e4(p+44);
46 c->seg.nsect = e4(p+48);
47 c->seg.flags = e4(p+52);
48 break;
49 case MachoCmdSymtab:
50 if(sz < 24)
51 return -1;
52 c->sym.symoff = e4(p+8);
53 c->sym.nsyms = e4(p+12);
54 c->sym.stroff = e4(p+16);
55 c->sym.strsize = e4(p+20);
56 break;
57 }
58 return 0;
59 }
62 Macho*
63 machoinit(int fd)
64 {
65 int i;
66 uchar hdr[7*4], *cmdp;
67 u32int (*e4)(uchar*);
68 ulong ncmd, cmdsz, ty, sz, off;
69 Macho *m;
71 if(seek(fd, 0, 0) < 0 || readn(fd, hdr, sizeof hdr) != sizeof hdr)
72 return nil;
74 if(beload4(hdr) == 0xFEEDFACE)
75 e4 = beload4;
76 else if(leload4(hdr) == 0xFEEDFACE)
77 e4 = leload4;
78 else{
79 werrstr("bad magic - not mach-o file");
80 return nil;
81 }
83 ncmd = e4(hdr+4*4);
84 cmdsz = e4(hdr+5*4);
85 if(ncmd > 0x10000 || cmdsz >= 0x01000000){
86 werrstr("implausible mach-o header ncmd=%lud cmdsz=%lud", ncmd, cmdsz);
87 return nil;
88 }
90 m = mallocz(sizeof(*m)+ncmd*sizeof(MachoCmd)+cmdsz, 1);
91 if(m == nil)
92 return nil;
94 m->fd = fd;
95 m->e4 = e4;
96 m->cputype = e4(hdr+1*4);
97 m->subcputype = e4(hdr+2*4);
98 m->filetype = e4(hdr+3*4);
99 m->ncmd = ncmd;
100 m->flags = e4(hdr+6*4);
102 m->cmd = (MachoCmd*)(m+1);
103 off = sizeof hdr;
104 cmdp = (uchar*)(m->cmd+ncmd);
105 if(readn(fd, cmdp, cmdsz) != cmdsz){
106 werrstr("reading cmds: %r");
107 free(m);
108 return nil;
111 for(i=0; i<ncmd; i++){
112 ty = e4(cmdp);
113 sz = e4(cmdp+4);
114 m->cmd[i].off = off;
115 unpackseg(cmdp, m, &m->cmd[i], ty, sz);
116 cmdp += sz;
117 off += sz;
120 return m;
123 void
124 machoclose(Macho *m)
126 close(m->fd);
127 free(m);