Index: include/lldb/Core/Module.h =================================================================== --- include/lldb/Core/Module.h +++ include/lldb/Core/Module.h @@ -680,7 +680,8 @@ /// data the symbol vendor provides. void ParseAllDebugSymbols(); - bool ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr); + bool ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr, + bool allow_section_end = false); /// Resolve the symbol context for the given address. /// Index: include/lldb/Core/Section.h =================================================================== --- include/lldb/Core/Section.h +++ include/lldb/Core/Section.h @@ -71,6 +71,14 @@ FindSectionContainingFileAddress(lldb::addr_t addr, uint32_t depth = UINT32_MAX) const; + /// Look up the given file address in the contained sections. Return a + /// section-relative Address object if a section is found. if + /// allow_section_end is true, an address pointing past the end of a section + /// is permitted and resolved relative to the section which ends at the given + /// address. + llvm::Optional
ResolveFileAddress(lldb::addr_t file_addr, + bool allow_section_end) const; + // Get the number of sections in this list only size_t GetSize() const { return m_sections.size(); } @@ -122,7 +130,11 @@ static int Compare(const Section &a, const Section &b); - bool ContainsFileAddress(lldb::addr_t vm_addr) const; + /// Return true iff this section contains the given file address. If + /// allow_section_end is true, the function returns true also for address + /// pointing past the end of the section. + bool ContainsFileAddress(lldb::addr_t vm_addr, + bool allow_section_end = false) const; SectionList &GetChildren() { return m_children; } Index: lit/SymbolFile/DWARF/debug-line-basic.s =================================================================== --- lit/SymbolFile/DWARF/debug-line-basic.s +++ lit/SymbolFile/DWARF/debug-line-basic.s @@ -1,7 +1,7 @@ # REQUIRES: lld, x86 # RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o -# RUN: ld.lld -z separate-code %t.o -o %t +# RUN: ld.lld %t.o -o %t # RUN: %lldb %t -o "image dump line-table -v a.c" -o exit | FileCheck %s Index: lit/SymbolFile/DWARF/dir-separator-no-comp-dir-relative-name.s =================================================================== --- lit/SymbolFile/DWARF/dir-separator-no-comp-dir-relative-name.s +++ lit/SymbolFile/DWARF/dir-separator-no-comp-dir-relative-name.s @@ -5,7 +5,7 @@ # REQUIRES: lld, x86 # RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o -# RUN: ld.lld -z separate-code %t.o -o %t +# RUN: ld.lld %t.o -o %t # RUN: %lldb %t -s %S/Inputs/dir-separator-no-comp-dir-relative-name.lldbinit -o exit | FileCheck %s # CHECK-LABEL: image dump line-table a.c Index: lit/SymbolFile/DWARF/dir-separator-no-comp-dir.s =================================================================== --- lit/SymbolFile/DWARF/dir-separator-no-comp-dir.s +++ lit/SymbolFile/DWARF/dir-separator-no-comp-dir.s @@ -4,7 +4,7 @@ # REQUIRES: lld, x86 # RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o -# RUN: ld.lld -z separate-code %t.o -o %t +# RUN: ld.lld %t.o -o %t # RUN: %lldb %t -s %S/Inputs/dir-separator-windows.lldbinit -o exit | FileCheck %s # CHECK-LABEL: image dump line-table a.c Index: lit/SymbolFile/DWARF/dir-separator-posix.s =================================================================== --- lit/SymbolFile/DWARF/dir-separator-posix.s +++ lit/SymbolFile/DWARF/dir-separator-posix.s @@ -4,7 +4,7 @@ # REQUIRES: lld, x86 # RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o -# RUN: ld.lld -z separate-code %t.o -o %t +# RUN: ld.lld %t.o -o %t # RUN: %lldb %t -s %S/Inputs/dir-separator-posix.lldbinit -o exit | FileCheck %s # CHECK-LABEL: image dump line-table a.c Index: lit/SymbolFile/DWARF/dir-separator-windows.s =================================================================== --- lit/SymbolFile/DWARF/dir-separator-windows.s +++ lit/SymbolFile/DWARF/dir-separator-windows.s @@ -4,7 +4,7 @@ # REQUIRES: lld, x86 # RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o -# RUN: ld.lld -z separate-code %t.o -o %t +# RUN: ld.lld %t.o -o %t # RUN: %lldb %t -s %S/Inputs/dir-separator-windows.lldbinit -o exit | FileCheck %s # CHECK-LABEL: image dump line-table a.c Index: source/Core/Module.cpp =================================================================== --- source/Core/Module.cpp +++ source/Core/Module.cpp @@ -423,15 +423,21 @@ return cu_sp; } -bool Module::ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) { +bool Module::ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr, + bool allow_section_end) { std::lock_guard guard(m_mutex); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "Module::ResolveFileAddress (vm_addr = 0x%" PRIx64 ")", vm_addr); SectionList *section_list = GetSectionList(); - if (section_list) - return so_addr.ResolveAddressUsingFileSections(vm_addr, section_list); + if (!section_list) + return false; + if (llvm::Optional
addr = + section_list->ResolveFileAddress(vm_addr, allow_section_end)) { + so_addr = *addr; + return true; + } return false; } Index: source/Core/Section.cpp =================================================================== --- source/Core/Section.cpp +++ source/Core/Section.cpp @@ -267,12 +267,13 @@ return true; } -bool Section::ContainsFileAddress(addr_t vm_addr) const { +bool Section::ContainsFileAddress(addr_t vm_addr, + bool allow_section_end) const { const addr_t file_addr = GetFileAddress(); 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(); + return offset < GetByteSize() + (allow_section_end ? 1 : 0); } } return false; @@ -586,6 +587,20 @@ return sect_sp; } +llvm::Optional
+SectionList::ResolveFileAddress(addr_t file_addr, + bool allow_section_end) const { + for (const SectionSP §ion_sp : m_sections) { + if (section_sp->ContainsFileAddress(file_addr, allow_section_end)) { + Address addr; + section_sp->ResolveContainedAddress( + file_addr - section_sp->GetFileAddress(), addr, allow_section_end); + return addr; + } + } + return llvm::None; +} + bool SectionList::ContainsSection(user_id_t sect_id) const { return FindSectionByID(sect_id).get() != nullptr; } Index: source/Symbol/LineTable.cpp =================================================================== --- source/Symbol/LineTable.cpp +++ source/Symbol/LineTable.cpp @@ -244,9 +244,9 @@ if (idx < m_entries.size()) { const Entry &entry = m_entries[idx]; ModuleSP module_sp(m_comp_unit->GetModule()); - if (module_sp && - module_sp->ResolveFileAddress(entry.file_addr, - line_entry.range.GetBaseAddress())) { + if (module_sp && module_sp->ResolveFileAddress( + entry.file_addr, line_entry.range.GetBaseAddress(), + /*allow_section_end = */ entry.is_terminal_entry)) { if (!entry.is_terminal_entry && idx + 1 < m_entries.size()) line_entry.range.SetByteSize(m_entries[idx + 1].file_addr - entry.file_addr); Index: unittests/Core/CMakeLists.txt =================================================================== --- unittests/Core/CMakeLists.txt +++ unittests/Core/CMakeLists.txt @@ -1,5 +1,6 @@ add_lldb_unittest(LLDBCoreTests MangledTest.cpp + ModuleTest.cpp RichManglingContextTest.cpp StreamCallbackTest.cpp UniqueCStringMapTest.cpp @@ -18,5 +19,6 @@ set(test_inputs mangled-function-names.yaml + resolve-file-address.yaml ) add_unittest_inputs(LLDBCoreTests "${test_inputs}") Index: unittests/Core/Inputs/resolve-file-address.yaml =================================================================== --- /dev/null +++ unittests/Core/Inputs/resolve-file-address.yaml @@ -0,0 +1,12 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x1000 + Size: 0x100 Index: unittests/Core/ModuleTest.cpp =================================================================== --- /dev/null +++ unittests/Core/ModuleTest.cpp @@ -0,0 +1,69 @@ +//===-- ModuleTest.cpp ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Module.h" +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" +#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h" +#include "TestingSupport/TestUtilities.h" +#include "lldb/Core/Section.h" +#include "lldb/Host/HostInfo.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Testing/Support/Error.h" +#include "gtest/gtest.h" + +using namespace lldb_private; +using namespace lldb; + +namespace { +class ModuleTest : public testing::Test { +public: + static void SetUpTestCase() { + FileSystem::Initialize(); + HostInfo::Initialize(); + ObjectFileELF::Initialize(); + SymbolFileSymtab::Initialize(); + } + + static void TearDownTestCase() { + SymbolFileSymtab::Terminate(); + ObjectFileELF::Terminate(); + HostInfo::Terminate(); + FileSystem::Terminate(); + } +}; +} // namespace + +llvm::Optional
resolveFileAddress(Module &M, addr_t FileAddr, + bool AllowSectionEnd) { + Address A; + if (M.ResolveFileAddress(FileAddr, A, AllowSectionEnd)) + return A; + return llvm::None; +} + +TEST_F(ModuleTest, ResolveFileAddress) { + llvm::SmallString<128> Obj; + ASSERT_EQ(llvm::sys::fs::createTemporaryFile("resolve-file-address-%%%%%%", + "obj", Obj), + std::error_code()); + llvm::FileRemover Deleter(Obj); + ASSERT_THAT_ERROR(ReadYAMLObjectFile("resolve-file-address.yaml", Obj), + llvm::Succeeded()); + + ModuleSpec Spec{FileSpec(Obj)}; + Spec.GetSymbolFileSpec().SetFile(Obj, FileSpec::Style::native); + auto M = std::make_shared(Spec); + + ASSERT_TRUE(M->GetSectionList()); + SectionSP S = M->GetSectionList()->FindSectionByName(ConstString(".text")); + ASSERT_TRUE(S); + + EXPECT_EQ(resolveFileAddress(*M, 0x1000, false), Address(S, 0)); + EXPECT_EQ(resolveFileAddress(*M, 0x1100, false), llvm::None); + EXPECT_EQ(resolveFileAddress(*M, 0x1100, true), Address(S, 0x100)); +}