aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/COFFObjectFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Object/COFFObjectFile.cpp')
-rw-r--r--llvm/lib/Object/COFFObjectFile.cpp57
1 files changed, 50 insertions, 7 deletions
diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp
index a52671f..65166b3 100644
--- a/llvm/lib/Object/COFFObjectFile.cpp
+++ b/llvm/lib/Object/COFFObjectFile.cpp
@@ -477,6 +477,25 @@ Error COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res,
uint32_t SectionStart = Section->VirtualAddress;
uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
if (SectionStart <= Addr && Addr < SectionEnd) {
+ // A table/directory entry can be pointing to somewhere in a stripped
+ // section, in an object that went through `objcopy --only-keep-debug`.
+ // In this case we don't want to cause the parsing of the object file to
+ // fail, otherwise it will be impossible to use this object as debug info
+ // in LLDB. Return SectionStrippedError here so that
+ // COFFObjectFile::initialize can ignore the error.
+ if (Section->SizeOfRawData == 0)
+ return make_error<SectionStrippedError>();
+ if (Section->SizeOfRawData < Section->VirtualSize &&
+ Addr >= SectionStart + Section->SizeOfRawData) {
+ if (ErrorContext)
+ return createStringError(object_error::parse_failed,
+ "RVA 0x%" PRIx32
+ " for %s found but data is incomplete",
+ Addr, ErrorContext);
+ return createStringError(
+ object_error::parse_failed,
+ "RVA 0x%" PRIx32 " found but data is incomplete", Addr);
+ }
uint32_t Offset = Addr - SectionStart;
Res = reinterpret_cast<uintptr_t>(base()) + Section->PointerToRawData +
Offset;
@@ -602,6 +621,9 @@ Error COFFObjectFile::initDelayImportTablePtr() {
uintptr_t IntPtr = 0;
if (Error E = getRvaPtr(RVA, IntPtr, "delay import table"))
return E;
+ if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
+ return E;
+
DelayImportDirectory = reinterpret_cast<
const delay_import_directory_table_entry *>(IntPtr);
return Error::success();
@@ -623,6 +645,9 @@ Error COFFObjectFile::initExportTablePtr() {
uintptr_t IntPtr = 0;
if (Error E = getRvaPtr(ExportTableRva, IntPtr, "export table"))
return E;
+ if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
+ return E;
+
ExportDirectory =
reinterpret_cast<const export_directory_table_entry *>(IntPtr);
return Error::success();
@@ -640,6 +665,9 @@ Error COFFObjectFile::initBaseRelocPtr() {
if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
"base reloc table"))
return E;
+ if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
+ return E;
+
BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
IntPtr);
BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
@@ -668,6 +696,9 @@ Error COFFObjectFile::initDebugDirectoryPtr() {
if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
"debug directory"))
return E;
+ if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
+ return E;
+
DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
IntPtr + DataEntry->Size);
@@ -700,6 +731,8 @@ Error COFFObjectFile::initTLSDirectoryPtr() {
if (Error E =
getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr, "TLS directory"))
return E;
+ if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
+ return E;
if (is64())
TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
@@ -722,6 +755,8 @@ Error COFFObjectFile::initLoadConfigPtr() {
if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr,
"load config table"))
return E;
+ if (Error E = checkOffset(Data, IntPtr, DataEntry->Size))
+ return E;
LoadConfig = (const void *)IntPtr;
return Error::success();
@@ -746,6 +781,14 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
+static Error ignoreStrippedErrors(Error E) {
+ if (E.isA<SectionStrippedError>()) {
+ consumeError(std::move(E));
+ return Error::success();
+ }
+ return std::move(E);
+}
+
Error COFFObjectFile::initialize() {
// Check that we at least have enough room for a header.
std::error_code EC;
@@ -861,28 +904,28 @@ Error COFFObjectFile::initialize() {
}
// Initialize the pointer to the beginning of the import table.
- if (Error E = initImportTablePtr())
+ if (Error E = ignoreStrippedErrors(initImportTablePtr()))
return E;
- if (Error E = initDelayImportTablePtr())
+ if (Error E = ignoreStrippedErrors(initDelayImportTablePtr()))
return E;
// Initialize the pointer to the export table.
- if (Error E = initExportTablePtr())
+ if (Error E = ignoreStrippedErrors(initExportTablePtr()))
return E;
// Initialize the pointer to the base relocation table.
- if (Error E = initBaseRelocPtr())
+ if (Error E = ignoreStrippedErrors(initBaseRelocPtr()))
return E;
// Initialize the pointer to the debug directory.
- if (Error E = initDebugDirectoryPtr())
+ if (Error E = ignoreStrippedErrors(initDebugDirectoryPtr()))
return E;
// Initialize the pointer to the TLS directory.
- if (Error E = initTLSDirectoryPtr())
+ if (Error E = ignoreStrippedErrors(initTLSDirectoryPtr()))
return E;
- if (Error E = initLoadConfigPtr())
+ if (Error E = ignoreStrippedErrors(initLoadConfigPtr()))
return E;
return Error::success();