void ProcessImageLoad(const struct mach_header* mh, intptr_t slide) { unsigned long size; std::vector<const char*> classNames; void* dataPtr = nullptr; #ifdef OBJC_ABI_2 const class_t** classes; ProcessProtocolsNew(mh, slide); classes = reinterpret_cast<const class_t**>( getsectdata(mh, SEG_OBJC_CLASSLIST_NEW, SECT_OBJC_CLASSLIST_NEW, &size) ); if (classes) { classNames = ProcessClassesNew(mh, slide, classes, size); dataPtr = (void*)*classes; } ProcessCategoriesNew(mh, slide); #else module_info* modinfo; ProcessProtocolsOld(mh, slide); modinfo = reinterpret_cast<module_info*>( getsectdata(mh, SEG_OBJC_MODINFO_OLD, SECT_OBJC_MODINFO_OLD, &size) ); if (modinfo && modinfo->symtab) { classNames = ProcessClassesOld(mh, slide, modinfo); dataPtr = modinfo; ProcessCategoriesOld(mh, slide, modinfo); } #endif UpdateClassRefs(mh); UpdateSelectors(mh, slide); // Do this only for dynamic libs (slide > 0) if (!classNames.empty() && slide > 0) { // Generate a NSFramework_XXXX class for GNUstep's NSBundle const char* path = dyld_image_path_containing_address(dataPtr); assert(path != nullptr); RegisterFramework(&classNames[0], classNames.size(), path); } static SEL selInit = sel_getUid("load"); while (!g_pendingInitClasses.empty()) { auto pair = g_pendingInitClasses.front(); g_pendingInitClasses.pop(); pair.second(reinterpret_cast<objc_object*>(pair.first), selInit); } }
static void* getStubAddr() { #if __LP64__ uint64_t size; #else uint32_t size; #endif uintptr_t slide = (uintptr_t)&_mh_dylib_header; // assume dylib is zero-base so slide == load address #if __i386__ return getsectdatafromheader(&_mh_dylib_header, "__IMPORT", "__jump_table", &size) + slide; #elif __ppc__ return getsectdatafromheader(&_mh_dylib_header, "TEXT", "__picsymbolstub1", &size) + slide; #elif __ppc64__ return getsectdatafromheader_64(&_mh_dylib_header, "__TEXT", "__picsymbolstub1", &size) + slide; #elif __x86_64__ return getsectdatafromheader_64(&_mh_dylib_header, "__TEXT", "__symbol_stub1", &size) + slide; #elif __arm__ void* p = getsectdata("__TEXT", "__picsymbolstub4", (unsigned long*)&size); if ( p != NULL ) return getsectdatafromheader(&_mh_dylib_header, "__TEXT", "__picsymbolstub4", &size) + slide; return getsectdatafromheader(&_mh_dylib_header, "__TEXT", "__symbolstub1", &size) + slide; #else #error unknown arch #endif }
std::vector<const char*> ProcessClassesNew(const struct mach_header* mh, intptr_t slide, const char* segment, const char* section, uint32_t image_index) { class_t **classes, **classes_end; unsigned long size; std::vector<const char*> classNames; classes = reinterpret_cast<class_t**>( getsectdata(mh, segment, section, &size) ); if (nullptr != classes) { classes_end = classes + size / sizeof(class_t*); while (classes < classes_end) { Class c = RegisterClass(*classes, slide, image_index); classNames.push_back(class_getName(c)); LOG << "Fixup @" << classes << " " << *classes << " -> " << c <<std::endl; *classes = (class_t*)c; classes++; } } return classNames; }
void UpdateCFStrings(const struct mach_header* mh) { unsigned long size; apple_cfstring* strings = reinterpret_cast<apple_cfstring*>( getsectdata(mh, "__DATA", "__cfstring", &size) ); if (strings) FixupCFStrings(strings, size / sizeof(apple_cfstring)); strings = reinterpret_cast<apple_cfstring*>( getsectdata(mh, "__DATA", "__ustring", &size) ); if (strings) FixupCFStrings(strings, size / sizeof(apple_cfstring)); }
void ProcessImageLoad(const struct mach_header* mh, intptr_t slide) { unsigned long size; #ifdef OBJC_ABI_2 const class_t** classes; ProcessProtocolsNew(mh, slide); classes = reinterpret_cast<const class_t**>( getsectdata(mh, SEG_OBJC_CLASSLIST_NEW, SECT_OBJC_CLASSLIST_NEW, &size) ); if (classes) ProcessClassesNew(mh, slide, classes, size); ProcessCategoriesNew(mh, slide); #else module_info* modinfo; ProcessProtocolsOld(mh, slide); modinfo = reinterpret_cast<module_info*>( getsectdata(mh, SEG_OBJC_MODINFO_OLD, SECT_OBJC_MODINFO_OLD, &size) ); if (modinfo && modinfo->symtab) { ProcessClassesOld(mh, slide, modinfo); ProcessCategoriesOld(mh, slide, modinfo); } #endif UpdateClassRefs(mh); UpdateSelectors(mh, slide); static SEL selInit = sel_getUid("load"); while (!g_pendingInitClasses.empty()) { auto pair = g_pendingInitClasses.front(); g_pendingInitClasses.pop(); pair.second(reinterpret_cast<objc_object*>(pair.first), selInit); } }
void UpdateSelectors(const struct mach_header* mh, intptr_t slide) { selref* sel_refs; msgref* msg_refs; unsigned long selsize, msgsize; sel_refs = reinterpret_cast<selref*>( getsectdata(mh, SEG_OBJC_SELREFS_NEW, SECT_OBJC_SELREFS_NEW, &selsize) ); msg_refs = reinterpret_cast<msgref*>( getsectdata(mh, SEG_OBJC_MSGREFS_NEW, SECT_OBJC_MSGREFS_NEW, &msgsize) ); if (!sel_refs) { sel_refs = reinterpret_cast<selref*>( getsectdata(mh, SEG_OBJC_SELREFS_OLD, SECT_OBJC_SELREFS_OLD, &selsize) ); } if (sel_refs) { for (size_t i = 0; i < selsize / sizeof(selref); i++) { SEL native = sel_getUid(sel_refs[i].selName); LOG << "ObjC SEL fixup @" << (sel_refs+i) << ": " << sel_refs[i].sel << " -> " << native << std::endl; sel_refs[i].sel = native; } } if (msg_refs) { for (size_t i = 0; i < msgsize / sizeof(msgref); i++) { SEL native = sel_getUid(msg_refs[i].sel.selName); LOG << "ObjC msgref fixup @" << &msg_refs[i].sel.sel << ": " << msg_refs[i].sel.sel << " -> " << native << std::endl; msg_refs[i].sel.sel = native; } } }
void UpdateClassRefs(const struct mach_header* mh) { unsigned long refsize, refsize_s; class_t **class_refs, **class_refs_end, **super_refs, **super_refs_end; class_refs = reinterpret_cast<class_t**>( getsectdata(mh, SEG_OBJC_CLASSREFS_NEW, SECT_OBJC_CLASSREFS_NEW, &refsize) ); super_refs = reinterpret_cast<class_t**>( getsectdata(mh, SEG_OBJC_SUPERREFS_NEW, SECT_OBJC_SUPERREFS_NEW, &refsize_s) ); if (class_refs) class_refs_end = class_refs + refsize / sizeof(class_t*); if (super_refs) super_refs_end = super_refs + refsize_s / sizeof(class_t*); if (class_refs) find_and_fix((void**) class_refs, (void**) class_refs_end, g_classPointers); if (super_refs) find_and_fix((void**) super_refs, (void**) super_refs_end, g_classPointers); }
void ProcessProtocolsNew(const struct mach_header* mh, intptr_t slide) { const protocol_t** protocol_list; unsigned long protosize; protocol_list = reinterpret_cast<const protocol_t**>( getsectdata(mh, SEG_OBJC_PROTOLIST_NEW, SECT_OBJC_PROTOLIST_NEW, &protosize) ); if (protocol_list) { unsigned long refsize; protocol_t** protocol_refs; protocol_t** protocol_refs_end; std::set<const protocol_t*> setProtocols; std::vector<const protocol_t*> vecProtocols; protocol_refs = reinterpret_cast<protocol_t**>( getsectdata(mh, SEG_OBJC_PROTOREFS_NEW, SECT_OBJC_PROTOREFS_NEW, &refsize) ); if (protocol_refs) protocol_refs_end = protocol_refs + refsize / sizeof(protocol_t*); std::copy(protocol_list, protocol_list+protosize/sizeof(protocol_t*), std::inserter(setProtocols, setProtocols.begin())); topology_sort<const protocol_t>(setProtocols, vecProtocols, [&setProtocols,slide](const protocol_t* p) { return p->protocols ? std::set<const protocol_t*>(p->protocols->begin(slide), p->protocols->end(slide)) : std::set<const protocol_t*>(); }); for (const protocol_t* proto : vecProtocols) { Protocol* p = RegisterProtocol(proto, slide); if (protocol_refs) find_and_fix(protocol_refs, protocol_refs_end, proto, p); } } }
rs_bool mapf_open( const char *path ) { kern_return_t rc; if (strncmp(path,"sect:",5) == 0) { char *s, name[1000]; strcpy( name, path+5 ); s = strchr( name, ':' ); *s++ = 0; image_file = -1; image_mapping_addr = (vm_address_t)getsectdata( name, s, (int *)&image_mapping_size ); if (!image_mapping_addr) { fprintf( stderr, "could not map segment %s, section %s\n", name, s ); return NO; } } else { image_file = open( path, O_RDONLY, 0 ); if (image_file < 0) { perror( path ); return NO; } image_mapping_size = lseek( image_file, 0L, SEEK_END ); rc = map_fd( image_file, (vm_offset_t)0, &image_mapping_addr, /* find_space */ TRUE, image_mapping_size ); if (rc != KERN_SUCCESS) { fprintf( stderr, "could not map file: %s\n", path ); close( image_file ); return NO; } } image_mapping_ptr = (void *)image_mapping_addr; return YES; }
void UpdateClassRefs(const struct mach_header* mh) { clsref* class_refs; unsigned long refsize; class_refs = reinterpret_cast<clsref*>( getsectdata(mh, SEG_OBJC_CLASSREFS_OLD, SECT_OBJC_CLASSREFS_OLD, &refsize) ); if (class_refs) { for (size_t i = 0; i < refsize / sizeof(clsref); i++) { Class c = (Class) objc_getClass(class_refs[i].clsName); LOG << "ObjC fixup classref @" << &class_refs[i].cls << ": " << class_refs[i].cls << " -> " << c << std::endl; class_refs[i].cls = c; } } }
Bool ML_(read_macho_debug_info)( struct _DebugInfo* di ) { struct symtab_command *symcmd = NULL; struct dysymtab_command *dysymcmd = NULL; HChar* dsymfilename = NULL; Bool have_uuid = False; UChar uuid[16]; ImageInfo ii; /* main file */ ImageInfo iid; /* auxiliary .dSYM file */ Bool ok; /* mmap the object file to look for di->soname and di->text_bias and uuid and nlist and STABS */ if (VG_(clo_verbosity) > 1) VG_(message)(Vg_DebugMsg, "%s (%#lx)\n", di->filename, di->rx_map_avma ); /* This should be ensured by our caller. */ vg_assert(di->have_rx_map); vg_assert(di->have_rw_map); VG_(memset)(&ii, 0, sizeof(ii)); VG_(memset)(&iid, 0, sizeof(iid)); VG_(memset)(&uuid, 0, sizeof(uuid)); ok = map_image_aboard( di, &ii, di->filename ); if (!ok) goto fail; vg_assert(ii.macho_img != NULL && ii.macho_img_szB > 0); /* Poke around in the Mach-O header, to find some important stuff. */ // Find LC_SYMTAB and LC_DYSYMTAB, if present. // Read di->soname from LC_ID_DYLIB if present, // or from LC_ID_DYLINKER if present, // or use "NONE". // Get di->text_bias (aka slide) based on the corresponding LC_SEGMENT // Get uuid for later dsym search di->text_bias = 0; { struct MACH_HEADER *mh = (struct MACH_HEADER *)ii.macho_img; struct load_command *cmd; Int c; for (c = 0, cmd = (struct load_command *)(mh+1); c < mh->ncmds; c++, cmd = (struct load_command *)(cmd->cmdsize + (unsigned long)cmd)) { if (cmd->cmd == LC_SYMTAB) { symcmd = (struct symtab_command *)cmd; } else if (cmd->cmd == LC_DYSYMTAB) { dysymcmd = (struct dysymtab_command *)cmd; } else if (cmd->cmd == LC_ID_DYLIB && mh->filetype == MH_DYLIB) { // GrP fixme bundle? struct dylib_command *dcmd = (struct dylib_command *)cmd; UChar *dylibname = dcmd->dylib.name.offset + (UChar *)dcmd; UChar *soname = VG_(strrchr)(dylibname, '/'); if (!soname) soname = dylibname; else soname++; di->soname = ML_(dinfo_strdup)("di.readmacho.dylibname", soname); } else if (cmd->cmd==LC_ID_DYLINKER && mh->filetype==MH_DYLINKER) { struct dylinker_command *dcmd = (struct dylinker_command *)cmd; UChar *dylinkername = dcmd->name.offset + (UChar *)dcmd; UChar *soname = VG_(strrchr)(dylinkername, '/'); if (!soname) soname = dylinkername; else soname++; di->soname = ML_(dinfo_strdup)("di.readmacho.dylinkername", soname); } // A comment from Julian about why varinfo[35] fail: // // My impression is, from comparing the output of otool -l for these // executables with the logic in ML_(read_macho_debug_info), // specifically the part that begins "else if (cmd->cmd == // LC_SEGMENT_CMD) {", that it's a complete hack which just happens // to work ok for text symbols. In particular, it appears to assume // that in a "struct load_command" of type LC_SEGMENT_CMD, the first // "struct SEGMENT_COMMAND" inside it is going to contain the info we // need. However, otool -l shows, and also the Apple docs state, // that a struct load_command may contain an arbitrary number of // struct SEGMENT_COMMANDs, so I'm not sure why it's OK to merely // snarf the first. But I'm not sure about this. // // The "Try for __DATA" block below simply adds acquisition of data // svma/bias values using the same assumption. It also needs // (probably) to deal with bss sections, but I don't understand how // this all ties together really, so it requires further study. // // If you can get your head around the relationship between MachO // segments, sections and load commands, this might be relatively // easy to fix properly. // // Basically we need to come up with plausible numbers for di-> // {text,data,bss}_{avma,svma}, from which the _bias numbers are // then trivially derived. Then I think the debuginfo reader should // work pretty well. else if (cmd->cmd == LC_SEGMENT_CMD) { struct SEGMENT_COMMAND *seg = (struct SEGMENT_COMMAND *)cmd; /* Try for __TEXT */ if (!di->text_present && 0 == VG_(strcmp)(seg->segname, "__TEXT") /* DDD: is the next line a kludge? -- JRS */ && seg->fileoff == 0 && seg->filesize != 0) { di->text_present = True; di->text_svma = (Addr)seg->vmaddr; di->text_avma = di->rx_map_avma; di->text_size = seg->vmsize; di->text_bias = di->text_avma - di->text_svma; /* Make the _debug_ values be the same as the svma/bias for the primary object, since there is no secondary (debuginfo) object, but nevertheless downstream biasing of Dwarf3 relies on the _debug_ values. */ di->text_debug_svma = di->text_svma; di->text_debug_bias = di->text_bias; } /* Try for __DATA */ if (!di->data_present && 0 == VG_(strcmp)(seg->segname, "__DATA") /* && DDD:seg->fileoff == 0 */ && seg->filesize != 0) { di->data_present = True; di->data_svma = (Addr)seg->vmaddr; di->data_avma = di->rw_map_avma; di->data_size = seg->vmsize; di->data_bias = di->data_avma - di->data_svma; di->data_debug_svma = di->data_svma; di->data_debug_bias = di->data_bias; } } else if (cmd->cmd == LC_UUID) { struct uuid_command *uuid_cmd = (struct uuid_command *)cmd; VG_(memcpy)(uuid, uuid_cmd->uuid, sizeof(uuid)); have_uuid = True; } } } if (!di->soname) { di->soname = ML_(dinfo_strdup)("di.readmacho.noname", "NONE"); } /* Now we have the base object to hand. Read symbols from it. */ if (ii.macho_img && ii.macho_img_szB > 0 && symcmd && dysymcmd) { /* Read nlist symbol table */ struct NLIST *syms; UChar *strs; XArray* /* DiSym */ candSyms = NULL; Word i, nCandSyms; if (ii.macho_img_szB < symcmd->stroff + symcmd->strsize || ii.macho_img_szB < symcmd->symoff + symcmd->nsyms * sizeof(struct NLIST)) { ML_(symerr)(di, False, "Invalid Mach-O file (5 too small)."); goto fail; } if (dysymcmd->ilocalsym + dysymcmd->nlocalsym > symcmd->nsyms || dysymcmd->iextdefsym + dysymcmd->nextdefsym > symcmd->nsyms) { ML_(symerr)(di, False, "Invalid Mach-O file (bad symbol table)."); goto fail; } syms = (struct NLIST *)(ii.macho_img + symcmd->symoff); strs = (UChar *)(ii.macho_img + symcmd->stroff); if (VG_(clo_verbosity) > 1) VG_(message)(Vg_DebugMsg, " reading syms from primary file (%d %d)\n", dysymcmd->nextdefsym, dysymcmd->nlocalsym ); /* Read candidate symbols into 'candSyms', so we can truncate overlapping ends and generally tidy up, before presenting them to ML_(addSym). */ candSyms = VG_(newXA)( ML_(dinfo_zalloc), "di.readmacho.candsyms.1", ML_(dinfo_free), sizeof(DiSym) ); vg_assert(candSyms); // extern symbols read_symtab(candSyms, di, syms + dysymcmd->iextdefsym, dysymcmd->nextdefsym, strs, symcmd->strsize); // static and private_extern symbols read_symtab(candSyms, di, syms + dysymcmd->ilocalsym, dysymcmd->nlocalsym, strs, symcmd->strsize); /* tidy up the cand syms -- trim overlapping ends. May resize candSyms. */ tidy_up_cand_syms( candSyms, di->trace_symtab ); /* and finally present them to ML_(addSym) */ nCandSyms = VG_(sizeXA)( candSyms ); for (i = 0; i < nCandSyms; i++) { DiSym* cand = (DiSym*) VG_(indexXA)( candSyms, i ); if (di->trace_symtab) VG_(printf)("nlist final: acquire avma %010lx-%010lx %s\n", cand->addr, cand->addr + cand->size - 1, cand->name ); ML_(addSym)( di, cand ); } VG_(deleteXA)( candSyms ); } /* If there's no UUID in the primary, don't even bother to try and read any DWARF, since we won't be able to verify it matches. Our policy is not to load debug info unless we can verify that it matches the primary. Just declare success at this point. And don't complain to the user, since that would cause us to complain on objects compiled without -g. (Some versions of XCode are observed to omit a UUID entry for object linked(?) without -g. Others don't appear to omit it.) */ if (!have_uuid) goto success; /* mmap the dSYM file to look for DWARF debug info. If successful, use the .macho_img and .macho_img_szB in iid. */ dsymfilename = find_separate_debug_file( di->filename ); /* Try to load it. */ if (dsymfilename) { Bool valid; if (VG_(clo_verbosity) > 1) VG_(message)(Vg_DebugMsg, " dSYM= %s\n", dsymfilename); ok = map_image_aboard( di, &iid, dsymfilename ); if (!ok) goto fail; /* check it has the right uuid. */ vg_assert(have_uuid); valid = iid.macho_img && iid.macho_img_szB > 0 && check_uuid_matches( (Addr)iid.macho_img, iid.macho_img_szB, uuid ); if (valid) goto read_the_dwarf; if (VG_(clo_verbosity) > 1) VG_(message)(Vg_DebugMsg, " dSYM does not have " "correct UUID (out of date?)\n"); } /* There was no dsym file, or it doesn't match. We'll have to try regenerating it, unless --dsymutil=no, in which case just complain instead. */ /* If this looks like a lib that we shouldn't run dsymutil on, just give up. (possible reasons: is system lib, or in /usr etc, or the dsym dir would not be writable by the user, or we're running as root) */ vg_assert(di->filename); if (is_systemish_library_name(di->filename)) goto success; if (!VG_(clo_dsymutil)) { if (VG_(clo_verbosity) == 1) { VG_(message)(Vg_DebugMsg, "%s:\n", di->filename); } if (VG_(clo_verbosity) > 0) VG_(message)(Vg_DebugMsg, "%sdSYM directory %s; consider using " "--dsymutil=yes\n", VG_(clo_verbosity) > 1 ? " " : "", dsymfilename ? "has wrong UUID" : "is missing"); goto success; } /* Run dsymutil */ { Int r; HChar* dsymutil = "/usr/bin/dsymutil "; HChar* cmd = ML_(dinfo_zalloc)( "di.readmacho.tmp1", VG_(strlen)(dsymutil) + VG_(strlen)(di->filename) + 30 /* misc */ ); VG_(strcpy)(cmd, dsymutil); if (0) VG_(strcat)(cmd, "--verbose "); VG_(strcat)(cmd, di->filename); VG_(message)(Vg_DebugMsg, "run: %s\n", cmd); r = VG_(system)( cmd ); if (r) VG_(message)(Vg_DebugMsg, "run: %s FAILED\n", dsymutil); ML_(dinfo_free)(cmd); dsymfilename = find_separate_debug_file(di->filename); } /* Try again to load it. */ if (dsymfilename) { Bool valid; if (VG_(clo_verbosity) > 1) VG_(message)(Vg_DebugMsg, " dsyms= %s\n", dsymfilename); ok = map_image_aboard( di, &iid, dsymfilename ); if (!ok) goto fail; /* check it has the right uuid. */ vg_assert(have_uuid); valid = iid.macho_img && iid.macho_img_szB > 0 && check_uuid_matches( (Addr)iid.macho_img, iid.macho_img_szB, uuid ); if (!valid) { if (VG_(clo_verbosity) > 0) { VG_(message)(Vg_DebugMsg, "WARNING: did not find expected UUID %02X%02X%02X%02X" "-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X" " in dSYM dir\n", (UInt)uuid[0], (UInt)uuid[1], (UInt)uuid[2], (UInt)uuid[3], (UInt)uuid[4], (UInt)uuid[5], (UInt)uuid[6], (UInt)uuid[7], (UInt)uuid[8], (UInt)uuid[9], (UInt)uuid[10], (UInt)uuid[11], (UInt)uuid[12], (UInt)uuid[13], (UInt)uuid[14], (UInt)uuid[15] ); VG_(message)(Vg_DebugMsg, "WARNING: for %s\n", di->filename); } unmap_image( &iid ); /* unmap_image zeroes the fields, so the following test makes sense. */ goto fail; } } /* Right. Finally we have our best try at the dwarf image, so go on to reading stuff out of it. */ read_the_dwarf: if (iid.macho_img && iid.macho_img_szB > 0) { UChar* debug_info_img = NULL; Word debug_info_sz; UChar* debug_abbv_img; Word debug_abbv_sz; UChar* debug_line_img; Word debug_line_sz; UChar* debug_str_img; Word debug_str_sz; UChar* debug_ranges_img; Word debug_ranges_sz; UChar* debug_loc_img; Word debug_loc_sz; UChar* debug_name_img; Word debug_name_sz; debug_info_img = getsectdata(iid.macho_img, iid.macho_img_szB, "__DWARF", "__debug_info", &debug_info_sz); debug_abbv_img = getsectdata(iid.macho_img, iid.macho_img_szB, "__DWARF", "__debug_abbrev", &debug_abbv_sz); debug_line_img = getsectdata(iid.macho_img, iid.macho_img_szB, "__DWARF", "__debug_line", &debug_line_sz); debug_str_img = getsectdata(iid.macho_img, iid.macho_img_szB, "__DWARF", "__debug_str", &debug_str_sz); debug_ranges_img = getsectdata(iid.macho_img, iid.macho_img_szB, "__DWARF", "__debug_ranges", &debug_ranges_sz); debug_loc_img = getsectdata(iid.macho_img, iid.macho_img_szB, "__DWARF", "__debug_loc", &debug_loc_sz); debug_name_img = getsectdata(iid.macho_img, iid.macho_img_szB, "__DWARF", "__debug_pubnames", &debug_name_sz); if (debug_info_img) { if (VG_(clo_verbosity) > 1) { if (0) VG_(message)(Vg_DebugMsg, "Reading dwarf3 for %s (%#lx) from %s" " (%ld %ld %ld %ld %ld %ld)\n", di->filename, di->text_avma, dsymfilename, debug_info_sz, debug_abbv_sz, debug_line_sz, debug_str_sz, debug_ranges_sz, debug_loc_sz ); VG_(message)(Vg_DebugMsg, " reading dwarf3 from dsyms file\n"); } /* The old reader: line numbers and unwind info only */ ML_(read_debuginfo_dwarf3) ( di, debug_info_img, debug_info_sz, debug_abbv_img, debug_abbv_sz, debug_line_img, debug_line_sz, debug_str_img, debug_str_sz ); /* The new reader: read the DIEs in .debug_info to acquire information on variable types and locations. But only if the tool asks for it, or the user requests it on the command line. */ if (VG_(needs).var_info /* the tool requires it */ || VG_(clo_read_var_info) /* the user asked for it */) { ML_(new_dwarf3_reader)( di, debug_info_img, debug_info_sz, debug_abbv_img, debug_abbv_sz, debug_line_img, debug_line_sz, debug_str_img, debug_str_sz, debug_ranges_img, debug_ranges_sz, debug_loc_img, debug_loc_sz ); } } } if (dsymfilename) ML_(dinfo_free)(dsymfilename); success: if (ii.img) unmap_image(&ii); if (iid.img) unmap_image(&iid); return True; /* NOTREACHED */ fail: ML_(symerr)(di, True, "Error reading Mach-O object."); if (ii.img) unmap_image(&ii); if (iid.img) unmap_image(&iid); return False; }
void *get_osx_section_end(const char *section) { unsigned long secsize; char *section_start = getsectdata("__DATA", section, &secsize); return get_real_address(section_start) + secsize; }
void *get_osx_section_start(const char *section) { unsigned long secsize; return get_real_address(getsectdata("__DATA", section, &secsize)); }
const char *find_system_image( const char *arg0, const char *dflt ) { static char temp[1024]; char *p; #ifdef __NeXT__ int n; if (getsectdata( "IMAGE", "system", &n )) { return "sect:IMAGE:system"; } #endif /* if the default is specified and exists, use it * * this is used by applications that supply their own * image */ if (dflt && os_file_exists_p(dflt)) return dflt; /* look in ~/lib/rs/$RSCHEME_VERSION/system.img */ if (os_getenv("HOME")) { strcpy( temp, os_getenv( "HOME" ) ); strcat( temp, "/lib/rs/" RSCHEME_VERSION "/system.img" ); if (os_file_exists_p(temp)) return temp; } /* look in [install]/resource/system.img */ strcpy( temp, rs_install_dir ); strcat( temp, "/resource/system.img" ); if (os_file_exists_p(temp)) return temp; /* If argv[0] is of the form foo/bin/blech then look for foo/resource/blech.img */ if ((p = strrchr(arg0,'/'))) { char *p2; strncpy( temp, arg0, p - arg0 ); temp[p - arg0] = 0; p2 = strrchr( temp, '/' ); if (p2) p2[1] = 0; strcat( temp, "resource/" ); strcat( temp, p+1 ); strcat( temp, ".img" ); } else strcpy( temp, "../resource/system.img" ); if (os_file_exists_p(temp)) return temp; return NULL; }