plan9port

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

crackmacho.c (3930B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <mach.h>
      4 #include "macho.h"
      5 
      6 static int mapmacho(Fhdr *fp, u64int base, Map *map, Regs**);
      7 
      8 static struct
      9 {
     10 	uint etype;
     11 	uint mtype;
     12 	Mach *mach;
     13 	char *name;
     14 	int (*coreregs)(Macho*, uchar**);
     15 } mtab[] =
     16 {
     17 	MachoCpuPower,	MPOWER,		&machpower, 		"powerpc",	coreregsmachopower,
     18 };
     19 
     20 static uchar*
     21 load(int fd, ulong off, int size)
     22 {
     23 	uchar *a;
     24 
     25 	a = malloc(size);
     26 	if(a == nil)
     27 		return nil;
     28 	if(seek(fd, off, 0) < 0 || readn(fd, a, size) != size){
     29 		free(a);
     30 		return nil;
     31 	}
     32 	return a;
     33 }
     34 
     35 int
     36 crackmacho(int fd, Fhdr *fp)
     37 {
     38 	int i;
     39 	Macho *m;
     40 
     41 	if((m = machoinit(fd)) == nil)
     42 		return -1;
     43 
     44 	fp->fd = fd;
     45 	fp->macho = m;
     46 
     47 	for(i=0; i<nelem(mtab); i++){
     48 		if(m->cputype != mtab[i].etype)
     49 			continue;
     50 		fp->mach = mtab[i].mach;
     51 		fp->mtype = mtab[i].mtype;
     52 		fp->mname = mtab[i].name;
     53 		m->coreregs = mtab[i].coreregs;
     54 		break;
     55 	}
     56 	if(i == nelem(mtab)){
     57 		werrstr("unsupported cpu type %ud", m->cputype);
     58 		goto err;
     59 	}
     60 
     61 	fp->atype = AMACH;
     62 	fp->aname = "mach";
     63 
     64 	if(mach == nil)
     65 		mach = fp->mach;
     66 
     67 	switch(m->filetype){
     68 	default:
     69 		werrstr("unsupported macho file type %lud", m->filetype);
     70 		goto err;
     71 	case MachoFileObject:
     72 		fp->ftype = FOBJ;
     73 		fp->fname = "object";
     74 		break;
     75 	case MachoFileExecutable:
     76 		fp->ftype = FEXEC;
     77 		fp->fname = "executable";
     78 		break;
     79 	case MachoFileFvmlib:
     80 		fp->ftype = FSHLIB;
     81 		fp->fname = "shared library";
     82 		break;
     83 	case MachoFileCore:
     84 		fp->ftype = FCORE;
     85 		fp->fname = "core";
     86 		break;
     87 	case MachoFilePreload:
     88 		fp->ftype = FBOOT;
     89 		fp->fname = "preloaded executable";
     90 		break;
     91 	}
     92 
     93 	fp->txtaddr = fp->dataddr = 0;
     94 	fp->txtsz = fp->datsz = 0;
     95 	for(i=0; i<m->ncmd; i++){
     96 		if(m->cmd[i].type != MachoCmdSegment)
     97 			continue;
     98 		if(strcmp(m->cmd[i].seg.name, "__TEXT") == 0){
     99 			fp->txtaddr = m->cmd[i].seg.vmaddr;
    100 			fp->txtsz = m->cmd[i].seg.vmsize;
    101 			fp->txtoff = m->cmd[i].seg.fileoff;
    102 		}
    103 		if(strcmp(m->cmd[i].seg.name, "__DATA") == 0){
    104 			fp->dataddr = m->cmd[i].seg.vmaddr;
    105 			fp->datsz = m->cmd[i].seg.filesz;
    106 			fp->datoff = m->cmd[i].seg.fileoff;
    107 			fp->bsssz = m->cmd[i].seg.vmsize - fp->datsz;
    108 		}
    109 	}
    110 
    111 	fp->map = mapmacho;
    112 	fp->syminit = symmacho;
    113 
    114 	for(i=0; i<m->ncmd; i++)
    115 		if(m->cmd[i].type == MachoCmdSymtab)
    116 			break;
    117 	if(i < m->ncmd){
    118 		fp->stabs.stabbase = load(fp->fd, m->cmd[i].sym.symoff, m->cmd[i].sym.nsym*16);
    119 		fp->stabs.stabsize = m->cmd[i].sym.nsym*16;
    120 		fp->stabs.strbase = (char*)load(fp->fd, m->cmd[i].sym.stroff, m->cmd[i].sym.strsize);
    121 		if(fp->stabs.stabbase == nil || fp->stabs.strbase == nil){
    122 			fp->stabs.stabbase = nil;
    123 			fp->stabs.strbase = nil;
    124 		}else{
    125 			fp->stabs.strsize = m->cmd[i].sym.strsize;
    126 			fp->stabs.e2 = (m->e4==beload4 ? beload2 : leload2);
    127 			fp->stabs.e4 = m->e4;
    128 		}
    129 	}
    130 
    131 	return 0;
    132 
    133 err:
    134 	machoclose(m);
    135 	return -1;
    136 }
    137 
    138 static int
    139 mapmacho(Fhdr *fp, u64int base, Map *map, Regs **rp)
    140 {
    141 	int i, n;
    142 	uchar *u;
    143 	Macho *m;
    144 	MachoCmd *c;
    145 	Seg s;
    146 	UregRegs *r;
    147 
    148 	m = fp->macho;
    149 	if(m == nil){
    150 		werrstr("not a macho file");
    151 		return -1;
    152 	}
    153 
    154 	for(i=0; i<m->ncmd; i++){
    155 		c = &m->cmd[i];
    156 		if(c->type != MachoCmdSegment)
    157 			continue;
    158 		if(c->seg.filesz){
    159 			memset(&s, 0, sizeof s);
    160 			s.file = fp->filename;
    161 			s.fd = fp->fd;
    162 			if(fp->ftype == FCORE)
    163 				s.name = "core";
    164 			else if(strcmp(c->seg.name, "__DATA") == 0)
    165 				s.name = "data";
    166 			else
    167 				s.name = "text";
    168 			s.base = base+c->seg.vmaddr;
    169 			s.size = c->seg.filesz;
    170 			s.offset = c->seg.fileoff;
    171 			if(addseg(map, s) < 0)
    172 				return -1;
    173 		}
    174 		if(c->seg.filesz < c->seg.vmsize){
    175 			memset(&s, 0, sizeof s);
    176 			s.name = "zero";
    177 			s.base = base + c->seg.vmaddr + c->seg.filesz;
    178 			s.size = c->seg.vmsize - c->seg.filesz;
    179 			if(addseg(map, s) < 0)
    180 				return -1;
    181 		}
    182 	}
    183 
    184 	if(fp->ftype == FCORE && m->coreregs){
    185 		n = m->coreregs(m, &u);
    186 		if(n < 0){
    187 			fprint(2, "mapping registers: %r\n");
    188 			goto noregs;
    189 		}
    190 		if((r = mallocz(sizeof *r, 1)) == nil)
    191 			return -1;
    192 		r->r.rw = _uregrw;
    193 		r->ureg = u;
    194 		*rp = &r->r;
    195 	}
    196 noregs:
    197 	return 0;
    198 }