/// Load the interesting main binary symbols' addresses into /// MainBinarySymbolAddresses. void MachODebugMapParser::loadMainBinarySymbols( const MachOObjectFile &MainBinary) { section_iterator Section = MainBinary.section_end(); MainBinarySymbolAddresses.clear(); for (const auto &Sym : MainBinary.symbols()) { SymbolRef::Type Type = Sym.getType(); // Skip undefined and STAB entries. if ((Type & SymbolRef::ST_Debug) || (Type & SymbolRef::ST_Unknown)) continue; // The only symbols of interest are the global variables. These // are the only ones that need to be queried because the address // of common data won't be described in the debug map. All other // addresses should be fetched for the debug map. if (!(Sym.getFlags() & SymbolRef::SF_Global)) continue; ErrorOr<section_iterator> SectionOrErr = Sym.getSection(); if (!SectionOrErr) continue; Section = *SectionOrErr; if (Section == MainBinary.section_end() || Section->isText()) continue; uint64_t Addr = Sym.getValue(); ErrorOr<StringRef> NameOrErr = Sym.getName(); if (!NameOrErr) continue; StringRef Name = *NameOrErr; if (Name.size() == 0 || Name[0] == '\0') continue; MainBinarySymbolAddresses[Name] = Addr; } }
static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) { DataRefImpl Symb = I->getRawDataRefImpl(); uint8_t NType = getNType(Obj, Symb); switch (NType & MachO::N_TYPE) { case MachO::N_ABS: return 's'; case MachO::N_INDR: return 'i'; case MachO::N_SECT: { section_iterator Sec = Obj.section_end(); Obj.getSymbolSection(Symb, Sec); DataRefImpl Ref = Sec->getRawDataRefImpl(); StringRef SectionName; Obj.getSectionName(Ref, SectionName); StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref); if (SegmentName == "__TEXT" && SectionName == "__text") return 't'; else if (SegmentName == "__DATA" && SectionName == "__data") return 'd'; else if (SegmentName == "__DATA" && SectionName == "__bss") return 'b'; else return 's'; } } return '?'; }
/// Load the interesting main binary symbols' addresses into /// MainBinarySymbolAddresses. void MachODebugMapParser::loadMainBinarySymbols( const MachOObjectFile &MainBinary) { section_iterator Section = MainBinary.section_end(); MainBinarySymbolAddresses.clear(); for (const auto &Sym : MainBinary.symbols()) { Expected<SymbolRef::Type> TypeOrErr = Sym.getType(); if (!TypeOrErr) { // TODO: Actually report errors helpfully. consumeError(TypeOrErr.takeError()); continue; } SymbolRef::Type Type = *TypeOrErr; // Skip undefined and STAB entries. if ((Type == SymbolRef::ST_Debug) || (Type == SymbolRef::ST_Unknown)) continue; // The only symbols of interest are the global variables. These // are the only ones that need to be queried because the address // of common data won't be described in the debug map. All other // addresses should be fetched for the debug map. uint8_t SymType = MainBinary.getSymbolTableEntry(Sym.getRawDataRefImpl()).n_type; if (!(SymType & (MachO::N_EXT | MachO::N_PEXT))) continue; Expected<section_iterator> SectionOrErr = Sym.getSection(); if (!SectionOrErr) { // TODO: Actually report errors helpfully. consumeError(SectionOrErr.takeError()); continue; } Section = *SectionOrErr; if (Section == MainBinary.section_end() || Section->isText()) continue; uint64_t Addr = Sym.getValue(); Expected<StringRef> NameOrErr = Sym.getName(); if (!NameOrErr) { // TODO: Actually report errors helpfully. consumeError(NameOrErr.takeError()); continue; } StringRef Name = *NameOrErr; if (Name.size() == 0 || Name[0] == '\0') continue; MainBinarySymbolAddresses[Name] = Addr; } }
section_iterator RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj, uint64_t Addr) { section_iterator SI = Obj.section_begin(); section_iterator SE = Obj.section_end(); for (; SI != SE; ++SI) { uint64_t SAddr = SI->getAddress(); uint64_t SSize = SI->getSize(); if ((Addr >= SAddr) && (Addr < SAddr + SSize)) return SI; } return SE; }