From 044929d075cff7883a020526ec8b795b30f9f086 Mon Sep 17 00:00:00 2001 From: Ely Ronnen Date: Fri, 23 May 2025 08:26:46 +0200 Subject: [PATCH] [lldb] Change synthetic symbol names to have file address (#138416) * Changes the default synthetic symbol names to contain their file address This is a new PR after the first PR (#137512) was reverted because it didn't update the way unnamed symbols were searched in the symbol table, which relied on the index being in the name. This time also added extra test to make sure the symbol is found as expected --- lldb/include/lldb/Symbol/Symbol.h | 2 +- lldb/source/Symbol/Symbol.cpp | 4 +- lldb/source/Symbol/Symtab.cpp | 13 +++--- .../python_api/unnamed_symbol_lookup/Makefile | 23 +++++++++++ .../TestUnnamedSymbolLookup.py | 40 +++++++++++++++++++ .../python_api/unnamed_symbol_lookup/main.c | 6 +++ .../ObjectFile/ELF/eh_frame-symbols.yaml | 4 +- .../Breakpad/symtab-sorted-by-size.test | 2 +- .../Shell/SymbolFile/Breakpad/symtab.test | 2 +- 9 files changed, 84 insertions(+), 12 deletions(-) create mode 100644 lldb/test/API/python_api/unnamed_symbol_lookup/Makefile create mode 100644 lldb/test/API/python_api/unnamed_symbol_lookup/TestUnnamedSymbolLookup.py create mode 100644 lldb/test/API/python_api/unnamed_symbol_lookup/main.c diff --git a/lldb/include/lldb/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h index e05c845a69f3..688c8a5931fe 100644 --- a/lldb/include/lldb/Symbol/Symbol.h +++ b/lldb/include/lldb/Symbol/Symbol.h @@ -258,7 +258,7 @@ public: bool ContainsFileAddress(lldb::addr_t file_addr) const; static llvm::StringRef GetSyntheticSymbolPrefix() { - return "___lldb_unnamed_symbol"; + return "___lldb_unnamed_symbol_"; } /// Decode a serialized version of this object from data. diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp index 4828de4fdfa3..d6689a647062 100644 --- a/lldb/source/Symbol/Symbol.cpp +++ b/lldb/source/Symbol/Symbol.cpp @@ -639,7 +639,9 @@ void Symbol::SynthesizeNameIfNeeded() const { // breakpoints on them. llvm::SmallString<256> name; llvm::raw_svector_ostream os(name); - os << GetSyntheticSymbolPrefix() << GetID(); + os << GetSyntheticSymbolPrefix() + << llvm::format_hex_no_prefix( + m_addr_range.GetBaseAddress().GetFileAddress(), 0); m_mangled.SetDemangledName(ConstString(os.str())); } } diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp index 9aee5d3e813d..9a3e8476fa35 100644 --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -654,8 +654,8 @@ uint32_t Symtab::GetNameIndexes(ConstString symbol_name, if (count) return count; // Synthetic symbol names are not added to the name indexes, but they start - // with a prefix and end with a the symbol UserID. This allows users to find - // these symbols without having to add them to the name indexes. These + // with a prefix and end with the symbol file address. This allows users to + // find these symbols without having to add them to the name indexes. These // queries will not happen very often since the names don't mean anything, so // performance is not paramount in this case. llvm::StringRef name = symbol_name.GetStringRef(); @@ -663,11 +663,12 @@ uint32_t Symtab::GetNameIndexes(ConstString symbol_name, if (!name.consume_front(Symbol::GetSyntheticSymbolPrefix())) return 0; // Not a synthetic symbol name - // Extract the user ID from the symbol name - unsigned long long uid = 0; - if (getAsUnsignedInteger(name, /*Radix=*/10, uid)) + // Extract the file address from the symbol name + unsigned long long file_address = 0; + if (getAsUnsignedInteger(name, /*Radix=*/16, file_address)) return 0; // Failed to extract the user ID as an integer - Symbol *symbol = FindSymbolByID(uid); + + Symbol *symbol = FindSymbolAtFileAddress(static_cast(file_address)); if (symbol == nullptr) return 0; const uint32_t symbol_idx = GetIndexForSymbol(symbol); diff --git a/lldb/test/API/python_api/unnamed_symbol_lookup/Makefile b/lldb/test/API/python_api/unnamed_symbol_lookup/Makefile new file mode 100644 index 000000000000..4e29185e9dd5 --- /dev/null +++ b/lldb/test/API/python_api/unnamed_symbol_lookup/Makefile @@ -0,0 +1,23 @@ +C_SOURCES := main.c + +include Makefile.rules + +all: a.out.stripped + +ifeq "$(OS)" "Darwin" +STRIP_COMMAND = $(STRIP) -s keep_symbols.txt +else +STRIP_COMMAND = $(STRIP) --keep-symbol=main +endif + +a.out.stripped: a.out +ifeq "$(OS)" "Darwin" + echo "_main" > keep_symbols.txt + $(STRIP) -s keep_symbols.txt -o a.out.stripped a.out +else + $(STRIP) --keep-symbol=main -o a.out.stripped a.out +endif + +ifneq "$(CODESIGN)" "" + $(CODESIGN) -fs - a.out.stripped +endif diff --git a/lldb/test/API/python_api/unnamed_symbol_lookup/TestUnnamedSymbolLookup.py b/lldb/test/API/python_api/unnamed_symbol_lookup/TestUnnamedSymbolLookup.py new file mode 100644 index 000000000000..09d43a34c7e3 --- /dev/null +++ b/lldb/test/API/python_api/unnamed_symbol_lookup/TestUnnamedSymbolLookup.py @@ -0,0 +1,40 @@ +""" +Test lookup unnamed symbols. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestUnnamedSymbolLookup(TestBase): + def test_unnamed_symbol_lookup(self): + """Test looking up unnamed symbol synthetic name""" + self.build() + (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint( + self, "main", exe_name="a.out.stripped" + ) + + main_frame = thread.GetFrameAtIndex(0) + + # Step until reaching the unnamed symbol called from main + for _ in range(100): + thread.StepInto() + if thread.GetFrameAtIndex(0) != main_frame: + break + + thread.StepInto() + + self.assertEqual( + main_frame, thread.GetFrameAtIndex(1), "Expected to be called from main" + ) + symbol = thread.GetFrameAtIndex(0).GetSymbol() + self.assertIsNotNone(symbol, "unnamed symbol called from main not reached") + self.assertTrue(symbol.name.startswith("___lldb_unnamed_symbol")) + + exe_module = symbol.GetStartAddress().GetModule() + found_symbols = exe_module.FindSymbols(symbol.name) + self.assertIsNotNone(found_symbols) + self.assertEqual(found_symbols.GetSize(), 1) diff --git a/lldb/test/API/python_api/unnamed_symbol_lookup/main.c b/lldb/test/API/python_api/unnamed_symbol_lookup/main.c new file mode 100644 index 000000000000..ec8350706b3c --- /dev/null +++ b/lldb/test/API/python_api/unnamed_symbol_lookup/main.c @@ -0,0 +1,6 @@ +__attribute__((nodebug)) int stripped_function(int val) { return val * val; } + +int main(void) { + stripped_function(10); + return 0; +} diff --git a/lldb/test/Shell/ObjectFile/ELF/eh_frame-symbols.yaml b/lldb/test/Shell/ObjectFile/ELF/eh_frame-symbols.yaml index 0dcc9fb76bd4..709c37e79d87 100644 --- a/lldb/test/Shell/ObjectFile/ELF/eh_frame-symbols.yaml +++ b/lldb/test/Shell/ObjectFile/ELF/eh_frame-symbols.yaml @@ -3,8 +3,8 @@ # CHECK: Index UserID DSX Type File Address/Value Load Address Size Flags Name # CHECK: [ 0] 1 SourceFile 0x0000000000000000 0x0000000000000000 0x00000004 - -# CHECK: [ 1] 2 SX Code 0x0000000000201180 0x0000000000000010 0x00000000 ___lldb_unnamed_symbol{{[0-9]*}} -# CHECK: [ 2] 3 SX Code 0x0000000000201190 0x0000000000000006 0x00000000 ___lldb_unnamed_symbol{{[0-9]*}} +# CHECK: [ 1] 2 SX Code 0x0000000000201180 0x0000000000000010 0x00000000 ___lldb_unnamed_symbol_{{[0-9a-f]*}} +# CHECK: [ 2] 3 SX Code 0x0000000000201190 0x0000000000000006 0x00000000 ___lldb_unnamed_symbol_{{[0-9a-f]*}} --- !ELF FileHeader: diff --git a/lldb/test/Shell/SymbolFile/Breakpad/symtab-sorted-by-size.test b/lldb/test/Shell/SymbolFile/Breakpad/symtab-sorted-by-size.test index 98052ea20bed..00e04eb39a98 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/symtab-sorted-by-size.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/symtab-sorted-by-size.test @@ -3,7 +3,7 @@ # RUN: -s %s | FileCheck %s # CHECK: num_symbols = 4 (sorted by size): -# CHECK: [ 0] 0 SX Code 0x0000000000400000 0x00000000000000b0 0x00000000 ___lldb_unnamed_symbol0 +# CHECK: [ 0] 0 SX Code 0x0000000000400000 0x00000000000000b0 0x00000000 ___lldb_unnamed_symbol_400000 # CHECK: [ 1] 0 X Code 0x00000000004000d0 0x0000000000000022 0x00000000 _start # CHECK: [ 2] 0 X Code 0x00000000004000b0 0x0000000000000010 0x00000000 f1 # CHECK: [ 3] 0 X Code 0x00000000004000c0 0x0000000000000010 0x00000000 f2 diff --git a/lldb/test/Shell/SymbolFile/Breakpad/symtab.test b/lldb/test/Shell/SymbolFile/Breakpad/symtab.test index ef41bb3bea95..a32eb5808426 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/symtab.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/symtab.test @@ -5,7 +5,7 @@ # CHECK-LABEL: (lldb) image dump symtab symtab.out # CHECK: Symtab, file = {{.*}}symtab.out, num_symbols = 4: # CHECK: Index UserID DSX Type File Address/Value Load Address Size Flags Name -# CHECK: [ 0] 0 SX Code 0x0000000000400000 0x00000000000000b0 0x00000000 ___lldb_unnamed_symbol{{[0-9]*}} +# CHECK: [ 0] 0 SX Code 0x0000000000400000 0x00000000000000b0 0x00000000 ___lldb_unnamed_symbol_{{[0-9a-f]*}} # CHECK: [ 1] 0 X Code 0x00000000004000b0 0x0000000000000010 0x00000000 f1 # CHECK: [ 2] 0 X Code 0x00000000004000c0 0x0000000000000010 0x00000000 f2 # CHECK: [ 3] 0 X Code 0x00000000004000d0 0x0000000000000022 0x00000000 _start