From a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46 Mon Sep 17 00:00:00 2001 From: rsc Date: Mon, 19 Apr 2004 19:29:25 +0000 Subject: libmach --- src/libmach/crackmacho.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 src/libmach/crackmacho.c (limited to 'src/libmach/crackmacho.c') diff --git a/src/libmach/crackmacho.c b/src/libmach/crackmacho.c new file mode 100644 index 00000000..bfc0fd62 --- /dev/null +++ b/src/libmach/crackmacho.c @@ -0,0 +1,198 @@ +#include +#include +#include +#include "macho.h" + +static int mapmacho(Fhdr *fp, ulong base, Map *map, Regs**); + +static struct +{ + uint etype; + uint mtype; + Mach *mach; + char *name; + int (*coreregs)(Macho*, uchar**); +} mtab[] = +{ + MachoCpuPower, MPOWER, &machpower, "powerpc", coreregsmachopower, +}; + +static uchar* +load(int fd, ulong off, int size) +{ + uchar *a; + + a = malloc(size); + if(a == nil) + return nil; + if(seek(fd, off, 0) < 0 || readn(fd, a, size) != size){ + free(a); + return nil; + } + return a; +} + +int +crackmacho(int fd, Fhdr *fp) +{ + int i; + Macho *m; + + if((m = machoinit(fd)) == nil) + return -1; + + fp->fd = fd; + fp->macho = m; + + for(i=0; icputype != mtab[i].etype) + continue; + fp->mach = mtab[i].mach; + fp->mtype = mtab[i].mtype; + fp->mname = mtab[i].name; + m->coreregs = mtab[i].coreregs; + break; + } + if(i == nelem(mtab)){ + werrstr("unsupported cpu type %ud", m->cputype); + goto err; + } + + fp->atype = AMACH; + fp->aname = "mach"; + + if(mach == nil) + mach = fp->mach; + + switch(m->filetype){ + default: + werrstr("unsupported macho file type %lud", m->filetype); + goto err; + case MachoFileObject: + fp->ftype = FOBJ; + fp->fname = "object"; + break; + case MachoFileExecutable: + fp->ftype = FEXEC; + fp->fname = "executable"; + break; + case MachoFileFvmlib: + fp->ftype = FSHLIB; + fp->fname = "shared library"; + break; + case MachoFileCore: + fp->ftype = FCORE; + fp->fname = "core"; + break; + case MachoFilePreload: + fp->ftype = FBOOT; + fp->fname = "preloaded executable"; + break; + } + + fp->txtaddr = fp->dataddr = 0; + fp->txtsz = fp->datsz = 0; + for(i=0; incmd; i++){ + if(m->cmd[i].type != MachoCmdSegment) + continue; + if(strcmp(m->cmd[i].seg.name, "__TEXT") == 0){ + fp->txtaddr = m->cmd[i].seg.vmaddr; + fp->txtsz = m->cmd[i].seg.vmsize; + fp->txtoff = m->cmd[i].seg.fileoff; + } + if(strcmp(m->cmd[i].seg.name, "__DATA") == 0){ + fp->dataddr = m->cmd[i].seg.vmaddr; + fp->datsz = m->cmd[i].seg.filesz; + fp->datoff = m->cmd[i].seg.fileoff; + fp->bsssz = m->cmd[i].seg.vmsize - fp->datsz; + } + } + + fp->map = mapmacho; + fp->syminit = symmacho; + + for(i=0; incmd; i++) + if(m->cmd[i].type == MachoCmdSymtab) + break; + if(i < m->ncmd){ + fp->stabs.stabbase = load(fp->fd, m->cmd[i].sym.symoff, m->cmd[i].sym.nsyms*16); + fp->stabs.stabsize = m->cmd[i].sym.nsyms*16; + fp->stabs.strbase = load(fp->fd, m->cmd[i].sym.stroff, m->cmd[i].sym.strsize); + if(fp->stabs.stabbase == nil || fp->stabs.strbase == nil){ + fp->stabs.stabbase = nil; + fp->stabs.strbase = nil; + }else{ + fp->stabs.strsize = m->cmd[i].sym.strsize; + fp->stabs.e2 = (m->e4==beload4 ? beload2 : leload2); + fp->stabs.e4 = m->e4; + } + } + + return 0; + +err: + machoclose(m); + return -1; +} + +static int +mapmacho(Fhdr *fp, ulong base, Map *map, Regs **rp) +{ + int i, n; + uchar *u; + Macho *m; + MachoCmd *c; + Seg s; + UregRegs *r; + + m = fp->macho; + if(m == nil){ + werrstr("not a macho file"); + return -1; + } + + for(i=0; incmd; i++){ + c = &m->cmd[i]; + if(c->type != MachoCmdSegment) + continue; + if(c->seg.filesz){ + memset(&s, 0, sizeof s); + s.file = fp->filename; + s.fd = fp->fd; + if(fp->ftype == FCORE) + s.name = "core"; + else if(strcmp(c->seg.name, "__DATA") == 0) + s.name = "data"; + else + s.name = "text"; + s.base = base+c->seg.vmaddr; + s.size = c->seg.filesz; + s.offset = c->seg.fileoff; + if(addseg(map, s) < 0) + return -1; + } + if(c->seg.filesz < c->seg.vmsize){ + memset(&s, 0, sizeof s); + s.name = "zero"; + s.base = base + c->seg.vmaddr + c->seg.filesz; + s.size = c->seg.vmsize - c->seg.filesz; + if(addseg(map, s) < 0) + return -1; + } + } + + if(fp->ftype == FCORE && m->coreregs){ + n = m->coreregs(m, &u); + if(n < 0){ + fprint(2, "mapping registers: %r\n"); + goto noregs; + } + if((r = mallocz(sizeof *r, 1)) == nil) + return -1; + r->r.rw = _uregrw; + r->ureg = u; + *rp = &r->r; + } +noregs: + return 0; +} -- cgit v1.2.3