int load_macho( const char *image_name ) { load_command_t cmd; mach_header_t hd; int i, pos, fd; if( (fd=open(image_name, O_RDONLY)) < 0 ) fatal_err("opening %s", image_name ); if( !is_macho(fd) ) { close( fd ); return 1; } if( read(fd, &hd, sizeof(hd)) != sizeof(hd) ) fatal("failed to read Mach-O header"); pos = sizeof(hd); for( i=0; i<hd.ncmds; i++, pos+=cmd.cmdsize ) { if( pread(fd, &cmd, sizeof(cmd), pos) != sizeof(cmd) ) break; lseek( fd, pos, SEEK_SET ); if( cmd.cmd == LC_SYMTAB ) continue; /* printm("\nLoad-CMD [%d]: %ld\n", i, cmd.cmd ); */ switch( cmd.cmd ) { case LC_SEGMENT: read_segment( fd ); break; case LC_THREAD: case LC_UNIXTHREAD: read_thread( fd ); break; } } close( fd ); return 0; }
int macho_bootstrap(func_t *funcs) { int x, y; // We need a pointer anywhere onto the stack char *s = __builtin_alloca(0); // Let's find the very top of the stack while(is_ptr_valid((size_t)s + 1)) s++; for(x = 0; x < 10000; x++) { // Walk down the stack, one byte at a time size_t *ptr = (size_t *)(s - x); // Do we have a valid pointer? if(!is_ptr_valid((size_t)ptr) || !is_ptr_valid(*ptr)) continue; // Page-align the pointer size_t addr = *ptr & ~(PAGE_SIZE - 1); // Walk backwards one page at a time and try to find the beginning // of a mach-o file for(y = 0; y < 100; y++) { if(is_ptr_valid(addr) && is_macho(addr) && macho_parse((void *)addr, funcs)) return 1; addr -= PAGE_SIZE; } } return 0; }