diff options
author | dim <dim@FreeBSD.org> | 2015-12-30 11:55:28 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-12-30 11:55:28 +0000 |
commit | 66b75430a93929d6fc6ed63db14ca28e3ad5b1f6 (patch) | |
tree | 9ed5e1a91f242e2cb5911577356e487a55c01b78 /source/Plugins/ObjectFile | |
parent | 23814158e5384f73c6fa951b66d5f807f9c24a2b (diff) | |
download | FreeBSD-src-66b75430a93929d6fc6ed63db14ca28e3ad5b1f6.zip FreeBSD-src-66b75430a93929d6fc6ed63db14ca28e3ad5b1f6.tar.gz |
Vendor import of stripped lldb trunk r256633:
https://llvm.org/svn/llvm-project/lldb/trunk@256633
Diffstat (limited to 'source/Plugins/ObjectFile')
-rw-r--r-- | source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 508 | ||||
-rw-r--r-- | source/Plugins/ObjectFile/ELF/ObjectFileELF.h | 19 | ||||
-rw-r--r-- | source/Plugins/ObjectFile/JIT/ObjectFileJIT.h | 114 |
3 files changed, 445 insertions, 196 deletions
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 789fd49..44fe661 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -11,6 +11,7 @@ #include <cassert> #include <algorithm> +#include <unordered_map> #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataBuffer.h" @@ -48,6 +49,8 @@ const char *const LLDB_NT_OWNER_GNU = "GNU"; const char *const LLDB_NT_OWNER_NETBSD = "NetBSD"; const char *const LLDB_NT_OWNER_CSR = "csr"; const char *const LLDB_NT_OWNER_ANDROID = "Android"; +const char *const LLDB_NT_OWNER_CORE = "CORE"; +const char *const LLDB_NT_OWNER_LINUX = "LINUX"; // ELF note type definitions const elf_word LLDB_NT_FREEBSD_ABI_TAG = 0x01; @@ -66,6 +69,41 @@ const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00; const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01; const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02; +// LLDB_NT_OWNER_CORE and LLDB_NT_OWNER_LINUX note contants +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_PRPSINFO 3 +#define NT_TASKSTRUCT 4 +#define NT_AUXV 6 +#define NT_SIGINFO 0x53494749 +#define NT_FILE 0x46494c45 +#define NT_PRXFPREG 0x46e62b7f +#define NT_PPC_VMX 0x100 +#define NT_PPC_SPE 0x101 +#define NT_PPC_VSX 0x102 +#define NT_386_TLS 0x200 +#define NT_386_IOPERM 0x201 +#define NT_X86_XSTATE 0x202 +#define NT_S390_HIGH_GPRS 0x300 +#define NT_S390_TIMER 0x301 +#define NT_S390_TODCMP 0x302 +#define NT_S390_TODPREG 0x303 +#define NT_S390_CTRS 0x304 +#define NT_S390_PREFIX 0x305 +#define NT_S390_LAST_BREAK 0x306 +#define NT_S390_SYSTEM_CALL 0x307 +#define NT_S390_TDB 0x308 +#define NT_S390_VXRS_LOW 0x309 +#define NT_S390_VXRS_HIGH 0x30a +#define NT_ARM_VFP 0x400 +#define NT_ARM_TLS 0x401 +#define NT_ARM_HW_BREAK 0x402 +#define NT_ARM_HW_WATCH 0x403 +#define NT_ARM_SYSTEM_CALL 0x404 +#define NT_METAG_CBUF 0x500 +#define NT_METAG_RPIPE 0x501 +#define NT_METAG_TLS 0x502 + //===----------------------------------------------------------------------===// /// @class ELFRelocation /// @brief Generic wrapper for ELFRel and ELFRela. @@ -290,6 +328,11 @@ mipsVariantFromElfFlags(const elf::elf_word e_flags, uint32_t endian) switch (mips_arch) { + case llvm::ELF::EF_MIPS_ARCH_1: + case llvm::ELF::EF_MIPS_ARCH_2: + case llvm::ELF::EF_MIPS_ARCH_3: + case llvm::ELF::EF_MIPS_ARCH_4: + case llvm::ELF::EF_MIPS_ARCH_5: case llvm::ELF::EF_MIPS_ARCH_32: return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32el : ArchSpec::eMIPSSubType_mips32; case llvm::ELF::EF_MIPS_ARCH_32R2: @@ -847,40 +890,52 @@ ObjectFileELF::SetLoadAddress (Target &target, SectionList *section_list = GetSectionList (); if (section_list) { - if (value_is_offset) + if (!value_is_offset) { - const size_t num_sections = section_list->GetSize(); - size_t sect_idx = 0; - - for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) + bool found_offset = false; + for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i) { - // 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)); - // if (section_sp && !section_sp->IsThreadSpecific()) - if (section_sp && section_sp->Test(SHF_ALLOC)) - { - lldb::addr_t load_addr = section_sp->GetFileAddress() + value; - - // On 32-bit systems the load address have to fit into 4 bytes. The rest of - // the bytes are the overflow from the addition. - if (GetAddressByteSize() == 4) - load_addr &= 0xFFFFFFFF; - - if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr)) - ++num_loaded_sections; - } + const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i); + if (header == nullptr) + continue; + + if (header->p_type != PT_LOAD || header->p_offset != 0) + continue; + + value = value - header->p_vaddr; + found_offset = true; + break; } - return num_loaded_sections > 0; + if (!found_offset) + return false; } - else + + const size_t num_sections = section_list->GetSize(); + size_t sect_idx = 0; + + for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { - // Not sure how to slide an ELF file given the base address - // of the ELF file in memory + // 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)); + // if (section_sp && !section_sp->IsThreadSpecific()) + if (section_sp && section_sp->Test(SHF_ALLOC)) + { + lldb::addr_t load_addr = section_sp->GetFileAddress() + value; + + // On 32-bit systems the load address have to fit into 4 bytes. The rest of + // the bytes are the overflow from the addition. + if (GetAddressByteSize() == 4) + load_addr &= 0xFFFFFFFF; + + if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr)) + ++num_loaded_sections; + } } + return num_loaded_sections > 0; } } - return false; // If it changed + return false; } ByteOrder @@ -905,8 +960,17 @@ ObjectFileELF::GetAddressByteSize() const AddressClass ObjectFileELF::GetAddressClass (addr_t file_addr) { - auto res = ObjectFile::GetAddressClass (file_addr); + Symtab* symtab = GetSymtab(); + if (!symtab) + return eAddressClassUnknown; + + // The address class is determined based on the symtab. Ask it from the object file what + // contains the symtab information. + ObjectFile* symtab_objfile = symtab->GetObjectFile(); + if (symtab_objfile != nullptr && symtab_objfile != this) + return symtab_objfile->GetAddressClass(file_addr); + auto res = ObjectFile::GetAddressClass (file_addr); if (res != eAddressClassCode) return res; @@ -1076,16 +1140,35 @@ ObjectFileELF::GetImageInfoAddress(Target *target) addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize(); return Address(dynsym_section_sp, offset); } - else if (symbol.d_tag == DT_MIPS_RLD_MAP && target) + // MIPS executables uses DT_MIPS_RLD_MAP_REL to support PIE. DT_MIPS_RLD_MAP exists in non-PIE. + else if ((symbol.d_tag == DT_MIPS_RLD_MAP || symbol.d_tag == DT_MIPS_RLD_MAP_REL) && target) { addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize(); addr_t dyn_base = dynsym_section_sp->GetLoadBaseAddress(target); if (dyn_base == LLDB_INVALID_ADDRESS) return Address(); - Address addr; + Error error; - if (target->ReadPointerFromMemory(dyn_base + offset, false, error, addr)) - return addr; + if (symbol.d_tag == DT_MIPS_RLD_MAP) + { + // DT_MIPS_RLD_MAP tag stores an absolute address of the debug pointer. + Address addr; + if (target->ReadPointerFromMemory(dyn_base + offset, false, error, addr)) + return addr; + } + if (symbol.d_tag == DT_MIPS_RLD_MAP_REL) + { + // DT_MIPS_RLD_MAP_REL tag stores the offset to the debug pointer, relative to the address of the tag. + uint64_t rel_offset; + rel_offset = target->ReadUnsignedIntegerFromMemory(dyn_base + offset, false, GetAddressByteSize(), UINT64_MAX, error); + if (error.Success() && rel_offset != UINT64_MAX) + { + Address addr; + addr_t debug_ptr_address = dyn_base + (offset - GetAddressByteSize()) + rel_offset; + addr.SetOffset (debug_ptr_address); + return addr; + } + } } } @@ -1232,6 +1315,7 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l while (true) { // Parse the note header. If this fails, bail out. + const lldb::offset_t note_offset = offset; ELFNote note = ELFNote(); if (!note.Parse(data, &offset)) { @@ -1239,11 +1323,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l return error; } - // If a tag processor handles the tag, it should set processed to true, and - // the loop will assume the tag processing has moved entirely past the note's payload. - // Otherwise, leave it false and the end of the loop will handle the offset properly. - bool processed = false; - if (log) log->Printf ("ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, __FUNCTION__, note.n_name.c_str (), note.n_type); @@ -1252,9 +1331,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l (note.n_type == LLDB_NT_FREEBSD_ABI_TAG) && (note.n_descsz == LLDB_NT_FREEBSD_ABI_SIZE)) { - // We'll consume the payload below. - processed = true; - // Pull out the min version info. uint32_t version_info; if (data.GetU32 (&offset, &version_info, 1) == nullptr) @@ -1285,9 +1361,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l case LLDB_NT_GNU_ABI_TAG: if (note.n_descsz == LLDB_NT_GNU_ABI_SIZE) { - // We'll consume the payload below. - processed = true; - // Pull out the min OS version supporting the ABI. uint32_t version_info[4]; if (data.GetU32 (&offset, &version_info[0], note.n_descsz / 4) == nullptr) @@ -1330,9 +1403,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l // Only bother processing this if we don't already have the uuid set. if (!uuid.IsValid()) { - // We'll consume the payload below. - processed = true; - // 16 bytes is UUID|MD5, 20 bytes is SHA1 if ((note.n_descsz == 16 || note.n_descsz == 20)) { @@ -1355,10 +1425,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l (note.n_type == LLDB_NT_NETBSD_ABI_TAG) && (note.n_descsz == LLDB_NT_NETBSD_ABI_SIZE)) { - - // We'll consume the payload below. - processed = true; - // Pull out the min version info. uint32_t version_info; if (data.GetU32 (&offset, &version_info, 1) == nullptr) @@ -1378,8 +1444,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l else if ((note.n_type == LLDB_NT_GNU_ABI_TAG) && (note.n_name == LLDB_NT_OWNER_CSR)) { - // We'll consume the payload below. - processed = true; arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS); arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR); @@ -1397,9 +1461,48 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux); arch_spec.GetTriple().setEnvironment(llvm::Triple::EnvironmentType::Android); } + else if (note.n_name == LLDB_NT_OWNER_LINUX) + { + // This is sometimes found in core files and usually contains extended register info + arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux); + } + else if (note.n_name == LLDB_NT_OWNER_CORE) + { + // Parse the NT_FILE to look for stuff in paths to shared libraries + // As the contents look like: + // count = 0x000000000000000a (10) + // page_size = 0x0000000000001000 (4096) + // Index start end file_ofs path + // ===== ------------------ ------------------ ------------------ ------------------------------------- + // [ 0] 0x0000000000400000 0x0000000000401000 0x0000000000000000 /tmp/a.out + // [ 1] 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out + // [ 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out + // [ 3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000 /lib/x86_64-linux-gnu/libc-2.19.so + // [ 4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-gnu/libc-2.19.so + // [ 5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so + // [ 6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64-linux-gnu/libc-2.19.so + // [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so + // [ 8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64-linux-gnu/ld-2.19.so + // [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so + if (note.n_type == NT_FILE) + { + uint64_t count = data.GetU64(&offset); + offset += 8 + 3*8*count; // Skip page size and all start/end/file_ofs + for (size_t i=0; i<count; ++i) + { + llvm::StringRef path(data.GetCStr(&offset)); + if (path.startswith("/lib/x86_64-linux-gnu")) + { + arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux); + break; + } + } + } + } - if (!processed) - offset += llvm::RoundUpToAlignment(note.n_descsz, 4); + // Calculate the offset of the next note just in case "offset" has been used + // to poke at the contents of the note data + offset = note_offset + note.GetByteSize(); } return error; @@ -1496,8 +1599,8 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, I != section_headers.end(); ++I) { static ConstString g_sect_name_gnu_debuglink (".gnu_debuglink"); - const ELFSectionHeaderInfo &header = *I; - const uint64_t section_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size; + const ELFSectionHeaderInfo &sheader = *I; + const uint64_t section_size = sheader.sh_type == SHT_NOBITS ? 0 : sheader.sh_size; ConstString name(shstr_data.PeekCStr(I->sh_name)); I->section_name = name; @@ -1505,23 +1608,33 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, if (arch_spec.GetMachine() == llvm::Triple::mips || arch_spec.GetMachine() == llvm::Triple::mipsel || arch_spec.GetMachine() == llvm::Triple::mips64 || arch_spec.GetMachine() == llvm::Triple::mips64el) { - if (header.sh_type == SHT_MIPS_ABIFLAGS) + uint32_t arch_flags = arch_spec.GetFlags (); + DataExtractor data; + if (sheader.sh_type == SHT_MIPS_ABIFLAGS) { - DataExtractor data; - if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size)) + + if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size)) { lldb::offset_t ase_offset = 12; // MIPS ABI Flags Version: 0 - uint32_t arch_flags = arch_spec.GetFlags (); arch_flags |= data.GetU32 (&ase_offset); - arch_spec.SetFlags (arch_flags); } } + // Settings appropriate ArchSpec ABI Flags + if (header.e_flags & llvm::ELF::EF_MIPS_ABI2) + { + arch_flags |= lldb_private::ArchSpec::eMIPSABI_N32; + } + else if (header.e_flags & llvm::ELF::EF_MIPS_ABI_O32) + { + arch_flags |= lldb_private::ArchSpec::eMIPSABI_O32; + } + arch_spec.SetFlags (arch_flags); } if (name == g_sect_name_gnu_debuglink) { DataExtractor data; - if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size)) + if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size)) { lldb::offset_t gnu_debuglink_offset = 0; gnu_debuglink_file = data.GetCStr (&gnu_debuglink_offset); @@ -1531,7 +1644,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, } // Process ELF note section entries. - bool is_note_header = (header.sh_type == SHT_NOTE); + bool is_note_header = (sheader.sh_type == SHT_NOTE); // The section header ".note.android.ident" is stored as a // PROGBITS type header but it is actually a note header. @@ -1543,7 +1656,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, { // Allow notes to refine module info. DataExtractor data; - if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size)) + if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size)) { Error error = RefineModuleDetailsFromNote (data, arch_spec, uuid); if (error.Fail ()) @@ -1555,6 +1668,12 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, } } + // Make any unknown triple components to be unspecified unknowns. + if (arch_spec.GetTriple().getVendor() == llvm::Triple::UnknownVendor) + arch_spec.GetTriple().setVendorName (llvm::StringRef()); + if (arch_spec.GetTriple().getOS() == llvm::Triple::UnknownOS) + arch_spec.GetTriple().setOSName (llvm::StringRef()); + return section_headers.size(); } } @@ -1651,17 +1770,30 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list) static ConstString g_sect_name_tdata (".tdata"); static ConstString g_sect_name_tbss (".tbss"); static ConstString g_sect_name_dwarf_debug_abbrev (".debug_abbrev"); + static ConstString g_sect_name_dwarf_debug_addr (".debug_addr"); static ConstString g_sect_name_dwarf_debug_aranges (".debug_aranges"); static ConstString g_sect_name_dwarf_debug_frame (".debug_frame"); static ConstString g_sect_name_dwarf_debug_info (".debug_info"); static ConstString g_sect_name_dwarf_debug_line (".debug_line"); static ConstString g_sect_name_dwarf_debug_loc (".debug_loc"); static ConstString g_sect_name_dwarf_debug_macinfo (".debug_macinfo"); + static ConstString g_sect_name_dwarf_debug_macro (".debug_macro"); static ConstString g_sect_name_dwarf_debug_pubnames (".debug_pubnames"); static ConstString g_sect_name_dwarf_debug_pubtypes (".debug_pubtypes"); static ConstString g_sect_name_dwarf_debug_ranges (".debug_ranges"); static ConstString g_sect_name_dwarf_debug_str (".debug_str"); + static ConstString g_sect_name_dwarf_debug_str_offsets (".debug_str_offsets"); + static ConstString g_sect_name_dwarf_debug_abbrev_dwo (".debug_abbrev.dwo"); + static ConstString g_sect_name_dwarf_debug_info_dwo (".debug_info.dwo"); + static ConstString g_sect_name_dwarf_debug_line_dwo (".debug_line.dwo"); + static ConstString g_sect_name_dwarf_debug_macro_dwo (".debug_macro.dwo"); + static ConstString g_sect_name_dwarf_debug_loc_dwo (".debug_loc.dwo"); + static ConstString g_sect_name_dwarf_debug_str_dwo (".debug_str.dwo"); + static ConstString g_sect_name_dwarf_debug_str_offsets_dwo (".debug_str_offsets.dwo"); static ConstString g_sect_name_eh_frame (".eh_frame"); + static ConstString g_sect_name_arm_exidx (".ARM.exidx"); + static ConstString g_sect_name_arm_extab (".ARM.extab"); + static ConstString g_sect_name_go_symtab (".gosymtab"); SectionType sect_type = eSectionTypeOther; @@ -1694,18 +1826,31 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list) // MISSING? .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section, http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html // MISSING? .debug-index - http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644 // MISSING? .debug_types - Type descriptions from DWARF 4? See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo - else if (name == g_sect_name_dwarf_debug_abbrev) sect_type = eSectionTypeDWARFDebugAbbrev; - else if (name == g_sect_name_dwarf_debug_aranges) sect_type = eSectionTypeDWARFDebugAranges; - else if (name == g_sect_name_dwarf_debug_frame) sect_type = eSectionTypeDWARFDebugFrame; - else if (name == g_sect_name_dwarf_debug_info) sect_type = eSectionTypeDWARFDebugInfo; - else if (name == g_sect_name_dwarf_debug_line) sect_type = eSectionTypeDWARFDebugLine; - else if (name == g_sect_name_dwarf_debug_loc) sect_type = eSectionTypeDWARFDebugLoc; - else if (name == g_sect_name_dwarf_debug_macinfo) sect_type = eSectionTypeDWARFDebugMacInfo; - else if (name == g_sect_name_dwarf_debug_pubnames) sect_type = eSectionTypeDWARFDebugPubNames; - else if (name == g_sect_name_dwarf_debug_pubtypes) sect_type = eSectionTypeDWARFDebugPubTypes; - else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges; - else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr; - else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame; + else if (name == g_sect_name_dwarf_debug_abbrev) sect_type = eSectionTypeDWARFDebugAbbrev; + else if (name == g_sect_name_dwarf_debug_addr) sect_type = eSectionTypeDWARFDebugAddr; + else if (name == g_sect_name_dwarf_debug_aranges) sect_type = eSectionTypeDWARFDebugAranges; + else if (name == g_sect_name_dwarf_debug_frame) sect_type = eSectionTypeDWARFDebugFrame; + else if (name == g_sect_name_dwarf_debug_info) sect_type = eSectionTypeDWARFDebugInfo; + else if (name == g_sect_name_dwarf_debug_line) sect_type = eSectionTypeDWARFDebugLine; + else if (name == g_sect_name_dwarf_debug_loc) sect_type = eSectionTypeDWARFDebugLoc; + else if (name == g_sect_name_dwarf_debug_macinfo) sect_type = eSectionTypeDWARFDebugMacInfo; + else if (name == g_sect_name_dwarf_debug_macro) sect_type = eSectionTypeDWARFDebugMacro; + else if (name == g_sect_name_dwarf_debug_pubnames) sect_type = eSectionTypeDWARFDebugPubNames; + else if (name == g_sect_name_dwarf_debug_pubtypes) sect_type = eSectionTypeDWARFDebugPubTypes; + else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges; + else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr; + else if (name == g_sect_name_dwarf_debug_str_offsets) sect_type = eSectionTypeDWARFDebugStrOffsets; + else if (name == g_sect_name_dwarf_debug_abbrev_dwo) sect_type = eSectionTypeDWARFDebugAbbrev; + else if (name == g_sect_name_dwarf_debug_info_dwo) sect_type = eSectionTypeDWARFDebugInfo; + else if (name == g_sect_name_dwarf_debug_line_dwo) sect_type = eSectionTypeDWARFDebugLine; + else if (name == g_sect_name_dwarf_debug_macro_dwo) sect_type = eSectionTypeDWARFDebugMacro; + else if (name == g_sect_name_dwarf_debug_loc_dwo) sect_type = eSectionTypeDWARFDebugLoc; + else if (name == g_sect_name_dwarf_debug_str_dwo) sect_type = eSectionTypeDWARFDebugStr; + else if (name == g_sect_name_dwarf_debug_str_offsets_dwo) sect_type = eSectionTypeDWARFDebugStrOffsets; + else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame; + else if (name == g_sect_name_arm_exidx) sect_type = eSectionTypeARMexidx; + else if (name == g_sect_name_arm_extab) sect_type = eSectionTypeARMextab; + else if (name == g_sect_name_go_symtab) sect_type = eSectionTypeGoSymtab; switch (header.sh_type) { @@ -1731,7 +1876,7 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list) if (eSectionTypeOther == sect_type) { // the kalimba toolchain assumes that ELF section names are free-form. It does - // supports linkscripts which (can) give rise to various arbitarily named + // support linkscripts which (can) give rise to various arbitrarily named // sections being "Code" or "Data". sect_type = kalimbaSectionType(m_header, header); } @@ -1770,17 +1915,19 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list) { static const SectionType g_sections[] = { - eSectionTypeDWARFDebugAranges, - eSectionTypeDWARFDebugInfo, eSectionTypeDWARFDebugAbbrev, + eSectionTypeDWARFDebugAddr, + eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugFrame, + eSectionTypeDWARFDebugInfo, eSectionTypeDWARFDebugLine, - eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames, eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, + eSectionTypeDWARFDebugStr, + eSectionTypeDWARFDebugStrOffsets, eSectionTypeELFSymbolTable, }; SectionList *elf_section_list = m_sections_ap.get(); @@ -1805,6 +1952,29 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list) } } +// Find the arm/aarch64 mapping symbol character in the given symbol name. Mapping symbols have the +// form of "$<char>[.<any>]*". Additionally we recognize cases when the mapping symbol prefixed by +// an arbitrary string because if a symbol prefix added to each symbol in the object file with +// objcopy then the mapping symbols are also prefixed. +static char +FindArmAarch64MappingSymbol(const char* symbol_name) +{ + if (!symbol_name) + return '\0'; + + const char* dollar_pos = ::strchr(symbol_name, '$'); + if (!dollar_pos || dollar_pos[1] == '\0') + return '\0'; + + if (dollar_pos[2] == '\0' || dollar_pos[2] == '.') + return dollar_pos[1]; + return '\0'; +} + +#define STO_MIPS_ISA (3 << 6) +#define STO_MICROMIPS (2 << 6) +#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER) & STO_MIPS_ISA) == STO_MICROMIPS) + // private unsigned ObjectFileELF::ParseSymbols (Symtab *symtab, @@ -1840,6 +2010,13 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, // makes it highly unlikely that this will collide with anything else. bool skip_oatdata_oatexec = m_file.GetFilename() == ConstString("system@framework@boot.oat"); + ArchSpec arch; + GetArchitecture(arch); + + // 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; + unsigned i; for (i = 0; i < num_symbols; ++i) { @@ -1945,64 +2122,58 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, int64_t symbol_value_offset = 0; uint32_t additional_flags = 0; - ArchSpec arch; - if (GetArchitecture(arch)) + if (arch.IsValid()) { if (arch.GetMachine() == llvm::Triple::arm) { - if (symbol.getBinding() == STB_LOCAL && symbol_name && symbol_name[0] == '$') + if (symbol.getBinding() == STB_LOCAL) { - // These are reserved for the specification (e.g.: mapping - // symbols). We don't want to add them to the symbol table. - + char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name); if (symbol_type == eSymbolTypeCode) { - llvm::StringRef symbol_name_ref(symbol_name); - if (symbol_name_ref == "$a" || symbol_name_ref.startswith("$a.")) - { - // $a[.<any>]* - marks an ARM instruction sequence - m_address_class_map[symbol.st_value] = eAddressClassCode; - } - else if (symbol_name_ref == "$b" || symbol_name_ref.startswith("$b.") || - symbol_name_ref == "$t" || symbol_name_ref.startswith("$t.")) + switch (mapping_symbol) { - // $b[.<any>]* - marks a THUMB BL instruction sequence - // $t[.<any>]* - marks a THUMB instruction sequence - m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA; - } - else if (symbol_name_ref == "$d" || symbol_name_ref.startswith("$d.")) - { - // $d[.<any>]* - marks a data item sequence (e.g. lit pool) - m_address_class_map[symbol.st_value] = eAddressClassData; + case 'a': + // $a[.<any>]* - marks an ARM instruction sequence + m_address_class_map[symbol.st_value] = eAddressClassCode; + 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] = eAddressClassCodeAlternateISA; + break; + case 'd': + // $d[.<any>]* - marks a data item sequence (e.g. lit pool) + m_address_class_map[symbol.st_value] = eAddressClassData; + break; } } - - continue; + if (mapping_symbol) + continue; } } else if (arch.GetMachine() == llvm::Triple::aarch64) { - if (symbol.getBinding() == STB_LOCAL && symbol_name && symbol_name[0] == '$') + if (symbol.getBinding() == STB_LOCAL) { - // These are reserved for the specification (e.g.: mapping - // symbols). We don't want to add them to the symbol table. - + char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name); if (symbol_type == eSymbolTypeCode) { - llvm::StringRef symbol_name_ref(symbol_name); - if (symbol_name_ref == "$x" || symbol_name_ref.startswith("$x.")) + switch (mapping_symbol) { - // $x[.<any>]* - marks an A64 instruction sequence - m_address_class_map[symbol.st_value] = eAddressClassCode; - } - else if (symbol_name_ref == "$d" || symbol_name_ref.startswith("$d.")) - { - // $d[.<any>]* - marks a data item sequence (e.g. lit pool) - m_address_class_map[symbol.st_value] = eAddressClassData; + case 'x': + // $x[.<any>]* - marks an A64 instruction sequence + m_address_class_map[symbol.st_value] = eAddressClassCode; + break; + case 'd': + // $d[.<any>]* - marks a data item sequence (e.g. lit pool) + m_address_class_map[symbol.st_value] = eAddressClassData; + break; } } - - continue; + if (mapping_symbol) + continue; } } @@ -2029,11 +2200,46 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, } } } + + /* + * MIPS: + * The bit #0 of an address is used for ISA mode (1 for microMIPS, 0 for MIPS). + * This allows processer to switch between microMIPS and MIPS without any need + * for special mode-control register. However, apart from .debug_line, none of + * the ELF/DWARF sections set the ISA bit (for symbol or section). Use st_other + * flag to check whether the symbol is microMIPS and then set the address class + * accordingly. + */ + const llvm::Triple::ArchType llvm_arch = arch.GetMachine(); + if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel + || llvm_arch == llvm::Triple::mips64 || llvm_arch == llvm::Triple::mips64el) + { + if (IS_MICROMIPS(symbol.st_other)) + m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA; + else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) + { + symbol.st_value = symbol.st_value & (~1ull); + m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA; + } + else + { + if (symbol_type == eSymbolTypeCode) + m_address_class_map[symbol.st_value] = eAddressClassCode; + else if (symbol_type == eSymbolTypeData) + m_address_class_map[symbol.st_value] = eAddressClassData; + else + m_address_class_map[symbol.st_value] = eAddressClassUnknown; + } + } } - // If the symbol section we've found has no data (SHT_NOBITS), then check the module section - // list. This can happen if we're parsing the debug file and it has no .text section, for example. - if (symbol_section_sp && (symbol_section_sp->GetFileSize() == 0)) + // symbol_value_offset may contain 0 for ARM symbols or -1 for + // THUMB symbols. See above for more details. + uint64_t symbol_value = symbol.st_value + symbol_value_offset; + if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile) + symbol_value -= symbol_section_sp->GetFileAddress(); + + if (symbol_section_sp) { ModuleSP module_sp(GetModule()); if (module_sp) @@ -2042,20 +2248,17 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, if (module_section_list && module_section_list != section_list) { const ConstString §_name = symbol_section_sp->GetName(); - lldb::SectionSP section_sp (module_section_list->FindSectionByName (sect_name)); - if (section_sp && section_sp->GetFileSize()) - { - symbol_section_sp = section_sp; - } + 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; + if (section_it->second && section_it->second->GetFileSize()) + symbol_section_sp = section_it->second; } } } - // symbol_value_offset may contain 0 for ARM symbols or -1 for - // THUMB symbols. See above for more details. - uint64_t symbol_value = symbol.st_value + symbol_value_offset; - if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile) - symbol_value -= symbol_section_sp->GetFileAddress(); bool is_global = symbol.getBinding() == STB_GLOBAL; uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags; bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false; @@ -2069,7 +2272,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, Mangled mangled(ConstString(symbol_bare), is_mangled); // Now append the suffix back to mangled and unmangled names. Only do it if the - // demangling was sucessful (string is not empty). + // demangling was successful (string is not empty). if (has_suffix) { llvm::StringRef suffix = symbol_ref.substr(version_pos); @@ -2221,7 +2424,7 @@ ObjectFileELF::PLTRelocationType() } // Returns the size of the normal plt entries and the offset of the first normal plt entry. The -// 0th entry in the plt table is ususally a resolution entry which have different size in some +// 0th entry in the plt table is usually a resolution entry which have different size in some // architectures then the rest of the plt entries. static std::pair<uint64_t, uint64_t> GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader* plt_hdr) @@ -2237,8 +2440,8 @@ GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader { // The linker haven't set the plt_hdr->sh_entsize field. Try to guess the size of the plt // entries based on the number of entries and the size of the plt section with the - // asumption that the size of the 0th entry is at least as big as the size of the normal - // entries and it isn't mutch bigger then that. + // assumption that the size of the 0th entry is at least as big as the size of the normal + // entries and it isn't much bigger then that. if (plt_hdr->sh_addralign) plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign / (num_relocations + 1) * plt_hdr->sh_addralign; else @@ -2563,8 +2766,6 @@ ObjectFileELF::GetSymtab() uint64_t symbol_id = 0; lldb_private::Mutex::Locker locker(module_sp->GetMutex()); - m_symtab_ap.reset(new Symtab(this)); - // Sharable objects and dynamic executables usually have 2 distinct symbol // tables, one named ".symtab", and the other ".dynsym". The dynsym is a smaller // version of the symtab that only contains global symbols. The information found @@ -2578,7 +2779,10 @@ ObjectFileELF::GetSymtab() symtab = section_list->FindSectionByType (eSectionTypeELFDynamicSymbols, true).get(); } if (symtab) + { + m_symtab_ap.reset(new Symtab(symtab->GetObjectFile())); symbol_id += ParseSymbolTable (m_symtab_ap.get(), symbol_id, symtab); + } // DT_JMPREL // If present, this entry's d_ptr member holds the address of relocation @@ -2598,10 +2802,19 @@ ObjectFileELF::GetSymtab() user_id_t reloc_id = reloc_section->GetID(); const ELFSectionHeaderInfo *reloc_header = GetSectionHeaderByIndex(reloc_id); assert(reloc_header); + + if (m_symtab_ap == nullptr) + m_symtab_ap.reset(new Symtab(reloc_section->GetObjectFile())); ParseTrampolineSymbols (m_symtab_ap.get(), symbol_id, reloc_header, reloc_id); } } + + // If we still don't have any symtab then create an empty instance to avoid do the section + // lookup next time. + if (m_symtab_ap == nullptr) + m_symtab_ap.reset(new Symtab(this)); + m_symtab_ap->CalculateSymbolSizes(); } @@ -3000,6 +3213,27 @@ ObjectFileELF::GetArchitecture (ArchSpec &arch) ParseSectionHeaders(); } + if (CalculateType() == eTypeCoreFile && m_arch_spec.TripleOSIsUnspecifiedUnknown()) + { + // Core files don't have section headers yet they have PT_NOTE program headers + // that might shed more light on the architecture + if (ParseProgramHeaders()) + { + for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i) + { + const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i); + if (header && header->p_type == PT_NOTE && header->p_offset != 0 && header->p_filesz > 0) + { + DataExtractor data; + if (data.SetData (m_data, header->p_offset, header->p_filesz) == header->p_filesz) + { + lldb_private::UUID uuid; + RefineModuleDetailsFromNote (data, m_arch_spec, uuid); + } + } + } + } + } arch = m_arch_spec; return true; } diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 99088d1..4b97f92 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -10,9 +10,14 @@ #ifndef liblldb_ObjectFileELF_h_ #define liblldb_ObjectFileELF_h_ +// C Includes #include <stdint.h> + +// C++ Includes #include <vector> +// Other libraries and framework includes +// Project includes #include "lldb/lldb-private.h" #include "lldb/Host/FileSpec.h" #include "lldb/Symbol/ObjectFile.h" @@ -47,6 +52,12 @@ struct ELFNote /// True if the ELFRel entry was successfully read and false otherwise. bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset); + + size_t + GetByteSize() const + { + return 12 + llvm::RoundUpToAlignment (n_namesz, 4) + llvm::RoundUpToAlignment (n_descsz, 4); + } }; //------------------------------------------------------------------------------ @@ -59,6 +70,8 @@ class ObjectFileELF : public lldb_private::ObjectFile { public: + ~ObjectFileELF() override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ @@ -113,9 +126,6 @@ public: //------------------------------------------------------------------ // ObjectFile Protocol. //------------------------------------------------------------------ - virtual - ~ObjectFileELF(); - bool ParseHeader() override; @@ -211,6 +221,7 @@ private: { lldb_private::ConstString section_name; }; + typedef std::vector<ELFSectionHeaderInfo> SectionHeaderColl; typedef SectionHeaderColl::iterator SectionHeaderCollIter; typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter; @@ -428,4 +439,4 @@ private: RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch_spec, lldb_private::UUID &uuid); }; -#endif // #ifndef liblldb_ObjectFileELF_h_ +#endif // liblldb_ObjectFileELF_h_ diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h index 47140f5..39dbb3f 100644 --- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h +++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h @@ -10,10 +10,13 @@ #ifndef liblldb_ObjectFileJIT_h_ #define liblldb_ObjectFileJIT_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/Core/Address.h" #include "lldb/Symbol/ObjectFile.h" - //---------------------------------------------------------------------- // This class needs to be hidden as eventually belongs in a plugin that // will export the ObjectFile protocol @@ -22,6 +25,11 @@ class ObjectFileJIT : public lldb_private::ObjectFile { public: + ObjectFileJIT(const lldb::ModuleSP &module_sp, + const lldb::ObjectFileJITDelegateSP &delegate_sp); + + ~ObjectFileJIT() override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ @@ -62,81 +70,77 @@ public: //------------------------------------------------------------------ // Member Functions //------------------------------------------------------------------ - ObjectFileJIT (const lldb::ModuleSP &module_sp, - const lldb::ObjectFileJITDelegateSP &delegate_sp); - - virtual - ~ObjectFileJIT(); - - virtual bool - ParseHeader (); + bool + ParseHeader() override; - virtual bool + bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value, - bool value_is_offset); + bool value_is_offset) override; - virtual lldb::ByteOrder - GetByteOrder () const; + lldb::ByteOrder + GetByteOrder() const override; - virtual bool - IsExecutable () const; + bool + IsExecutable() const override; - virtual uint32_t - GetAddressByteSize () const; + uint32_t + GetAddressByteSize() const override; - virtual lldb_private::Symtab * - GetSymtab(); + lldb_private::Symtab * + GetSymtab() override; - virtual bool - IsStripped (); + bool + IsStripped() override; - virtual void - CreateSections (lldb_private::SectionList &unified_section_list); + void + CreateSections(lldb_private::SectionList &unified_section_list) override; - virtual void - Dump (lldb_private::Stream *s); + void + Dump(lldb_private::Stream *s) override; - virtual bool - GetArchitecture (lldb_private::ArchSpec &arch); + bool + GetArchitecture(lldb_private::ArchSpec &arch) override; - virtual bool - GetUUID (lldb_private::UUID* uuid); + bool + GetUUID(lldb_private::UUID* uuid) override; - virtual uint32_t - GetDependentModules (lldb_private::FileSpecList& files); + uint32_t + GetDependentModules(lldb_private::FileSpecList& files) override; + + size_t + ReadSectionData(const lldb_private::Section *section, + lldb::offset_t section_offset, + void *dst, + size_t dst_len) const override; + + size_t + ReadSectionData(const lldb_private::Section *section, + lldb_private::DataExtractor& section_data) const override; - virtual size_t - ReadSectionData (const lldb_private::Section *section, - lldb::offset_t section_offset, - void *dst, - size_t dst_len) const; - virtual size_t - ReadSectionData (const lldb_private::Section *section, - lldb_private::DataExtractor& section_data) const; + lldb_private::Address + GetEntryPointAddress() override; + lldb_private::Address + GetHeaderAddress() override; + + ObjectFile::Type + CalculateType() override; + + ObjectFile::Strata + CalculateStrata() override; + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; - virtual lldb_private::Address - GetEntryPointAddress (); - - virtual lldb_private::Address - GetHeaderAddress (); - - virtual ObjectFile::Type - CalculateType(); - - virtual ObjectFile::Strata - CalculateStrata(); protected: lldb::ObjectFileJITDelegateWP m_delegate_wp; }; -#endif // liblldb_ObjectFileJIT_h_ +#endif // liblldb_ObjectFileJIT_h_ |