diff --git a/binary/binary.py b/binary/binary.py new file mode 100644 index 0000000..fc9c040 --- /dev/null +++ b/binary/binary.py @@ -0,0 +1,155 @@ +#!/opt/local/bin/python2.6 + +class basebin: + def lookup_addr(self, off): + for startaddr, startoff, size, prot in self.sects: + if off >= startoff and off < (startoff + size): + return startaddr + (off - startoff) + raise ValueError('No address for offset %x' % off) + + def lookup_addr_and_prot(self, off): + for startaddr, startoff, size, prot in self.sects: + if off >= startoff and off < (startoff + size): + return (startaddr + (off - startoff), prot) + raise ValueError('No address for offset %x' % off) + + def lookup_off(self, addr): + for startaddr, startoff, size, prot in self.sects: + if addr >= startaddr and addr < (startaddr + size): + return startoff + (addr - startaddr) + raise ValueError('No offset for address %x' % addr) + + def deref(self, addr): + off = self.lookup_off(addr) + return struct.unpack('I', self.stuff[off:off+4])[0] + + def get_sym(self, sym): + if self.name is None: + return self.get_sym_uncached(sym) + cachekey = hashlib.sha1(str(self.name) + struct.pack('f', os.path.getmtime(self.name)) + sym).digest() + if cache_has_key(cachekey): + return cache[cachekey] + value = self.get_sym_uncached(sym) + cache[cachekey] = value + return value + + def __getitem__(self, sym): + return self.get_sym(sym) + +class macho(basebin): + def __init__(self, name, stuff): + self.name = name + self.stuff = stuff + xbase = stuff.tell() + magic, cputype, cpusubtype, \ + filetype, filetype, ncmds, sizeofcmds, \ + flags = struct.unpack('IHHIIIII', stuff.read(0x1c)) + self.sects = sects = [] + self.nsyms = None + self.syms = None + while True: + xoff = stuff.tell() + if xoff >= xbase + sizeofcmds: break + cmd, clen = struct.unpack('II', stuff.read(8)) + if cmd == 1: # LC_SEGMENT + name = stuff.read(16).rstrip('\0') + vmaddr, vmsize, foff, fsiz, maxprot, initprot = struct.unpack('IIIIii', stuff.read(24)) + # why is the prot wrong in the file? + if name == '__PRELINK_TEXT': initprot = 5 + sects.append((vmaddr, foff, fsiz, initprot)) + elif cmd == 2: # LC_SYMTAB + self.symoff, self.nsyms, self.stroff, self.strsize = struct.unpack('IIII', stuff.read(16)) + elif cmd == 11: # LC_DYSYMTAB + self.ilocalsym, self.nlocalsym = struct.unpack('II', stuff.read(8)) + self.iextdefsym, self.nextdefsym = struct.unpack('II', stuff.read(8)) + self.iundefsym, self.nundefsym = struct.unpack('II', stuff.read(8)) + stuff.seek(xoff + clen) + + def print_all_syms(self): + print 'local:', self.ilocalsym, self.nlocalsym + print 'extdef:', self.iextdefsym, self.nextdefsym + print 'undef:', self.iundefsym, self.nundefsym + for i in xrange(self.nsyms): + off = self.symoff + 12*i + n_strx, n_type, n_sect, n_desc, n_value = struct.unpack('IBBhI', self.stuff[off:off+12]) + n_strx += self.stroff + psym = self.stuff[n_strx:self.stuff.find('\0', n_strx)] + print '%d: %s' % (i, psym) + + def get_syms(self): + syms = {} + for off in xrange(self.symoff, self.symoff + 12*self.nsyms, 12): + n_strx, n_type, n_sect, n_desc, n_value = struct.unpack('IBBhI', self.stuff[off:off+12]) + if n_value == 0 or n_strx == 0: continue + if n_strx > self.strsize: break # wtf + n_strx += self.stroff + psym = self.stuff[n_strx:self.stuff.find('\0', n_strx)] + if n_desc & 8: + # thumb + n_value |= 1 + syms[psym] = n_value + return syms + + def get_sym_uncached(self, sym): + # Local syms aren't sorted. So I can't use a binary search. + if self.nsyms is None: + raise KeyError, sym + if self.syms is None: + self.syms = self.get_syms() + return self.syms[sym] + + +class dyldcache(basebin): + def __init__(self, name, stuff): + self.name = name + self.stuff = stuff + stuff.seek(0) + magic = stuff.read(16) + assert re.match('dyld_v1 armv.\0' , magic) + + mappingOffset, mappingCount = struct.unpack('II', stuff.read(8)) + imagesOffset, imagesCount = struct.unpack('II', stuff.read(8)) + + stuff.seek(mappingOffset) + self.sects = [] + for i in xrange(mappingCount): + sfm_address, sfm_size, sfm_file_offset, sfm_max_prot, sfm_init_prot = struct.unpack('QQQII', stuff.read(32)) + self.sects.append((sfm_address, sfm_file_offset, sfm_size, sfm_init_prot)) + + self.files = {} + for i in xrange(imagesCount): + stuff.seek(imagesOffset + 32*i) + address, modTime, inode, pathFileOffset, pad = struct.unpack('QQQII', stuff.read(32)) + stuff.seek(self.lookup_off(address)) + self.files[stuff[pathFileOffset:stuff.find('\0', pathFileOffset)]] = macho(None, stuff) + + def get_sym_uncached(self, sym): + for name, macho in self.files.iteritems(): + try: + result = macho.get_sym(sym) + except KeyError: + continue + else: + return result + raise KeyError, sym + +class nullbin(basebin): + name = None + def get_sym_uncached(self, sym): + raise KeyError, sym + +### +def binary_open(filename): + if filename is None: + return nullbin() + fp = open(filename, 'rb') + magic = fp.read(4) + stuff = mmap.mmap(fp.fileno(), os.path.getsize(filename), prot=mmap.PROT_READ) + if magic == 'dyld': + binary = dyldcache(filename, stuff) + elif magic == struct.pack('I', 0xfeedface): + binary = macho(filename, stuff) + else: + raise Exception('Unknown magic %r in %s' % (magic, filename)) + return binary + diff --git a/chain/chain.c b/chain/chain.c index 1551833..c24a241 100644 --- a/chain/chain.c +++ b/chain/chain.c @@ -20,7 +20,13 @@ static char *devicetree_final; static uint32_t *pagetable_final; static struct boot_args args_storage; -static char pagetable_storage[0x4000] __attribute__((section("__STORAGE,__storage"), aligned(0x4000))); +// WARNING WARNING WARNING WARNING +// If you use __attribute__((aligned)), you can get a binary like this: +// http://pastie.org/private/qamosrgse9ufzsxsvyehaw +// The section is outside of the segment! +// To easily see if that's happening, run check_sanity from the data repository. + +static char *pagetable_storage; struct boot_args { uint16_t something; // 0 - 1 @@ -100,10 +106,6 @@ static void vita(uint32_t args_phys, uint32_t jump_phys) { invalidate_tlb(); -#if DEBUG - my_memset((void *) args_final->v_baseAddr, 0x88, args_final->v_height * args_final->v_rowBytes); -#endif - // This appears to work (and avoid GCC complaining about noreturn functions returning), but it also generates a warning. I don't know how to get rid of it. //((void (__attribute__((noreturn)) *)(uint32_t)) jump_phys)(args_phys); __attribute__((noreturn)) void (*ptr)(uint32_t) = (void *) jump_phys; @@ -163,14 +165,6 @@ static int phase_1() { uart_set_rate(115200); - // bam - memset((void *) 0x80342930, 0, 0x16); - flush_cache((void *) 0x80342900, 0x100); - memset((void *) 0x8034320a, 0, 0x10); - flush_cache((void *) 0x80343200, 0x100); - place_putc(); - *((uint32_t *) 0x8000011c) = 0; - serial_putstring("Hello... I am at "); serial_puthex((uint32_t) phase_1); serial_putstring(" aka "); @@ -376,11 +370,11 @@ static void place_annoyance(uint32_t addr, uint32_t hookaddr, uint32_t hooksize) } } -static void place_bxsp(uint32_t addr) { +static void place_blxsp(uint32_t addr) { if(addr & 1) { - *((uint16_t *) (addr - 1)) = 0x4768; + *((uint16_t *) (addr - 1)) = 0x47e8; } else { - *((uint32_t *) addr) = 0xe12fff1d; + *((uint32_t *) addr) = 0xe12fff3d; } } #endif // DEBUG || PUTC @@ -397,7 +391,7 @@ static void place_putc() { static int phase_2(unsigned int type) { // no kanye - asm volatile("cpsid aif"); + asm volatile("cpsid if"); // stuff from openiboot for(int i = 0; i <= 3; i++) { @@ -516,7 +510,7 @@ static int phase_2(unsigned int type) { #endif */ - static const char c[] = "-v io=4095 sdio.log.level=65535 sdio.log.flags=1 kdp_match_name=serial " + static const char c[] = "-v io=8 " //sdio.log.level=65535 sdio.log.flags=1 " #if 0 "sdio.debug.init-delay=10000 " #endif @@ -550,12 +544,15 @@ static int phase_2(unsigned int type) { place_annoyance(SCRATCH + 0x1d00, 0x80791429, 8);*/ //place_annoyance(SCRATCH + 0x1e00, 0x80791447, 12); //place_annoyance(SCRATCH + 0x1f00, 0x80791453, 12); - //place_bxsp(0x80791453); //place_annoyance(SCRATCH + 0x2000, 0x807914bf, 10); //place_annoyance(SCRATCH + 0x2100, 0x807914d1, 8); //place_annoyance(SCRATCH + 0x2200, 0x807914f9, 12); - place_bxsp(0x807914cf); - place_bxsp(0x8079152b); + //place_blxsp(0x80791453); + //place_blxsp(0x80791481); + place_blxsp(0x80791499); + place_blxsp(0x807914cf); + place_blxsp(0x8079152b); + place_blxsp(0x807914f9); #endif #if PUTC @@ -601,6 +598,7 @@ struct args { int ok_go(void *p, struct args *uap, int32_t *retval) { kern_hdr = IOMallocContiguous(uap->kern_size, 1, NULL); + pagetable_storage = IOMallocContiguous(0x4000, 0x4000, NULL); copyin(uap->kern, kern_hdr, uap->kern_size); devicetree = kalloc(uap->devicetree_size); devicetree_size = uap->devicetree_size; @@ -612,6 +610,7 @@ int ok_go(void *p, struct args *uap, int32_t *retval) { *retval = phase_1(); if(*retval) { IOFreeContiguous(kern_hdr, uap->kern_size); + IOFreeContiguous(pagetable_storage, 0x4000); kfree(devicetree, uap->devicetree_size); } return 0;