diff options
Diffstat (limited to 'source/Plugins/ObjectFile/ELF')
| -rw-r--r-- | source/Plugins/ObjectFile/ELF/ELFHeader.cpp | 5 | ||||
| -rw-r--r-- | source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 451 | ||||
| -rw-r--r-- | source/Plugins/ObjectFile/ELF/ObjectFileELF.h | 94 | 
3 files changed, 367 insertions, 183 deletions
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp index 12392c24407b..641a7cc3e0e2 100644 --- a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp +++ b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp @@ -180,7 +180,7 @@ ELFHeader::GetRelocationJumpSlotType() const          slot = R_PPC64_JMP_SLOT;          break;      case EM_386: -    case EM_486: +    case EM_IAMCU: // FIXME: is this correct?          slot = R_386_JUMP_SLOT;          break;      case EM_X86_64: @@ -278,9 +278,8 @@ ELFSymbol::typeToCString(unsigned char type)      ENUM_TO_CSTR(STT_FILE);      ENUM_TO_CSTR(STT_COMMON);      ENUM_TO_CSTR(STT_TLS); -    ENUM_TO_CSTR(STT_LOOS); -    ENUM_TO_CSTR(STT_HIOS);      ENUM_TO_CSTR(STT_GNU_IFUNC); +    ENUM_TO_CSTR(STT_HIOS);      ENUM_TO_CSTR(STT_LOPROC);      ENUM_TO_CSTR(STT_HIPROC);      } diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index e7bf20e18008..f9cec2415382 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -27,7 +27,6 @@  #include "lldb/Symbol/SymbolContext.h"  #include "lldb/Target/SectionLoadList.h"  #include "lldb/Target/Target.h" -#include "lldb/Host/HostInfo.h"  #include "llvm/ADT/PointerUnion.h"  #include "llvm/ADT/StringRef.h" @@ -48,6 +47,7 @@ const char *const LLDB_NT_OWNER_FREEBSD = "FreeBSD";  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";  // ELF note type definitions  const elf_word LLDB_NT_FREEBSD_ABI_TAG  = 0x01; @@ -283,8 +283,39 @@ kalimbaVariantFromElfFlags(const elf::elf_word e_flags)  }  static uint32_t +mipsVariantFromElfFlags(const elf::elf_word e_flags, uint32_t endian) +{ +    const uint32_t mips_arch = e_flags & llvm::ELF::EF_MIPS_ARCH; +    uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown; + +    switch (mips_arch) +    { +        case llvm::ELF::EF_MIPS_ARCH_32: +            return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32el : ArchSpec::eMIPSSubType_mips32; +        case llvm::ELF::EF_MIPS_ARCH_32R2: +            return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r2el : ArchSpec::eMIPSSubType_mips32r2; +        case llvm::ELF::EF_MIPS_ARCH_32R6: +            return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r6el : ArchSpec::eMIPSSubType_mips32r6; +        case llvm::ELF::EF_MIPS_ARCH_64: +            return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64el : ArchSpec::eMIPSSubType_mips64; +        case llvm::ELF::EF_MIPS_ARCH_64R2: +            return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64r2el : ArchSpec::eMIPSSubType_mips64r2; +        case llvm::ELF::EF_MIPS_ARCH_64R6: +            return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64r6el : ArchSpec::eMIPSSubType_mips64r6; +        default: +            break; +    } + +    return arch_variant; +} + +static uint32_t  subTypeFromElfHeader(const elf::ELFHeader& header)  { +    if (header.e_machine == llvm::ELF::EM_MIPS) +        return mipsVariantFromElfFlags (header.e_flags, +            header.e_ident[EI_DATA]); +      return          llvm::ELF::EM_CSR_KALIMBA == header.e_machine ?          kalimbaVariantFromElfFlags(header.e_flags) : @@ -365,7 +396,7 @@ ObjectFileELF::CreateInstance (const lldb::ModuleSP &module_sp,  {      if (!data_sp)      { -        data_sp = file->MemoryMapFileContents(file_offset, length); +        data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length);          data_offset = 0;      } @@ -376,7 +407,7 @@ ObjectFileELF::CreateInstance (const lldb::ModuleSP &module_sp,          {              // Update the data to contain the entire file if it doesn't already              if (data_sp->GetByteSize() < length) { -                data_sp = file->MemoryMapFileContents(file_offset, length); +                data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length);                  data_offset = 0;                  magic = data_sp->GetBytes();              } @@ -566,6 +597,12 @@ OSABIAsCString (unsigned char osabi_byte)  #undef _MAKE_OSABI_CASE  } +// +// WARNING : This function is being deprecated +// It's functionality has moved to ArchSpec::SetArchitecture +// This function is only being kept to validate the move. +// +// TODO : Remove this function  static bool  GetOsFromOSABI (unsigned char osabi_byte, llvm::Triple::OSType &ostype)  { @@ -604,29 +641,33 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,          {              if (data_sp)              { -                ModuleSpec spec; -                spec.GetFileSpec() = file; +                ModuleSpec spec (file);                  const uint32_t sub_type = subTypeFromElfHeader(header);                  spec.GetArchitecture().SetArchitecture(eArchTypeELF,                                                         header.e_machine, -                                                       sub_type); +                                                       sub_type, +                                                       header.e_ident[EI_OSABI]);                  if (spec.GetArchitecture().IsValid())                  {                      llvm::Triple::OSType ostype; -                    // First try to determine the OS type from the OSABI field in the elf header. +                    llvm::Triple::VendorType vendor; +                    llvm::Triple::OSType spec_ostype = spec.GetArchitecture ().GetTriple ().getOS ();                      if (log)                          log->Printf ("ObjectFileELF::%s file '%s' module OSABI: %s", __FUNCTION__, file.GetPath ().c_str (), OSABIAsCString (header.e_ident[EI_OSABI])); -                    if (GetOsFromOSABI (header.e_ident[EI_OSABI], ostype) && ostype != llvm::Triple::OSType::UnknownOS) -                    { -                        spec.GetArchitecture ().GetTriple ().setOS (ostype); -                        // Also clear the vendor so we don't end up with situations like -                        // x86_64-apple-FreeBSD. -                        spec.GetArchitecture ().GetTriple ().setVendor (llvm::Triple::VendorType::UnknownVendor); +                    // SetArchitecture should have set the vendor to unknown +                    vendor = spec.GetArchitecture ().GetTriple ().getVendor (); +                    assert(vendor == llvm::Triple::UnknownVendor); +                    // +                    // Validate it is ok to remove GetOsFromOSABI +                    GetOsFromOSABI (header.e_ident[EI_OSABI], ostype); +                    assert(spec_ostype == ostype); +                    if (spec_ostype != llvm::Triple::OSType::UnknownOS) +                    {                          if (log)                              log->Printf ("ObjectFileELF::%s file '%s' set ELF module OS type from ELF header OSABI.", __FUNCTION__, file.GetPath ().c_str ());                      } @@ -636,7 +677,7 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,                      size_t section_header_end = header.e_shoff + header.e_shnum * header.e_shentsize;                      if (section_header_end > data_sp->GetByteSize())                      { -                        data_sp = file.MemoryMapFileContents (file_offset, section_header_end); +                        data_sp = file.MemoryMapFileContentsIfLocal (file_offset, section_header_end);                          data.SetData(data_sp);                      } @@ -647,14 +688,7 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,                      GetSectionHeaderInfo(section_headers, data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc, spec.GetArchitecture ()); -                    // If the module vendor is not set and the module OS matches this host OS, set the module vendor to the host vendor.                      llvm::Triple &spec_triple = spec.GetArchitecture ().GetTriple (); -                    if (spec_triple.getVendor () == llvm::Triple::VendorType::UnknownVendor) -                    { -                        const llvm::Triple &host_triple = HostInfo::GetArchitecture().GetTriple(); -                        if (spec_triple.getOS () == host_triple.getOS ()) -                            spec_triple.setVendor (host_triple.getVendor ()); -                    }                      if (log)                          log->Printf ("ObjectFileELF::%s file '%s' module set to triple: %s (architecture %s)", __FUNCTION__, file.GetPath ().c_str (), spec_triple.getTriple ().c_str (), spec.GetArchitecture ().GetArchitectureName ()); @@ -678,7 +712,7 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,                                  size_t program_headers_end = header.e_phoff + header.e_phnum * header.e_phentsize;                                  if (program_headers_end > data_sp->GetByteSize())                                  { -                                    data_sp = file.MemoryMapFileContents(file_offset, program_headers_end); +                                    data_sp = file.MemoryMapFileContentsIfLocal(file_offset, program_headers_end);                                      data.SetData(data_sp);                                  }                                  ProgramHeaderColl program_headers; @@ -693,7 +727,7 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,                                  if (segment_data_end > data_sp->GetByteSize())                                  { -                                    data_sp = file.MemoryMapFileContents(file_offset, segment_data_end); +                                    data_sp = file.MemoryMapFileContentsIfLocal(file_offset, segment_data_end);                                      data.SetData(data_sp);                                  } @@ -702,7 +736,7 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,                              else                              {                                  // Need to map entire file into memory to calculate the crc. -                                data_sp = file.MemoryMapFileContents (file_offset, SIZE_MAX); +                                data_sp = file.MemoryMapFileContentsIfLocal (file_offset, SIZE_MAX);                                  data.SetData(data_sp);                                  gnu_debuglink_crc = calc_gnu_debuglink_crc32 (data.GetDataStart(), data.GetByteSize());                              } @@ -773,10 +807,10 @@ ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp,  }  ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp, -                              DataBufferSP& data_sp, +                              DataBufferSP& header_data_sp,                                const lldb::ProcessSP &process_sp,                                addr_t header_addr) : -    ObjectFile(module_sp, process_sp, LLDB_INVALID_ADDRESS, data_sp), +    ObjectFile(module_sp, process_sp, header_addr, header_data_sp),      m_header(),      m_uuid(),      m_gnu_debuglink_file(), @@ -826,7 +860,14 @@ ObjectFileELF::SetLoadAddress (Target &target,                      // if (section_sp && !section_sp->IsThreadSpecific())                      if (section_sp && section_sp->Test(SHF_ALLOC))                      { -                        if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + value)) +                        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;                      }                  } @@ -869,25 +910,18 @@ ObjectFileELF::GetAddressClass (addr_t file_addr)      if (res != eAddressClassCode)          return res; -    ArchSpec arch_spec; -    GetArchitecture(arch_spec); -    if (arch_spec.GetMachine() != llvm::Triple::arm) -        return res; - -    auto symtab = GetSymtab(); -    if (symtab == nullptr) -        return res; - -    auto symbol = symtab->FindSymbolContainingFileAddress(file_addr); -    if (symbol == nullptr) -        return res; +    auto ub = m_address_class_map.upper_bound(file_addr); +    if (ub == m_address_class_map.begin()) +    { +        // No entry in the address class map before the address. Return +        // default address class for an address in a code section. +        return eAddressClassCode; +    } -    // Thumb symbols have the lower bit set in the flags field so we just check -    // for that. -    if (symbol->GetFlags() & ARM_ELF_SYM_IS_THUMB) -        res = eAddressClassCodeAlternateISA; +    // Move iterator to the address class entry preceding address +    --ub; -    return res; +    return ub->second;  }  size_t @@ -906,7 +940,28 @@ bool  ObjectFileELF::ParseHeader()  {      lldb::offset_t offset = 0; -    return m_header.Parse(m_data, &offset); +    if (!m_header.Parse(m_data, &offset)) +        return false; + +    if (!IsInMemory()) +        return true; + +    // For in memory object files m_data might not contain the full object file. Try to load it +    // until the end of the "Section header table" what is at the end of the ELF file. +    addr_t file_size = m_header.e_shoff + m_header.e_shnum * m_header.e_shentsize; +    if (m_data.GetByteSize() < file_size) +    { +        ProcessSP process_sp (m_process_wp.lock()); +        if (!process_sp) +            return false; + +        DataBufferSP data_sp = ReadMemory(process_sp, m_memory_addr, file_size); +        if (!data_sp) +            return false; +        m_data.SetData(data_sp, 0, file_size); +    } + +    return true;  }  bool @@ -1337,6 +1392,11 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l                  (void)cstr;              }          } +        else if (note.n_name == LLDB_NT_OWNER_ANDROID) +        { +            arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux); +            arch_spec.GetTriple().setEnvironment(llvm::Triple::EnvironmentType::Android); +        }          if (!processed)              offset += llvm::RoundUpToAlignment(note.n_descsz, 4); @@ -1366,32 +1426,15 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers,      // We'll refine this with note data as we parse the notes.      if (arch_spec.GetTriple ().getOS () == llvm::Triple::OSType::UnknownOS)      { +        llvm::Triple::OSType ostype; +        llvm::Triple::OSType spec_ostype;          const uint32_t sub_type = subTypeFromElfHeader(header); -        arch_spec.SetArchitecture (eArchTypeELF, header.e_machine, sub_type); - -        switch (arch_spec.GetAddressByteSize()) -        { -        case 4: -            { -                const ArchSpec host_arch32 = HostInfo::GetArchitecture(HostInfo::eArchKind32); -                if (host_arch32.GetCore() == arch_spec.GetCore()) -                { -                    arch_spec.GetTriple().setOSName(HostInfo::GetOSString().data()); -                    arch_spec.GetTriple().setVendorName(HostInfo::GetVendorString().data()); -                } -            } -            break; -        case 8: -            { -                const ArchSpec host_arch64 = HostInfo::GetArchitecture(HostInfo::eArchKind64); -                if (host_arch64.GetCore() == arch_spec.GetCore()) -                { -                    arch_spec.GetTriple().setOSName(HostInfo::GetOSString().data()); -                    arch_spec.GetTriple().setVendorName(HostInfo::GetVendorString().data()); -                } -            } -            break; -        } +        arch_spec.SetArchitecture (eArchTypeELF, header.e_machine, sub_type, header.e_ident[EI_OSABI]); +        // +        // Validate if it is ok to remove GetOsFromOSABI +        GetOsFromOSABI (header.e_ident[EI_OSABI], ostype); +        spec_ostype = arch_spec.GetTriple ().getOS (); +        assert(spec_ostype == ostype);      }      // If there are no section headers we are done. @@ -1453,7 +1496,15 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers,                  }                  // Process ELF note section entries. -                if (header.sh_type == SHT_NOTE) +                bool is_note_header = (header.sh_type == SHT_NOTE); + +                // The section header ".note.android.ident" is stored as a +                // PROGBITS type header but it is actually a note header. +                static ConstString g_sect_name_android_ident (".note.android.ident"); +                if (!is_note_header && name == g_sect_name_android_ident) +                    is_note_header = true; + +                if (is_note_header)                  {                      // Allow notes to refine module info.                      DataExtractor data; @@ -1504,6 +1555,13 @@ ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id)      return DataExtractor(m_data, segment_header->p_offset, segment_header->p_filesz);  } +std::string +ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const +{ +    size_t pos = symbol_name.find("@"); +    return symbol_name.substr(0, pos).str(); +} +  //----------------------------------------------------------------------  // ParseSectionHeaders  //---------------------------------------------------------------------- @@ -1525,6 +1583,17 @@ ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id)      return NULL;  } +lldb::user_id_t +ObjectFileELF::GetSectionIndexByName(const char* name) +{ +    if (!name || !name[0] || !ParseSectionHeaders()) +        return 0; +    for (size_t i = 1; i < m_section_headers.size(); ++i) +        if (m_section_headers[i].section_name == ConstString(name)) +            return i; +    return 0; +} +  void  ObjectFileELF::CreateSections(SectionList &unified_section_list)  { @@ -1826,45 +1895,92 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,              }          } -        ArchSpec arch;          int64_t symbol_value_offset = 0;          uint32_t additional_flags = 0; -        if (GetArchitecture(arch) && -            arch.GetMachine() == llvm::Triple::arm) +        ArchSpec arch; +        if (GetArchitecture(arch))          { -            // ELF symbol tables may contain some mapping symbols. They provide -            // information about the underlying data. There are three of them -            // currently defined: -            //   $a[.<any>]* - marks an ARM instruction sequence -            //   $t[.<any>]* - marks a THUMB instruction sequence -            //   $d[.<any>]* - marks a data item sequence (e.g. lit pool) -            // These symbols interfere with normal debugger operations and we -            // don't need them. We can drop them here. - -            static const llvm::StringRef g_armelf_arm_marker("$a"); -            static const llvm::StringRef g_armelf_thumb_marker("$t"); -            static const llvm::StringRef g_armelf_data_marker("$d"); -            llvm::StringRef symbol_name_ref(symbol_name); - -            if (symbol_name && -                (symbol_name_ref.startswith(g_armelf_arm_marker) || -                 symbol_name_ref.startswith(g_armelf_thumb_marker) || -                 symbol_name_ref.startswith(g_armelf_data_marker))) -                continue; +            if (arch.GetMachine() == llvm::Triple::arm) +            { +                if (symbol.getBinding() == STB_LOCAL && symbol_name && symbol_name[0] == '$') +                { +                    // These are reserved for the specification (e.g.: mapping +                    // symbols). We don't want to add them to the symbol table. -            // THUMB functions have the lower bit of their address set. Fixup -            // the actual address and mark the symbol as THUMB. -            if (symbol_type == eSymbolTypeCode && symbol.st_value & 1) +                    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.")) +                        { +                            // $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; +                        } +                    } + +                    continue; +                } +            } +            else if (arch.GetMachine() == llvm::Triple::aarch64)              { -                // Substracting 1 from the address effectively unsets -                // the low order bit, which results in the address -                // actually pointing to the beginning of the symbol. -                // This delta will be used below in conjuction with -                // symbol.st_value to produce the final symbol_value -                // that we store in the symtab. -                symbol_value_offset = -1; -                additional_flags = ARM_ELF_SYM_IS_THUMB; +                if (symbol.getBinding() == STB_LOCAL && symbol_name && symbol_name[0] == '$') +                { +                    // These are reserved for the specification (e.g.: mapping +                    // symbols). We don't want to add them to the symbol table. + +                    if (symbol_type == eSymbolTypeCode) +                    { +                        llvm::StringRef symbol_name_ref(symbol_name); +                        if (symbol_name_ref == "$x" || symbol_name_ref.startswith("$x.")) +                        { +                            // $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; +                        } +                    } + +                    continue; +                } +            } + +            if (arch.GetMachine() == llvm::Triple::arm) +            { +                if (symbol_type == eSymbolTypeCode) +                { +                    if (symbol.st_value & 1) +                    { +                        // Subtracting 1 from the address effectively unsets +                        // the low order bit, which results in the address +                        // actually pointing to the beginning of the symbol. +                        // This delta will be used below in conjunction with +                        // symbol.st_value to produce the final symbol_value +                        // that we store in the symtab. +                        symbol_value_offset = -1; +                        additional_flags = ARM_ELF_SYM_IS_THUMB; +                        m_address_class_map[symbol.st_value^1] = eAddressClassCodeAlternateISA; +                    } +                    else +                    { +                        // This address is ARM +                        m_address_class_map[symbol.st_value] = eAddressClassCode; +                    } +                }              }          } @@ -1890,30 +2006,53 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,          // 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; +        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; +        llvm::StringRef symbol_ref(symbol_name); + +        // Symbol names may contain @VERSION suffixes. Find those and strip them temporarily. +        size_t version_pos = symbol_ref.find('@'); +        bool has_suffix = version_pos != llvm::StringRef::npos; +        llvm::StringRef symbol_bare = symbol_ref.substr(0, version_pos); +        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). +        if (has_suffix) +        { +            llvm::StringRef suffix = symbol_ref.substr(version_pos); + +            llvm::StringRef mangled_name = mangled.GetMangledName().GetStringRef(); +            if (! mangled_name.empty()) +                mangled.SetMangledName( ConstString((mangled_name + suffix).str()) ); + +            llvm::StringRef demangled_name = mangled.GetDemangledName().GetStringRef(); +            if (! demangled_name.empty()) +                mangled.SetDemangledName( ConstString((demangled_name + suffix).str()) ); +        } +          Symbol dc_symbol(              i + start_id,       // ID is the original symbol table index. -            symbol_name,        // Symbol name. -            is_mangled,         // Is the symbol name mangled? +            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?              false,              // Is this symbol artificial? -            symbol_section_sp,  // Section in which this symbol is defined or null. -            symbol_value,       // Offset in section or symbol value. -            symbol.st_size,     // Size in bytes of this symbol. -            true,               // Size is valid -            flags);             // Symbol flags. +            AddressRange( +                symbol_section_sp,  // Section in which this symbol is defined or null. +                symbol_value,       // Offset in section or symbol value. +                symbol.st_size),    // Size in bytes of this symbol. +            symbol.st_size != 0,    // Size is valid if it is not 0 +            has_suffix,             // Contains linker annotations? +            flags);                 // Symbol flags.          symtab->AddSymbol(dc_symbol);      } -      return i;  } @@ -2033,6 +2172,36 @@ ObjectFileELF::PLTRelocationType()      return 0;  } +// 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 +// architectures then the rest of the plt entries. +static std::pair<uint64_t, uint64_t> +GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader* plt_hdr) +{ +    const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize; + +    // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16 bytes. +    // So round the entsize up by the alignment if addralign is set. +    elf_xword plt_entsize = plt_hdr->sh_addralign ? +        llvm::RoundUpToAlignment (plt_hdr->sh_entsize, plt_hdr->sh_addralign) : plt_hdr->sh_entsize; + +    if (plt_entsize == 0) +    { +        // 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. +        if (plt_hdr->sh_addralign) +            plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign / (num_relocations + 1) * plt_hdr->sh_addralign; +        else +            plt_entsize = plt_hdr->sh_size / (num_relocations + 1); +    } + +    elf_xword plt_offset = plt_hdr->sh_size - num_relocations * plt_entsize; + +    return std::make_pair(plt_entsize, plt_offset); +} +  static unsigned  ParsePLTRelocations(Symtab *symbol_table,                      user_id_t start_id, @@ -2049,10 +2218,9 @@ ParsePLTRelocations(Symtab *symbol_table,      ELFRelocation rel(rel_type);      ELFSymbol symbol;      lldb::offset_t offset = 0; -    // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16 bytes. -    // So round the entsize up by the alignment if addralign is set. -    const elf_xword plt_entsize = plt_hdr->sh_addralign ? -        llvm::RoundUpToAlignment (plt_hdr->sh_entsize, plt_hdr->sh_addralign) : plt_hdr->sh_entsize; + +    uint64_t plt_offset, plt_entsize; +    std::tie(plt_entsize, plt_offset) = GetPltEntrySizeAndOffset(rel_hdr, plt_hdr);      const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;      typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel); @@ -2081,13 +2249,12 @@ ParsePLTRelocations(Symtab *symbol_table,              continue;          lldb::offset_t symbol_offset = reloc_symbol(rel) * sym_hdr->sh_entsize; -        uint64_t plt_index = (i + 1) * plt_entsize; -          if (!symbol.Parse(symtab_data, &symbol_offset))              break;          const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);          bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false; +        uint64_t plt_index = plt_offset + i * plt_entsize;          Symbol jump_symbol(              i + start_id,    // Symbol table index @@ -2102,6 +2269,7 @@ ParsePLTRelocations(Symtab *symbol_table,              plt_index,       // Offset in section or symbol value.              plt_entsize,     // Size in bytes of this symbol.              true,            // Size is valid +            false,           // Contains linker annotations?              0);              // Symbol flags.          symbol_table->AddSymbol(jump_symbol); @@ -2123,6 +2291,13 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,      user_id_t symtab_id = rel_hdr->sh_link;      user_id_t plt_id = rel_hdr->sh_info; +    // If the link field doesn't point to the appropriate symbol name table then +    // try to find it by name as some compiler don't fill in the link fields. +    if (!symtab_id) +        symtab_id = GetSectionIndexByName(".dynsym"); +    if (!plt_id) +        plt_id = GetSectionIndexByName(".plt"); +      if (!symtab_id || !plt_id)          return 0; @@ -2234,7 +2409,7 @@ ObjectFileELF::RelocateSection(Symtab* symtab, const ELFHeader *hdr, const ELFSe                  symbol = symtab->FindSymbolByID(reloc_symbol(rel));                  if (symbol)                  { -                    addr_t value = symbol->GetAddress().GetFileAddress(); +                    addr_t value = symbol->GetAddressRef().GetFileAddress();                      DataBufferSP& data_buffer_sp = debug_data.GetSharedDataBuffer();                      uint64_t* dst = reinterpret_cast<uint64_t*>(data_buffer_sp->GetBytes() + rel_section->GetFileOffset() + ELFRelocation::RelocOffset64(rel));                      *dst = value + ELFRelocation::RelocAddend64(rel); @@ -2247,7 +2422,7 @@ ObjectFileELF::RelocateSection(Symtab* symtab, const ELFHeader *hdr, const ELFSe                  symbol = symtab->FindSymbolByID(reloc_symbol(rel));                  if (symbol)                  { -                    addr_t value = symbol->GetAddress().GetFileAddress(); +                    addr_t value = symbol->GetAddressRef().GetFileAddress();                      value += ELFRelocation::RelocAddend32(rel);                      assert((reloc_type(rel) == R_X86_64_32 && (value <= UINT32_MAX)) ||                             (reloc_type(rel) == R_X86_64_32S && @@ -2333,7 +2508,7 @@ ObjectFileELF::GetSymtab()      if (m_symtab_ap.get() == NULL)      { -        SectionList *section_list = GetSectionList(); +        SectionList *section_list = module_sp->GetSectionList();          if (!section_list)              return NULL; @@ -2379,6 +2554,7 @@ ObjectFileELF::GetSymtab()                  ParseTrampolineSymbols (m_symtab_ap.get(), symbol_id, reloc_header, reloc_id);              }          } +        m_symtab_ap->CalculateSymbolSizes();      }      for (SectionHeaderCollIter I = m_section_headers.begin(); @@ -2443,6 +2619,7 @@ ObjectFileELF::ResolveSymbolForAddress(const Address& so_addr, bool verify_uniqu                          offset,               // Offset in section or symbol value.                          range.GetByteSize(),  // Size in bytes of this symbol.                          true,                 // Size is valid. +                        false,                // Contains linker annotations?                          0);                   // Symbol flags.                  if (symbol_id == m_symtab_ap->AddSymbol(eh_symbol))                      return m_symtab_ap->SymbolAtIndex(symbol_id); @@ -2631,22 +2808,22 @@ ObjectFileELF::DumpELFProgramHeader_p_flags(Stream *s, elf_word p_flags)  void  ObjectFileELF::DumpELFProgramHeaders(Stream *s)  { -    if (ParseProgramHeaders()) +    if (!ParseProgramHeaders()) +        return; + +    s->PutCString("Program Headers\n"); +    s->PutCString("IDX  p_type          p_offset p_vaddr  p_paddr  " +                  "p_filesz p_memsz  p_flags                   p_align\n"); +    s->PutCString("==== --------------- -------- -------- -------- " +                  "-------- -------- ------------------------- --------\n"); + +    uint32_t idx = 0; +    for (ProgramHeaderCollConstIter I = m_program_headers.begin(); +         I != m_program_headers.end(); ++I, ++idx)      { -        s->PutCString("Program Headers\n"); -        s->PutCString("IDX  p_type          p_offset p_vaddr  p_paddr  " -                      "p_filesz p_memsz  p_flags                   p_align\n"); -        s->PutCString("==== --------------- -------- -------- -------- " -                      "-------- -------- ------------------------- --------\n"); - -        uint32_t idx = 0; -        for (ProgramHeaderCollConstIter I = m_program_headers.begin(); -             I != m_program_headers.end(); ++I, ++idx) -        { -            s->Printf("[%2u] ", idx); -            ObjectFileELF::DumpELFProgramHeader(s, *I); -            s->EOL(); -        } +        s->Printf("[%2u] ", idx); +        ObjectFileELF::DumpELFProgramHeader(s, *I); +        s->EOL();      }  } diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index b10dfb532cd0..99088d166b12 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -104,11 +104,11 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;      //------------------------------------------------------------------      // ObjectFile Protocol. @@ -116,64 +116,64 @@ public:      virtual      ~ObjectFileELF(); -    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::AddressClass -    GetAddressClass (lldb::addr_t file_addr); +    lldb::AddressClass +    GetAddressClass (lldb::addr_t file_addr) override; -    virtual lldb_private::Symtab * -    GetSymtab(); +    lldb_private::Symtab * +    GetSymtab() override; -    virtual lldb_private::Symbol * -    ResolveSymbolForAddress(const lldb_private::Address& so_addr, bool verify_unique); +    lldb_private::Symbol * +    ResolveSymbolForAddress(const lldb_private::Address& so_addr, bool verify_unique) 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 lldb_private::FileSpecList -    GetDebugSymbolFilePaths(); +    lldb_private::FileSpecList +    GetDebugSymbolFilePaths() override; -    virtual uint32_t -    GetDependentModules(lldb_private::FileSpecList& files); +    uint32_t +    GetDependentModules(lldb_private::FileSpecList& files) override; -    virtual lldb_private::Address -    GetImageInfoAddress(lldb_private::Target *target); +    lldb_private::Address +    GetImageInfoAddress(lldb_private::Target *target) override; -    virtual lldb_private::Address -    GetEntryPointAddress (); +    lldb_private::Address +    GetEntryPointAddress () override; -    virtual ObjectFile::Type -    CalculateType(); +    ObjectFile::Type +    CalculateType() override; -    virtual ObjectFile::Strata -    CalculateStrata(); +    ObjectFile::Strata +    CalculateStrata() override;      // Returns number of program headers found in the ELF file.      size_t @@ -187,6 +187,9 @@ public:      lldb_private::DataExtractor      GetSegmentDataByIndex(lldb::user_id_t id); +    std::string +    StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override; +  private:      ObjectFileELF(const lldb::ModuleSP &module_sp,                    lldb::DataBufferSP& data_sp, @@ -196,7 +199,7 @@ private:                    lldb::offset_t length);      ObjectFileELF (const lldb::ModuleSP &module_sp, -                   lldb::DataBufferSP& data_sp, +                   lldb::DataBufferSP& header_data_sp,                     const lldb::ProcessSP &process_sp,                     lldb::addr_t header_addr); @@ -216,6 +219,8 @@ private:      typedef DynamicSymbolColl::iterator         DynamicSymbolCollIter;      typedef DynamicSymbolColl::const_iterator   DynamicSymbolCollConstIter; +    typedef std::map<lldb::addr_t, lldb::AddressClass> FileAddressToAddressClassMap; +      /// Version of this reader common to all plugins based on this class.      static const uint32_t m_plugin_version = 1;      static const uint32_t g_core_uuid_magic; @@ -249,6 +254,9 @@ private:      /// The architecture detected from parsing elf file contents.      lldb_private::ArchSpec m_arch_spec; +    /// The address class for each symbol in the elf file +    FileAddressToAddressClassMap m_address_class_map; +      /// Returns a 1 based index of the given section header.      size_t      SectionIndex(const SectionHeaderCollIter &I);  | 
