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 } ctab[] =
44 { /* Font Tab 4 */
45 M386, ALINUX, coreregslinux386,
46 M386, ANONE, coreregslinux386, /* [sic] */
47 M386, AFREEBSD, coreregsfreebsd386,
48 };
50 int
51 crackelf(int fd, Fhdr *fp)
52 {
53 int i, havetext, havedata;
54 Elf *elf;
55 ElfProg *p;
56 ElfSect *s1, *s2;
58 if((elf = elfinit(fd)) == nil)
59 return -1;
61 fp->fd = fd;
62 fp->elf = elf;
63 fp->dwarf = dwarfopen(elf); /* okay to fail */
64 fp->syminit = symelf;
66 if((s1 = elfsection(elf, ".stab")) != nil && s1->link!=0 && s1->link < elf->nsect){
67 s2 = &elf->sect[s1->link];
68 if(elfmap(elf, s1) >= 0 && elfmap(elf, s2) >= 0){
69 fp->stabs.stabbase = s1->base;
70 fp->stabs.stabsize = s1->size;
71 fp->stabs.strbase = (char*)s2->base;
72 fp->stabs.strsize = s2->size;
73 fp->stabs.e2 = elf->hdr.e2;
74 fp->stabs.e4 = elf->hdr.e4;
75 }
76 }
78 for(i=0; i<nelem(mtab); i++){
79 if(elf->hdr.machine != mtab[i].etype)
80 continue;
81 fp->mach = mtab[i].mach;
82 fp->mname = mtab[i].name;
83 fp->mtype = mtab[i].mtype;
84 break;
85 }
86 if(i == nelem(mtab)){
87 werrstr("unsupported machine type %d", elf->hdr.machine);
88 goto err;
89 }
91 if(mach == nil)
92 mach = fp->mach;
94 fp->aname = "unknown";
95 for(i=0; i<nelem(atab); i++){
96 if(elf->hdr.abi != atab[i].etype)
97 continue;
98 fp->atype = atab[i].atype;
99 fp->aname = atab[i].aname;
100 break;
103 switch(elf->hdr.type){
104 default:
105 werrstr("unknown file type %d", elf->hdr.type);
106 goto err;
107 case ElfTypeExecutable:
108 fp->ftype = FEXEC;
109 fp->fname = "executable";
110 break;
111 case ElfTypeRelocatable:
112 fp->ftype = FRELOC;
113 fp->fname = "relocatable";
114 break;
115 case ElfTypeSharedObject:
116 fp->ftype = FSHOBJ;
117 fp->fname = "shared object";
118 break;
119 case ElfTypeCore:
120 fp->ftype = FCORE;
121 fp->fname = "core dump";
122 break;
125 fp->map = mapelf;
127 if(fp->ftype == FCORE){
128 for(i=0; i<nelem(ctab); i++){
129 if(ctab[i].atype != fp->atype
130 || ctab[i].mtype != fp->mtype)
131 continue;
132 elf->coreregs = ctab[i].coreregs;
133 break;
135 return 0;
138 fp->entry = elf->hdr.entry;
140 /* First r-x section we find is the text and initialized data */
141 /* First rw- section we find is the r/w data */
142 havetext = 0;
143 havedata = 0;
144 for(i=0; i<elf->nprog; i++){
145 p = &elf->prog[i];
146 if(p->type != ElfProgLoad)
147 continue;
148 if(!havetext && p->flags == (ElfProgFlagRead|ElfProgFlagExec) && p->align >= mach->pgsize){
149 havetext = 1;
150 fp->txtaddr = p->vaddr;
151 fp->txtsz = p->memsz;
152 fp->txtoff = p->offset;
154 if(!havedata && p->flags == (ElfProgFlagRead|ElfProgFlagWrite) && p->align >= mach->pgsize){
155 havedata = 1;
156 fp->dataddr = p->vaddr;
157 fp->datsz = p->filesz;
158 fp->datoff = p->offset;
159 fp->bsssz = p->memsz - p->filesz;
162 if(!havetext){
163 werrstr("did not find text segment in elf binary");
164 goto err;
166 if(!havedata){
167 werrstr("did not find data segment in elf binary");
168 goto err;
170 return 0;
172 err:
173 elfclose(elf);
174 return -1;
177 static int
178 mapelf(Fhdr *fp, ulong base, Map *map, Regs **regs)
180 int i;
181 Elf *elf;
182 ElfProg *p;
183 ulong sz;
184 ulong lim;
185 Seg s;
187 elf = fp->elf;
188 if(elf == nil){
189 werrstr("not an elf file");
190 return -1;
193 for(i=0; i<elf->nprog; i++){
194 p = &elf->prog[i];
195 if(p->type != ElfProgLoad)
196 continue;
197 if(p->align < mach->pgsize)
198 continue;
199 if(p->filesz){
200 memset(&s, 0, sizeof s);
201 s.file = fp->filename;
202 s.fd = fp->fd;
203 if(fp->ftype == FCORE)
204 s.name = "core";
205 else if(p->flags == 5)
206 s.name = "text";
207 else
208 s.name = "data";
209 s.base = base+p->vaddr;
210 s.size = p->filesz;
211 s.offset = p->offset;
212 if(addseg(map, s) < 0)
213 return -1;
215 /*
216 * If memsz > filesz, we're supposed to zero fill.
217 * Core files have zeroed sections where the pages
218 * can be filled in from the text file, so if this is a core
219 * we only fill in that which isn't yet mapped.
220 */
221 if(fp->ftype == FCORE){
222 sz = p->filesz;
223 while(sz < p->memsz){
224 if(addrtoseg(map, base+p->vaddr+sz, &s) < 0){
225 lim = base + p->vaddr + p->memsz;
226 if(addrtosegafter(map, base+p->vaddr+sz, &s) >= 0 && s.base < lim)
227 lim = s.base;
228 memset(&s, 0, sizeof s);
229 s.name = "zero";
230 s.base = base + p->vaddr + sz;
231 s.size = lim - s.base;
232 s.offset = p->offset;
233 if(addseg(map, s) < 0)
234 return -1;
235 }else
236 sz = (s.base+s.size) - (base + p->vaddr);
238 }else{
239 if(p->filesz < p->memsz){
240 memset(&s, 0, sizeof s);
241 s.name = "zero";
242 s.base = base + p->vaddr + p->filesz;
243 s.size = p->memsz - p->filesz;
244 if(addseg(map, s) < 0)
245 return -1;
250 if(fp->ftype == FCORE){
251 if(mapcoreregs(fp, map, regs) < 0)
252 fprint(2, "warning: reading core regs: %r");
255 return 0;
258 static int
259 unpacknote(Elf *elf, uchar *a, uchar *ea, ElfNote *note, uchar **pa)
261 if(a+12 > ea)
262 return -1;
263 note->namesz = elf->hdr.e4(a);
264 note->descsz = elf->hdr.e4(a+4);
265 note->type = elf->hdr.e4(a+8);
266 a += 12;
267 note->name = (char*)a;
268 /* XXX fetch alignment constants from elsewhere */
269 a += (note->namesz+3)&~3;
270 note->desc = (uchar*)a;
271 a += (note->descsz+3)&~3;
272 if(a > ea)
273 return -1;
274 *pa = a;
275 return 0;
278 static int
279 mapcoreregs(Fhdr *fp, Map *map, Regs **rp)
281 int i;
282 uchar *a, *sa, *ea, *uregs;
283 uint n;
284 ElfNote note;
285 ElfProg *p;
286 Elf *elf;
287 UregRegs *r;
289 elf = fp->elf;
290 if(elf->coreregs == nil){
291 werrstr("cannot parse %s %s cores", fp->mname, fp->aname);
292 return -1;
295 for(i=0; i<elf->nprog; i++){
296 p = &elf->prog[i];
297 if(p->type != ElfProgNote)
298 continue;
299 n = p->filesz;
300 a = malloc(n);
301 if(a == nil)
302 return -1;
303 if(seek(fp->fd, p->offset, 0) < 0 || readn(fp->fd, a, n) != n){
304 free(a);
305 continue;
307 sa = a;
308 ea = a+n;
309 while(a < ea){
310 note.offset = (a-sa) + p->offset;
311 if(unpacknote(elf, a, ea, &note, &a) < 0)
312 break;
313 switch(note.type){
314 case ElfNotePrStatus:
315 if((n = (*elf->coreregs)(elf, &note, &uregs)) < 0){
316 free(sa);
317 return -1;
319 free(sa);
320 if((r = mallocz(sizeof(*r), 1)) == nil){
321 free(uregs);
322 return -1;
324 r->r.rw = _uregrw;
325 r->ureg = uregs;
326 *rp = &r->r;
327 return 0;
328 case ElfNotePrFpreg:
329 case ElfNotePrPsinfo:
330 case ElfNotePrTaskstruct:
331 case ElfNotePrAuxv:
332 case ElfNotePrXfpreg:
333 break;
335 // fprint(2, "0x%lux note %s/%lud %p\n", note.offset, note.name, note.type, note.desc);
337 free(sa);
339 fprint(2, "could not find registers in core file\n");
340 return -1;