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 }