bool NativeExeSymbol::hasPrivateSymbols() const { auto Dbi = File.getPDBDbiStream(); if (Dbi) return !Dbi->isStripped(); consumeError(Dbi.takeError()); return false; }
ErrorOr<std::vector<MemoryBufferRef>> BinaryHolder::MapArchiveAndGetMemberBuffers( StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) { StringRef ArchiveFilename = Filename.substr(0, Filename.find('(')); auto ErrOrBuff = MemoryBuffer::getFileOrSTDIN(ArchiveFilename); if (auto Err = ErrOrBuff.getError()) return Err; if (Verbose) outs() << "\topened new archive '" << ArchiveFilename << "'\n"; changeBackingMemoryBuffer(std::move(*ErrOrBuff)); std::vector<MemoryBufferRef> ArchiveBuffers; auto ErrOrFat = object::MachOUniversalBinary::create( CurrentMemoryBuffer->getMemBufferRef()); if (!ErrOrFat) { consumeError(ErrOrFat.takeError()); // Not a fat binary must be a standard one. ArchiveBuffers.push_back(CurrentMemoryBuffer->getMemBufferRef()); } else { CurrentFatBinary = std::move(*ErrOrFat); CurrentFatBinaryName = ArchiveFilename; ArchiveBuffers = getMachOFatMemoryBuffers( CurrentFatBinaryName, *CurrentMemoryBuffer, *CurrentFatBinary); } for (auto MemRef : ArchiveBuffers) { auto ErrOrArchive = object::Archive::create(MemRef); if (!ErrOrArchive) return errorToErrorCode(ErrOrArchive.takeError()); CurrentArchives.push_back(std::move(*ErrOrArchive)); } return GetArchiveMemberBuffers(Filename, Timestamp); }
PDB_UniqueId NativeExeSymbol::getGuid() const { auto IS = File.getPDBInfoStream(); if (IS) return IS->getGuid(); consumeError(IS.takeError()); return PDB_UniqueId{{0}}; }
bool NativeExeSymbol::hasCTypes() const { auto Dbi = File.getPDBDbiStream(); if (Dbi) return Dbi->hasCTypes(); consumeError(Dbi.takeError()); return false; }
static Expected<StringRef> getDynamicStrTab(const ELFFile<ELFT> *Elf) { auto DynamicEntriesOrError = Elf->dynamicEntries(); if (!DynamicEntriesOrError) return DynamicEntriesOrError.takeError(); for (const typename ELFT::Dyn &Dyn : *DynamicEntriesOrError) { if (Dyn.d_tag == ELF::DT_STRTAB) { auto MappedAddrOrError = Elf->toMappedAddr(Dyn.getPtr()); if (!MappedAddrOrError) consumeError(MappedAddrOrError.takeError()); return StringRef(reinterpret_cast<const char *>(*MappedAddrOrError)); } } // If the dynamic segment is not present, we fall back on the sections. auto SectionsOrError = Elf->sections(); if (!SectionsOrError) return SectionsOrError.takeError(); for (const typename ELFT::Shdr &Sec : *SectionsOrError) { if (Sec.sh_type == ELF::SHT_DYNSYM) return Elf->getStringTableForSymtab(Sec); } return createError("dynamic string table not found"); }
uint32_t NativeExeSymbol::getAge() const { auto IS = File.getPDBInfoStream(); if (IS) return IS->getAge(); consumeError(IS.takeError()); return 0; }
/// Load the current object file symbols into CurrentObjectAddresses. void MachODebugMapParser::loadCurrentObjectFileSymbols( const object::MachOObjectFile &Obj) { CurrentObjectAddresses.clear(); for (auto Sym : Obj.symbols()) { uint64_t Addr = Sym.getValue(); Expected<StringRef> Name = Sym.getName(); if (!Name) { // TODO: Actually report errors helpfully. consumeError(Name.takeError()); continue; } // The value of some categories of symbols isn't meaningful. For // example common symbols store their size in the value field, not // their address. Absolute symbols have a fixed address that can // conflict with standard symbols. These symbols (especially the // common ones), might still be referenced by relocations. These // relocations will use the symbol itself, and won't need an // object file address. The object file address field is optional // in the DebugMap, leave it unassigned for these symbols. if (Sym.getFlags() & (SymbolRef::SF_Absolute | SymbolRef::SF_Common)) CurrentObjectAddresses[*Name] = None; else CurrentObjectAddresses[*Name] = Addr; } }
void printDynamicSection(const ELFFile<ELFT> *Elf, StringRef Filename) { ArrayRef<typename ELFT::Dyn> DynamicEntries = unwrapOrError(Elf->dynamicEntries(), Filename); outs() << "Dynamic Section:\n"; for (const typename ELFT::Dyn &Dyn : DynamicEntries) { if (Dyn.d_tag == ELF::DT_NULL) continue; std::string Str = Elf->getDynamicTagAsString(Dyn.d_tag); outs() << format(" %-21s", Str.c_str()); const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 "\n" : "0x%08" PRIx64 "\n"; if (Dyn.d_tag == ELF::DT_NEEDED || Dyn.d_tag == ELF::DT_RPATH || Dyn.d_tag == ELF::DT_RUNPATH || Dyn.d_tag == ELF::DT_SONAME || Dyn.d_tag == ELF::DT_AUXILIARY || Dyn.d_tag == ELF::DT_FILTER) { Expected<StringRef> StrTabOrErr = getDynamicStrTab(Elf); if (StrTabOrErr) { const char *Data = StrTabOrErr.get().data(); outs() << (Data + Dyn.d_un.d_val) << "\n"; continue; } warn(toString(StrTabOrErr.takeError())); consumeError(StrTabOrErr.takeError()); } outs() << format(Fmt, (uint64_t)Dyn.d_un.d_val); } }
/// 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; } }
void MappingContextTraits<CVType, pdb::yaml::SerializationContext>::mapping( IO &IO, CVType &Record, pdb::yaml::SerializationContext &Context) { if (IO.outputting()) { codeview::TypeDeserializer Deserializer; codeview::TypeVisitorCallbackPipeline Pipeline; Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Context.Dumper); codeview::CVTypeVisitor Visitor(Pipeline); consumeError(Visitor.visitTypeRecord(Record)); } }
TEST(URITest, ResolveFailed) { auto FailedResolve = [](StringRef Uri) { auto Path = URI::resolve(parseOrDie(Uri)); if (!Path) { consumeError(Path.takeError()); return true; } return false; }; // Invalid scheme. EXPECT_TRUE(FailedResolve("no:/a/b/c")); // File path needs to be absolute. EXPECT_TRUE(FailedResolve("file:a/b/c")); }
static void mapping(IO &IO, pdb::yaml::PdbTpiFieldListRecord &Obj, pdb::yaml::SerializationContext &Context) { assert(IO.outputting()); codeview::TypeVisitorCallbackPipeline Pipeline; BinaryByteStream Data(Obj.Record.Data, llvm::support::little); BinaryStreamReader FieldReader(Data); codeview::FieldListDeserializer Deserializer(FieldReader); // For PDB to Yaml, deserialize into a high level record type, then dump // it. Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Context.Dumper); codeview::CVTypeVisitor Visitor(Pipeline); consumeError(Visitor.visitMemberRecord(Obj.Record)); }
std::unique_ptr<IPDBEnumSymbols> NativeExeSymbol::findChildren(PDB_SymType Type) const { switch (Type) { case PDB_SymType::Compiland: { auto Dbi = File.getPDBDbiStream(); if (Dbi) { const DbiModuleList &Modules = Dbi->modules(); return std::unique_ptr<IPDBEnumSymbols>( new NativeEnumModules(Session, Modules)); } consumeError(Dbi.takeError()); break; } default: break; } return nullptr; }
ErrorOr<std::vector<MemoryBufferRef>> BinaryHolder::GetMemoryBuffersForFile( StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) { if (Verbose) outs() << "trying to open '" << Filename << "'\n"; // Try that first as it doesn't involve any filesystem access. if (auto ErrOrArchiveMembers = GetArchiveMemberBuffers(Filename, Timestamp)) return *ErrOrArchiveMembers; // If the name ends with a closing paren, there is a huge chance // it is an archive member specification. if (Filename.endswith(")")) if (auto ErrOrArchiveMembers = MapArchiveAndGetMemberBuffers(Filename, Timestamp)) return *ErrOrArchiveMembers; // Otherwise, just try opening a standard file. If this is an // archive member specifiaction and any of the above didn't handle it // (either because the archive is not there anymore, or because the // archive doesn't contain the requested member), this will still // provide a sensible error message. auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(Filename); if (auto Err = ErrOrFile.getError()) return Err; changeBackingMemoryBuffer(std::move(*ErrOrFile)); if (Verbose) outs() << "\tloaded file.\n"; auto ErrOrFat = object::MachOUniversalBinary::create( CurrentMemoryBuffer->getMemBufferRef()); if (!ErrOrFat) { consumeError(ErrOrFat.takeError()); // Not a fat binary must be a standard one. Return a one element vector. return std::vector<MemoryBufferRef>{CurrentMemoryBuffer->getMemBufferRef()}; } CurrentFatBinary = std::move(*ErrOrFat); CurrentFatBinaryName = Filename; return getMachOFatMemoryBuffers(CurrentFatBinaryName, *CurrentMemoryBuffer, *CurrentFatBinary); }
static void mapping(IO &IO, pdb::yaml::PdbTpiFieldListRecord &Obj, pdb::yaml::SerializationContext &Context) { codeview::TypeVisitorCallbackPipeline Pipeline; codeview::TypeDeserializer Deserializer; codeview::TypeSerializationVisitor Serializer(Context.FieldListBuilder, Context.TypeTableBuilder); pdb::TpiHashUpdater Hasher; if (IO.outputting()) { // For PDB to Yaml, deserialize into a high level record type, then dump // it. Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Context.Dumper); } else { // For Yaml to PDB, extract from the high level record type, then write it // to bytes. Pipeline.addCallbackToPipeline(Context.Dumper); Pipeline.addCallbackToPipeline(Serializer); Pipeline.addCallbackToPipeline(Hasher); } codeview::CVTypeVisitor Visitor(Pipeline); consumeError(Visitor.visitMemberRecord(Obj.Record)); }
static void mapping(IO &IO, pdb::yaml::PdbTpiFieldListRecord &Obj, codeview::CVTypeVisitor &Visitor) { consumeError(Visitor.visitMemberRecord(Obj.Record)); }