#define is_magic(a) ( ((a) == MH_MAGIC) || ((a) == MH_MAGIC_64) ) #define is_cigam(a) ( ((a) == MH_CIGAM) || ((a) == MH_CIGAM_64) ) //-------------------------------------------------------------------------- static void swap_fat_header(fat_header *fh) { fh->magic = swap32(fh->magic); fh->nfat_arch = swap32(fh->nfat_arch); } //-------------------------------------------------------------------------- static void swap_fat_arch(fat_arch *fa) { fa->cputype = swap32(fa->cputype); fa->cpusubtype = swap32(fa->cpusubtype); fa->offset = swap32(fa->offset); fa->size = swap32(fa->size); fa->align = swap32(fa->align); } #if defined(LOADER_COMPILE) || defined(BUILD_DWARF) || defined(DWARFER) || defined(BUILD_EFD) || defined(BUILD_DEBUGGER) // --------------------------------------------------------------------------- int macho_arch_to_ida_arch(cpu_type_t cputype, cpu_subtype_t /*cpusubtype*/, bool *is_64) { bool _64 = false; int target = -1; switch ( cputype ) { default: case CPU_TYPE_VAX: case CPU_TYPE_ROMP: case CPU_TYPE_NS32032: case CPU_TYPE_NS32332: case CPU_TYPE_MC88000: break; case CPU_TYPE_MC680x0: target = PLFM_68K; break; case CPU_TYPE_I860: target = PLFM_I860; break; case CPU_TYPE_I386: target = PLFM_386; break; case CPU_TYPE_POWERPC: target = PLFM_PPC; break; case CPU_TYPE_HPPA: target = PLFM_HPPA; break; case CPU_TYPE_SPARC: target = PLFM_SPARC; break; case CPU_TYPE_MIPS: target = PLFM_MIPS; break; case CPU_TYPE_ARM: case CPU_TYPE_ARM64_32: target = PLFM_ARM; break; #ifdef __EA64__ // see also below, the error message for it case CPU_TYPE_ARM64: _64 = true; target = PLFM_ARM; break; case CPU_TYPE_X86_64: _64 = true; target = PLFM_386; break; #endif case CPU_TYPE_POWERPC64: target = PLFM_PPC; break; } if ( is_64 != NULL ) *is_64 = _64; //-V547 'A = false' return target; } #endif //-------------------------------------------------------------------------- bool macho_file_t::parse_header() { qlseek(li, start_offset); uint32 magic; if ( qlread(li, &magic, sizeof(magic)) != sizeof(magic) ) return false; if ( magic == FAT_MAGIC || magic == FAT_CIGAM ) return parse_fat_header(); else return is_magic(magic) || is_cigam(magic); } //-------------------------------------------------------------------------- bool macho_file_t::parse_fat_header() { qlseek(li, start_offset); if ( qlread(li, &fheader, sizeof(fheader)) != sizeof(fheader) ) return false; int code = (fheader.magic == FAT_MAGIC); if ( fheader.magic == FAT_CIGAM ) { swap_fat_header(&fheader); code = 2; } if ( code == 0 || fheader.nfat_arch > 16 ) return false; uint64 fsize = qlsize(li); uint32 archs_size = fheader.nfat_arch * sizeof(fat_arch); if ( sizeof(fat_header) + archs_size >= fsize ) return false; fat_archs.resize(fheader.nfat_arch); if ( qlread(li, fat_archs.begin(), archs_size) != archs_size ) { fat_archs.clear(); return false; } for ( uint32_t i=0; i < fheader.nfat_arch; i++ ) { fat_arch *parch = &fat_archs[i]; if ( code == 2 ) swap_fat_arch(parch); if ( parch->size <= sizeof(mach_header) || parch->size >= fsize || parch->offset < sizeof(fat_header) + archs_size || parch->offset + parch->size > fsize ) { fat_archs.clear(); return false; } } return true; } //-------------------------------------------------------------------------- bool macho_file_t::get_fat_header(fat_header *fh) { if ( fat_archs.empty() ) return false; *fh = fheader; return true; } //-------------------------------------------------------------------------- bool macho_file_t::get_fat_arch(uint n, fat_arch *fa) { if ( n >= fat_archs.size() ) { memset(fa, 0, sizeof(*fa)); return false; } *fa = fat_archs[n]; return true; }