/* * This routine returns the section structure for the named section in the * named segment for the mach_header pointer passed to it if it exist. * Otherwise it returns zero. If fSwap == YES (the mach header has been * swapped to the endiannes of the current machine, but the segments and * sections are different) then the segment and sections are swapped. */ const struct section * getsectbynamefromheaderwithswap( struct mach_header *mhp, const char *segname, const char *sectname, int fSwap) { struct segment_command *sgp; struct section *sp; uint32_t i, j; sgp = (struct segment_command *) ((char *)mhp + sizeof(struct mach_header)); for(i = 0; i < mhp->ncmds; i++) { if(sgp->cmd == (fSwap ? OSSwapInt32(LC_SEGMENT) : LC_SEGMENT)) { if (fSwap) { #ifdef __LITTLE_ENDIAN__ swap_segment_command(sgp, NX_BigEndian); #else swap_segment_command(sgp, NX_LittleEndian); #endif /* __LITTLE_ENDIAN__ */ } if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || mhp->filetype == MH_OBJECT) { sp = (struct section *)((char *)sgp + sizeof(struct segment_command)); if (fSwap) { #ifdef __LITTLE_ENDIAN__ swap_section(sp, sgp->nsects, NX_BigEndian); #else swap_section(sp, sgp->nsects, NX_LittleEndian); #endif /* __LITTLE_ENDIAN__ */ } for(j = 0; j < sgp->nsects; j++) { if(strncmp(sp->sectname, sectname, sizeof(sp->sectname)) == 0 && strncmp(sp->segname, segname, sizeof(sp->segname)) == 0) return(sp); sp = (struct section *)((char *)sp + sizeof(struct section)); } } sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); } else { sgp = (struct segment_command *)((char *)sgp + (fSwap ? OSSwapInt32(sgp->cmdsize) : sgp->cmdsize)); } } return((struct section *)0); }
void dump_segment_commands(FILE *obj_file, int offset, int is_swap, uint32_t ncmds) { int actual_offset = offset; for (int i = 0; i < ncmds; i++) { struct load_command *cmd = load_bytes(obj_file, actual_offset, sizeof(struct load_command)); if (is_swap) { swap_load_command(cmd, 0); } if (cmd->cmd == LC_SEGMENT_64) { struct segment_command_64 *segment = load_bytes(obj_file, actual_offset, sizeof(struct segment_command_64)); if (is_swap) { swap_segment_command_64(segment, 0); } printf("segname: %s\n", segment->segname); free(segment); } else if (cmd->cmd == LC_SEGMENT) { struct segment_command *segment = load_bytes(obj_file, actual_offset, sizeof(struct segment_command)); if (is_swap) { swap_segment_command(segment, 0); } printf("segname: %s\n", segment->segname); free(segment); } actual_offset += cmd->cmdsize; free(cmd); } }
boolean_t macho_unswap_32( u_char * file) { boolean_t result = FALSE; enum NXByteOrder order = 0; struct mach_header *hdr = (struct mach_header *) file; struct load_command *lc = (struct load_command *) &hdr[1]; struct segment_command *seg = NULL; u_long offset = 0; u_int i = 0; if (NXHostByteOrder() == NX_LittleEndian) { order = NX_BigEndian; } else { order = NX_LittleEndian; } if (!hdr || hdr->magic != MH_MAGIC) goto finish; offset = sizeof(*hdr); for (i = 0; i < hdr->ncmds; ++i) { lc = (struct load_command *) (file + offset); offset += lc->cmdsize; if (lc->cmd == LC_SEGMENT) { seg = (struct segment_command *) lc; swap_segment_command(seg, order); } else { swap_load_command(lc, order); } } swap_mach_header(hdr, order); result = TRUE; finish: return result; }
static boolean_t macho_swap_32( u_char * file) { boolean_t result = FALSE; struct mach_header *hdr = (struct mach_header *) file; struct load_command *lc = (struct load_command *) &hdr[1]; struct segment_command *seg = NULL; u_long offset = 0; u_int cmd = 0; u_int cmdsize = 0; u_int i = 0; if (!hdr || hdr->magic != MH_CIGAM) goto finish; swap_mach_header(hdr, NXHostByteOrder()); offset = sizeof(*hdr); for (i = 0; i < hdr->ncmds; ++i) { lc = (struct load_command *) (file + offset); cmd = OSSwapInt32(lc->cmd); cmdsize = OSSwapInt32(lc->cmdsize); offset += cmdsize; if (cmd == LC_SEGMENT) { seg = (struct segment_command *) lc; swap_segment_command(seg, NXHostByteOrder()); } else { swap_load_command(lc, NXHostByteOrder()); } } result = TRUE; finish: return result; }
enum bool swap_object_headers( void *mach_header, struct load_command *load_commands) { unsigned long i; uint32_t magic, ncmds, sizeofcmds, cmd_multiple; cpu_type_t cputype; cpu_subtype_t cpusubtype; struct mach_header *mh; struct mach_header_64 *mh64; enum byte_sex target_byte_sex; struct load_command *lc, l; struct segment_command *sg; struct segment_command_64 *sg64; struct section *s; struct section_64 *s64; struct symtab_command *st; struct dysymtab_command *dyst; struct symseg_command *ss; struct fvmlib_command *fl; struct thread_command *ut; struct ident_command *id; struct dylib_command *dl; struct sub_framework_command *sub; struct sub_umbrella_command *usub; struct sub_library_command *lsub; struct sub_client_command *csub; struct prebound_dylib_command *pbdylib; struct dylinker_command *dyld; struct routines_command *rc; struct routines_command_64 *rc64; struct twolevel_hints_command *hints; struct prebind_cksum_command *cs; struct uuid_command *uuid; unsigned long flavor, count, nflavor; char *p, *state; magic = *((uint32_t *)mach_header); if(magic == MH_MAGIC){ mh = (struct mach_header *)mach_header; ncmds = mh->ncmds; sizeofcmds = mh->sizeofcmds; cputype = mh->cputype; cpusubtype = mh->cpusubtype; cmd_multiple = 4; mh64 = NULL; } else{ mh64 = (struct mach_header_64 *)mach_header; ncmds = mh64->ncmds; sizeofcmds = mh64->sizeofcmds; cputype = mh64->cputype; cpusubtype = mh64->cpusubtype; cmd_multiple = 8; mh = NULL; } /* * Make a pass through the load commands checking them to the level * that they can be parsed and then swapped. */ for(i = 0, lc = load_commands; i < ncmds; i++){ l = *lc; /* check load command size for a correct multiple size */ if(lc->cmdsize % cmd_multiple != 0){ error("in swap_object_headers(): malformed load command %lu " "(cmdsize not a multiple of %u)", i, cmd_multiple); return(FALSE); } /* check that load command does not extends past end of commands */ if((char *)lc + lc->cmdsize > (char *)load_commands + sizeofcmds){ error("in swap_object_headers(): truncated or malformed load " "command %lu (extends past the end of the all load " "commands)", i); return(FALSE); } /* check that the load command size is not zero */ if(lc->cmdsize == 0){ error("in swap_object_headers(): malformed load command %lu " "(cmdsize is zero)", i); return(FALSE); } switch(lc->cmd){ case LC_SEGMENT: sg = (struct segment_command *)lc; if(sg->cmdsize != sizeof(struct segment_command) + sg->nsects * sizeof(struct section)){ error("in swap_object_headers(): malformed load command " "(inconsistent cmdsize in LC_SEGMENT command %lu for " "the number of sections)", i); return(FALSE); } break; case LC_SEGMENT_64: sg64 = (struct segment_command_64 *)lc; if(sg64->cmdsize != sizeof(struct segment_command_64) + sg64->nsects * sizeof(struct section_64)){ error("in swap_object_headers(): malformed load command " "(inconsistent cmdsize in LC_SEGMENT_64 command %lu " "for the number of sections)", i); return(FALSE); } break; case LC_SYMTAB: st = (struct symtab_command *)lc; if(st->cmdsize != sizeof(struct symtab_command)){ error("in swap_object_headers(): malformed load commands " "(LC_SYMTAB command %lu has incorrect cmdsize", i); return(FALSE); } break; case LC_DYSYMTAB: dyst = (struct dysymtab_command *)lc; if(dyst->cmdsize != sizeof(struct dysymtab_command)){ error("in swap_object_headers(): malformed load commands " "(LC_DYSYMTAB command %lu has incorrect cmdsize", i); return(FALSE); } break; case LC_SYMSEG: ss = (struct symseg_command *)lc; if(ss->cmdsize != sizeof(struct symseg_command)){ error("in swap_object_headers(): malformed load command " "(LC_SYMSEG command %lu has incorrect cmdsize", i); return(FALSE); } break; case LC_IDFVMLIB: case LC_LOADFVMLIB: fl = (struct fvmlib_command *)lc; if(fl->cmdsize < sizeof(struct fvmlib_command)){ error("in swap_object_headers(): malformed load commands " "(%s command %lu has too small cmdsize field)", fl->cmd == LC_IDFVMLIB ? "LC_IDFVMLIB" : "LC_LOADFVMLIB", i); return(FALSE); } if(fl->fvmlib.name.offset >= fl->cmdsize){ error("in swap_object_headers(): truncated or malformed " "load commands (name.offset field of %s command %lu " "extends past the end of all load commands)", fl->cmd == LC_IDFVMLIB ? "LC_IDFVMLIB" : "LC_LOADFVMLIB", i); return(FALSE); } break; case LC_ID_DYLIB: case LC_LOAD_DYLIB: case LC_LOAD_WEAK_DYLIB: dl = (struct dylib_command *)lc; if(dl->cmdsize < sizeof(struct dylib_command)){ error("in swap_object_headers(): malformed load commands " "(%s command %lu has too small cmdsize field)", dl->cmd == LC_ID_DYLIB ? "LC_ID_DYLIB" : (dl->cmd == LC_LOAD_DYLIB ? "LC_LOAD_DYLIB" : "LC_LOAD_WEAK_DYLIB"), i); return(FALSE); } if(dl->dylib.name.offset >= dl->cmdsize){ error("in swap_object_headers(): truncated or malformed " "load commands (name.offset field of %s command %lu " "extends past the end of all load commands)", dl->cmd == LC_ID_DYLIB ? "LC_ID_DYLIB" : (dl->cmd == LC_LOAD_DYLIB ? "LC_LOAD_DYLIB" : "LC_LOAD_WEAK_DYLIB"), i); return(FALSE); } break; case LC_SUB_FRAMEWORK: sub = (struct sub_framework_command *)lc; if(sub->cmdsize < sizeof(struct sub_framework_command)){ error("in swap_object_headers(): malformed load commands " "(LC_SUB_FRAMEWORK command %lu has too small cmdsize " "field)", i); return(FALSE); } if(sub->umbrella.offset >= sub->cmdsize){ error("in swap_object_headers(): truncated or malformed " "load commands (umbrella.offset field of " "LC_SUB_FRAMEWORK command %lu extends past the end " "of all load commands)", i); return(FALSE); } break; case LC_SUB_UMBRELLA: usub = (struct sub_umbrella_command *)lc; if(usub->cmdsize < sizeof(struct sub_umbrella_command)){ error("in swap_object_headers(): malformed load commands " "(LC_SUB_UMBRELLA command %lu has too small cmdsize " "field)", i); return(FALSE); } if(usub->sub_umbrella.offset >= usub->cmdsize){ error("in swap_object_headers(): truncated or malformed " "load commands (sub_umbrella.offset field of " "LC_SUB_UMBRELLA command %lu extends past the end " "of all load commands)", i); return(FALSE); } break; case LC_SUB_LIBRARY: lsub = (struct sub_library_command *)lc; if(lsub->cmdsize < sizeof(struct sub_library_command)){ error("in swap_object_headers(): malformed load commands " "(LC_SUB_LIBRARY command %lu has too small cmdsize " "field)", i); return(FALSE); } if(lsub->sub_library.offset >= lsub->cmdsize){ error("in swap_object_headers(): truncated or malformed " "load commands (sub_library.offset field of " "LC_SUB_LIBRARY command %lu extends past the end " "of all load commands)", i); return(FALSE); } break; case LC_SUB_CLIENT: csub = (struct sub_client_command *)lc; if(csub->cmdsize < sizeof(struct sub_client_command)){ error("in swap_object_headers(): malformed load commands " "(LC_SUB_CLIENT command %lu has too small cmdsize " "field)", i); return(FALSE); } if(csub->client.offset >= csub->cmdsize){ error("in swap_object_headers(): truncated or malformed " "load commands (client.offset field of " "LC_SUB_CLIENT command %lu extends past the end " "of all load commands)", i); return(FALSE); } break; case LC_PREBOUND_DYLIB: pbdylib = (struct prebound_dylib_command *)lc; if(pbdylib->cmdsize < sizeof(struct prebound_dylib_command)){ error("in swap_object_headers(): malformed load commands " "(LC_PREBOUND_DYLIB command %lu has too small " "cmdsize field)", i); return(FALSE); } if(pbdylib->name.offset >= pbdylib->cmdsize){ error("in swap_object_headers(): truncated or malformed " "load commands (name.offset field of " "LC_PREBOUND_DYLIB command %lu extends past the end " "of all load commands)", i); return(FALSE); } if(pbdylib->linked_modules.offset >= pbdylib->cmdsize){ error("in swap_object_headers(): truncated or malformed " "load commands (linked_modules.offset field of " "LC_PREBOUND_DYLIB command %lu extends past the end " "of all load commands)", i); return(FALSE); } break; case LC_ID_DYLINKER: case LC_LOAD_DYLINKER: dyld = (struct dylinker_command *)lc; if(dyld->cmdsize < sizeof(struct dylinker_command)){ error("in swap_object_headers(): malformed load commands " "(%s command %lu has too small cmdsize field)", dyld->cmd == LC_ID_DYLINKER ? "LC_ID_DYLINKER" : "LC_LOAD_DYLINKER", i); return(FALSE); } if(dyld->name.offset >= dyld->cmdsize){ error("in swap_object_headers(): truncated or malformed " "load commands (name.offset field of %s command %lu " "extends past the end of all load commands)", dyld->cmd == LC_ID_DYLINKER ? "LC_ID_DYLINKER" : "LC_LOAD_DYLINKER", i); return(FALSE); } break; case LC_UNIXTHREAD: case LC_THREAD: ut = (struct thread_command *)lc; state = (char *)ut + sizeof(struct thread_command); if(cputype == CPU_TYPE_MC680x0){ struct m68k_thread_state_regs *cpu; struct m68k_thread_state_68882 *fpu; struct m68k_thread_state_user_reg *user_reg; nflavor = 0; p = (char *)ut + ut->cmdsize; while(state < p){ flavor = *((unsigned long *)state); state += sizeof(unsigned long); count = *((unsigned long *)state); state += sizeof(unsigned long); switch(flavor){ case M68K_THREAD_STATE_REGS: if(count != M68K_THREAD_STATE_REGS_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not M68K_THREAD_STATE_REGS_COUNT for " "flavor number %lu which is a M68K_THREAD_" "STATE_REGS flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } cpu = (struct m68k_thread_state_regs *)state; state += sizeof(struct m68k_thread_state_regs); break; case M68K_THREAD_STATE_68882: if(count != M68K_THREAD_STATE_68882_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not M68K_THREAD_STATE_68882_COUNT for " "flavor number %lu which is a M68K_THREAD_" "STATE_68882 flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } fpu = (struct m68k_thread_state_68882 *)state; state += sizeof(struct m68k_thread_state_68882); break; case M68K_THREAD_STATE_USER_REG: if(count != M68K_THREAD_STATE_USER_REG_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not M68K_THREAD_STATE_USER_REG_COUNT for " "flavor number %lu which is a M68K_THREAD_" "STATE_USER_REG flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } user_reg = (struct m68k_thread_state_user_reg *)state; state += sizeof(struct m68k_thread_state_user_reg); break; default: error("in swap_object_headers(): malformed " "load commands (unknown " "flavor %lu for flavor number %lu in %s command" " %lu can't byte swap it)", flavor, nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } nflavor++; } break; } if(cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_VEO || cputype == CPU_TYPE_POWERPC64){ ppc_thread_state_t *cpu; ppc_float_state_t *fpu; ppc_exception_state_t *except; ppc_thread_state64_t *cpu64; nflavor = 0; p = (char *)ut + ut->cmdsize; while(state < p){ flavor = *((unsigned long *)state); state += sizeof(unsigned long); count = *((unsigned long *)state); state += sizeof(unsigned long); switch(flavor){ case PPC_THREAD_STATE: if(count != PPC_THREAD_STATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not PPC_THREAD_STATE_COUNT for " "flavor number %lu which is a PPC_THREAD_" "STATE flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } cpu = (ppc_thread_state_t *)state; state += sizeof(ppc_thread_state_t); break; case PPC_FLOAT_STATE: if(count != PPC_FLOAT_STATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not PPC_FLOAT_STATE_COUNT for " "flavor number %lu which is a PPC_FLOAT_" "STATE flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } fpu = (ppc_float_state_t *)state; state += sizeof(ppc_float_state_t); break; case PPC_EXCEPTION_STATE: if(count != PPC_EXCEPTION_STATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not PPC_EXCEPTION_STATE_COUNT for " "flavor number %lu which is a PPC_EXCEPT" "ION_STATE flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } except = (ppc_exception_state_t *)state; state += sizeof(ppc_exception_state_t); break; case PPC_THREAD_STATE64: if(count != PPC_THREAD_STATE64_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not PPC_THREAD_STATE64_COUNT for " "flavor number %lu which is a PPC_THREAD_" "STATE64 flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } cpu64 = (ppc_thread_state64_t *)state; state += sizeof(ppc_thread_state64_t); break; default: error("in swap_object_headers(): malformed " "load commands (unknown " "flavor %lu for flavor number %lu in %s command" " %lu can't byte swap it)", flavor, nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } nflavor++; } break; } if(cputype == CPU_TYPE_MC88000){ m88k_thread_state_grf_t *cpu; m88k_thread_state_xrf_t *fpu; m88k_thread_state_user_t *user; m88110_thread_state_impl_t *spu; nflavor = 0; p = (char *)ut + ut->cmdsize; while(state < p){ flavor = *((unsigned long *)state); state += sizeof(unsigned long); count = *((unsigned long *)state); state += sizeof(unsigned long); switch(flavor){ case M88K_THREAD_STATE_GRF: if(count != M88K_THREAD_STATE_GRF_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not M88K_THREAD_STATE_GRF_COUNT for " "flavor number %lu which is a M88K_THREAD_" "STATE_GRF flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } cpu = (m88k_thread_state_grf_t *)state; state += sizeof(m88k_thread_state_grf_t); break; case M88K_THREAD_STATE_XRF: if(count != M88K_THREAD_STATE_XRF_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not M88K_THREAD_STATE_XRF_COUNT for " "flavor number %lu which is a M88K_THREAD_" "STATE_XRF flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } fpu = (m88k_thread_state_xrf_t *)state; state += sizeof(m88k_thread_state_xrf_t); break; case M88K_THREAD_STATE_USER: if(count != M88K_THREAD_STATE_USER_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not M88K_THREAD_STATE_USER_COUNT for " "flavor number %lu which is a M88K_THREAD_" "STATE_USER flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } user = (m88k_thread_state_user_t *)state; state += sizeof(m88k_thread_state_user_t); break; case M88110_THREAD_STATE_IMPL: if(count != M88110_THREAD_STATE_IMPL_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not M88110_THREAD_STATE_IMPL_COUNT for " "flavor number %lu which is a M88110_THREAD" "_STATE_IMPL flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } spu = (m88110_thread_state_impl_t *)state; state += sizeof(m88110_thread_state_impl_t); break; default: error("in swap_object_headers(): malformed " "load commands (unknown " "flavor %lu for flavor number %lu in %s command" " %lu can't byte swap it)", flavor, nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } nflavor++; } break; } if(cputype == CPU_TYPE_I860){ struct i860_thread_state_regs *cpu; nflavor = 0; p = (char *)ut + ut->cmdsize; while(state < p){ flavor = *((unsigned long *)state); state += sizeof(unsigned long); count = *((unsigned long *)state); state += sizeof(unsigned long); switch(flavor){ case I860_THREAD_STATE_REGS: if(count != I860_THREAD_STATE_REGS_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not I860_THREAD_STATE_REGS_COUNT for " "flavor number %lu which is a I860_THREAD_" "STATE_REGS flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } cpu = (struct i860_thread_state_regs *)state; state += sizeof(struct i860_thread_state_regs); break; default: error("in swap_object_headers(): malformed " "load commands (unknown " "flavor %lu for flavor number %lu in %s command" " %lu can't byte swap it)", flavor, nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } nflavor++; } break; } if(cputype == CPU_TYPE_I386 #ifdef x86_THREAD_STATE64 || cputype == CPU_TYPE_X86_64 #endif /* x86_THREAD_STATE64 */ ){ i386_thread_state_t *cpu; #ifdef x86_THREAD_STATE64 x86_thread_state64_t *cpu64; #endif /* x86_THREAD_STATE64 */ /* current i386 thread states */ #if i386_THREAD_STATE == 1 struct i386_float_state *fpu; i386_exception_state_t *exc; #endif /* i386_THREAD_STATE == 1 */ /* i386 thread states on older releases */ #if i386_THREAD_STATE == -1 i386_thread_fpstate_t *fpu; i386_thread_exceptstate_t *exc; i386_thread_cthreadstate_t *user; #endif /* i386_THREAD_STATE == -1 */ nflavor = 0; p = (char *)ut + ut->cmdsize; while(state < p){ flavor = *((unsigned long *)state); state += sizeof(unsigned long); count = *((unsigned long *)state); state += sizeof(unsigned long); switch(flavor){ case i386_THREAD_STATE: /* current i386 thread states */ #if i386_THREAD_STATE == 1 case -1: #endif /* i386_THREAD_STATE == 1 */ /* i386 thread states on older releases */ #if i386_THREAD_STATE == -1 case 1: #endif /* i386_THREAD_STATE == -1 */ if(count != i386_THREAD_STATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not i386_THREAD_STATE_COUNT for flavor " "number %lu which is a i386_THREAD_STATE " "flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } cpu = (i386_thread_state_t *)state; state += sizeof(i386_thread_state_t); break; /* current i386 thread states */ #if i386_THREAD_STATE == 1 case i386_FLOAT_STATE: if(count != i386_FLOAT_STATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not i386_FLOAT_STATE_COUNT for flavor " "number %lu which is a i386_FLOAT_STATE " "flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } fpu = (struct i386_float_state *)state; state += sizeof(struct i386_float_state); break; case i386_EXCEPTION_STATE: if(count != I386_EXCEPTION_STATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not I386_EXCEPTION_STATE_COUNT for " "flavor number %lu which is a i386_" "EXCEPTION_STATE flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } exc = (i386_exception_state_t *)state; state += sizeof(i386_exception_state_t); break; #endif /* i386_THREAD_STATE == 1 */ /* i386 thread states on older releases */ #if i386_THREAD_STATE == -1 case i386_THREAD_FPSTATE: if(count != i386_THREAD_FPSTATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not i386_THREAD_FPSTATE_COUNT for flavor " "number %lu which is a i386_THREAD_FPSTATE " "flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } fpu = (i386_thread_fpstate_t *)state; state += sizeof(i386_thread_fpstate_t); break; case i386_THREAD_EXCEPTSTATE: if(count != i386_THREAD_EXCEPTSTATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not i386_THREAD_EXCEPTSTATE_COUNT for " "flavor number %lu which is a i386_THREAD_" "EXCEPTSTATE flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } exc = (i386_thread_exceptstate_t *)state; state += sizeof(i386_thread_fpstate_t); break; case i386_THREAD_CTHREADSTATE: if(count != i386_THREAD_CTHREADSTATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not i386_THREAD_CTHREADSTATE_COUNT for " "flavor number %lu which is a i386_THREAD_" "CTHREADSTATE flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } user = (i386_thread_cthreadstate_t *)state; state += sizeof(i386_thread_fpstate_t); break; #endif /* i386_THREAD_STATE == -1 */ #ifdef x86_THREAD_STATE64 case x86_THREAD_STATE64: if(count != x86_THREAD_STATE64_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not x86_THREAD_STATE64_COUNT for " "flavor number %lu which is an x86_THREAD_" "STATE64 flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } cpu64 = (x86_thread_state64_t *)state; state += sizeof(x86_thread_state64_t); break; #endif /* x86_THREAD_STATE64 */ default: error("in swap_object_headers(): malformed " "load commands (unknown " "flavor %lu for flavor number %lu in %s command" " %lu can't byte swap it)", flavor, nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } nflavor++; } break; } if(cputype == CPU_TYPE_HPPA){ struct hp_pa_integer_thread_state *cpu; struct hp_pa_frame_thread_state *frame; struct hp_pa_fp_thread_state *fpu; nflavor = 0; p = (char *)ut + ut->cmdsize; while(state < p){ flavor = *((unsigned long *)state); state += sizeof(unsigned long); count = *((unsigned long *)state); state += sizeof(unsigned long); switch(flavor){ case HPPA_INTEGER_THREAD_STATE: if(count != HPPA_INTEGER_THREAD_STATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not HPPA_INTEGER_THREAD_STATE_COUNT for " "flavor number %lu which is a HPPA_INTEGER" "_THREAD_STATE flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } cpu = (struct hp_pa_integer_thread_state *)state; state += sizeof(struct hp_pa_integer_thread_state); break; case HPPA_FRAME_THREAD_STATE: if(count != HPPA_FRAME_THREAD_STATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not HPPA_FRAME_THREAD_STATE_COUNT for " "flavor number %lu which is a HPPA_FRAME" "_THREAD_STATE flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } frame = (struct hp_pa_frame_thread_state *)state; state += sizeof(struct hp_pa_frame_thread_state); break; case HPPA_FP_THREAD_STATE: if(count != HPPA_FP_THREAD_STATE_COUNT){ error("in swap_object_headers(): malformed " "load commands (count " "not HPPA_FP_THREAD_STATE_COUNT for " "flavor number %lu which is a HPPA_FP" "_THREAD_STATE flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } fpu = (struct hp_pa_fp_thread_state *)state; state += sizeof(struct hp_pa_fp_thread_state); break; default: error("in swap_object_headers(): malformed " "load commands (unknown " "flavor %lu for flavor number %lu in %s command" " %lu can't byte swap it)", flavor, nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } nflavor++; } break; } if(cputype == CPU_TYPE_SPARC) { struct sparc_thread_state_regs *cpu; struct sparc_thread_state_fpu *fpu; nflavor = 0; p = (char *)ut + ut->cmdsize; while (state < p) { flavor = *((unsigned long *) state); state += sizeof(unsigned long); count = *((unsigned int *) state); state += sizeof(unsigned long); switch (flavor) { case SPARC_THREAD_STATE_REGS: if (count != SPARC_THREAD_STATE_REGS_COUNT) { error("in swap_object_headers(): malformed " "load commands (count " "not SPARC_THREAD_STATE_REGS_COUNT for " "flavor number %lu which is a SPARC_THREAD_" "STATE_REGS flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } cpu = (struct sparc_thread_state_regs *) state; state += sizeof(struct sparc_thread_state_regs); break; case SPARC_THREAD_STATE_FPU: if (count != SPARC_THREAD_STATE_FPU_COUNT) { error("in swap_object_headers(): malformed " "load commands (count " "not SPARC_THREAD_STATE_FPU_COUNT for " "flavor number %lu which is a SPARC_THREAD_" "STATE_FPU flavor in %s command %lu)", nflavor, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); } fpu = (struct sparc_thread_state_fpu *) state; state += sizeof(struct sparc_thread_state_fpu); break; } } break; } if (cputype == CPU_TYPE_ARM) { nflavor = 0; p = (char *)ut + ut->cmdsize; while (state < p) { state += 8 + sizeof(arm_thread_state_t); nflavor++; } break; } error("in swap_object_headers(): malformed load commands " "(unknown cputype (%d) and cpusubtype (%d) of object and " "can't byte swap %s command %lu)", cputype, cpusubtype, ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" : "LC_THREAD", i); return(FALSE); case LC_IDENT: id = (struct ident_command *)lc; if((char *)id + id->cmdsize > (char *)load_commands + sizeofcmds){ error("in swap_object_headers(): truncated or malformed " "load commands (cmdsize field of LC_IDENT command %lu " "extends past the end of the load commands)", i); return(FALSE); } break; case LC_ROUTINES: rc = (struct routines_command *)lc; if(rc->cmdsize != sizeof(struct routines_command)){ error("in swap_object_headers(): malformed load commands (" "LC_ROUTINES command %lu has incorrect cmdsize", i); return(FALSE); } break; case LC_ROUTINES_64: rc64 = (struct routines_command_64 *)lc; if(rc64->cmdsize != sizeof(struct routines_command_64)){ error("in swap_object_headers(): malformed load commands (" "LC_ROUTINES_64 command %lu has incorrect cmdsize", i); return(FALSE); } break; case LC_TWOLEVEL_HINTS: hints = (struct twolevel_hints_command *)lc; if(hints->cmdsize != sizeof(struct twolevel_hints_command)){ error("in swap_object_headers(): malformed load commands " "(LC_TWOLEVEL_HINTS command %lu has incorrect " "cmdsize", i); return(FALSE); } break; case LC_PREBIND_CKSUM: cs = (struct prebind_cksum_command *)lc; if(cs->cmdsize != sizeof(struct prebind_cksum_command)){ error("in swap_object_headers(): malformed load commands " "(LC_PREBIND_CKSUM command %lu has incorrect cmdsize", i); return(FALSE); } break; case LC_UUID: uuid = (struct uuid_command *)lc; if(uuid->cmdsize != sizeof(struct uuid_command)){ error("in swap_object_headers(): malformed load commands " "(LC_UUID command %lu has incorrect cmdsize", i); return(FALSE); } break; default: error("in swap_object_headers(): malformed load commands " "(unknown load command %lu)", i); return(FALSE); } lc = (struct load_command *)((char *)lc + l.cmdsize); /* check that next load command does not extends past the end */ if((char *)lc > (char *)load_commands + sizeofcmds){ error("in swap_object_headers(): truncated or malformed load " "commands (load command %lu extends past the end of all " "load commands)", i + 1); return(FALSE); } } /* check for an inconsistent size of the load commands */ if((char *)load_commands + sizeofcmds != (char *)lc){ error("in swap_object_headers(): malformed load commands " "(inconsistent sizeofcmds field in mach header)"); return(FALSE); } /* * Now knowing the load commands can be parsed swap them. */ target_byte_sex = get_host_byte_sex() == BIG_ENDIAN_BYTE_SEX ? LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX; for(i = 0, lc = load_commands; i < ncmds; i++){ l = *lc; switch(lc->cmd){ case LC_SEGMENT: sg = (struct segment_command *)lc; s = (struct section *) ((char *)sg + sizeof(struct segment_command)); swap_section(s, sg->nsects, target_byte_sex); swap_segment_command(sg, target_byte_sex); break; case LC_SEGMENT_64: sg64 = (struct segment_command_64 *)lc; s64 = (struct section_64 *) ((char *)sg64 + sizeof(struct segment_command_64)); swap_section_64(s64, sg64->nsects, target_byte_sex); swap_segment_command_64(sg64, target_byte_sex); break; case LC_SYMTAB: st = (struct symtab_command *)lc; swap_symtab_command(st, target_byte_sex); break; case LC_DYSYMTAB: dyst = (struct dysymtab_command *)lc; swap_dysymtab_command(dyst, target_byte_sex); break; case LC_SYMSEG: ss = (struct symseg_command *)lc; swap_symseg_command(ss, target_byte_sex); break; case LC_IDFVMLIB: case LC_LOADFVMLIB: fl = (struct fvmlib_command *)lc; swap_fvmlib_command(fl, target_byte_sex); break; case LC_ID_DYLIB: case LC_LOAD_DYLIB: case LC_LOAD_WEAK_DYLIB: dl = (struct dylib_command *)lc; swap_dylib_command(dl, target_byte_sex); break; case LC_SUB_FRAMEWORK: sub = (struct sub_framework_command *)lc; swap_sub_framework_command(sub, target_byte_sex); break; case LC_SUB_UMBRELLA: usub = (struct sub_umbrella_command *)lc; swap_sub_umbrella_command(usub, target_byte_sex); break; case LC_SUB_LIBRARY: lsub = (struct sub_library_command *)lc; swap_sub_library_command(lsub, target_byte_sex); break; case LC_SUB_CLIENT: csub = (struct sub_client_command *)lc; swap_sub_client_command(csub, target_byte_sex); break; case LC_PREBOUND_DYLIB: pbdylib = (struct prebound_dylib_command *)lc; swap_prebound_dylib_command(pbdylib, target_byte_sex); break; case LC_ID_DYLINKER: case LC_LOAD_DYLINKER: dyld = (struct dylinker_command *)lc; swap_dylinker_command(dyld, target_byte_sex); break; case LC_UNIXTHREAD: case LC_THREAD: ut = (struct thread_command *)lc; state = (char *)ut + sizeof(struct thread_command); p = (char *)ut + ut->cmdsize; swap_thread_command(ut, target_byte_sex); if(cputype == CPU_TYPE_MC680x0){ struct m68k_thread_state_regs *cpu; struct m68k_thread_state_68882 *fpu; struct m68k_thread_state_user_reg *user_reg; while(state < p){ flavor = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(flavor); state += sizeof(unsigned long); count = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(count); state += sizeof(unsigned long); switch(flavor){ case M68K_THREAD_STATE_REGS: cpu = (struct m68k_thread_state_regs *)state; swap_m68k_thread_state_regs(cpu, target_byte_sex); state += sizeof(struct m68k_thread_state_regs); break; case M68K_THREAD_STATE_68882: fpu = (struct m68k_thread_state_68882 *)state; swap_m68k_thread_state_68882(fpu, target_byte_sex); state += sizeof(struct m68k_thread_state_68882); break; case M68K_THREAD_STATE_USER_REG: user_reg = (struct m68k_thread_state_user_reg *)state; swap_m68k_thread_state_user_reg(user_reg, target_byte_sex); state += sizeof(struct m68k_thread_state_user_reg); break; } } break; } if(cputype == CPU_TYPE_POWERPC || cputype == CPU_TYPE_VEO || cputype == CPU_TYPE_POWERPC64){ ppc_thread_state_t *cpu; ppc_thread_state64_t *cpu64; ppc_float_state_t *fpu; ppc_exception_state_t *except; while(state < p){ flavor = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(flavor); state += sizeof(unsigned long); count = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(count); state += sizeof(unsigned long); switch(flavor){ case PPC_THREAD_STATE: cpu = (ppc_thread_state_t *)state; swap_ppc_thread_state_t(cpu, target_byte_sex); state += sizeof(ppc_thread_state_t); break; case PPC_THREAD_STATE64: cpu64 = (ppc_thread_state64_t *)state; swap_ppc_thread_state64_t(cpu64, target_byte_sex); state += sizeof(ppc_thread_state64_t); break; case PPC_FLOAT_STATE: fpu = (ppc_float_state_t *)state; swap_ppc_float_state_t(fpu, target_byte_sex); state += sizeof(ppc_float_state_t); case PPC_EXCEPTION_STATE: except = (ppc_exception_state_t *)state; swap_ppc_exception_state_t(except, target_byte_sex); state += sizeof(ppc_exception_state_t); break; } } break; } if(cputype == CPU_TYPE_MC88000){ m88k_thread_state_grf_t *cpu; m88k_thread_state_xrf_t *fpu; m88k_thread_state_user_t *user; m88110_thread_state_impl_t *spu; while(state < p){ flavor = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(flavor); state += sizeof(unsigned long); count = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(count); state += sizeof(unsigned long); switch(flavor){ case M88K_THREAD_STATE_GRF: cpu = (m88k_thread_state_grf_t *)state; swap_m88k_thread_state_grf_t(cpu, target_byte_sex); state += sizeof(m88k_thread_state_grf_t); break; case M88K_THREAD_STATE_XRF: fpu = (m88k_thread_state_xrf_t *)state; swap_m88k_thread_state_xrf_t(fpu, target_byte_sex); state += sizeof(m88k_thread_state_xrf_t); break; case M88K_THREAD_STATE_USER: user = (m88k_thread_state_user_t *)state; swap_m88k_thread_state_user_t(user, target_byte_sex); state += sizeof(m88k_thread_state_user_t); break; case M88110_THREAD_STATE_IMPL: spu = (m88110_thread_state_impl_t *)state; swap_m88110_thread_state_impl_t(spu, target_byte_sex); state += sizeof(m88110_thread_state_impl_t); break; } } break; } if(cputype == CPU_TYPE_I860){ struct i860_thread_state_regs *cpu; while(state < p){ flavor = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(flavor); state += sizeof(unsigned long); count = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(count); state += sizeof(unsigned long); switch(flavor){ case I860_THREAD_STATE_REGS: cpu = (struct i860_thread_state_regs *)state; swap_i860_thread_state_regs(cpu, target_byte_sex); state += sizeof(struct i860_thread_state_regs); break; } } break; } if(cputype == CPU_TYPE_I386 #ifdef x86_THREAD_STATE64 || cputype == CPU_TYPE_X86_64 #endif /* x86_THREAD_STATE64 */ ){ i386_thread_state_t *cpu; #ifdef x86_THREAD_STATE64 x86_thread_state64_t *cpu64; #endif /* x86_THREAD_STATE64 */ /* current i386 thread states */ #if i386_THREAD_STATE == 1 struct i386_float_state *fpu; i386_exception_state_t *exc; #endif /* i386_THREAD_STATE == 1 */ /* i386 thread states on older releases */ #if i386_THREAD_STATE == -1 i386_thread_fpstate_t *fpu; i386_thread_exceptstate_t *exc; i386_thread_cthreadstate_t *user; #endif /* i386_THREAD_STATE == -1 */ while(state < p){ flavor = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(flavor); state += sizeof(unsigned long); count = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(count); state += sizeof(unsigned long); switch(flavor){ case i386_THREAD_STATE: /* current i386 thread states */ #if i386_THREAD_STATE == 1 case -1: #endif /* i386_THREAD_STATE == 1 */ /* i386 thread states on older releases */ #if i386_THREAD_STATE == -1 case 1: #endif /* i386_THREAD_STATE == -1 */ cpu = (i386_thread_state_t *)state; swap_i386_thread_state(cpu, target_byte_sex); state += sizeof(i386_thread_state_t); break; /* current i386 thread states */ #if i386_THREAD_STATE == 1 case i386_FLOAT_STATE: fpu = (struct i386_float_state *)state; swap_i386_float_state(fpu, target_byte_sex); state += sizeof(struct i386_float_state); break; case i386_EXCEPTION_STATE: exc = (i386_exception_state_t *)state; swap_i386_exception_state(exc, target_byte_sex); state += sizeof(i386_exception_state_t); break; #endif /* i386_THREAD_STATE == 1 */ /* i386 thread states on older releases */ #if i386_THREAD_STATE == -1 case i386_THREAD_FPSTATE: fpu = (i386_thread_fpstate_t *)state; swap_i386_thread_fpstate(fpu, target_byte_sex); state += sizeof(i386_thread_fpstate_t); break; case i386_THREAD_EXCEPTSTATE: exc = (i386_thread_exceptstate_t *)state; swap_i386_thread_exceptstate(exc, target_byte_sex); state += sizeof(i386_thread_exceptstate_t); break; case i386_THREAD_CTHREADSTATE: user = (i386_thread_cthreadstate_t *)state; swap_i386_thread_cthreadstate(user,target_byte_sex); state += sizeof(i386_thread_cthreadstate_t); break; #endif /* i386_THREAD_STATE == -1 */ #ifdef x86_THREAD_STATE64 case x86_THREAD_STATE64: cpu64 = (x86_thread_state64_t *)state; swap_x86_thread_state64(cpu64, target_byte_sex); state += sizeof(x86_thread_state64_t); break; #endif /* x86_THREAD_STATE64 */ } } break; } if(cputype == CPU_TYPE_HPPA){ struct hp_pa_integer_thread_state *cpu; struct hp_pa_frame_thread_state *frame; struct hp_pa_fp_thread_state *fpu; while(state < p){ flavor = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(flavor); state += sizeof(unsigned long); count = *((unsigned long *)state); *((unsigned long *)state) = SWAP_LONG(count); state += sizeof(unsigned long); switch(flavor){ case HPPA_INTEGER_THREAD_STATE: cpu = (struct hp_pa_integer_thread_state *)state; swap_hppa_integer_thread_state(cpu, target_byte_sex); state += sizeof(struct hp_pa_integer_thread_state); break; case HPPA_FRAME_THREAD_STATE: frame = (struct hp_pa_frame_thread_state *)state; swap_hppa_frame_thread_state(frame, target_byte_sex); state += sizeof(struct hp_pa_frame_thread_state); break; case HPPA_FP_THREAD_STATE: fpu = (struct hp_pa_fp_thread_state *)state; swap_hppa_fp_thread_state(fpu, target_byte_sex); state += sizeof(struct hp_pa_fp_thread_state); break; } } break; } if(cputype == CPU_TYPE_SPARC) { struct sparc_thread_state_regs *cpu; struct sparc_thread_state_fpu *fpu; while (state < p) { flavor = *((unsigned long *) state); *((unsigned long *) state) = SWAP_LONG(flavor); state += sizeof(unsigned long); count = *((unsigned int *) state); *((unsigned int *) state) = SWAP_LONG(count); state += sizeof(unsigned long); switch (flavor) { case SPARC_THREAD_STATE_REGS: cpu = (struct sparc_thread_state_regs *) state; swap_sparc_thread_state_regs(cpu, target_byte_sex); state += sizeof(struct sparc_thread_state_regs); break; case SPARC_THREAD_STATE_FPU: fpu = (struct sparc_thread_state_fpu *) state; swap_sparc_thread_state_fpu(fpu, target_byte_sex); state += sizeof(struct sparc_thread_state_fpu); break; } } break; } if (cputype == CPU_TYPE_ARM) { arm_thread_state_t *thread_state; while (state < p) { u_int32_t n; n = *((u_int32_t *)state); *((u_int32_t *)state) = SWAP_LONG(n); state += 4; n = *((u_int32_t *)state); *((u_int32_t *)state) = SWAP_LONG(n); state += 4; thread_state = (arm_thread_state_t *)state; swap_arm_thread_state(thread_state, target_byte_sex); state += sizeof(arm_thread_state_t); } } break; case LC_IDENT: id = (struct ident_command *)lc; swap_ident_command(id, target_byte_sex); break; case LC_ROUTINES: rc = (struct routines_command *)lc; swap_routines_command(rc, target_byte_sex); break; case LC_ROUTINES_64: rc64 = (struct routines_command_64 *)lc; swap_routines_command_64(rc64, target_byte_sex); break; case LC_TWOLEVEL_HINTS: hints = (struct twolevel_hints_command *)lc; swap_twolevel_hints_command(hints, target_byte_sex); break; case LC_PREBIND_CKSUM: cs = (struct prebind_cksum_command *)lc; swap_prebind_cksum_command(cs, target_byte_sex); break; case LC_UUID: uuid = (struct uuid_command *)lc; swap_uuid_command(uuid, target_byte_sex); break; } lc = (struct load_command *)((char *)lc + l.cmdsize); } if(mh != NULL) swap_mach_header(mh, target_byte_sex); else swap_mach_header_64(mh64, target_byte_sex); return(TRUE); }
static int register_mach_header(const char* build, const char* project, const char* path, struct fat_arch* fa, int fd, int* isMachO) { ssize_t res; uint32_t magic; int swap = 0; struct mach_header* mh = NULL; struct mach_header_64* mh64 = NULL; if (isMachO) *isMachO = 0; res = read(fd, &magic, sizeof(uint32_t)); if (res < sizeof(uint32_t)) { return 0; } // // 32-bit, read the rest of the header // if (magic == MH_MAGIC || magic == MH_CIGAM) { if (isMachO) *isMachO = 1; mh = malloc(sizeof(struct mach_header)); if (mh == NULL) return -1; memset(mh, 0, sizeof(struct mach_header)); mh->magic = magic; res = read(fd, &mh->cputype, sizeof(struct mach_header) - sizeof(uint32_t)); if (res < sizeof(struct mach_header) - sizeof(uint32_t)) { return 0; } if (magic == MH_CIGAM) { swap = 1; swap_mach_header(mh, NXHostByteOrder()); } // // 64-bit, read the rest of the header // } else if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64) { if (isMachO) *isMachO = 1; mh64 = malloc(sizeof(struct mach_header_64)); if (mh64 == NULL) return -1; memset(mh64, 0, sizeof(struct mach_header_64)); mh64->magic = magic; res = read(fd, &mh64->cputype, sizeof(struct mach_header_64) - sizeof(uint32_t)); if (res < sizeof(struct mach_header_64) - sizeof(uint32_t)) { return 0; } if (magic == MH_CIGAM_64) { swap = 1; swap_mach_header_64(mh64, NXHostByteOrder()); } // // Not a Mach-O // } else { return 0; } switch (mh64 ? mh64->filetype : mh->filetype) { case MH_EXECUTE: case MH_DYLIB: case MH_BUNDLE: break; case MH_OBJECT: default: return 0; } res = SQL("INSERT INTO mach_o_objects (magic, type, cputype, cpusubtype, flags, build, project, path) VALUES (%u, %u, %u, %u, %u, %Q, %Q, %Q)", mh64 ? mh64->magic : mh->magic, mh64 ? mh64->filetype : mh->filetype, mh64 ? mh64->cputype : mh->cputype, mh64 ? mh64->cpusubtype : mh->cpusubtype, mh64 ? mh64->flags : mh->flags, build, project, path); uint64_t serial = sqlite3_last_insert_rowid((sqlite3*)_DBPluginGetDataStorePtr()); // // Information needed to parse the symbol table // int count_nsect = 0; unsigned char text_nsect = NO_SECT; unsigned char data_nsect = NO_SECT; unsigned char bss_nsect = NO_SECT; uint32_t nsyms = 0; uint8_t *symbols = NULL; uint32_t strsize = 0; uint8_t *strings = NULL; int i; uint32_t ncmds = mh64 ? mh64->ncmds : mh->ncmds; for (i = 0; i < ncmds; ++i) { // // Read a generic load command into memory. // At first, we only know it has a type and size. // struct load_command lctmp; ssize_t res = read(fd, &lctmp, sizeof(struct load_command)); if (res < sizeof(struct load_command)) { return 0; } uint32_t cmd = swap ? OSSwapInt32(lctmp.cmd) : lctmp.cmd; uint32_t cmdsize = swap ? OSSwapInt32(lctmp.cmdsize) : lctmp.cmdsize; if (cmdsize == 0) continue; struct load_command* lc = malloc(cmdsize); if (lc == NULL) { return 0; } memset(lc, 0, cmdsize); memcpy(lc, &lctmp, sizeof(lctmp)); // Read the remainder of the load command. res = read(fd, (uint8_t*)lc + sizeof(struct load_command), cmdsize - sizeof(struct load_command)); if (res < (cmdsize - sizeof(struct load_command))) { free(lc); return 0; } // // LC_LOAD_DYLIB and LC_LOAD_WEAK_DYLIB // Add dylibs as unresolved "lib" dependencies. // if (cmd == LC_LOAD_DYLIB || cmd == LC_LOAD_WEAK_DYLIB) { struct dylib_command *dylib = (struct dylib_command*)lc; if (swap) swap_dylib_command(dylib, NXHostByteOrder()); // sections immediately follow the dylib_command structure, and are // reflected in the cmdsize. int strsize = dylib->cmdsize - sizeof(struct dylib_command); char* str = malloc(strsize+1); strncpy(str, (char*)((uint8_t*)dylib + dylib->dylib.name.offset), strsize); str[strsize] = 0; // NUL-terminate res = SQL("INSERT INTO unresolved_dependencies (build,project,type,dependency) VALUES (%Q,%Q,%Q,%Q)", build, project, "lib", str); free(str); // // LC_LOAD_DYLINKER // Add the dynamic linker (usually dyld) as an unresolved "lib" dependency. // } else if (cmd == LC_LOAD_DYLINKER) { struct dylinker_command *dylinker = (struct dylinker_command*)lc; if (swap) swap_dylinker_command(dylinker, NXHostByteOrder()); // sections immediately follow the dylib_command structure, and are // reflected in the cmdsize. int strsize = dylinker->cmdsize - sizeof(struct dylinker_command); char* str = malloc(strsize+1); strncpy(str, (char*)((uint8_t*)dylinker + dylinker->name.offset), strsize); str[strsize] = 0; // NUL-terminate res = SQL("INSERT INTO unresolved_dependencies (build,project,type,dependency) VALUES (%Q,%Q,%Q,%Q)", build, project, "lib", str); free(str); // // LC_SYMTAB // Read the symbol table into memory, we'll process it after we're // done with the load commands. // } else if (cmd == LC_SYMTAB && symbols == NULL) { struct symtab_command *symtab = (struct symtab_command*)lc; if (swap) swap_symtab_command(symtab, NXHostByteOrder()); nsyms = symtab->nsyms; uint32_t symsize = nsyms * (mh64 ? sizeof(struct nlist_64) : sizeof(struct nlist)); symbols = malloc(symsize); strsize = symtab->strsize; // XXX: check strsize != 0 strings = malloc(strsize); off_t save = lseek(fd, 0, SEEK_CUR); off_t origin = fa ? fa->offset : 0; lseek(fd, (off_t)symtab->symoff + origin, SEEK_SET); res = read(fd, symbols, symsize); if (res < symsize) { /* XXX: leaks */ return 0; } lseek(fd, (off_t)symtab->stroff + origin, SEEK_SET); res = read(fd, strings, strsize); if (res < strsize) { /* XXX: leaks */ return 0; } lseek(fd, save, SEEK_SET); // // LC_SEGMENT // We're looking for the section number of the text, data, and bss segments // in order to parse symbols. // } else if (cmd == LC_SEGMENT) { struct segment_command* seg = (struct segment_command*)lc; if (swap) swap_segment_command(seg, NXHostByteOrder()); // sections immediately follow the segment_command structure, and are // reflected in the cmdsize. int k; for (k = 0; k < seg->nsects; ++k) { struct section* sect = (struct section*)((uint8_t*)seg + sizeof(struct segment_command) + k * sizeof(struct section)); if (swap) swap_section(sect, 1, NXHostByteOrder()); if (strcmp(sect->sectname, SECT_TEXT) == 0 && strcmp(sect->segname, SEG_TEXT) == 0) { text_nsect = ++count_nsect; } else if (strcmp(sect->sectname, SECT_DATA) == 0 && strcmp(sect->segname, SEG_DATA) == 0) { data_nsect = ++count_nsect; } else if (strcmp(sect->sectname, SECT_BSS) == 0 && strcmp(sect->segname, SEG_DATA) == 0) { bss_nsect = ++count_nsect; } else { ++count_nsect; } } // // LC_SEGMENT_64 // Same as LC_SEGMENT, but for 64-bit binaries. // } else if (lc->cmd == LC_SEGMENT_64) { struct segment_command_64* seg = (struct segment_command_64*)lc; if (swap) swap_segment_command_64(seg, NXHostByteOrder()); // sections immediately follow the segment_command structure, and are // reflected in the cmdsize. int k; for (k = 0; k < seg->nsects; ++k) { struct section_64* sect = (struct section_64*)((uint8_t*)seg + sizeof(struct segment_command_64) + k * sizeof(struct section_64)); if (swap) swap_section_64(sect, 1, NXHostByteOrder()); if (strcmp(sect->sectname, SECT_TEXT) == 0 && strcmp(sect->segname, SEG_TEXT) == 0) { text_nsect = ++count_nsect; } else if (strcmp(sect->sectname, SECT_DATA) == 0 && strcmp(sect->segname, SEG_DATA) == 0) { data_nsect = ++count_nsect; } else if (strcmp(sect->sectname, SECT_BSS) == 0 && strcmp(sect->segname, SEG_DATA) == 0) { bss_nsect = ++count_nsect; } else { ++count_nsect; } } } free(lc); } // // Finished processing the load commands, now insert symbols into the database. // int j; for (j = 0; j < nsyms; ++j) { struct nlist_64 symbol; if (mh64) { memcpy(&symbol, (symbols + j * sizeof(struct nlist_64)), sizeof(struct nlist_64)); if (swap) swap_nlist_64(&symbol, 1, NXHostByteOrder()); } else { symbol.n_value = 0; memcpy(&symbol, (symbols + j * sizeof(struct nlist)), sizeof(struct nlist)); if (swap) swap_nlist_64(&symbol, 1, NXHostByteOrder()); // we copied a 32-bit nlist into a 64-bit one, adjust the value accordingly // all other fields are identical sizes symbol.n_value >>= 32; } char type = '?'; switch (symbol.n_type & N_TYPE) { case N_UNDF: case N_PBUD: type = 'u'; if (symbol.n_value != 0) { type = 'c'; } break; case N_ABS: type = 'a'; break; case N_SECT: if (symbol.n_sect == text_nsect) { type = 't'; } else if (symbol.n_sect == data_nsect) { type = 'd'; } else if (symbol.n_sect == bss_nsect) { type = 'b'; } else { type = 's'; } break; case N_INDR: type = 'i'; break; } // uppercase indicates an externally visible symbol if ((symbol.n_type & N_EXT) && type != '?') { type = toupper(type); } if (type != '?' && type != 'u' && type != 'c') { const uint8_t* name = (const uint8_t*)""; if (symbol.n_un.n_strx != 0) { name = (uint8_t*)(strings + symbol.n_un.n_strx); } res = SQL("INSERT INTO mach_o_symbols VALUES (%lld, \'%c\', %lld, %Q)", serial, type, symbol.n_value, name); } } return 0; }