aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
diff options
context:
space:
mode:
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.cpp176
1 files changed, 133 insertions, 43 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 0d95a1c12bde..890db5c27481 100644
--- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -717,6 +717,20 @@ bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
// Iterate through the object file sections to find all of the sections
// that have SHF_ALLOC in their flag bits.
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
+
+ // PT_TLS segments can have the same p_vaddr and p_paddr as other
+ // PT_LOAD segments so we shouldn't load them. If we do load them, then
+ // the SectionLoadList will incorrectly fill in the instance variable
+ // SectionLoadList::m_addr_to_sect with the same address as a PT_LOAD
+ // segment and we won't be able to resolve addresses in the PT_LOAD
+ // segment whose p_vaddr entry matches that of the PT_TLS. Any variables
+ // that appear in the PT_TLS segments get resolved by the DWARF
+ // expressions. If this ever changes we will need to fix all object
+ // file plug-ins, but until then, we don't want PT_TLS segments to
+ // remove the entry from SectionLoadList::m_addr_to_sect when we call
+ // SetSectionLoadAddress() below.
+ if (section_sp->IsThreadSpecific())
+ continue;
if (section_sp->Test(SHF_ALLOC) ||
section_sp->GetType() == eSectionTypeContainer) {
lldb::addr_t load_addr = section_sp->GetFileAddress();
@@ -1682,7 +1696,6 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
return llvm::StringSwitch<SectionType>(Name)
.Case(".ARM.exidx", eSectionTypeARMexidx)
.Case(".ARM.extab", eSectionTypeARMextab)
- .Cases(".bss", ".tbss", eSectionTypeZeroFill)
.Case(".ctf", eSectionTypeDebug)
.Cases(".data", ".tdata", eSectionTypeData)
.Case(".eh_frame", eSectionTypeEHFrame)
@@ -1699,6 +1712,10 @@ SectionType ObjectFileELF::GetSectionType(const ELFSectionHeaderInfo &H) const {
if (H.sh_flags & SHF_EXECINSTR)
return eSectionTypeCode;
break;
+ case SHT_NOBITS:
+ if (H.sh_flags & SHF_ALLOC)
+ return eSectionTypeZeroFill;
+ break;
case SHT_SYMTAB:
return eSectionTypeELFSymbolTable;
case SHT_DYNSYM:
@@ -1854,6 +1871,39 @@ public:
};
}
+// We have to do this because ELF doesn't have section IDs, and also
+// doesn't require section names to be unique. (We use the section index
+// for section IDs, but that isn't guaranteed to be the same in separate
+// debug images.)
+static SectionSP FindMatchingSection(const SectionList &section_list,
+ SectionSP section) {
+ SectionSP sect_sp;
+
+ addr_t vm_addr = section->GetFileAddress();
+ ConstString name = section->GetName();
+ offset_t byte_size = section->GetByteSize();
+ bool thread_specific = section->IsThreadSpecific();
+ uint32_t permissions = section->GetPermissions();
+ uint32_t alignment = section->GetLog2Align();
+
+ for (auto sect : section_list) {
+ if (sect->GetName() == name &&
+ sect->IsThreadSpecific() == thread_specific &&
+ sect->GetPermissions() == permissions &&
+ sect->GetByteSize() == byte_size && sect->GetFileAddress() == vm_addr &&
+ sect->GetLog2Align() == alignment) {
+ sect_sp = sect;
+ break;
+ } else {
+ sect_sp = FindMatchingSection(sect->GetChildren(), section);
+ if (sect_sp)
+ break;
+ }
+ }
+
+ return sect_sp;
+}
+
void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
if (m_sections_up)
return;
@@ -2027,13 +2077,17 @@ static char FindArmAarch64MappingSymbol(const char *symbol_name) {
#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER)&STO_MIPS_ISA) == STO_MICROMIPS)
// private
-unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
- SectionList *section_list,
- const size_t num_symbols,
- const DataExtractor &symtab_data,
- const DataExtractor &strtab_data) {
+std::pair<unsigned, ObjectFileELF::FileAddressToAddressClassMap>
+ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
+ SectionList *section_list, const size_t num_symbols,
+ const DataExtractor &symtab_data,
+ const DataExtractor &strtab_data) {
ELFSymbol symbol;
lldb::offset_t offset = 0;
+ // The changes these symbols would make to the class map. We will also update
+ // m_address_class_map but need to tell the caller what changed because the
+ // caller may be another object file.
+ FileAddressToAddressClassMap address_class_map;
static ConstString text_section_name(".text");
static ConstString init_section_name(".init");
@@ -2067,10 +2121,12 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
SectionList *module_section_list =
module_sp ? module_sp->GetSectionList() : nullptr;
- // Local cache to avoid doing a FindSectionByName for each symbol. The "const
- // char*" key must came from a ConstString object so they can be compared by
- // pointer
- std::unordered_map<const char *, lldb::SectionSP> section_name_to_section;
+ // We might have debug information in a separate object, in which case
+ // we need to map the sections from that object to the sections in the
+ // main object during symbol lookup. If we had to compare the sections
+ // for every single symbol, that would be expensive, so this map is
+ // used to accelerate the process.
+ std::unordered_map<lldb::SectionSP, lldb::SectionSP> section_map;
unsigned i;
for (i = 0; i < num_symbols; ++i) {
@@ -2178,18 +2234,18 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
switch (mapping_symbol) {
case 'a':
// $a[.<any>]* - marks an ARM instruction sequence
- m_address_class_map[symbol.st_value] = AddressClass::eCode;
+ address_class_map[symbol.st_value] = AddressClass::eCode;
break;
case 'b':
case 't':
// $b[.<any>]* - marks a THUMB BL instruction sequence
// $t[.<any>]* - marks a THUMB instruction sequence
- m_address_class_map[symbol.st_value] =
+ address_class_map[symbol.st_value] =
AddressClass::eCodeAlternateISA;
break;
case 'd':
// $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = AddressClass::eData;
+ address_class_map[symbol.st_value] = AddressClass::eData;
break;
}
}
@@ -2203,11 +2259,11 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
switch (mapping_symbol) {
case 'x':
// $x[.<any>]* - marks an A64 instruction sequence
- m_address_class_map[symbol.st_value] = AddressClass::eCode;
+ address_class_map[symbol.st_value] = AddressClass::eCode;
break;
case 'd':
// $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = AddressClass::eData;
+ address_class_map[symbol.st_value] = AddressClass::eData;
break;
}
}
@@ -2225,11 +2281,11 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
// conjunction with symbol.st_value to produce the final
// symbol_value that we store in the symtab.
symbol_value_offset = -1;
- m_address_class_map[symbol.st_value ^ 1] =
+ address_class_map[symbol.st_value ^ 1] =
AddressClass::eCodeAlternateISA;
} else {
// This address is ARM
- m_address_class_map[symbol.st_value] = AddressClass::eCode;
+ address_class_map[symbol.st_value] = AddressClass::eCode;
}
}
}
@@ -2250,17 +2306,17 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
*/
if (arch.IsMIPS()) {
if (IS_MICROMIPS(symbol.st_other))
- m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
+ address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) {
symbol.st_value = symbol.st_value & (~1ull);
- m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
+ address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
} else {
if (symbol_type == eSymbolTypeCode)
- m_address_class_map[symbol.st_value] = AddressClass::eCode;
+ address_class_map[symbol.st_value] = AddressClass::eCode;
else if (symbol_type == eSymbolTypeData)
- m_address_class_map[symbol.st_value] = AddressClass::eData;
+ address_class_map[symbol.st_value] = AddressClass::eData;
else
- m_address_class_map[symbol.st_value] = AddressClass::eUnknown;
+ address_class_map[symbol.st_value] = AddressClass::eUnknown;
}
}
}
@@ -2275,14 +2331,14 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
if (symbol_section_sp && module_section_list &&
module_section_list != section_list) {
- ConstString sect_name = symbol_section_sp->GetName();
- auto section_it = section_name_to_section.find(sect_name.GetCString());
- if (section_it == section_name_to_section.end())
- section_it =
- section_name_to_section
- .emplace(sect_name.GetCString(),
- module_section_list->FindSectionByName(sect_name))
- .first;
+ auto section_it = section_map.find(symbol_section_sp);
+ if (section_it == section_map.end()) {
+ section_it = section_map
+ .emplace(symbol_section_sp,
+ FindMatchingSection(*module_section_list,
+ symbol_section_sp))
+ .first;
+ }
if (section_it->second)
symbol_section_sp = section_it->second;
}
@@ -2321,13 +2377,30 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
bool symbol_size_valid =
symbol.st_size != 0 || symbol.getType() != STT_FUNC;
+ bool is_trampoline = false;
+ if (arch.IsValid() && (arch.GetMachine() == llvm::Triple::aarch64)) {
+ // On AArch64, trampolines are registered as code.
+ // If we detect a trampoline (which starts with __AArch64ADRPThunk_ or
+ // __AArch64AbsLongThunk_) we register the symbol as a trampoline. This
+ // way we will be able to detect the trampoline when we step in a function
+ // and step through the trampoline.
+ if (symbol_type == eSymbolTypeCode) {
+ llvm::StringRef trampoline_name = mangled.GetName().GetStringRef();
+ if (trampoline_name.starts_with("__AArch64ADRPThunk_") ||
+ trampoline_name.starts_with("__AArch64AbsLongThunk_")) {
+ symbol_type = eSymbolTypeTrampoline;
+ is_trampoline = true;
+ }
+ }
+ }
+
Symbol dc_symbol(
i + start_id, // ID is the original symbol table index.
mangled,
symbol_type, // Type of this symbol
is_global, // Is this globally visible?
false, // Is this symbol debug info?
- false, // Is this symbol a trampoline?
+ is_trampoline, // Is this symbol a trampoline?
false, // Is this symbol artificial?
AddressRange(symbol_section_sp, // Section in which this symbol is
// defined or null.
@@ -2340,24 +2413,33 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
dc_symbol.SetIsWeak(true);
symtab->AddSymbol(dc_symbol);
}
- return i;
+
+ m_address_class_map.merge(address_class_map);
+ return {i, address_class_map};
}
-unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
- user_id_t start_id,
- lldb_private::Section *symtab) {
+std::pair<unsigned, ObjectFileELF::FileAddressToAddressClassMap>
+ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id,
+ lldb_private::Section *symtab) {
if (symtab->GetObjectFile() != this) {
// If the symbol table section is owned by a different object file, have it
// do the parsing.
ObjectFileELF *obj_file_elf =
static_cast<ObjectFileELF *>(symtab->GetObjectFile());
- return obj_file_elf->ParseSymbolTable(symbol_table, start_id, symtab);
+ auto [num_symbols, address_class_map] =
+ obj_file_elf->ParseSymbolTable(symbol_table, start_id, symtab);
+
+ // The other object file returned the changes it made to its address
+ // class map, make the same changes to ours.
+ m_address_class_map.merge(address_class_map);
+
+ return {num_symbols, address_class_map};
}
// Get section list for this object file.
SectionList *section_list = m_sections_up.get();
if (!section_list)
- return 0;
+ return {};
user_id_t symtab_id = symtab->GetID();
const ELFSectionHeaderInfo *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
@@ -2383,7 +2465,7 @@ unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
}
}
- return 0;
+ return {0, {}};
}
size_t ObjectFileELF::ParseDynamicSymbols() {
@@ -2920,8 +3002,12 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
// while the reverse is not necessarily true.
Section *symtab =
section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get();
- if (symtab)
- symbol_id += ParseSymbolTable(&lldb_symtab, symbol_id, symtab);
+ if (symtab) {
+ auto [num_symbols, address_class_map] =
+ ParseSymbolTable(&lldb_symtab, symbol_id, symtab);
+ m_address_class_map.merge(address_class_map);
+ symbol_id += num_symbols;
+ }
// The symtab section is non-allocable and can be stripped, while the
// .dynsym section which should always be always be there. To support the
@@ -2934,8 +3020,12 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
Section *dynsym =
section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true)
.get();
- if (dynsym)
- symbol_id += ParseSymbolTable(&lldb_symtab, symbol_id, dynsym);
+ if (dynsym) {
+ auto [num_symbols, address_class_map] =
+ ParseSymbolTable(&lldb_symtab, symbol_id, dynsym);
+ symbol_id += num_symbols;
+ m_address_class_map.merge(address_class_map);
+ }
}
// DT_JMPREL
@@ -3484,7 +3574,7 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() {
// decrease by one
llvm::StringRef loader_name(buffer, read_size - 1);
llvm::StringRef freebsd_kernel_loader_name("/red/herring");
- if (loader_name.equals(freebsd_kernel_loader_name))
+ if (loader_name == freebsd_kernel_loader_name)
return eStrataKernel;
}
}