[Lldb-commits] [lldb] r368010 - ObjectFileELF: permit thread-local sections with overlapping file addresses

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Tue Aug 6 03:04:28 PDT 2019


Author: labath
Date: Tue Aug  6 03:04:27 2019
New Revision: 368010

URL: http://llvm.org/viewvc/llvm-project?rev=368010&view=rev
Log:
ObjectFileELF: permit thread-local sections with overlapping file addresses

Summary:
In an attempt to make file-address-based lookups more predictable, in D55998
we started ignoring sections which would result in file address
overlaps. It turns out this was too aggressive because thread-local
sections typically will have file addresses which apear to overlap
regular data/code. This does not cause a problem at runtime because
thread-local sections are loaded into memory using special logic, but it
can cause problems for lldb when trying to lookup objects by their file
address.

This patch changes ObjectFileELF to permit thread-local sections to
overlap regular ones by essentially giving them a separate address
space. It also makes them more symmetrical to regular sections by
creating container sections from PT_TLS segments.

Simultaneously, the patch changes the regular file address lookup logic
to ignore sections with the thread-specific bit set. I believe this is
what the users looking up file addresses would typically expect, as
looking up thread-local data generally requires more complex logic (e.g.
DWARF has a special opcode for that).

Reviewers: clayborg, jingham, MaskRay

Subscribers: emaste, aprantl, arichardson, lldb-commits

Differential Revision: https://reviews.llvm.org/D65282

Added:
    lldb/trunk/lit/Modules/ELF/PT_LOAD-overlap-PT_TLS.yaml
    lldb/trunk/lit/Modules/ELF/PT_TLS-overlap-PT_LOAD.yaml
Modified:
    lldb/trunk/source/Core/Section.cpp
    lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp

Added: lldb/trunk/lit/Modules/ELF/PT_LOAD-overlap-PT_TLS.yaml
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Modules/ELF/PT_LOAD-overlap-PT_TLS.yaml?rev=368010&view=auto
==============================================================================
--- lldb/trunk/lit/Modules/ELF/PT_LOAD-overlap-PT_TLS.yaml (added)
+++ lldb/trunk/lit/Modules/ELF/PT_LOAD-overlap-PT_TLS.yaml Tue Aug  6 03:04:27 2019
@@ -0,0 +1,63 @@
+# Overlapping PT_LOAD and PT_TLS segments should be able to exist side by side.
+
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+# RUN: lldb %t -o "image lookup -a 0x1000" -b | FileCheck --check-prefix=LOOKUP %s
+
+# CHECK:        Index: 0
+# CHECK-NEXT:   ID: 0xffffffffffffffff
+# CHECK-NEXT:   Name: PT_TLS[0]
+# CHECK-NEXT:   Type: container
+# CHECK-NEXT:   Permissions: rw-
+# CHECK-NEXT:   Thread specific: yes
+# CHECK-NEXT:   VM address: 0x1000
+# CHECK-NEXT:   VM size: 16
+# CHECK-NEXT:   File size: 0
+# CHECK-NEXT:   Showing 1 subsections
+
+# CHECK:        Index: 1
+# CHECK-NEXT:   ID: 0xfffffffffffffffe
+# CHECK-NEXT:   Name: PT_LOAD[0]
+# CHECK-NEXT:   Type: container
+# CHECK-NEXT:   Permissions: rw-
+# CHECK-NEXT:   Thread specific: no
+# CHECK-NEXT:   VM address: 0x1000
+# CHECK-NEXT:   VM size: 16
+# CHECK-NEXT:   File size: 16
+# CHECK-NEXT:   Showing 1 subsections
+
+# LOOKUP-LABEL: image lookup -a 0x1000
+# LOOKUP:       Address: {{.*}}.PT_LOAD[0]..data + 0)
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_ARM
+Sections:
+  - Name:            .tbss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_ALLOC, SHF_WRITE, SHF_TLS ]
+    Address:         0x1000
+    AddressAlign:    0x4
+    Size:            0x10
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_WRITE ]
+    Address:         0x1000
+    AddressAlign:    0x4
+    Size:            0x10
+ProgramHeaders:
+  - Type: PT_TLS
+    Flags: [ PF_R, PF_W ]
+    VAddr: 0x1000
+    Align: 0x4
+    Sections:
+      - Section: .tbss
+  - Type: PT_LOAD
+    Flags: [ PF_W, PF_R ]
+    VAddr: 0x1000
+    Align: 0x4
+    Sections:
+      - Section: .data

Added: lldb/trunk/lit/Modules/ELF/PT_TLS-overlap-PT_LOAD.yaml
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/Modules/ELF/PT_TLS-overlap-PT_LOAD.yaml?rev=368010&view=auto
==============================================================================
--- lldb/trunk/lit/Modules/ELF/PT_TLS-overlap-PT_LOAD.yaml (added)
+++ lldb/trunk/lit/Modules/ELF/PT_TLS-overlap-PT_LOAD.yaml Tue Aug  6 03:04:27 2019
@@ -0,0 +1,63 @@
+# Overlapping PT_LOAD and PT_TLS segments should be able to exist side by side.
+
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+# RUN: lldb %t -o "image lookup -a 0x1000" -b | FileCheck --check-prefix=LOOKUP %s
+
+# CHECK:        Index: 0
+# CHECK-NEXT:   ID: 0xffffffffffffffff
+# CHECK-NEXT:   Name: PT_LOAD[0]
+# CHECK-NEXT:   Type: container
+# CHECK-NEXT:   Permissions: rw-
+# CHECK-NEXT:   Thread specific: no
+# CHECK-NEXT:   VM address: 0x1000
+# CHECK-NEXT:   VM size: 16
+# CHECK-NEXT:   File size: 16
+# CHECK-NEXT:   Showing 1 subsections
+
+# CHECK:        Index: 1
+# CHECK-NEXT:   ID: 0xfffffffffffffffe
+# CHECK-NEXT:   Name: PT_TLS[0]
+# CHECK-NEXT:   Type: container
+# CHECK-NEXT:   Permissions: rw-
+# CHECK-NEXT:   Thread specific: yes
+# CHECK-NEXT:   VM address: 0x1000
+# CHECK-NEXT:   VM size: 16
+# CHECK-NEXT:   File size: 0
+# CHECK-NEXT:   Showing 1 subsections
+
+# LOOKUP-LABEL: image lookup -a 0x1000
+# LOOKUP:       Address: {{.*}}.PT_LOAD[0]..data + 0)
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_ARM
+Sections:
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_WRITE ]
+    Address:         0x1000
+    AddressAlign:    0x4
+    Size:            0x10
+  - Name:            .tbss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_ALLOC, SHF_WRITE, SHF_TLS ]
+    Address:         0x1000
+    AddressAlign:    0x4
+    Size:            0x10
+ProgramHeaders:
+  - Type: PT_LOAD
+    Flags: [ PF_W, PF_R ]
+    VAddr: 0x1000
+    Align: 0x4
+    Sections:
+      - Section: .data
+  - Type: PT_TLS
+    Flags: [ PF_R, PF_W ]
+    VAddr: 0x1000
+    Align: 0x4
+    Sections:
+      - Section: .tbss

Modified: lldb/trunk/source/Core/Section.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Section.cpp?rev=368010&r1=368009&r2=368010&view=diff
==============================================================================
--- lldb/trunk/source/Core/Section.cpp (original)
+++ lldb/trunk/source/Core/Section.cpp Tue Aug  6 03:04:27 2019
@@ -269,7 +269,7 @@ bool Section::ResolveContainedAddress(ad
 
 bool Section::ContainsFileAddress(addr_t vm_addr) const {
   const addr_t file_addr = GetFileAddress();
-  if (file_addr != LLDB_INVALID_ADDRESS) {
+  if (file_addr != LLDB_INVALID_ADDRESS && !IsThreadSpecific()) {
     if (file_addr <= vm_addr) {
       const addr_t offset = (vm_addr - file_addr) * m_target_byte_size;
       return offset < GetByteSize();

Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=368010&r1=368009&r2=368010&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Tue Aug  6 03:04:27 2019
@@ -1712,6 +1712,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;
@@ -1726,18 +1728,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);
@@ -1772,6 +1779,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) {
@@ -1790,28 +1798,31 @@ void ObjectFileELF::CreateSections(Secti
     return;
 
   m_sections_up = llvm::make_unique<SectionList>();
-  VMAddressProvider address_provider(GetType());
+  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();
@@ -1826,7 +1837,9 @@ void ObjectFileELF::CreateSections(Secti
     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;
 
@@ -1857,7 +1870,7 @@ void ObjectFileELF::CreateSections(Secti
     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




More information about the lldb-commits mailing list