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 unpacknote(Elf *elf, uchar *a, uchar *ea, ElfNote *note, uchar **pa);
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 void (*elfcore)(Fhdr*, Elf*, ElfNote*);
43 } ctab[] =
44 { /* Font Tab 4 */
45 M386, ALINUX, elfcorelinux386,
46 M386, ANONE, elfcorelinux386, /* [sic] */
47 /* M386, AFREEBSD, elfcorefreebsd386, */
48 };
50 int
51 crackelf(int fd, Fhdr *fp)
52 {
53 uchar *a, *sa, *ea;
54 int i, havetext, havedata, n;
55 Elf *elf;
56 ElfNote note;
57 ElfProg *p;
58 ElfSect *s1, *s2;
59 void (*elfcore)(Fhdr*, Elf*, ElfNote*);
61 if((elf = elfinit(fd)) == nil)
62 return -1;
64 fp->fd = fd;
65 fp->elf = elf;
66 fp->dwarf = dwarfopen(elf); /* okay to fail */
67 fp->syminit = symelf;
69 if((s1 = elfsection(elf, ".stab")) != nil && s1->link!=0 && s1->link < elf->nsect){
70 s2 = &elf->sect[s1->link];
71 if(elfmap(elf, s1) >= 0 && elfmap(elf, s2) >= 0){
72 fp->stabs.stabbase = s1->base;
73 fp->stabs.stabsize = s1->size;
74 fp->stabs.strbase = (char*)s2->base;
75 fp->stabs.strsize = s2->size;
76 fp->stabs.e2 = elf->hdr.e2;
77 fp->stabs.e4 = elf->hdr.e4;
78 }
79 }
81 for(i=0; i<nelem(mtab); i++){
82 if(elf->hdr.machine != mtab[i].etype)
83 continue;
84 fp->mach = mtab[i].mach;
85 fp->mname = mtab[i].name;
86 fp->mtype = mtab[i].mtype;
87 break;
88 }
89 if(i == nelem(mtab)){
90 werrstr("unsupported machine type %d", elf->hdr.machine);
91 goto err;
92 }
94 if(mach == nil)
95 mach = fp->mach;
97 fp->aname = "unknown";
98 for(i=0; i<nelem(atab); i++){
99 if(elf->hdr.abi != atab[i].etype)
100 continue;
101 fp->atype = atab[i].atype;
102 fp->aname = atab[i].aname;
103 break;
106 switch(elf->hdr.type){
107 default:
108 werrstr("unknown file type %d", elf->hdr.type);
109 goto err;
110 case ElfTypeExecutable:
111 fp->ftype = FEXEC;
112 fp->fname = "executable";
113 break;
114 case ElfTypeRelocatable:
115 fp->ftype = FRELOC;
116 fp->fname = "relocatable";
117 break;
118 case ElfTypeSharedObject:
119 fp->ftype = FSHOBJ;
120 fp->fname = "shared object";
121 break;
122 case ElfTypeCore:
123 fp->ftype = FCORE;
124 fp->fname = "core dump";
125 break;
128 fp->map = mapelf;
130 if(fp->ftype == FCORE){
131 elfcore = nil;
132 for(i=0; i<nelem(ctab); i++){
133 if(ctab[i].atype != fp->atype
134 || ctab[i].mtype != fp->mtype)
135 continue;
136 elfcore = ctab[i].elfcore;
137 break;
139 if(elfcore)
140 for(i=0; i<elf->nprog; i++){
141 p = &elf->prog[i];
142 if(p->type != ElfProgNote)
143 continue;
144 n = p->filesz;
145 a = malloc(n);
146 if(a == nil)
147 goto err;
148 if(seek(fp->fd, p->offset, 0) < 0 || readn(fp->fd, a, n) != n){
149 free(a);
150 continue;
152 sa = a;
153 ea = a+n;
154 while(a < ea){
155 note.offset = (a-sa) + p->offset;
156 if(unpacknote(elf, a, ea, &note, &a) < 0)
157 break;
158 elfcore(fp, elf, &note);
160 free(sa);
162 return 0;
165 fp->entry = elf->hdr.entry;
167 /* First r-x section we find is the text and initialized data */
168 /* First rw- section we find is the r/w data */
169 havetext = 0;
170 havedata = 0;
171 for(i=0; i<elf->nprog; i++){
172 p = &elf->prog[i];
173 if(p->type != ElfProgLoad)
174 continue;
175 if(!havetext && p->flags == (ElfProgFlagRead|ElfProgFlagExec) && p->align >= mach->pgsize){
176 havetext = 1;
177 fp->txtaddr = p->vaddr;
178 fp->txtsz = p->memsz;
179 fp->txtoff = p->offset;
181 if(!havedata && p->flags == (ElfProgFlagRead|ElfProgFlagWrite) && p->align >= mach->pgsize){
182 havedata = 1;
183 fp->dataddr = p->vaddr;
184 fp->datsz = p->filesz;
185 fp->datoff = p->offset;
186 fp->bsssz = p->memsz - p->filesz;
189 if(!havetext){
190 werrstr("did not find text segment in elf binary");
191 goto err;
193 if(!havedata){
194 werrstr("did not find data segment in elf binary");
195 goto err;
197 return 0;
199 err:
200 elfclose(elf);
201 return -1;
204 static int
205 mapelf(Fhdr *fp, ulong base, Map *map, Regs **regs)
207 int i;
208 Elf *elf;
209 ElfProg *p;
210 ulong sz;
211 ulong lim;
212 Seg s;
214 elf = fp->elf;
215 if(elf == nil){
216 werrstr("not an elf file");
217 return -1;
220 for(i=0; i<elf->nprog; i++){
221 p = &elf->prog[i];
222 if(p->type != ElfProgLoad)
223 continue;
224 if(p->align < mach->pgsize)
225 continue;
226 if(p->filesz){
227 memset(&s, 0, sizeof s);
228 s.file = fp->filename;
229 s.fd = fp->fd;
230 if(fp->ftype == FCORE)
231 s.name = "core";
232 else if(p->flags == 5)
233 s.name = "text";
234 else
235 s.name = "data";
236 s.base = base+p->vaddr;
237 s.size = p->filesz;
238 s.offset = p->offset;
239 if(addseg(map, s) < 0)
240 return -1;
242 /*
243 * If memsz > filesz, we're supposed to zero fill.
244 * Core files have zeroed sections where the pages
245 * can be filled in from the text file, so if this is a core
246 * we only fill in that which isn't yet mapped.
247 */
248 if(fp->ftype == FCORE){
249 sz = p->filesz;
250 while(sz < p->memsz){
251 if(addrtoseg(map, base+p->vaddr+sz, &s) < 0){
252 lim = base + p->vaddr + p->memsz;
253 if(addrtosegafter(map, base+p->vaddr+sz, &s) >= 0 && s.base < lim)
254 lim = s.base;
255 memset(&s, 0, sizeof s);
256 s.name = "zero";
257 s.base = base + p->vaddr + sz;
258 s.size = lim - s.base;
259 s.offset = p->offset;
260 if(addseg(map, s) < 0)
261 return -1;
262 }else
263 sz = (s.base+s.size) - (base + p->vaddr);
265 }else{
266 if(p->filesz < p->memsz){
267 memset(&s, 0, sizeof s);
268 s.name = "zero";
269 s.base = base + p->vaddr + p->filesz;
270 s.size = p->memsz - p->filesz;
271 if(addseg(map, s) < 0)
272 return -1;
277 if(fp->nthread && regs)
278 *regs = coreregs(fp, fp->thread[0].id);
280 return 0;
283 static int
284 unpacknote(Elf *elf, uchar *a, uchar *ea, ElfNote *note, uchar **pa)
286 if(a+12 > ea)
287 return -1;
288 note->namesz = elf->hdr.e4(a);
289 note->descsz = elf->hdr.e4(a+4);
290 note->type = elf->hdr.e4(a+8);
291 a += 12;
292 note->name = (char*)a;
293 /* XXX fetch alignment constants from elsewhere */
294 a += (note->namesz+3)&~3;
295 note->desc = (uchar*)a;
296 a += (note->descsz+3)&~3;
297 if(a > ea)
298 return -1;
299 *pa = a;
300 return 0;