diff options
Diffstat (limited to 'llvm/lib/Object/COFFObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/COFFObjectFile.cpp | 57 |
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(); |