summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Object/COFFObjectFile.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-06-02 17:10:43 +0000
committerReid Kleckner <rnk@google.com>2016-06-02 17:10:43 +0000
commit2da433ea997e0a48696c4b253894a796c6c1af9f (patch)
tree349ea66cddd93832785072b15b2fd76b170f8890 /llvm/lib/Object/COFFObjectFile.cpp
parent6393ef135ca804bef2f4519a38ef9d9d002750a9 (diff)
downloadbcm5719-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.cpp72
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();
}
OpenPOWER on IntegriCloud