URI:
       tcrackelf.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tcrackelf.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, &note, &a) < 0)
          159                                         break;
          160                                 elfcore(fp, elf, &note);
          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 }