#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 = (char*)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; }