diff options
Diffstat (limited to 'source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
| -rw-r--r-- | source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 425 | 
1 files changed, 218 insertions, 207 deletions
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index d62afa34bbe8..3f8502548fc2 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -18,6 +18,7 @@  #include "lldb/Core/PluginManager.h"  #include "lldb/Core/Section.h"  #include "lldb/Host/FileSystem.h" +#include "lldb/Host/LZMA.h"  #include "lldb/Symbol/DWARFCallFrameInfo.h"  #include "lldb/Symbol/SymbolContext.h"  #include "lldb/Target/SectionLoadList.h" @@ -29,12 +30,13 @@  #include "lldb/Utility/Status.h"  #include "lldb/Utility/Stream.h"  #include "lldb/Utility/Timer.h" -  #include "llvm/ADT/IntervalMap.h"  #include "llvm/ADT/PointerUnion.h"  #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/ELF.h"  #include "llvm/Object/Decompressor.h"  #include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/CRC.h"  #include "llvm/Support/MathExtras.h"  #include "llvm/Support/MemoryBuffer.h"  #include "llvm/Support/MipsABIFlags.h" @@ -80,41 +82,6 @@ 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  /// Generic wrapper for ELFRel and ELFRela. @@ -264,8 +231,7 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {    const char *cstr = data.GetCStr(offset, llvm::alignTo(n_namesz, 4));    if (cstr == nullptr) {      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); -    if (log) -      log->Printf("Failed to parse note name lacking nul terminator"); +    LLDB_LOGF(log, "Failed to parse note name lacking nul terminator");      return false;    } @@ -333,6 +299,8 @@ static uint32_t subTypeFromElfHeader(const elf::ELFHeader &header) {    return LLDB_INVALID_CPUTYPE;  } +char ObjectFileELF::ID; +  // Arbitrary constant used as UUID prefix for core files.  const uint32_t ObjectFileELF::g_core_uuid_magic(0xE210C); @@ -429,67 +397,9 @@ bool ObjectFileELF::MagicBytesMatch(DataBufferSP &data_sp,    return false;  } -/* - * crc function from http://svnweb.freebsd.org/base/head/sys/libkern/crc32.c - * - *   COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or - *   code or tables extracted from it, as desired without restriction. - */ -static uint32_t calc_crc32(uint32_t crc, const void *buf, size_t size) { -  static const uint32_t g_crc32_tab[] = { -      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, -      0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, -      0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, -      0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, -      0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, -      0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, -      0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, -      0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, -      0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, -      0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, -      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, -      0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, -      0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, -      0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, -      0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, -      0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, -      0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, -      0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, -      0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, -      0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, -      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, -      0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, -      0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, -      0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, -      0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, -      0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, -      0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, -      0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, -      0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, -      0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, -      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, -      0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, -      0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, -      0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, -      0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, -      0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, -      0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, -      0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, -      0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, -      0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, -      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, -      0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, -      0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; -  const uint8_t *p = (const uint8_t *)buf; - -  crc = crc ^ ~0U; -  while (size--) -    crc = g_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); -  return crc ^ ~0U; -} - -static uint32_t calc_gnu_debuglink_crc32(const void *buf, size_t size) { -  return calc_crc32(0U, buf, size); +static uint32_t calc_crc32(uint32_t init, const DataExtractor &data) { +  return llvm::crc32( +      init, llvm::makeArrayRef(data.GetDataStart(), data.GetByteSize()));  }  uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32( @@ -509,8 +419,7 @@ uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32(          break;        } -      core_notes_crc = calc_crc32(core_notes_crc, segment_data.GetDataStart(), -                                  segment_data.GetByteSize()); +      core_notes_crc = calc_crc32(core_notes_crc, segment_data);      }    } @@ -608,10 +517,9 @@ size_t ObjectFileELF::GetModuleSpecifications(            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])); +          LLDB_LOGF(log, "ObjectFileELF::%s file '%s' module OSABI: %s", +                    __FUNCTION__, file.GetPath().c_str(), +                    OSABIAsCString(header.e_ident[EI_OSABI]));            // SetArchitecture should have set the vendor to unknown            vendor = spec.GetArchitecture().GetTriple().getVendor(); @@ -623,10 +531,10 @@ size_t ObjectFileELF::GetModuleSpecifications(            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()); +            LLDB_LOGF(log, +                      "ObjectFileELF::%s file '%s' set ELF module OS type " +                      "from ELF header OSABI.", +                      __FUNCTION__, file.GetPath().c_str());            }            data_sp = MapFileData(file, -1, file_offset); @@ -652,12 +560,12 @@ size_t ObjectFileELF::GetModuleSpecifications(            llvm::Triple &spec_triple = spec.GetArchitecture().GetTriple(); -          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()); +          LLDB_LOGF(log, +                    "ObjectFileELF::%s file '%s' module set to triple: %s " +                    "(architecture %s)", +                    __FUNCTION__, file.GetPath().c_str(), +                    spec_triple.getTriple().c_str(), +                    spec.GetArchitecture().GetArchitectureName());            if (!uuid.IsValid()) {              uint32_t core_notes_crc = 0; @@ -682,8 +590,7 @@ size_t ObjectFileELF::GetModuleSpecifications(                  core_notes_crc =                      CalculateELFNotesSegmentsCRC32(program_headers, data);                } else { -                gnu_debuglink_crc = calc_gnu_debuglink_crc32( -                    data.GetDataStart(), data.GetByteSize()); +                gnu_debuglink_crc = calc_crc32(0, data);                }              }              using u32le = llvm::support::ulittle32_t; @@ -721,27 +628,16 @@ ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp,                               DataBufferSP &data_sp, lldb::offset_t data_offset,                               const FileSpec *file, lldb::offset_t file_offset,                               lldb::offset_t length) -    : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset), -      m_header(), m_uuid(), m_gnu_debuglink_file(), m_gnu_debuglink_crc(0), -      m_program_headers(), m_section_headers(), m_dynamic_symbols(), -      m_filespec_up(), m_entry_point_address(), m_arch_spec() { +    : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset) {    if (file)      m_file = *file; -  ::memset(&m_header, 0, sizeof(m_header));  }  ObjectFileELF::ObjectFileELF(const lldb::ModuleSP &module_sp,                               DataBufferSP &header_data_sp,                               const lldb::ProcessSP &process_sp,                               addr_t header_addr) -    : ObjectFile(module_sp, process_sp, header_addr, header_data_sp), -      m_header(), m_uuid(), m_gnu_debuglink_file(), m_gnu_debuglink_crc(0), -      m_program_headers(), m_section_headers(), m_dynamic_symbols(), -      m_filespec_up(), m_entry_point_address(), m_arch_spec() { -  ::memset(&m_header, 0, sizeof(m_header)); -} - -ObjectFileELF::~ObjectFileELF() {} +    : ObjectFile(module_sp, process_sp, header_addr, header_data_sp) {}  bool ObjectFileELF::IsExecutable() const {    return ((m_header.e_type & ET_EXEC) != 0) || (m_header.e_entry != 0); @@ -872,8 +768,7 @@ UUID ObjectFileELF::GetUUID() {        }      } else {        if (!m_gnu_debuglink_crc) -        m_gnu_debuglink_crc = calc_gnu_debuglink_crc32(m_data.GetDataStart(), -                                                       m_data.GetByteSize()); +        m_gnu_debuglink_crc = calc_crc32(0, m_data);        if (m_gnu_debuglink_crc) {          // Use 4 bytes of crc from the .gnu_debuglink section.          u32le data(m_gnu_debuglink_crc); @@ -885,14 +780,10 @@ UUID ObjectFileELF::GetUUID() {    return m_uuid;  } -lldb_private::FileSpecList ObjectFileELF::GetDebugSymbolFilePaths() { -  FileSpecList file_spec_list; - -  if (!m_gnu_debuglink_file.empty()) { -    FileSpec file_spec(m_gnu_debuglink_file); -    file_spec_list.Append(file_spec); -  } -  return file_spec_list; +llvm::Optional<FileSpec> ObjectFileELF::GetDebugLink() { +  if (m_gnu_debuglink_file.empty()) +    return llvm::None; +  return FileSpec(m_gnu_debuglink_file);  }  uint32_t ObjectFileELF::GetDependentModules(FileSpecList &files) { @@ -1120,9 +1011,8 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,        return error;      } -    if (log) -      log->Printf("ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, -                  __FUNCTION__, note.n_name.c_str(), note.n_type); +    LLDB_LOGF(log, "ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, +              __FUNCTION__, note.n_name.c_str(), note.n_type);      // Process FreeBSD ELF notes.      if ((note.n_name == LLDB_NT_OWNER_FREEBSD) && @@ -1147,11 +1037,11 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,        arch_spec.GetTriple().setOSName(os_name);        arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor); -      if (log) -        log->Printf("ObjectFileELF::%s detected FreeBSD %" PRIu32 ".%" PRIu32 -                    ".%" PRIu32, -                    __FUNCTION__, version_major, version_minor, -                    static_cast<uint32_t>(version_info % 1000)); +      LLDB_LOGF(log, +                "ObjectFileELF::%s detected FreeBSD %" PRIu32 ".%" PRIu32 +                ".%" PRIu32, +                __FUNCTION__, version_major, version_minor, +                static_cast<uint32_t>(version_info % 1000));      }      // Process GNU ELF notes.      else if (note.n_name == LLDB_NT_OWNER_GNU) { @@ -1172,12 +1062,11 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,              arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);              arch_spec.GetTriple().setVendor(                  llvm::Triple::VendorType::UnknownVendor); -            if (log) -              log->Printf( -                  "ObjectFileELF::%s detected Linux, min version %" PRIu32 -                  ".%" PRIu32 ".%" PRIu32, -                  __FUNCTION__, version_info[1], version_info[2], -                  version_info[3]); +            LLDB_LOGF(log, +                      "ObjectFileELF::%s detected Linux, min version %" PRIu32 +                      ".%" PRIu32 ".%" PRIu32, +                      __FUNCTION__, version_info[1], version_info[2], +                      version_info[3]);              // FIXME we have the minimal version number, we could be propagating              // that.  version_info[1] = OS Major, version_info[2] = OS Minor,              // version_info[3] = Revision. @@ -1186,30 +1075,28 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,              arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);              arch_spec.GetTriple().setVendor(                  llvm::Triple::VendorType::UnknownVendor); -            if (log) -              log->Printf("ObjectFileELF::%s detected Hurd (unsupported), min " -                          "version %" PRIu32 ".%" PRIu32 ".%" PRIu32, -                          __FUNCTION__, version_info[1], version_info[2], -                          version_info[3]); +            LLDB_LOGF(log, +                      "ObjectFileELF::%s detected Hurd (unsupported), min " +                      "version %" PRIu32 ".%" PRIu32 ".%" PRIu32, +                      __FUNCTION__, version_info[1], version_info[2], +                      version_info[3]);              break;            case LLDB_NT_GNU_ABI_OS_SOLARIS:              arch_spec.GetTriple().setOS(llvm::Triple::OSType::Solaris);              arch_spec.GetTriple().setVendor(                  llvm::Triple::VendorType::UnknownVendor); -            if (log) -              log->Printf( -                  "ObjectFileELF::%s detected Solaris, min version %" PRIu32 -                  ".%" PRIu32 ".%" PRIu32, -                  __FUNCTION__, version_info[1], version_info[2], -                  version_info[3]); +            LLDB_LOGF(log, +                      "ObjectFileELF::%s detected Solaris, min version %" PRIu32 +                      ".%" PRIu32 ".%" PRIu32, +                      __FUNCTION__, version_info[1], version_info[2], +                      version_info[3]);              break;            default: -            if (log) -              log->Printf( -                  "ObjectFileELF::%s unrecognized OS in note, id %" PRIu32 -                  ", min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, -                  __FUNCTION__, version_info[0], version_info[1], -                  version_info[2], version_info[3]); +            LLDB_LOGF(log, +                      "ObjectFileELF::%s unrecognized OS in note, id %" PRIu32 +                      ", min version %" PRIu32 ".%" PRIu32 ".%" PRIu32, +                      __FUNCTION__, version_info[0], version_info[1], +                      version_info[2], version_info[3]);              break;            }          } @@ -1618,9 +1505,8 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers,                                              section_size) == section_size)) {              Status error = RefineModuleDetailsFromNote(data, arch_spec, uuid);              if (error.Fail()) { -              if (log) -                log->Printf("ObjectFileELF::%s ELF note processing failed: %s", -                            __FUNCTION__, error.AsCString()); +              LLDB_LOGF(log, "ObjectFileELF::%s ELF note processing failed: %s", +                        __FUNCTION__, error.AsCString());              }            }          } @@ -1790,6 +1676,8 @@ class VMAddressProvider {    VMMap Segments = VMMap(Alloc);    VMMap Sections = VMMap(Alloc);    lldb_private::Log *Log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES); +  size_t SegmentCount = 0; +  std::string SegmentName;    VMRange GetVMRange(const ELFSectionHeader &H) {      addr_t Address = H.sh_addr; @@ -1804,18 +1692,23 @@ class VMAddressProvider {    }  public: -  VMAddressProvider(ObjectFile::Type Type) : ObjectType(Type) {} +  VMAddressProvider(ObjectFile::Type Type, llvm::StringRef SegmentName) +      : ObjectType(Type), SegmentName(SegmentName) {} + +  std::string GetNextSegmentName() const { +    return llvm::formatv("{0}[{1}]", SegmentName, SegmentCount).str(); +  }    llvm::Optional<VMRange> GetAddressInfo(const ELFProgramHeader &H) {      if (H.p_memsz == 0) { -      LLDB_LOG(Log, -               "Ignoring zero-sized PT_LOAD segment. Corrupt object file?"); +      LLDB_LOG(Log, "Ignoring zero-sized {0} segment. Corrupt object file?", +               SegmentName);        return llvm::None;      }      if (Segments.overlaps(H.p_vaddr, H.p_vaddr + H.p_memsz)) { -      LLDB_LOG(Log, -               "Ignoring overlapping PT_LOAD segment. Corrupt object file?"); +      LLDB_LOG(Log, "Ignoring overlapping {0} segment. Corrupt object file?", +               SegmentName);        return llvm::None;      }      return VMRange(H.p_vaddr, H.p_memsz); @@ -1850,6 +1743,7 @@ public:    void AddSegment(const VMRange &Range, SectionSP Seg) {      Segments.insert(Range.GetRangeBase(), Range.GetRangeEnd(), std::move(Seg)); +    ++SegmentCount;    }    void AddSection(SectionAddressInfo Info, SectionSP Sect) { @@ -1867,29 +1761,32 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {    if (m_sections_up)      return; -  m_sections_up = llvm::make_unique<SectionList>(); -  VMAddressProvider address_provider(GetType()); +  m_sections_up = std::make_unique<SectionList>(); +  VMAddressProvider regular_provider(GetType(), "PT_LOAD"); +  VMAddressProvider tls_provider(GetType(), "PT_TLS"); -  size_t LoadID = 0;    for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) {      const ELFProgramHeader &PHdr = EnumPHdr.value(); -    if (PHdr.p_type != PT_LOAD) +    if (PHdr.p_type != PT_LOAD && PHdr.p_type != PT_TLS)        continue; -    auto InfoOr = address_provider.GetAddressInfo(PHdr); +    VMAddressProvider &provider = +        PHdr.p_type == PT_TLS ? tls_provider : regular_provider; +    auto InfoOr = provider.GetAddressInfo(PHdr);      if (!InfoOr)        continue; -    ConstString Name(("PT_LOAD[" + llvm::Twine(LoadID++) + "]").str());      uint32_t Log2Align = llvm::Log2_64(std::max<elf_xword>(PHdr.p_align, 1));      SectionSP Segment = std::make_shared<Section>( -        GetModule(), this, SegmentID(EnumPHdr.index()), Name, -        eSectionTypeContainer, InfoOr->GetRangeBase(), InfoOr->GetByteSize(), -        PHdr.p_offset, PHdr.p_filesz, Log2Align, /*flags*/ 0); +        GetModule(), this, SegmentID(EnumPHdr.index()), +        ConstString(provider.GetNextSegmentName()), eSectionTypeContainer, +        InfoOr->GetRangeBase(), InfoOr->GetByteSize(), PHdr.p_offset, +        PHdr.p_filesz, Log2Align, /*flags*/ 0);      Segment->SetPermissions(GetPermissions(PHdr)); +    Segment->SetIsThreadSpecific(PHdr.p_type == PT_TLS);      m_sections_up->AddSection(Segment); -    address_provider.AddSegment(*InfoOr, std::move(Segment)); +    provider.AddSegment(*InfoOr, std::move(Segment));    }    ParseSectionHeaders(); @@ -1904,7 +1801,9 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {      const uint64_t file_size =          header.sh_type == SHT_NOBITS ? 0 : header.sh_size; -    auto InfoOr = address_provider.GetAddressInfo(header); +    VMAddressProvider &provider = +        header.sh_flags & SHF_TLS ? tls_provider : regular_provider; +    auto InfoOr = provider.GetAddressInfo(header);      if (!InfoOr)        continue; @@ -1935,13 +1834,77 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {      section_sp->SetIsThreadSpecific(header.sh_flags & SHF_TLS);      (InfoOr->Segment ? InfoOr->Segment->GetChildren() : *m_sections_up)          .AddSection(section_sp); -    address_provider.AddSection(std::move(*InfoOr), std::move(section_sp)); +    provider.AddSection(std::move(*InfoOr), std::move(section_sp));    }    // For eTypeDebugInfo files, the Symbol Vendor will take care of updating the    // unified section list.    if (GetType() != eTypeDebugInfo)      unified_section_list = *m_sections_up; +   +  // If there's a .gnu_debugdata section, we'll try to read the .symtab that's +  // embedded in there and replace the one in the original object file (if any). +  // If there's none in the orignal object file, we add it to it. +  if (auto gdd_obj_file = GetGnuDebugDataObjectFile()) { +    if (auto gdd_objfile_section_list = gdd_obj_file->GetSectionList()) { +      if (SectionSP symtab_section_sp = +              gdd_objfile_section_list->FindSectionByType( +                  eSectionTypeELFSymbolTable, true)) { +        SectionSP module_section_sp = unified_section_list.FindSectionByType( +            eSectionTypeELFSymbolTable, true); +        if (module_section_sp) +          unified_section_list.ReplaceSection(module_section_sp->GetID(), +                                              symtab_section_sp); +        else +          unified_section_list.AddSection(symtab_section_sp); +      } +    } +  }   +} + +std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() { +  if (m_gnu_debug_data_object_file != nullptr) +    return m_gnu_debug_data_object_file; + +  SectionSP section = +      GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata")); +  if (!section) +    return nullptr; + +  if (!lldb_private::lzma::isAvailable()) { +    GetModule()->ReportWarning( +        "No LZMA support found for reading .gnu_debugdata section"); +    return nullptr; +  } + +  // Uncompress the data +  DataExtractor data; +  section->GetSectionData(data); +  llvm::SmallVector<uint8_t, 0> uncompressedData; +  auto err = lldb_private::lzma::uncompress(data.GetData(), uncompressedData); +  if (err) { +    GetModule()->ReportWarning( +        "An error occurred while decompression the section %s: %s", +        section->GetName().AsCString(), llvm::toString(std::move(err)).c_str()); +    return nullptr; +  } + +  // Construct ObjectFileELF object from decompressed buffer +  DataBufferSP gdd_data_buf( +      new DataBufferHeap(uncompressedData.data(), uncompressedData.size())); +  auto fspec = GetFileSpec().CopyByAppendingPathComponent( +      llvm::StringRef("gnu_debugdata")); +  m_gnu_debug_data_object_file.reset(new ObjectFileELF( +      GetModule(), gdd_data_buf, 0, &fspec, 0, gdd_data_buf->GetByteSize())); + +  // This line is essential; otherwise a breakpoint can be set but not hit. +  m_gnu_debug_data_object_file->SetType(ObjectFile::eTypeDebugInfo); + +  ArchSpec spec = m_gnu_debug_data_object_file->GetArchitecture(); +  if (spec && m_gnu_debug_data_object_file->SetModulesArchitecture(spec)) +    return m_gnu_debug_data_object_file; +   +  return nullptr;  }  // Find the arm/aarch64 mapping symbol character in the given symbol name. @@ -2246,8 +2209,6 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,      bool is_global = symbol.getBinding() == STB_GLOBAL;      uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags; -    bool is_mangled = (symbol_name[0] == '_' && symbol_name[1] == 'Z'); -      llvm::StringRef symbol_ref(symbol_name);      // Symbol names may contain @VERSION suffixes. Find those and strip them @@ -2255,7 +2216,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,      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); +    Mangled mangled(symbol_bare);      // Now append the suffix back to mangled and unmangled names. Only do it if      // the demangling was successful (string is not empty). @@ -2486,14 +2447,11 @@ static unsigned ParsePLTRelocations(        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          symbol_name,           // symbol name. -        is_mangled,            // is the symbol name mangled?          eSymbolTypeTrampoline, // Type of this symbol          false,                 // Is this globally visible?          false,                 // Is this symbol debug info? @@ -2654,7 +2612,7 @@ unsigned ObjectFileELF::ApplyRelocations(                 ((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN))) {              Log *log =                  lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES); -            log->Printf("Failed to apply debug info relocations"); +            LLDB_LOGF(log, "Failed to apply debug info relocations");              break;            }            uint32_t truncated_addr = (value & 0xFFFFFFFF); @@ -2749,19 +2707,29 @@ Symtab *ObjectFileELF::GetSymtab() {      // while the reverse is not necessarily true.      Section *symtab =          section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get(); -    if (!symtab) { -      // The symtab section is non-allocable and can be stripped, so if it -      // doesn't exist then use the dynsym section which should always be -      // there. -      symtab = -          section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true) -              .get(); -    }      if (symtab) {        m_symtab_up.reset(new Symtab(symtab->GetObjectFile()));        symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, symtab);      } +    // The symtab section is non-allocable and can be stripped, while the +    // .dynsym section which should always be always be there. To support the +    // minidebuginfo case we parse .dynsym when there's a .gnu_debuginfo +    // section, nomatter if .symtab was already parsed or not. This is because +    // minidebuginfo normally removes the .symtab symbols which have their +    // matching .dynsym counterparts. +    if (!symtab || +        GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) { +      Section *dynsym = +          section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true) +              .get(); +      if (dynsym) { +        if (!m_symtab_up) +          m_symtab_up.reset(new Symtab(dynsym->GetObjectFile())); +        symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, dynsym); +      } +    } +      // DT_JMPREL      //      If present, this entry's d_ptr member holds the address of      //      relocation @@ -2803,6 +2771,50 @@ Symtab *ObjectFileELF::GetSymtab() {      if (m_symtab_up == nullptr)        m_symtab_up.reset(new Symtab(this)); +    // In the event that there's no symbol entry for the entry point we'll +    // artifically create one. We delegate to the symtab object the figuring +    // out of the proper size, this will usually make it span til the next +    // symbol it finds in the section. This means that if there are missing +    // symbols the entry point might span beyond its function definition. +    // We're fine with this as it doesn't make it worse than not having a +    // symbol entry at all. +    if (CalculateType() == eTypeExecutable) { +      ArchSpec arch = GetArchitecture(); +      auto entry_point_addr = GetEntryPointAddress(); +      bool is_valid_entry_point = +          entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset(); +      addr_t entry_point_file_addr = entry_point_addr.GetFileAddress(); +      if (is_valid_entry_point && !m_symtab_up->FindSymbolContainingFileAddress( +                                      entry_point_file_addr)) { +        uint64_t symbol_id = m_symtab_up->GetNumSymbols(); +        Symbol symbol(symbol_id, +                      GetNextSyntheticSymbolName().GetCString(), // Symbol name. +                      eSymbolTypeCode, // Type of this symbol. +                      true,            // Is this globally visible? +                      false,           // Is this symbol debug info? +                      false,           // Is this symbol a trampoline? +                      true,            // Is this symbol artificial? +                      entry_point_addr.GetSection(), // Section where this +                                                     // symbol is defined. +                      0,     // Offset in section or symbol value. +                      0,     // Size. +                      false, // Size is valid. +                      false, // Contains linker annotations? +                      0);    // Symbol flags. +        m_symtab_up->AddSymbol(symbol); +        // When the entry point is arm thumb we need to explicitly set its +        // class address to reflect that. This is important because expression +        // evaluation relies on correctly setting a breakpoint at this +        // address. +        if (arch.GetMachine() == llvm::Triple::arm && +            (entry_point_file_addr & 1)) +          m_address_class_map[entry_point_file_addr ^ 1] = +              AddressClass::eCodeAlternateISA; +        else +          m_address_class_map[entry_point_file_addr] = AddressClass::eCode; +      } +    } +      m_symtab_up->CalculateSymbolSizes();    } @@ -2881,7 +2893,6 @@ void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table,          Symbol eh_symbol(              symbol_id,       // Symbol table index.              symbol_name,     // Symbol name. -            false,           // Is the symbol name mangled?              eSymbolTypeCode, // Type of this symbol.              true,            // Is this globally visible?              false,           // Is this symbol debug info?  | 
