crackelf.c (6474B)
1 #include <u.h> 2 #include <libc.h> 3 #include <mach.h> 4 #include "elf.h" 5 #include "dwarf.h" 6 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); 9 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 }; 26 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 }; 38 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 }; 51 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*); 62 63 if((elf = elfinit(fd)) == nil) 64 return -1; 65 66 fp->fd = fd; 67 fp->elf = elf; 68 fp->dwarf = dwarfopen(elf); /* okay to fail */ 69 fp->syminit = symelf; 70 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 } 82 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 } 95 96 if(mach == nil) 97 mach = fp->mach; 98 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; 106 } 107 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; 128 } 129 130 fp->map = mapelf; 131 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; 140 } 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; 153 } 154 sa = a; 155 ea = a+n; 156 while(a < ea){ 157 note.offset = (a-sa) + p->offset; 158 if(unpacknote(elf, a, ea, ¬e, &a) < 0) 159 break; 160 elfcore(fp, elf, ¬e); 161 } 162 free(sa); 163 } 164 return 0; 165 } 166 167 fp->entry = elf->hdr.entry; 168 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; 182 } 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; 189 } 190 } 191 if(!havetext){ 192 werrstr("did not find text segment in elf binary"); 193 goto err; 194 } 195 if(!havedata){ 196 werrstr("did not find data segment in elf binary"); 197 goto err; 198 } 199 return 0; 200 201 err: 202 elfclose(elf); 203 return -1; 204 } 205 206 static int 207 mapelf(Fhdr *fp, u64int base, Map *map, Regs **regs) 208 { 209 int i; 210 Elf *elf; 211 ElfProg *p; 212 u64int sz; 213 u64int lim; 214 Seg s; 215 216 elf = fp->elf; 217 if(elf == nil){ 218 werrstr("not an elf file"); 219 return -1; 220 } 221 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; 243 } 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); 266 } 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; 275 } 276 } 277 } 278 279 if(fp->nthread && regs) 280 *regs = coreregs(fp, fp->thread[0].id); 281 282 return 0; 283 } 284 285 static int 286 unpacknote(Elf *elf, uchar *a, uchar *ea, ElfNote *note, uchar **pa) 287 { 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; 303 }