plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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, &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 }