/// Interpret the STAB entries to fill the DebugMap. void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex, uint8_t Type, uint8_t SectionIndex, uint16_t Flags, uint64_t Value) { if (!(Type & MachO::N_STAB)) return; const char *Name = &MainBinaryStrings.data()[StringIndex]; // An N_OSO entry represents the start of a new object file description. if (Type == MachO::N_OSO) { sys::TimeValue Timestamp; Timestamp.fromEpochTime(Value); return switchToNewDebugMapObject(Name, Timestamp); } // If the last N_OSO object file wasn't found, // CurrentDebugMapObject will be null. Do not update anything // until we find the next valid N_OSO entry. if (!CurrentDebugMapObject) return; uint32_t Size = 0; switch (Type) { case MachO::N_GSYM: // This is a global variable. We need to query the main binary // symbol table to find its address as it might not be in the // debug map (for common symbols). Value = getMainBinarySymbolAddress(Name); break; case MachO::N_FUN: // Functions are scopes in STABS. They have an end marker that // contains the function size. if (Name[0] == '\0') { Size = Value; Value = CurrentFunctionAddress; Name = CurrentFunctionName; break; } else { CurrentFunctionName = Name; CurrentFunctionAddress = Value; return; } case MachO::N_STSYM: break; default: return; } auto ObjectSymIt = CurrentObjectAddresses.find(Name); if (ObjectSymIt == CurrentObjectAddresses.end()) return Warning("could not find object file symbol for symbol " + Twine(Name)); if (!CurrentDebugMapObject->addSymbol(Name, ObjectSymIt->getValue(), Value, Size)) return Warning(Twine("failed to insert symbol '") + Name + "' in the debug map."); }
/// Load the current object file symbols into CurrentObjectAddresses. void MachODebugMapParser::loadCurrentObjectFileSymbols( const object::MachOObjectFile &Obj) { CurrentObjectAddresses.clear(); for (auto Sym : Obj.symbols()) { StringRef Name; uint64_t Addr = UnknownAddressOrSize; SymbolRef::Type Type; StringRef SecName; // Undefined symbols won't have an address, but we still want // them, because they might be referenced in the debug information. Sym.getAddress(Addr); object::section_iterator Section = Obj.section_end(); if (!Sym.getSection(Section) && Section != Obj.section_end()) Section->getName(SecName); if (Sym.getName(Name) || Name.empty() || Sym.getType(Type) || Type == SymbolRef::ST_Other) continue; CurrentObjectAddresses.insert(std::make_pair(Name, std::make_pair(Addr, SecName))); uint32_t Flags; Flags = Sym.getFlags(); uint64_t Value; // FIXME: We put every symbol in the debug map, because of the // behavior expected from lookupObjectAddress. Value = getMainBinarySymbolAddress(Name); // Symbols with no known address on either side are of absolutely // no use. if (Addr != UnknownAddressOrSize || Value != UnknownAddressOrSize) CurrentDebugMapObject->addSymbol(Name, Addr, Value, 0, SecName, true); } }