--- /dev/null
+# 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
--- /dev/null
+# 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
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;
}
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);
void AddSegment(const VMRange &Range, SectionSP Seg) {
Segments.insert(Range.GetRangeBase(), Range.GetRangeEnd(), std::move(Seg));
+ ++SegmentCount;
}
void AddSection(SectionAddressInfo Info, SectionSP Sect) {
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();
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;
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