aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-09-02 21:17:18 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-08 17:34:50 +0000
commit06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (patch)
tree62f873df87c7c675557a179e0c4c83fe9f3087bc /contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
parentcf037972ea8863e2bab7461d77345367d2c1e054 (diff)
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp140
1 files changed, 109 insertions, 31 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 5b75738e070c..700af84a14c0 100644
--- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -13,7 +13,6 @@
#include <optional>
#include <unordered_map>
-#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
@@ -27,6 +26,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/FileSpecList.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RangeMap.h"
@@ -555,6 +555,14 @@ size_t ObjectFileELF::GetModuleSpecifications(
if (header.Parse(data, &header_offset)) {
if (data_sp) {
ModuleSpec spec(file);
+ // In Android API level 23 and above, bionic dynamic linker is able to
+ // load .so file directly from zip file. In that case, .so file is
+ // page aligned and uncompressed, and this module spec should retain the
+ // .so file offset and file size to pass through the information from
+ // lldb-server to LLDB. For normal file, file_offset should be 0,
+ // length should be the size of the file.
+ spec.SetObjectOffset(file_offset);
+ spec.SetObjectSize(length);
const uint32_t sub_type = subTypeFromElfHeader(header);
spec.GetArchitecture().SetArchitecture(
@@ -586,8 +594,12 @@ size_t ObjectFileELF::GetModuleSpecifications(
__FUNCTION__, file.GetPath().c_str());
}
+ // When ELF file does not contain GNU build ID, the later code will
+ // calculate CRC32 with this data_sp file_offset and length. It is
+ // important for Android zip .so file, which is a slice of a file,
+ // to not access the outside of the file slice range.
if (data_sp->GetByteSize() < length)
- data_sp = MapFileData(file, -1, file_offset);
+ data_sp = MapFileData(file, length, file_offset);
if (data_sp)
data.SetData(data_sp);
// In case there is header extension in the section #0, the header we
@@ -623,7 +635,7 @@ size_t ObjectFileELF::GetModuleSpecifications(
if (!gnu_debuglink_crc) {
LLDB_SCOPED_TIMERF(
"Calculating module crc32 %s with size %" PRIu64 " KiB",
- file.GetLastPathComponent().AsCString(),
+ file.GetFilename().AsCString(),
(length - file_offset) / 1024);
// For core files - which usually don't happen to have a
@@ -1661,6 +1673,7 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
.Case(".ARM.exidx", eSectionTypeARMexidx)
.Case(".ARM.extab", eSectionTypeARMextab)
.Cases(".bss", ".tbss", eSectionTypeZeroFill)
+ .Case(".ctf", eSectionTypeDebug)
.Cases(".data", ".tdata", eSectionTypeData)
.Case(".eh_frame", eSectionTypeEHFrame)
.Case(".gnu_debugaltlink", eSectionTypeDWARFGNUDebugAltLink)
@@ -2029,7 +2042,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
// contain the note section specifying the environment to Android but the
// custom extension and file name makes it highly unlikely that this will
// collide with anything else.
- ConstString file_extension = m_file.GetFileNameExtension();
+ llvm::StringRef file_extension = m_file.GetFileNameExtension();
bool skip_oatdata_oatexec =
file_extension == ".oat" || file_extension == ".odex";
@@ -2637,6 +2650,44 @@ static void ApplyELF64ABS32Relocation(Symtab *symtab, ELFRelocation &rel,
}
}
+static void ApplyELF32ABS32RelRelocation(Symtab *symtab, ELFRelocation &rel,
+ DataExtractor &debug_data,
+ Section *rel_section) {
+ Log *log = GetLog(LLDBLog::Modules);
+ Symbol *symbol = symtab->FindSymbolByID(ELFRelocation::RelocSymbol32(rel));
+ if (symbol) {
+ addr_t value = symbol->GetAddressRef().GetFileAddress();
+ if (value == LLDB_INVALID_ADDRESS) {
+ const char *name = symbol->GetName().GetCString();
+ LLDB_LOGF(log, "Debug info symbol invalid: %s", name);
+ return;
+ }
+ assert(llvm::isUInt<32>(value) && "Valid addresses are 32-bit");
+ DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
+ // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
+ WritableDataBuffer *data_buffer =
+ llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
+ uint8_t *dst = data_buffer->GetBytes() + rel_section->GetFileOffset() +
+ ELFRelocation::RelocOffset32(rel);
+ // Implicit addend is stored inline as a signed value.
+ int32_t addend;
+ memcpy(&addend, dst, sizeof(int32_t));
+ // The sum must be positive. This extra check prevents UB from overflow in
+ // the actual range check below.
+ if (addend < 0 && static_cast<uint32_t>(-addend) > value) {
+ LLDB_LOGF(log, "Debug info relocation overflow: 0x%" PRIx64,
+ static_cast<int64_t>(value) + addend);
+ return;
+ }
+ if (!llvm::isUInt<32>(value + addend)) {
+ LLDB_LOGF(log, "Debug info relocation out of range: 0x%" PRIx64, value);
+ return;
+ }
+ uint32_t addr = value + addend;
+ memcpy(dst, &addr, sizeof(uint32_t));
+ }
+}
+
unsigned ObjectFileELF::ApplyRelocations(
Symtab *symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr,
@@ -2666,38 +2717,64 @@ unsigned ObjectFileELF::ApplyRelocations(
Symbol *symbol = nullptr;
if (hdr->Is32Bit()) {
- switch (reloc_type(rel)) {
- case R_386_32:
- symbol = symtab->FindSymbolByID(reloc_symbol(rel));
- if (symbol) {
- addr_t f_offset =
- rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel);
- DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
- // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
- WritableDataBuffer *data_buffer =
- llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
- uint32_t *dst = reinterpret_cast<uint32_t *>(
- data_buffer->GetBytes() + f_offset);
-
- addr_t value = symbol->GetAddressRef().GetFileAddress();
- if (rel.IsRela()) {
- value += ELFRelocation::RelocAddend32(rel);
+ switch (hdr->e_machine) {
+ case llvm::ELF::EM_ARM:
+ switch (reloc_type(rel)) {
+ case R_ARM_ABS32:
+ ApplyELF32ABS32RelRelocation(symtab, rel, debug_data, rel_section);
+ break;
+ case R_ARM_REL32:
+ GetModule()->ReportError("unsupported AArch32 relocation:"
+ " .rel{0}[{1}], type {2}",
+ rel_section->GetName().AsCString(), i,
+ reloc_type(rel));
+ break;
+ default:
+ assert(false && "unexpected relocation type");
+ }
+ break;
+ case llvm::ELF::EM_386:
+ switch (reloc_type(rel)) {
+ case R_386_32:
+ symbol = symtab->FindSymbolByID(reloc_symbol(rel));
+ if (symbol) {
+ addr_t f_offset =
+ rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel);
+ DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
+ // ObjectFileELF creates a WritableDataBuffer in CreateInstance.
+ WritableDataBuffer *data_buffer =
+ llvm::cast<WritableDataBuffer>(data_buffer_sp.get());
+ uint32_t *dst = reinterpret_cast<uint32_t *>(
+ data_buffer->GetBytes() + f_offset);
+
+ addr_t value = symbol->GetAddressRef().GetFileAddress();
+ if (rel.IsRela()) {
+ value += ELFRelocation::RelocAddend32(rel);
+ } else {
+ value += *dst;
+ }
+ *dst = value;
} else {
- value += *dst;
+ GetModule()->ReportError(".rel{0}[{1}] unknown symbol id: {2:d}",
+ rel_section->GetName().AsCString(), i,
+ reloc_symbol(rel));
}
- *dst = value;
- } else {
- GetModule()->ReportError(".rel{0}[{1}] unknown symbol id: {2:d}",
+ break;
+ case R_386_NONE:
+ case R_386_PC32:
+ GetModule()->ReportError("unsupported i386 relocation:"
+ " .rel{0}[{1}], type {2}",
rel_section->GetName().AsCString(), i,
- reloc_symbol(rel));
+ reloc_type(rel));
+ break;
+ default:
+ assert(false && "unexpected relocation type");
+ break;
}
break;
- case R_386_PC32:
default:
- GetModule()->ReportError("unsupported 32-bit relocation:"
- " .rel{0}[{1}], type {2}",
- rel_section->GetName().AsCString(), i,
- reloc_type(rel));
+ GetModule()->ReportError("unsupported 32-bit ELF machine arch: {0}", hdr->e_machine);
+ break;
}
} else {
switch (hdr->e_machine) {
@@ -2743,7 +2820,8 @@ unsigned ObjectFileELF::ApplyRelocations(
}
break;
default:
- assert(false && "unsupported machine");
+ GetModule()->ReportError("unsupported 64-bit ELF machine arch: {0}", hdr->e_machine);
+ break;
}
}
}