diff options
author | Reid Kleckner <rnk@google.com> | 2016-06-02 17:10:43 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2016-06-02 17:10:43 +0000 |
commit | 2da433ea997e0a48696c4b253894a796c6c1af9f (patch) | |
tree | 349ea66cddd93832785072b15b2fd76b170f8890 /llvm/lib/Object/COFFObjectFile.cpp | |
parent | 6393ef135ca804bef2f4519a38ef9d9d002750a9 (diff) | |
download | bcm5719-llvm-2da433ea997e0a48696c4b253894a796c6c1af9f.tar.gz bcm5719-llvm-2da433ea997e0a48696c4b253894a796c6c1af9f.zip |
[COFF] Expose the PE debug data directory and dump it
This directory is used to find if there is a PDB associated with an
executable. I plan to use this functionality to teach llvm-symbolizer
whether it should use DIA or DWARF to symbolize a given DLL.
Reviewers: majnemer
Differential Revision: http://reviews.llvm.org/D20885
llvm-svn: 271539
Diffstat (limited to 'llvm/lib/Object/COFFObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/COFFObjectFile.cpp | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp index 5f464969adb..8390edda3bf 100644 --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/lib/Object/COFFObjectFile.cpp @@ -453,6 +453,27 @@ std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { return object_error::parse_failed; } +std::error_code +COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, + ArrayRef<uint8_t> &Contents) const { + for (const SectionRef &S : sections()) { + const coff_section *Section = getCOFFSection(S); + uint32_t SectionStart = Section->VirtualAddress; + // Check if this RVA is within the section bounds. Be careful about integer + // overflow. + uint32_t OffsetIntoSection = RVA - SectionStart; + if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && + Size <= Section->VirtualSize - OffsetIntoSection) { + uintptr_t Begin = + uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; + Contents = + ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); + return std::error_code(); + } + } + return object_error::parse_failed; +} + // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name // table entry. std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, @@ -466,6 +487,24 @@ std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, return std::error_code(); } +std::error_code COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, + const debug_pdb_info *&PDBInfo, + StringRef &PDBFileName) const { + ArrayRef<uint8_t> InfoBytes; + if (std::error_code EC = getRvaAndSizeAsBytes( + DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) + return EC; + if (InfoBytes.size() < sizeof(debug_pdb_info) + 1) + return object_error::parse_failed; + PDBInfo = reinterpret_cast<const debug_pdb_info *>(InfoBytes.data()); + InfoBytes = InfoBytes.drop_front(sizeof(debug_pdb_info)); + PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), + InfoBytes.size()); + // Truncate the name at the first null byte. Ignore any padding. + PDBFileName = PDBFileName.split('\0').first; + return std::error_code(); +} + // Find the import table. std::error_code COFFObjectFile::initImportTablePtr() { // First, we get the RVA of the import table. If the file lacks a pointer to @@ -551,6 +590,31 @@ std::error_code COFFObjectFile::initBaseRelocPtr() { return std::error_code(); } +std::error_code COFFObjectFile::initDebugDirectoryPtr() { + // Get the RVA of the debug directory. Do nothing if it does not exist. + const data_directory *DataEntry; + if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) + return std::error_code(); + + // Do nothing if the RVA is NULL. + if (DataEntry->RelativeVirtualAddress == 0) + return std::error_code(); + + // Check that the size is a multiple of the entry size. + if (DataEntry->Size % sizeof(debug_directory) != 0) + return object_error::parse_failed; + + uintptr_t IntPtr = 0; + if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) + return EC; + DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); + if (std::error_code EC = getRvaPtr( + DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr)) + return EC; + DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr); + return std::error_code(); +} + COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), @@ -558,8 +622,8 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), ImportDirectory(nullptr), NumberOfImportDirectory(0), DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), - ExportDirectory(nullptr), BaseRelocHeader(nullptr), - BaseRelocEnd(nullptr) { + ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), + DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { // Check that we at least have enough room for a header. if (!checkSize(Data, EC, sizeof(coff_file_header))) return; @@ -675,6 +739,10 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) if ((EC = initBaseRelocPtr())) return; + // Initialize the pointer to the export table. + if ((EC = initDebugDirectoryPtr())) + return; + EC = std::error_code(); } |