Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <mach.h>
4 #include "macho.h"
6 static int mapmacho(Fhdr *fp, u64int base, Map *map, Regs**);
8 static struct
9 {
10 uint etype;
11 uint mtype;
12 Mach *mach;
13 char *name;
14 int (*coreregs)(Macho*, uchar**);
15 } mtab[] =
16 {
17 MachoCpuPower, MPOWER, &machpower, "powerpc", coreregsmachopower,
18 };
20 static uchar*
21 load(int fd, ulong off, int size)
22 {
23 uchar *a;
25 a = malloc(size);
26 if(a == nil)
27 return nil;
28 if(seek(fd, off, 0) < 0 || readn(fd, a, size) != size){
29 free(a);
30 return nil;
31 }
32 return a;
33 }
35 int
36 crackmacho(int fd, Fhdr *fp)
37 {
38 int i;
39 Macho *m;
41 if((m = machoinit(fd)) == nil)
42 return -1;
44 fp->fd = fd;
45 fp->macho = m;
47 for(i=0; i<nelem(mtab); i++){
48 if(m->cputype != mtab[i].etype)
49 continue;
50 fp->mach = mtab[i].mach;
51 fp->mtype = mtab[i].mtype;
52 fp->mname = mtab[i].name;
53 m->coreregs = mtab[i].coreregs;
54 break;
55 }
56 if(i == nelem(mtab)){
57 werrstr("unsupported cpu type %ud", m->cputype);
58 goto err;
59 }
61 fp->atype = AMACH;
62 fp->aname = "mach";
64 if(mach == nil)
65 mach = fp->mach;
67 switch(m->filetype){
68 default:
69 werrstr("unsupported macho file type %lud", m->filetype);
70 goto err;
71 case MachoFileObject:
72 fp->ftype = FOBJ;
73 fp->fname = "object";
74 break;
75 case MachoFileExecutable:
76 fp->ftype = FEXEC;
77 fp->fname = "executable";
78 break;
79 case MachoFileFvmlib:
80 fp->ftype = FSHLIB;
81 fp->fname = "shared library";
82 break;
83 case MachoFileCore:
84 fp->ftype = FCORE;
85 fp->fname = "core";
86 break;
87 case MachoFilePreload:
88 fp->ftype = FBOOT;
89 fp->fname = "preloaded executable";
90 break;
91 }
93 fp->txtaddr = fp->dataddr = 0;
94 fp->txtsz = fp->datsz = 0;
95 for(i=0; i<m->ncmd; i++){
96 if(m->cmd[i].type != MachoCmdSegment)
97 continue;
98 if(strcmp(m->cmd[i].seg.name, "__TEXT") == 0){
99 fp->txtaddr = m->cmd[i].seg.vmaddr;
100 fp->txtsz = m->cmd[i].seg.vmsize;
101 fp->txtoff = m->cmd[i].seg.fileoff;
103 if(strcmp(m->cmd[i].seg.name, "__DATA") == 0){
104 fp->dataddr = m->cmd[i].seg.vmaddr;
105 fp->datsz = m->cmd[i].seg.filesz;
106 fp->datoff = m->cmd[i].seg.fileoff;
107 fp->bsssz = m->cmd[i].seg.vmsize - fp->datsz;
111 fp->map = mapmacho;
112 fp->syminit = symmacho;
114 for(i=0; i<m->ncmd; i++)
115 if(m->cmd[i].type == MachoCmdSymtab)
116 break;
117 if(i < m->ncmd){
118 fp->stabs.stabbase = load(fp->fd, m->cmd[i].sym.symoff, m->cmd[i].sym.nsym*16);
119 fp->stabs.stabsize = m->cmd[i].sym.nsym*16;
120 fp->stabs.strbase = (char*)load(fp->fd, m->cmd[i].sym.stroff, m->cmd[i].sym.strsize);
121 if(fp->stabs.stabbase == nil || fp->stabs.strbase == nil){
122 fp->stabs.stabbase = nil;
123 fp->stabs.strbase = nil;
124 }else{
125 fp->stabs.strsize = m->cmd[i].sym.strsize;
126 fp->stabs.e2 = (m->e4==beload4 ? beload2 : leload2);
127 fp->stabs.e4 = m->e4;
131 return 0;
133 err:
134 machoclose(m);
135 return -1;
138 static int
139 mapmacho(Fhdr *fp, u64int base, Map *map, Regs **rp)
141 int i, n;
142 uchar *u;
143 Macho *m;
144 MachoCmd *c;
145 Seg s;
146 UregRegs *r;
148 m = fp->macho;
149 if(m == nil){
150 werrstr("not a macho file");
151 return -1;
154 for(i=0; i<m->ncmd; i++){
155 c = &m->cmd[i];
156 if(c->type != MachoCmdSegment)
157 continue;
158 if(c->seg.filesz){
159 memset(&s, 0, sizeof s);
160 s.file = fp->filename;
161 s.fd = fp->fd;
162 if(fp->ftype == FCORE)
163 s.name = "core";
164 else if(strcmp(c->seg.name, "__DATA") == 0)
165 s.name = "data";
166 else
167 s.name = "text";
168 s.base = base+c->seg.vmaddr;
169 s.size = c->seg.filesz;
170 s.offset = c->seg.fileoff;
171 if(addseg(map, s) < 0)
172 return -1;
174 if(c->seg.filesz < c->seg.vmsize){
175 memset(&s, 0, sizeof s);
176 s.name = "zero";
177 s.base = base + c->seg.vmaddr + c->seg.filesz;
178 s.size = c->seg.vmsize - c->seg.filesz;
179 if(addseg(map, s) < 0)
180 return -1;
184 if(fp->ftype == FCORE && m->coreregs){
185 n = m->coreregs(m, &u);
186 if(n < 0){
187 fprint(2, "mapping registers: %r\n");
188 goto noregs;
190 if((r = mallocz(sizeof *r, 1)) == nil)
191 return -1;
192 r->r.rw = _uregrw;
193 r->ureg = u;
194 *rp = &r->r;
196 noregs:
197 return 0;