diff --git a/include/revng/Model/Importer/Binary/BinaryImporterHelper.h b/include/revng/Model/Importer/Binary/BinaryImporterHelper.h index 8f9e82aac..0455ae7da 100644 --- a/include/revng/Model/Importer/Binary/BinaryImporterHelper.h +++ b/include/revng/Model/Importer/Binary/BinaryImporterHelper.h @@ -94,65 +94,37 @@ public: return &Binary->Functions()[Address]; } - /// Similar to registerFunctionEntry but if another function at the same - /// address already exists, return that one. This is necessary in certain - /// situations where the raw address is available but it's not known its type - /// (e.g., Thumb vs regular ARM). - model::Function *matchFunctionEntry(const MetaAddress &Address) { - revng_assert(Address.isValid()); - - if (not isExecutable(Address)) { - report("match Function", Address); - return nullptr; - } - - llvm::SmallVector Candidates; - Candidates.push_back(Address); - + /// \return the MetaAddress of a function at the relocated address \p Address, + /// possibly already existing in the model. + MetaAddress + matchFunctionEntry(uint64_t Address, + model::Architecture::Values Architecture) const { using namespace MetaAddressType; - for (auto CodeType : archCodeTypes(arch(Address.type()))) { - if (CodeType == Address.type()) + llvm::SmallVector Candidates; + + auto Primary = MetaAddress::fromPC(Architecture, Address); + if (Primary.isValid()) + Candidates.push_back(Primary); + + uint64_t BareAddress = Primary.isValid() ? Primary.address() : Address; + for (auto CodeType : archCodeTypes(Architecture)) { + + if (Primary.isValid() and CodeType == Primary.type()) continue; - auto NewAddress = Address.replaceType(CodeType); - if (NewAddress.isValid()) - Candidates.push_back(std::move(NewAddress)); + MetaAddress Alternative(BareAddress, CodeType); + if (Alternative.isValid()) + Candidates.push_back(Alternative); } - unsigned Matches = 0; - auto EndIt = Binary->Functions().end(); - auto ResultIt = EndIt; - for (const auto &Candidate : Candidates) { - auto MatchIt = Binary->Functions().find(Candidate); - if (MatchIt != EndIt) { - ++Matches; - if (ResultIt == EndIt) { - // Take the first match - ResultIt = MatchIt; - } - } - } + if (Candidates.empty()) + return MetaAddress::invalid(); - if (ResultIt == EndIt) { - revng_log(Logger, - "Warning: no match for function at " - << Address.toString() << ". Creating it despite this."); - return &Binary->Functions()[Address]; - } else if (Matches == 1 and ResultIt->Entry() != Address) { - revng_log(Logger, - "Matching " << ResultIt->Entry().toString() << " for " - << Address.toString()); - return &*ResultIt; - } else if (Matches > 1 and ResultIt->Entry() != Address) { - revng_log(Logger, - "Warning: multiple matches for " - << Address.toString() << ". Returning " - << ResultIt->Entry().toString() << "."); - return &*ResultIt; - } else { - // We have a single match of the given address - return &*ResultIt; - } + for (const auto &Candidate : Candidates) + if (Binary->Functions().contains(Candidate)) + return Candidate; + + return Candidates.front(); } void setEntryPoint(const MetaAddress &Address) { @@ -170,7 +142,7 @@ public: static uint64_t u64(uint64_t Value) { return Value; } private: - void report(const char *Action, const MetaAddress &Address) { + void report(const char *Action, const MetaAddress &Address) const { revng_log(Logger, "Cannot " << Action << " " << Address.toString() << " since it's not in an executable segment."); diff --git a/include/revng/Model/Importer/DebugInfo/DwarfImporter.h b/include/revng/Model/Importer/DebugInfo/DwarfImporter.h index d7152f297..fa2f57fb3 100644 --- a/include/revng/Model/Importer/DebugInfo/DwarfImporter.h +++ b/include/revng/Model/Importer/DebugInfo/DwarfImporter.h @@ -9,27 +9,28 @@ #include "revng/Model/Binary.h" #include "revng/Model/Importer/Binary/BinaryDescriptor.h" #include "revng/Support/Configuration.h" +#include "revng/Support/LDDTree.h" struct ImporterOptions; class DwarfImporter { -public: - using AddressWhitelist = std::set; - private: TupleTree &Model; std::vector LoadedFiles; using DwarfID = std::pair; std::map DwarfToModel; - const AddressWhitelist *FunctionWhitelist = nullptr; + + /// When unset the importer accepts every subprogram; otherwise only those + /// whose MetaAddress appears in the map are kept. Keys carry the code type + /// (Code_arm vs Code_arm_thumb, etc.), so the lookup is exact and + /// architecture-aware. + std::optional> WhitelistByAddress; public: DwarfImporter(TupleTree &Model, - const std::optional &FunctionWhitelist) : - Model(Model), - FunctionWhitelist(FunctionWhitelist.has_value() ? - &*FunctionWhitelist : - static_cast(nullptr)) {} + std::optional> + Whitelist) : + Model(Model), WhitelistByAddress(std::move(Whitelist)) {} public: model::UpcastableType findType(DwarfID ID) { @@ -46,11 +47,21 @@ public: TupleTree &getModel() { return Model; } - bool isFunctionAllowed(uint64_t Address) const { - if (FunctionWhitelist == nullptr) + bool isFunctionAllowed(const MetaAddress &Address) const { + if (not WhitelistByAddress.has_value()) return true; - return FunctionWhitelist->contains(Address); + return WhitelistByAddress->contains(Address); + } + + bool isIfunc(const MetaAddress &Address) const { + if (not WhitelistByAddress.has_value()) + return false; + + auto It = WhitelistByAddress->find(Address); + if (It == WhitelistByAddress->end()) + return false; + return It->second.IsIfunc; } public: diff --git a/include/revng/Model/Importer/DebugInfo/PDBImporter.h b/include/revng/Model/Importer/DebugInfo/PDBImporter.h index f5e2eedeb..68e9f07de 100644 --- a/include/revng/Model/Importer/DebugInfo/PDBImporter.h +++ b/include/revng/Model/Importer/DebugInfo/PDBImporter.h @@ -17,31 +17,29 @@ #include "revng/Model/Importer/Binary/BinaryDescriptor.h" #include "revng/Model/Importer/Binary/BinaryImporterHelper.h" #include "revng/Support/Configuration.h" +#include "revng/Support/LDDTree.h" struct ImporterOptions; class PDBImporter : public BinaryImporterHelper { -public: - using AddressWhitelist = std::set; - private: MetaAddress ImageBase; llvm::pdb::PDBFile *ThePDBFile = nullptr; llvm::pdb::NativeSession *TheNativeSession = nullptr; std::unique_ptr Session; std::optional ExpectedGUID; - const AddressWhitelist *FunctionWhitelist = nullptr; + std::optional> WhitelistByAddress; public: PDBImporter(TupleTree &Model, const MetaAddress &ImageBase, - const std::optional &FunctionWhitelist); + std::optional> Whitelist); PDBImporter(TupleTree &Model, - const std::optional &FunctionWhitelist) : + std::optional> Whitelist) : PDBImporter(Model, MetaAddress::fromGeneric(Model->Architecture(), 0), - FunctionWhitelist) {} + std::move(Whitelist)) {} TupleTree &getModel() { return Binary; } const MetaAddress &getBaseAddress() { return ImageBase; } @@ -56,10 +54,10 @@ public: bool loadDataFromPDB(llvm::StringRef PDBFileName); - bool isFunctionAllowed(uint64_t Address) const { - if (FunctionWhitelist == nullptr) + bool isFunctionAllowed(const MetaAddress &Address) const { + if (not WhitelistByAddress.has_value()) return true; - return FunctionWhitelist->contains(Address); + return WhitelistByAddress->contains(Address); } }; diff --git a/include/revng/Support/LDDTree.h b/include/revng/Support/LDDTree.h index 5a64acf96..db7abf9fb 100644 --- a/include/revng/Support/LDDTree.h +++ b/include/revng/Support/LDDTree.h @@ -21,6 +21,7 @@ #include "revng/Model/OperatingSystem.h" #include "revng/Support/Configuration.h" #include "revng/Support/Debug.h" +#include "revng/Support/MetaAddress.h" namespace revng { class RootEntry; @@ -34,7 +35,14 @@ concept IsObjectFile = std::derived_from; class LDDTree { public: using SymbolSet = std::set; - using SymbolAddressMap = std::map; + + struct Symbol { + MetaAddress Address = MetaAddress::invalid(); + bool IsIfunc = false; + }; + + using SymbolMap = std::map; + class DependencyFile; class Dependency; @@ -217,14 +225,14 @@ public: class LDDTree::Dependency : public DependencyFile { private: /// Subset of the requested symbols that are provided by this library. - SymbolAddressMap ProvidedSymbols; + SymbolMap ProvidedSymbols; /// Identifier the library requesting this. std::string RequestedBy; public: Dependency(DependencyFile &&TheDependencyFile, - SymbolAddressMap ProvidedSymbols, + SymbolMap ProvidedSymbols, std::string RequestedBy) : DependencyFile(std::move(TheDependencyFile)), ProvidedSymbols(std::move(ProvidedSymbols)), @@ -252,9 +260,9 @@ public: Stream << " none\n"; } else { Stream << "\n"; - for (auto &[Name, Address] : ProvidedSymbols) - Stream << Prefix << " " << Name << " at 0x" - << llvm::utohexstr(Address, true) << "\n"; + for (auto &[Name, Symbol] : ProvidedSymbols) + Stream << Prefix << " " << Name << " at " << Symbol.Address.toString() + << (Symbol.IsIfunc ? " (IFUNC)" : "") << "\n"; } } }; diff --git a/lib/Model/Importer/Binary/ELFImporter.cpp b/lib/Model/Importer/Binary/ELFImporter.cpp index 18fb67a96..b1ee09c1c 100644 --- a/lib/Model/Importer/Binary/ELFImporter.cpp +++ b/lib/Model/Importer/Binary/ELFImporter.cpp @@ -366,7 +366,7 @@ Error ELFImporter::import(const ImporterOptions &Options) { Task.advance("Parse debug info", true); { auto ImportLogger = importLogger(TheBinary.canonicalPath()); - DwarfImporter Importer(Model, std::nullopt); + DwarfImporter Importer(Model, SymbolsByAddress); Importer.import(Root, TheBinary, AdjustedOptions); } @@ -717,6 +717,21 @@ uint64_t ELFImporter::gnuHashSymbolCount() const { return FirstSymbolIndex + *Index + 1; } +template +void ELFImporter::recordSymbol(const MetaAddress &Address, + bool IsIfunc) { + revng_assert(Address.isValid()); + auto Inserted = SymbolsByAddress + .try_emplace(Address, + LDDTree::Symbol{ .Address = Address, + .IsIfunc = IsIfunc }) + .second; + if (not Inserted) { + revng_log(ELFImporterLog, + "Duplicate symbol entry at " << Address.toString() << " ignored"); + } +} + // TODO: we might want to return an error from here so we can propagate it // further up. template @@ -771,6 +786,8 @@ void ELFImporter::parseSymbols(object::ELFFile &TheELF, if (IsCode) { revng_assert(Address.isValid()); + recordSymbol(Address, Symbol.getType() == ELF::STT_GNU_IFUNC); + if (Model->Functions().tryGet(Address) == nullptr) { auto *Function = registerFunctionEntry(Address); if (Function != nullptr and MaybeName and MaybeName->size() > 0) { @@ -950,9 +967,12 @@ void ELFImporter::parseDynamicSymbol(Elf_Sym_Impl &Symbol, if (IsCode) { Address = relocate(fromPC(Symbol.st_value)); + revng_assert(Address.isValid()); + + recordSymbol(Address, Symbol.getType() == ELF::STT_GNU_IFUNC); + // TODO: record model::Function::IsDynamic = true model::Function *Function = nullptr; - revng_assert(Address.isValid()); auto It = Model->Functions().find(Address); if (It != Model->Functions().end()) { Function = &*It; @@ -1459,10 +1479,8 @@ Error importELF(TupleTree &Model, return Importer->import(Options); } -std::vector> +LDDTree::SymbolMap elfExportedSymbols(const llvm::object::ELFObjectFileBase &ObjectFile) { - std::vector> Result; - TupleTree Model; auto Architecture = model::Architecture::fromLLVMArchitecture(ObjectFile .makeTriple() @@ -1471,7 +1489,7 @@ elfExportedSymbols(const llvm::object::ELFObjectFileBase &ObjectFile) { revng_log(ELFImporterLog, "Cannot derive architecture for the ELF, skipping its " "exported symbols"); - return Result; + return {}; } Model->Architecture() = Architecture; @@ -1490,12 +1508,29 @@ elfExportedSymbols(const llvm::object::ELFObjectFileBase &ObjectFile) { if (auto Error = Importer->parseDynamicSymbolsOnly()) { revng_log(ELFImporterLog, "parseDynamicSymbolsOnly failed: " << Error); consumeError(std::move(Error)); - return Result; + return {}; } - for (model::Function &Function : Model->Functions()) - for (const auto &Name : Function.ExportedNames()) - Result.push_back({ Name, Function.Entry().asPC() }); + // Project SymbolsByAddress through `ExportedNames()` to get the name-keyed + // dynamic-exports view. Function.Entry() already carries the typed + // MetaAddress, so the lookup against SymbolsByAddress is exact. + LDDTree::SymbolMap Result; + for (model::Function &Function : Model->Functions()) { + MetaAddress Address = Function.Entry(); + auto It = Importer->SymbolsByAddress.find(Address); + auto End = Importer->SymbolsByAddress.end(); + bool IsIfunc = It != End and It->second.IsIfunc; + + for (const auto &Name : Function.ExportedNames()) { + LDDTree::Symbol Symbol{ .Address = Address, .IsIfunc = IsIfunc }; + auto [Slot, Inserted] = Result.try_emplace(Name, Symbol); + if (not Inserted) { + // TODO: this should probably be invalid + revng_log(ELFImporterLog, + "Duplicate exported symbol " << Name << " ignored"); + } + } + } return Result; } diff --git a/lib/Model/Importer/Binary/ELFImporter.h b/lib/Model/Importer/Binary/ELFImporter.h index 453a87703..49837123b 100644 --- a/lib/Model/Importer/Binary/ELFImporter.h +++ b/lib/Model/Importer/Binary/ELFImporter.h @@ -9,6 +9,7 @@ #include "revng/Model/Importer/Binary/BinaryImporterHelper.h" #include "revng/Model/Importer/Binary/Options.h" #include "revng/Model/RawBinaryView.h" +#include "revng/Support/LDDTree.h" #include "revng/Support/MetaAddress.h" #include "DwarfReader.h" @@ -52,6 +53,12 @@ public: }; class ELFImporterBase { +public: + /// Every defined function symbol encountered while parsing the static + /// and/or dynamic symbol tables, keyed by the relocated MetaAddress that + /// matches the function's entry in `Model->Functions()`. + std::map SymbolsByAddress; + public: virtual ~ELFImporterBase() = default; @@ -161,6 +168,9 @@ private: void parseDynamicSymbol(llvm::object::Elf_Sym_Impl &Symbol, llvm::StringRef Dynstr); + /// Record a defined code symbol in SymbolsByAddress, logging duplicates. + void recordSymbol(const MetaAddress &Address, bool IsIfunc); + protected: template using SmallVectorImpl = llvm::SmallVectorImpl; @@ -186,5 +196,5 @@ protected: /// Enumerate the function symbols exported through the dynamic symbol table /// of an ELF binary -std::vector> +LDDTree::SymbolMap elfExportedSymbols(const llvm::object::ELFObjectFileBase &ObjectFile); diff --git a/lib/Model/Importer/Binary/ELFLDDTree.cpp b/lib/Model/Importer/Binary/ELFLDDTree.cpp index 9f11c63a7..5794a3cc5 100644 --- a/lib/Model/Importer/Binary/ELFLDDTree.cpp +++ b/lib/Model/Importer/Binary/ELFLDDTree.cpp @@ -116,8 +116,7 @@ public: using QueueEntry = typename Queue::Entry; public: - static std::vector> - getExportedSymbols(const T &ELFObjectFile) { + static LDDTree::SymbolMap getExportedSymbols(const T &ELFObjectFile) { return elfExportedSymbols(ELFObjectFile); } diff --git a/lib/Model/Importer/Binary/FindMissingTypes.h b/lib/Model/Importer/Binary/FindMissingTypes.h index d2637ebc2..3d69a9d33 100644 --- a/lib/Model/Importer/Binary/FindMissingTypes.h +++ b/lib/Model/Importer/Binary/FindMissingTypes.h @@ -82,13 +82,13 @@ void findMissingTypes(LDDTree &Dependencies, Dependency.fullPathForExternalTools(), BinaryReference); - std::optional> RequestedFunctions; - RequestedFunctions.emplace(); - for (const auto &[Name, Address] : Dependency.providedSymbols()) { - RequestedFunctions->insert(Address); + std::optional> Whitelist; + Whitelist.emplace(); + for (const auto &[Name, Symbol] : Dependency.providedSymbols()) { // TODO: usually this reponsability is demanded to BinaryImporterHelper - auto FunctionAddress = MetaAddress::fromPC(Binary->Architecture(), - Options.BaseAddress + Address); + auto FunctionAddress = Symbol.Address + Options.BaseAddress; + (*Whitelist)[FunctionAddress] = Symbol; + auto &Function = DependencyModel->Functions()[FunctionAddress]; Function.Name() = Name; Function.ExportedNames().insert(Name); @@ -97,7 +97,7 @@ void findMissingTypes(LDDTree &Dependencies, ImportLogger ImportLogger(DependencyModel, Logger, TheBinary.canonicalPath()); - ImporterType Importer(DependencyModel, RequestedFunctions); + ImporterType Importer(DependencyModel, std::move(Whitelist)); Importer.import(Dependencies.Root, TheBinary, AdjustedOptions); revng_log(Logger, DependencyName << " imported successfully"); diff --git a/lib/Model/Importer/Binary/LDDTreeObjectFileTraits.h b/lib/Model/Importer/Binary/LDDTreeObjectFileTraits.h index 4e276f4b7..a0f55a8bc 100644 --- a/lib/Model/Importer/Binary/LDDTreeObjectFileTraits.h +++ b/lib/Model/Importer/Binary/LDDTreeObjectFileTraits.h @@ -74,9 +74,7 @@ concept LDDTreeObjectFileTraitsConcept = requires(T Trait, &Root) { typename T::ResolutionInfo; - { - T::getExportedSymbols(Object) - } -> std::same_as>>; + { T::getExportedSymbols(Object) } -> std::same_as; { T::getDependencies(Root, String, String, Object) @@ -220,15 +218,15 @@ const LDDTree LDDTree::fromPath(const revng::RootEntry &Root, continue; } - LDDTree::SymbolAddressMap ProvidedSymbols; + LDDTree::SymbolMap ProvidedSymbols; // Purge from MissingSymbols those exported if (SymbolsRequested) { - for (auto &[SymbolName, SymbolAddress] : + for (auto &[SymbolName, SymbolData] : ObjectFileTraits::getExportedSymbols(*Binary)) { if (Result.MissingSymbols->contains(SymbolName)) { Result.MissingSymbols->erase(SymbolName); - ProvidedSymbols[SymbolName] = SymbolAddress; + ProvidedSymbols[SymbolName] = SymbolData; } } } diff --git a/lib/Model/Importer/Binary/PECOFFLDDTree.cpp b/lib/Model/Importer/Binary/PECOFFLDDTree.cpp index 8185d1402..1d20c170a 100644 --- a/lib/Model/Importer/Binary/PECOFFLDDTree.cpp +++ b/lib/Model/Importer/Binary/PECOFFLDDTree.cpp @@ -34,9 +34,14 @@ public: using QueueEntry = typename Queue::Entry; public: - static std::vector> + static LDDTree::SymbolMap getExportedSymbols(const COFFObjectFile &COFFObjectFile) { - std::vector> Result; + LDDTree::SymbolMap Result; + + auto FromLLVMArchitecture = model::Architecture::fromLLVMArchitecture; + auto Architecture = FromLLVMArchitecture(COFFObjectFile.getArch()); + if (Architecture == model::Architecture::Invalid) + return Result; for (const ExportDirectoryEntryRef &Entry : COFFObjectFile.export_directories()) { @@ -56,7 +61,11 @@ public: continue; } - Result.push_back({ SymbolName.str(), RVA }); + MetaAddress Address = MetaAddress::fromPC(Architecture, RVA); + if (not Address.isValid()) + continue; + + Result[SymbolName.str()] = LDDTree::Symbol{ .Address = Address }; } return Result; diff --git a/lib/Model/Importer/DebugInfo/DwarfToModelConverter.cpp b/lib/Model/Importer/DebugInfo/DwarfToModelConverter.cpp index 9ba99d12b..efc754a8c 100644 --- a/lib/Model/Importer/DebugInfo/DwarfToModelConverter.cpp +++ b/lib/Model/Importer/DebugInfo/DwarfToModelConverter.cpp @@ -861,6 +861,33 @@ DwarfToModelConverter::getSubprogramPrototype(const DWARFDie &InitialDie) { return Model->recordNewType(std::move(NewType)).second; } +/// Substitute a glibc IFUNC resolver prototype (no args, returns a pointer +/// to a CABIFunctionDefinition) with the pointee prototype. +static model::UpcastableType +unwrapIfuncResolverPrototype(model::Binary &Binary, + const MetaAddress &Address, + model::UpcastableType Prototype) { + auto *Definition = Prototype->tryGetAsDefinition(); + auto *Resolver = dyn_cast_or_null(Definition); + if (Resolver == nullptr or not Resolver->Arguments().empty() + or Resolver->ReturnType().isEmpty() + or not Resolver->ReturnType()->isPointer()) + return Prototype; + + auto *PointeeDefinition = Resolver->ReturnType() + ->getPointee() + .tryGetAsDefinition(); + if (not isa_and_nonnull(PointeeDefinition)) + return Prototype; + + revng_log(DILogger, + "Ifunc resolver at " << Address.toString() + << ": substituting resolver prototype " + << Resolver->ID() << " with pointee CABI " + << PointeeDefinition->ID()); + return Binary.makeType(PointeeDefinition->key()); +} + void DwarfToModelConverter::createFunctions() { revng_log(DILogger, "createFunctions"); LoggerIndent Indent(DILogger); @@ -879,8 +906,13 @@ void DwarfToModelConverter::createFunctions() { if (auto MaybeLowPC = getAddress(Die)) { // TODO: do a proper check to see if it's in a valid segment if (*MaybeLowPC != 0) { - if (Importer.isFunctionAllowed(*MaybeLowPC)) { - LowPC = relocate(fromPC(*MaybeLowPC)); + // Relocate the raw DWARF address first, then let matchFunctionEntry + // pick the code type that matches the model. + uint64_t Relocated = relocate(*MaybeLowPC).address(); + MetaAddress Match = matchFunctionEntry(Relocated, + Model->Architecture()); + if (Match.isValid() and Importer.isFunctionAllowed(Match)) { + LowPC = Match; } else { revng_log(DILogger, "Ignoring disallowed function at 0x" @@ -903,46 +935,44 @@ void DwarfToModelConverter::createFunctions() { << LowPC.toString() << " and name \"" << SymbolName << "\""); - // Get/create the local function - // Note: here we use matchFunctionEntry because, just being fed the - // DWARF, we don't have enough information to determine whether this - // function is regular ARM or is Thumb. - // matchFunctionEntry relies on previously available functions to - // determine this. DwarfToModelConverter should not use without - // processing ELF symbols first. - // Newer DWARF versions have DW_LNS_set_isa, but currently we can't rely - // on that. - if (auto *Function = matchFunctionEntry(LowPC)) { + // Use the existing model::Function or create a new one at LowPC. + auto &Function = Model->Functions()[LowPC]; - if (Prototype.isEmpty()) { - revng_log(DILogger, "Can't get the prototype"); - } else if (not Function->prototype()) { - revng_log(DILogger, - "Assigning prototype " - << Prototype->tryGetAsDefinition()->ID()); - Function->Prototype() = std::move(Prototype); + if (Prototype.isEmpty()) { + revng_log(DILogger, "Can't get the prototype"); + } else if (not Function.prototype()) { + // For STT_GNU_IFUNC the DWARF describes the resolver, not the + // resolved function; unwrap it. + if (Importer.isIfunc(LowPC)) + Prototype = unwrapIfuncResolverPrototype(*Model, + LowPC, + std::move(Prototype)); + + revng_log(DILogger, + "Assigning prototype " + << Prototype->tryGetAsDefinition()->ID()); + Function.Prototype() = std::move(Prototype); + } else { + revng_log(DILogger, + "Function already has a prototype, not setting it."); + } + + if (SymbolName.size() != 0) { + // Note: DWARF support + if (Function.Name().empty()) { + Function.Name() = SymbolName; } else { revng_log(DILogger, - "Function already has a prototype, not setting it."); + "Function already has a name: " << Function.Name() + << ". Not updating " + "it."); } - if (SymbolName.size() != 0) { - // Note: DWARF support - if (Function->Name().empty()) { - Function->Name() = SymbolName; - } else { - revng_log(DILogger, - "Function already has a name: " << Function->Name() - << ". Not updating " - "it."); - } - - Function->ExportedNames().insert(SymbolName); - } - - if (isNoReturn(*CU.get(), Die)) - Function->Attributes().insert(model::FunctionAttribute::NoReturn); + Function.ExportedNames().insert(SymbolName); } + + if (isNoReturn(*CU.get(), Die)) + Function.Attributes().insert(model::FunctionAttribute::NoReturn); } else if (not SymbolName.empty() and DynamicFunctions.contains(SymbolName)) { // It's a dynamic function diff --git a/lib/Model/Importer/DebugInfo/PDBImporter.cpp b/lib/Model/Importer/DebugInfo/PDBImporter.cpp index a031d4cb1..a93eda189 100644 --- a/lib/Model/Importer/DebugInfo/PDBImporter.cpp +++ b/lib/Model/Importer/DebugInfo/PDBImporter.cpp @@ -32,15 +32,13 @@ using namespace llvm::pdb; PDBImporter::PDBImporter(TupleTree &Model, const MetaAddress &ImageBase, - const std::optional - &FunctionWhitelist) : + std::optional> + Whitelist) : BinaryImporterHelper(Model, ImageBase.isValid() ? ImageBase.address() : 0, Log), ImageBase(ImageBase), - FunctionWhitelist(FunctionWhitelist.has_value() ? - &*FunctionWhitelist : - static_cast(nullptr)) { + WhitelistByAddress(std::move(Whitelist)) { // When we import debug info, we assume we already have parsed Segments processSegments(); diff --git a/lib/Model/Importer/DebugInfo/PDBImporterImpl.cpp b/lib/Model/Importer/DebugInfo/PDBImporterImpl.cpp index 7ecedff04..8f670e313 100644 --- a/lib/Model/Importer/DebugInfo/PDBImporterImpl.cpp +++ b/lib/Model/Importer/DebugInfo/PDBImporterImpl.cpp @@ -693,15 +693,16 @@ void PDBImporterImpl::handleProcedureSymbol(ProcSym &Procedure) { Procedure .CodeOffset); - if (not Importer.isFunctionAllowed(FunctionVirtualAddress)) { - revng_log(Log, "Ignoring disallowed function"); - return; - } - // Relocate the symbol. MetaAddress FunctionAddress = Importer.toPC(Importer.getBaseAddress() + FunctionVirtualAddress); + if (not FunctionAddress.isValid() + or not Importer.isFunctionAllowed(FunctionAddress)) { + revng_log(Log, "Ignoring disallowed function"); + return; + } + if (not Model->Functions().contains(FunctionAddress)) { if (auto *Function = Importer.registerFunctionEntry(FunctionAddress)) { revng_log(Log, "New function registered");