Index: lit/Modules/ELF/PT_LOAD-overlap-PT_TLS.yaml =================================================================== --- /dev/null +++ lit/Modules/ELF/PT_LOAD-overlap-PT_TLS.yaml @@ -0,0 +1,89 @@ +# 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" -o "image lookup -a 0x1010" -b \ +# RUN: | 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: 32 +# CHECK-NEXT: File size: 32 +# CHECK-NEXT: Showing 1 subsections + +# CHECK: Index: 2 +# CHECK-NEXT: ID: 0xfffffffffffffffd +# CHECK-NEXT: Name: PT_TLS[1] +# CHECK-NEXT: Type: container +# CHECK-NEXT: Permissions: rw- +# CHECK-NEXT: Thread specific: yes +# CHECK-NEXT: VM address: 0x1010 +# 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) +# LOOKUP-LABEL: image lookup -a 0x1010 +# LOOKUP: Address: {{.*}}.PT_LOAD[0]..data + 16) + +!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: 0x20 + - Name: .tdata + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_WRITE, SHF_TLS ] + Address: 0x1010 + 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 + - Type: PT_TLS + Flags: [ PF_R, PF_W ] + VAddr: 0x1010 + Align: 0x4 + Sections: + - Section: .tdata Index: source/Core/Section.cpp =================================================================== --- source/Core/Section.cpp +++ source/Core/Section.cpp @@ -269,7 +269,7 @@ 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(); Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -1772,6 +1772,8 @@ 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; @@ -1786,18 +1788,22 @@ } public: - VMAddressProvider(ObjectFile::Type Type) : ObjectType(Type) {} + VMAddressProvider(ObjectFile::Type Type, llvm::StringRef SegmentName) + : ObjectType(Type), SegmentName(SegmentName) {} + + size_t GetSegmentCount() const { return SegmentCount; } + llvm::StringRef GetSegmentName() const { return SegmentName; } llvm::Optional 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); @@ -1832,6 +1838,7 @@ void AddSegment(const VMRange &Range, SectionSP Seg) { Segments.insert(Range.GetRangeBase(), Range.GetRangeEnd(), std::move(Seg)); + ++SegmentCount; } void AddSection(SectionAddressInfo Info, SectionSP Sect) { @@ -1850,28 +1857,33 @@ return; m_sections_up = llvm::make_unique(); - 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()); + ConstString Name(llvm::formatv("{0}[{1}]", provider.GetSegmentName(), + provider.GetSegmentCount()) + .str()); uint32_t Log2Align = llvm::Log2_64(std::max(PHdr.p_align, 1)); SectionSP Segment = std::make_shared
( GetModule(), this, SegmentID(EnumPHdr.index()), Name, 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(); @@ -1886,7 +1898,9 @@ 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; @@ -1917,7 +1931,7 @@ 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