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