Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <mach.h>
4 #include "elf.h"
5 #include "dwarf.h"
7 static int mapelf(Fhdr *fp, ulong base, Map *map, Regs**);
8 static int mapcoreregs(Fhdr *fp, Map *map, Regs**);
10 static struct
11 {
12 uint etype;
13 uint mtype;
14 Mach *mach;
15 char *name;
16 } mtab[] =
17 { /* Font Tab 4 */
18 ElfMachSparc, MSPARC, nil, "sparc",
19 ElfMach386, M386, &mach386, "386",
20 ElfMachMips, MMIPS, nil, "mips",
21 ElfMachArm, MARM, nil, "arm",
22 ElfMachPower, MPOWER, nil, "powerpc",
23 ElfMachPower64, MNONE, nil, "powerpc64",
24 };
26 static struct
27 {
28 uint etype;
29 uint atype;
30 char *aname;
31 } atab[] =
32 { /* Font Tab 4 */
33 ElfAbiSystemV, ALINUX, "linux", /* [sic] */
34 ElfAbiLinux, ALINUX, "linux",
35 ElfAbiFreeBSD, AFREEBSD, "freebsd",
36 };
38 static struct
39 {
40 uint mtype;
41 uint atype;
42 int (*coreregs)(Elf*, ElfNote*, uchar**);
43 int (*corecmd)(Elf*, ElfNote*, char**);
44 } ctab[] =
45 { /* Font Tab 4 */
46 M386, ALINUX,
47 coreregslinux386,
48 corecmdlinux386,
49 M386, ANONE,
50 coreregslinux386, /* [sic] */
51 corecmdlinux386, /* [sic] */
52 M386, AFREEBSD,
53 coreregsfreebsd386,
54 corecmdfreebsd386,
55 };
57 int
58 crackelf(int fd, Fhdr *fp)
59 {
60 int i, havetext, havedata;
61 Elf *elf;
62 ElfProg *p;
63 ElfSect *s1, *s2;
65 if((elf = elfinit(fd)) == nil)
66 return -1;
68 fp->fd = fd;
69 fp->elf = elf;
70 fp->dwarf = dwarfopen(elf); /* okay to fail */
71 fp->syminit = symelf;
73 if((s1 = elfsection(elf, ".stab")) != nil && s1->link!=0 && s1->link < elf->nsect){
74 s2 = &elf->sect[s1->link];
75 if(elfmap(elf, s1) >= 0 && elfmap(elf, s2) >= 0){
76 fp->stabs.stabbase = s1->base;
77 fp->stabs.stabsize = s1->size;
78 fp->stabs.strbase = (char*)s2->base;
79 fp->stabs.strsize = s2->size;
80 fp->stabs.e2 = elf->hdr.e2;
81 fp->stabs.e4 = elf->hdr.e4;
82 }
83 }
85 for(i=0; i<nelem(mtab); i++){
86 if(elf->hdr.machine != mtab[i].etype)
87 continue;
88 fp->mach = mtab[i].mach;
89 fp->mname = mtab[i].name;
90 fp->mtype = mtab[i].mtype;
91 break;
92 }
93 if(i == nelem(mtab)){
94 werrstr("unsupported machine type %d", elf->hdr.machine);
95 goto err;
96 }
98 if(mach == nil)
99 mach = fp->mach;
101 fp->aname = "unknown";
102 for(i=0; i<nelem(atab); i++){
103 if(elf->hdr.abi != atab[i].etype)
104 continue;
105 fp->atype = atab[i].atype;
106 fp->aname = atab[i].aname;
107 break;
110 switch(elf->hdr.type){
111 default:
112 werrstr("unknown file type %d", elf->hdr.type);
113 goto err;
114 case ElfTypeExecutable:
115 fp->ftype = FEXEC;
116 fp->fname = "executable";
117 break;
118 case ElfTypeRelocatable:
119 fp->ftype = FRELOC;
120 fp->fname = "relocatable";
121 break;
122 case ElfTypeSharedObject:
123 fp->ftype = FSHOBJ;
124 fp->fname = "shared object";
125 break;
126 case ElfTypeCore:
127 fp->ftype = FCORE;
128 fp->fname = "core dump";
129 break;
132 fp->map = mapelf;
134 if(fp->ftype == FCORE){
135 for(i=0; i<nelem(ctab); i++){
136 if(ctab[i].atype != fp->atype
137 || ctab[i].mtype != fp->mtype)
138 continue;
139 elf->coreregs = ctab[i].coreregs;
140 break;
142 return 0;
145 fp->entry = elf->hdr.entry;
147 /* First r-x section we find is the text and initialized data */
148 /* First rw- section we find is the r/w data */
149 havetext = 0;
150 havedata = 0;
151 for(i=0; i<elf->nprog; i++){
152 p = &elf->prog[i];
153 if(p->type != ElfProgLoad)
154 continue;
155 if(!havetext && p->flags == (ElfProgFlagRead|ElfProgFlagExec) && p->align >= mach->pgsize){
156 havetext = 1;
157 fp->txtaddr = p->vaddr;
158 fp->txtsz = p->memsz;
159 fp->txtoff = p->offset;
161 if(!havedata && p->flags == (ElfProgFlagRead|ElfProgFlagWrite) && p->align >= mach->pgsize){
162 havedata = 1;
163 fp->dataddr = p->vaddr;
164 fp->datsz = p->filesz;
165 fp->datoff = p->offset;
166 fp->bsssz = p->memsz - p->filesz;
169 if(!havetext){
170 werrstr("did not find text segment in elf binary");
171 goto err;
173 if(!havedata){
174 werrstr("did not find data segment in elf binary");
175 goto err;
177 return 0;
179 err:
180 elfclose(elf);
181 return -1;
184 static int
185 mapelf(Fhdr *fp, ulong base, Map *map, Regs **regs)
187 int i;
188 Elf *elf;
189 ElfProg *p;
190 ulong sz;
191 ulong lim;
192 Seg s;
194 elf = fp->elf;
195 if(elf == nil){
196 werrstr("not an elf file");
197 return -1;
200 for(i=0; i<elf->nprog; i++){
201 p = &elf->prog[i];
202 if(p->type != ElfProgLoad)
203 continue;
204 if(p->align < mach->pgsize)
205 continue;
206 if(p->filesz){
207 memset(&s, 0, sizeof s);
208 s.file = fp->filename;
209 s.fd = fp->fd;
210 if(fp->ftype == FCORE)
211 s.name = "core";
212 else if(p->flags == 5)
213 s.name = "text";
214 else
215 s.name = "data";
216 s.base = base+p->vaddr;
217 s.size = p->filesz;
218 s.offset = p->offset;
219 if(addseg(map, s) < 0)
220 return -1;
222 /*
223 * If memsz > filesz, we're supposed to zero fill.
224 * Core files have zeroed sections where the pages
225 * can be filled in from the text file, so if this is a core
226 * we only fill in that which isn't yet mapped.
227 */
228 if(fp->ftype == FCORE){
229 sz = p->filesz;
230 while(sz < p->memsz){
231 if(addrtoseg(map, base+p->vaddr+sz, &s) < 0){
232 lim = base + p->vaddr + p->memsz;
233 if(addrtosegafter(map, base+p->vaddr+sz, &s) >= 0 && s.base < lim)
234 lim = s.base;
235 memset(&s, 0, sizeof s);
236 s.name = "zero";
237 s.base = base + p->vaddr + sz;
238 s.size = lim - s.base;
239 s.offset = p->offset;
240 if(addseg(map, s) < 0)
241 return -1;
242 }else
243 sz = (s.base+s.size) - (base + p->vaddr);
245 }else{
246 if(p->filesz < p->memsz){
247 memset(&s, 0, sizeof s);
248 s.name = "zero";
249 s.base = base + p->vaddr + p->filesz;
250 s.size = p->memsz - p->filesz;
251 if(addseg(map, s) < 0)
252 return -1;
257 if(fp->ftype == FCORE){
258 if(mapcoreregs(fp, map, regs) < 0)
259 fprint(2, "warning: reading core regs: %r");
262 return 0;
265 static int
266 unpacknote(Elf *elf, uchar *a, uchar *ea, ElfNote *note, uchar **pa)
268 if(a+12 > ea)
269 return -1;
270 note->namesz = elf->hdr.e4(a);
271 note->descsz = elf->hdr.e4(a+4);
272 note->type = elf->hdr.e4(a+8);
273 a += 12;
274 note->name = (char*)a;
275 /* XXX fetch alignment constants from elsewhere */
276 a += (note->namesz+3)&~3;
277 note->desc = (uchar*)a;
278 a += (note->descsz+3)&~3;
279 if(a > ea)
280 return -1;
281 *pa = a;
282 return 0;
285 static int
286 mapcoreregs(Fhdr *fp, Map *map, Regs **rp)
288 int i;
289 uchar *a, *sa, *ea, *uregs;
290 uint n;
291 ElfNote note;
292 ElfProg *p;
293 Elf *elf;
294 UregRegs *r;
296 elf = fp->elf;
297 if(elf->coreregs == 0){
298 werrstr("cannot parse %s %s cores", fp->mname, fp->aname);
299 return -1;
302 for(i=0; i<elf->nprog; i++){
303 p = &elf->prog[i];
304 if(p->type != ElfProgNote)
305 continue;
306 n = p->filesz;
307 a = malloc(n);
308 if(a == nil)
309 return -1;
310 if(seek(fp->fd, p->offset, 0) < 0 || readn(fp->fd, a, n) != n){
311 free(a);
312 continue;
314 sa = a;
315 ea = a+n;
316 while(a < ea){
317 note.offset = (a-sa) + p->offset;
318 if(unpacknote(elf, a, ea, &note, &a) < 0)
319 break;
320 switch(note.type){
321 case ElfNotePrStatus:
322 if((n = (*elf->coreregs)(elf, &note, &uregs)) < 0){
323 free(sa);
324 return -1;
326 free(sa);
327 if((r = mallocz(sizeof(*r), 1)) == nil){
328 free(uregs);
329 return -1;
331 r->r.rw = _uregrw;
332 r->ureg = uregs;
333 *rp = &r->r;
334 return 0;
335 case ElfNotePrFpreg:
336 case ElfNotePrPsinfo:
337 case ElfNotePrTaskstruct:
338 case ElfNotePrAuxv:
339 case ElfNotePrXfpreg:
340 break;
342 // fprint(2, "0x%lux note %s/%lud %p\n", note.offset, note.name, note.type, note.desc);
344 free(sa);
346 fprint(2, "could not find registers in core file\n");
347 return -1;