Skip to content

[lldb] Fix prologue size calculation for discontinuous functions #131597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 20, 2025

Conversation

labath
Copy link
Collaborator

@labath labath commented Mar 17, 2025

When searching for the end of prologue, I'm only iterating through the address range (~basic block) which contains the function entry point. The reason for that is that even if some other range somehow contained the end-of-prologue marker, the fact that it's in a different range would imply it's reachable through some form of control flow, and that's usually not a good place to set an function entry breakpoint.

When searching for the end of prologue, I'm only iterating through the
address range (~basic block) which contains the function entry point.
The reason for that is that even if some other range somehow contained
the end-of-prologue marker, the fact that it's in a different range
would imply it's reachable through some form of control flow, and that's
usually not a good place to set an function entry breakpoint.
@labath labath requested a review from jimingham March 17, 2025 10:20
@labath labath requested a review from JDevlieghere as a code owner March 17, 2025 10:20
@llvmbot llvmbot added the lldb label Mar 17, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 17, 2025

@llvm/pr-subscribers-lldb

Author: Pavel Labath (labath)

Changes

When searching for the end of prologue, I'm only iterating through the address range (~basic block) which contains the function entry point. The reason for that is that even if some other range somehow contained the end-of-prologue marker, the fact that it's in a different range would imply it's reachable through some form of control flow, and that's usually not a good place to set an function entry breakpoint.


Full diff: https://github.com/llvm/llvm-project/pull/131597.diff

2 Files Affected:

  • (modified) lldb/source/Symbol/Function.cpp (+11-9)
  • (modified) lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s (+23-2)
diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp
index c80f37ae68d9d..61e788da0e50b 100644
--- a/lldb/source/Symbol/Function.cpp
+++ b/lldb/source/Symbol/Function.cpp
@@ -662,10 +662,12 @@ uint32_t Function::GetPrologueByteSize() {
           }
         }
 
-        const addr_t func_start_file_addr =
-            m_range.GetBaseAddress().GetFileAddress();
-        const addr_t func_end_file_addr =
-            func_start_file_addr + m_range.GetByteSize();
+        AddressRange entry_range;
+        m_block.GetRangeContainingAddress(m_address, entry_range);
+        const addr_t range_start_file_addr = m_address.GetFileAddress();
+        const addr_t range_end_file_addr =
+            entry_range.GetBaseAddress().GetFileAddress() +
+            entry_range.GetByteSize();
 
         // Now calculate the offset to pass the subsequent line 0 entries.
         uint32_t first_non_zero_line = prologue_end_line_idx;
@@ -677,7 +679,7 @@ uint32_t Function::GetPrologueByteSize() {
               break;
           }
           if (line_entry.range.GetBaseAddress().GetFileAddress() >=
-              func_end_file_addr)
+              range_end_file_addr)
             break;
 
           first_non_zero_line++;
@@ -694,13 +696,13 @@ uint32_t Function::GetPrologueByteSize() {
 
         // Verify that this prologue end file address in the function's address
         // range just to be sure
-        if (func_start_file_addr < prologue_end_file_addr &&
-            prologue_end_file_addr < func_end_file_addr) {
-          m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr;
+        if (range_start_file_addr < prologue_end_file_addr &&
+            prologue_end_file_addr < range_end_file_addr) {
+          m_prologue_byte_size = prologue_end_file_addr - range_start_file_addr;
         }
 
         if (prologue_end_file_addr < line_zero_end_file_addr &&
-            line_zero_end_file_addr < func_end_file_addr) {
+            line_zero_end_file_addr < range_end_file_addr) {
           m_prologue_byte_size +=
               line_zero_end_file_addr - prologue_end_file_addr;
         }
diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s b/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s
index 197ab9aa14910..06934c2bfe9c4 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/discontinuous-function.s
@@ -16,22 +16,32 @@ image lookup -v -n foo
 # CHECK-LABEL: image lookup -v -n foo
 # CHECK: 1 match found in {{.*}}
 # CHECK: Summary: input.o`foo
-# CHECK: Function: id = {{.*}}, name = "foo", ranges = [0x0000000000000000-0x000000000000000e)[0x0000000000000014-0x000000000000001c)
+# CHECK: Function: id = {{.*}}, name = "foo", ranges = [0x0000000000000000-0x000000000000000f)[0x0000000000000015-0x000000000000001d)
 
 image lookup -v --regex -n '^foo$'
 # CHECK-LABEL: image lookup -v --regex -n '^foo$'
 # CHECK: 1 match found in {{.*}}
 # CHECK: Summary: input.o`foo
-# CHECK: Function: id = {{.*}}, name = "foo", ranges = [0x0000000000000000-0x000000000000000e)[0x0000000000000014-0x000000000000001c)
+# CHECK: Function: id = {{.*}}, name = "foo", ranges = [0x0000000000000000-0x000000000000000f)[0x0000000000000015-0x000000000000001d)
 
 expr -- &foo
 # CHECK-LABEL: expr -- &foo
 # CHECK: (void (*)()) $0 = 0x0000000000000007
 
+breakpoint set --name foo --skip-prologue false
+# CHECK-LABEL: breakpoint set --name foo --skip-prologue false
+# CHECK: Breakpoint 1: where = input.o`foo at -:1, address = 0x0000000000000007
+
+breakpoint set --name foo --skip-prologue true
+# CHECK-LABEL: breakpoint set --name foo --skip-prologue true
+# CHECK: Breakpoint 2: where = input.o`foo + 1 at -:2, address = 0x0000000000000008
+
 #--- input.s
         .text
 
+        .file   0 "." "-"
 foo.__part.1:
+        .loc    0 10
         .cfi_startproc
         callq   bar
         jmp     foo.__part.3
@@ -41,7 +51,10 @@ foo.__part.1:
 
         .type   foo,@function
 foo:
+        .loc    0 1
         .cfi_startproc
+        nop
+        .loc    0 2 prologue_end
         cmpl    $0, %edi
         je      foo.__part.2
         jmp     foo.__part.1
@@ -51,6 +64,7 @@ foo:
 
 bar:
         .cfi_startproc
+        .loc    0 100
         movl    $47, %eax
         retq
         .cfi_endproc
@@ -58,6 +72,7 @@ bar:
         .size   bar, .Lbar_end-bar
 
 foo.__part.2:
+        .loc    0 20
         .cfi_startproc
         callq   baz
         jmp     foo.__part.3
@@ -66,6 +81,7 @@ foo.__part.2:
         .cfi_endproc
 
 foo.__part.3:
+        .loc    0 30
         .cfi_startproc
         retq
 .Lfoo.__part.3_end:
@@ -87,6 +103,8 @@ foo.__part.3:
         .byte   35                              # DW_FORM_rnglistx
         .byte   116                             # DW_AT_rnglists_base
         .byte   23                              # DW_FORM_sec_offset
+        .byte   16                              # DW_AT_stmt_list
+        .byte   23                              # DW_FORM_sec_offset
         .byte   0                               # EOM(1)
         .byte   0                               # EOM(2)
         .byte   2                               # Abbreviation Code
@@ -127,6 +145,7 @@ foo.__part.3:
         .quad   0                               # DW_AT_low_pc
         .byte   1                               # DW_AT_ranges
         .long   .Lrnglists_table_base0          # DW_AT_rnglists_base
+        .long   .Lline_table_start0             # DW_AT_stmt_list
         .byte   2                               # Abbrev [2] DW_TAG_subprogram
         .quad   bar                             # DW_AT_low_pc
         .quad   .Lbar_end                       # DW_AT_high_pc
@@ -183,3 +202,5 @@ foo.__part.3:
 .Ldebug_list_header_end0:
 
         .section        ".note.GNU-stack","",@progbits
+        .section        .debug_line,"",@progbits
+.Lline_table_start0:

Comment on lines 667 to 670
const addr_t range_start_file_addr = m_address.GetFileAddress();
const addr_t range_end_file_addr =
entry_range.GetBaseAddress().GetFileAddress() +
entry_range.GetByteSize();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to do it this way rather than:

const addr_t range_start_file_addr = entry_range.GetBaseAddress().GetFileAddress();
const addr_t range_end_file_addr = range_start_file_addr + entry_range.GetByteSize();

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because in the most general case, the entry point may not be at the start of any particular range (either because of a perverse compiler or because the linker placed two of the ranges next to each other and we have merged them into one).

I'm going to add a comment about that.

@labath labath merged commit fdeb2ff into llvm:main Mar 20, 2025
10 checks passed
@labath labath deleted the rm-range branch March 20, 2025 15:01
@llvm-ci
Copy link
Collaborator

llvm-ci commented Mar 20, 2025

LLVM Buildbot has detected a new failure on builder lldb-remote-linux-ubuntu running on as-builder-9 while building lldb at step 16 "test-check-lldb-api".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/195/builds/6462

Here is the relevant piece of the build log for the reference
Step 16 (test-check-lldb-api) failure: Test just built components: check-lldb-api completed (failure)
...
PASS: lldb-api :: types/TestCharTypeExpr.py (1235 of 1244)
PASS: lldb-api :: python_api/watchpoint/watchlocation/TestTargetWatchAddress.py (1236 of 1244)
PASS: lldb-api :: types/TestIntegerType.py (1237 of 1244)
PASS: lldb-api :: types/TestRecursiveTypes.py (1238 of 1244)
PASS: lldb-api :: types/TestIntegerTypeExpr.py (1239 of 1244)
PASS: lldb-api :: types/TestShortType.py (1240 of 1244)
PASS: lldb-api :: types/TestShortTypeExpr.py (1241 of 1244)
PASS: lldb-api :: types/TestLongTypes.py (1242 of 1244)
PASS: lldb-api :: types/TestLongTypesExpr.py (1243 of 1244)
TIMEOUT: lldb-api :: python_api/process/cancel_attach/TestCancelAttach.py (1244 of 1244)
******************** TEST 'lldb-api :: python_api/process/cancel_attach/TestCancelAttach.py' FAILED ********************
Script:
--
/usr/bin/python3.12 /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./bin --libcxx-include-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/include/c++/v1 --libcxx-include-target-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/include/aarch64-unknown-linux-gnu/c++/v1 --libcxx-library-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./lib/aarch64-unknown-linux-gnu --arch aarch64 --build-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./bin/lldb --compiler /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang --dsymutil /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./bin --lldb-obj-root /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/tools/lldb --lldb-libs-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./lib --platform-url connect://jetson-agx-2198.lab.llvm.org:1234 --platform-working-dir /home/ubuntu/lldb-tests --sysroot /mnt/fs/jetson-agx-ubuntu --env ARCH_CFLAGS=-mcpu=cortex-a78 --platform-name remote-linux --skip-category=lldb-server /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/llvm-project/lldb/test/API/python_api/process/cancel_attach -p TestCancelAttach.py
--
Exit Code: -9
Timeout: Reached timeout of 600 seconds

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision fdeb2ff30407afbfc3596aaf417a2a91cdff20c9)
  clang revision fdeb2ff30407afbfc3596aaf417a2a91cdff20c9
  llvm revision fdeb2ff30407afbfc3596aaf417a2a91cdff20c9

--
Command Output (stderr):
--
WARNING:root:Custom libc++ is not supported for remote runs: ignoring --libcxx arguments
FAIL: LLDB (/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang-aarch64) :: test_scripted_implementation (TestCancelAttach.AttachCancelTestCase.test_scripted_implementation)

--

********************
Slowest Tests:
--------------------------------------------------------------------------
600.04s: lldb-api :: python_api/process/cancel_attach/TestCancelAttach.py
180.99s: lldb-api :: commands/command/script_alias/TestCommandScriptAlias.py
70.51s: lldb-api :: commands/process/attach/TestProcessAttach.py
40.58s: lldb-api :: functionalities/data-formatter/data-formatter-stl/libcxx-simulators/string/TestDataFormatterLibcxxStringSimulator.py
34.68s: lldb-api :: functionalities/completion/TestCompletion.py
33.65s: lldb-api :: functionalities/single-thread-step/TestSingleThreadStepTimeout.py
23.34s: lldb-api :: python_api/watchpoint/watchlocation/TestTargetWatchAddress.py
20.68s: lldb-api :: functionalities/gdb_remote_client/TestPlatformClient.py
20.64s: lldb-api :: commands/statistics/basic/TestStats.py
19.01s: lldb-api :: functionalities/thread/state/TestThreadStates.py
18.35s: lldb-api :: commands/dwim-print/TestDWIMPrint.py
14.60s: lldb-api :: commands/expression/expr-in-syscall/TestExpressionInSyscall.py
14.48s: lldb-api :: functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py
14.38s: lldb-api :: functionalities/inline-stepping/TestInlineStepping.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants