Skip to content

Conversation

@jimingham
Copy link
Collaborator

The test is currently passing everywhere but this 32-bit arm ubuntu bot. I don't have an easy way to debug this, so I'm skipping the test on that platform till we get a chance to figure this out.

The test is currently passing everywhere but this 32-bit arm ubuntu
bot.  I don't have an easy way to debug this, so I'm skipping the
test on that platform till we get a chance to figure this out.
@llvmbot
Copy link
Member

llvmbot commented Oct 30, 2024

@llvm/pr-subscribers-lldb

Author: None (jimingham)

Changes

The test is currently passing everywhere but this 32-bit arm ubuntu bot. I don't have an easy way to debug this, so I'm skipping the test on that platform till we get a chance to figure this out.


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

1 Files Affected:

  • (modified) lldb/test/API/functionalities/inline-stepping/TestInlineStepping.py (+2)
diff --git a/lldb/test/API/functionalities/inline-stepping/TestInlineStepping.py b/lldb/test/API/functionalities/inline-stepping/TestInlineStepping.py
index f52e0f0fd5bcfe..d3d00bca36b920 100644
--- a/lldb/test/API/functionalities/inline-stepping/TestInlineStepping.py
+++ b/lldb/test/API/functionalities/inline-stepping/TestInlineStepping.py
@@ -14,6 +14,8 @@ class TestInlineStepping(TestBase):
         compiler="icc",
         bugnumber="# Not really a bug.  ICC combines two inlined functions.",
     )
+
+    @skipIf(oslist=["ubuntu"], archs=["arm"]) # Fails for 32 bit arm
     def test_with_python_api(self):
         """Test stepping over and into inlined functions."""
         self.build()

@github-actions
Copy link

⚠️ Python code formatter, darker found issues in your code. ⚠️

You can test this locally with the following command:
darker --check --diff -r 5545f76dc94e76ef6800823bdd1e107ad2264717...effa929cd73cde63e31dbedf8c5fadcb767aae37 lldb/test/API/functionalities/inline-stepping/TestInlineStepping.py
View the diff from darker here.
--- TestInlineStepping.py	2024-10-30 19:58:22.000000 +0000
+++ TestInlineStepping.py	2024-10-30 20:02:02.390605 +0000
@@ -12,12 +12,11 @@
     @skipIf(oslist=["windows"], archs=["aarch64"])  # Flaky on buildbot
     @expectedFailureAll(
         compiler="icc",
         bugnumber="# Not really a bug.  ICC combines two inlined functions.",
     )
-
-    @skipIf(oslist=["linux"], archs=["arm"]) # Fails for 32 bit arm
+    @skipIf(oslist=["linux"], archs=["arm"])  # Fails for 32 bit arm
     def test_with_python_api(self):
         """Test stepping over and into inlined functions."""
         self.build()
         self.inline_stepping()
 

@DavidSpickett DavidSpickett changed the title Skip one inline stepping test for arm-ubuntu. [lldb][test] Skip one inline stepping test for arm-ubuntu. Oct 31, 2024
@DavidSpickett DavidSpickett merged commit a218f0f into llvm:main Oct 31, 2024
5 of 6 checks passed
@DavidSpickett
Copy link
Collaborator

I looked into this. Not sure what the stepping logic goes by but I do see there is no line table entry for the function call we expect to stop at after the first stop.

I have cut the cpp down to:

  1 inline void inline_trivial_1 () __attribute__((always_inline));
  2 
  3 static int inline_value;
  4 
  5 void inline_trivial_1() {
  6     asm volatile ("nop"); // In inline_trivial_1.
  7 }
  8 
  9 int main (int argc, char **argv) {
 10     inline_value = 0;    // Stop here and step over to set up stepping over.
 11     inline_trivial_1 (); // At inline_trivial_1 called from main.
 12     return 0;
 13 }

On Arm 32 bit this produces this code:

0000052c <main>:
 52c:   e92d4800        push    {fp, lr}
 530:   e1a0b00d        mov     fp, sp
 534:   e24dd00c        sub     sp, sp, #12
 538:   e3002000        movw    r2, #0
 53c:   e50b2004        str     r2, [fp, #-4]
 540:   e58d0004        str     r0, [sp, #4]
 544:   e58d1000        str     r1, [sp]
 548:   e3000000        movw    r0, #0
 54c:   e59f1014        ldr     r1, [pc, #20]   ; 568 <main+0x3c>
 550:   e08f1001        add     r1, pc, r1
 554:   e5810000        str     r0, [r1]
 558:   e320f000        nop     {0}
 55c:   e3000000        movw    r0, #0
 560:   e1a0d00b        mov     sp, fp
 564:   e8bd8800        pop     {fp, pc}
 568:   00010ae4        .word   0x00010ae4

And the line table is (idk what's important but line numbers are my guess):

$ ./bin/llvm-dwarfdump --debug-line ./lldb-test-build.noindex/functionalities/inline-stepping/TestInlineStepping.test_with_python_api_dwarf/a.out
<...>
Address            Line   Column File   ISA Discriminator OpIndex Flags
------------------ ------ ------ ------ --- ------------- ------- -------------
0x000000000000052c      9      0      1   0             0       0  is_stmt
0x0000000000000548     10     18      1   0             0       0  is_stmt prologue_end
0x0000000000000558      6      5      1   0             0       0  is_stmt
0x000000000000055c     12      5      1   0             0       0  is_stmt
0x0000000000000560     12      5      1   0             0       0  epilogue_begin
0x0000000000000568      0      5      1   0             0       0
0x000000000000056c      0      5      1   0             0       0  end_sequence

There's no entry for line 11. Though it does think the prologue ends at line 10 column 18, when I think it should be more like column 5? Before the assignment.

Compiling the test with g++ I get:

Address            Line   Column File   ISA Discriminator OpIndex Flags
------------------ ------ ------ ------ --- ------------- ------- -------------
0x00000000000004d8      9     34      1   0             0       0  is_stmt
0x00000000000004e2     10     18      1   0             0       0  is_stmt
0x00000000000004ea      6      5      1   0             0       0  is_stmt
0x00000000000004ec      7      1      1   0             0       0  is_stmt
0x00000000000004ee     12     12      1   0             0       0  is_stmt
0x00000000000004f0     13      1      1   0             0       0  is_stmt
0x0000000000000500     13      1      1   0             0       0  is_stmt end_sequence

lldb will still step right over line 11 if I give it the g++ binary.

gdb is able to step the g++ binary properly, but if I give it the clang compiled binary:

(gdb) run
Starting program: /home/david.spickett/build-llvm-arm/lldb-test-build.noindex/functionalities/inline-stepping/TestInlineStepping.test_with_python_api_dwarf/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".

Breakpoint 1, main (argc=1, argv=0xfffef3b4) at /home/david.spickett/llvm-project/lldb/test/API/functionalities/inline-stepping/calling.cpp:10
10          inline_value = 0;    // Stop here and step over to set up stepping over.
(gdb) n

Program received signal SIGILL, Illegal instruction.
0x00401058 in ?? ()

Which isn't a great sign.

However, on AArch64 where this does work, the code is:

0000000000000714 <main>:
 714:   d10043ff        sub     sp, sp, #0x10
 718:   2a0003e8        mov     w8, w0
 71c:   2a1f03e0        mov     w0, wzr
 720:   b9000fff        str     wzr, [sp, #12]
 724:   b9000be8        str     w8, [sp, #8]
 728:   f90003e1        str     x1, [sp]
 72c:   b0000088        adrp    x8, 11000 <__cxa_finalize@GLIBC_2.17>
 730:   b900351f        str     wzr, [x8, #52]
 734:   d503201f        nop
 738:   910043ff        add     sp, sp, #0x10
 73c:   d65f03c0        ret

And the line table:

Address            Line   Column File   ISA Discriminator OpIndex Flags
------------------ ------ ------ ------ --- ------------- ------- -------------
0x0000000000000714      9      0      1   0             0       0  is_stmt
0x000000000000072c     10     18      1   0             0       0  is_stmt prologue_end
0x0000000000000734      6      5      1   0             0       0  is_stmt
0x0000000000000738     12      5      1   0             0       0  is_stmt epilogue_begin
0x0000000000000740     12      5      1   0             0       0  is_stmt end_sequence

Still no entry for line 11, but lldb works on AArch64 despite that. Also, it marks prologue end as after the assignment like Arm did.

g++'s line table on AArch64:

Address            Line   Column File   ISA Discriminator OpIndex Flags
------------------ ------ ------ ------ --- ------------- ------- -------------
0x0000000000000714      9     34      1   0             0       0  is_stmt
0x0000000000000720     10     18      1   0             0       0  is_stmt
0x000000000000072c      6      5      1   0             0       0  is_stmt
0x0000000000000730      7      1      1   0             0       0  is_stmt
0x0000000000000734     12     12      1   0             0       0  is_stmt
0x0000000000000738     13      1      1   0             0       0  is_stmt
0x0000000000000740     13      1      1   0             0       0  is_stmt end_sequence

And the binary works fine with lldb.

If inline_trivial_1 returns a value, then the call to it will get a line table entry and the test will pass on Arm 32 bit.

Which means lldb must be looking at some other property that I don't know about. Otherwise it wouldn't work on AArch64 either.

@jimingham
Copy link
Collaborator Author

Thanks for the analysis. The other bit that lldb looks at (which is what I added with the patch this change is the result of) is the DW_AT_call_{file, line} info in the debug_info part of the DWARF for that function. Before we ignored that information when setting breakpoints. What do those look like?

@DavidSpickett
Copy link
Collaborator

dwarfdump: arm_dwarfdump.txt (this doesn't seem different to what AArch64 produces)
objdump: arm_objdump.txt
stepping log: arm_step_log.txt

In the log file I break on main then step (n) once. It might be relevant that we don't use hardware single step on Arm 32 bit (it exists we just don't use it). So perhaps the combination of software single step and this inlined function is a problem.

I noticed that although you can step into (s) and out of (fin) the inlined function, if I did instruction steps (ni), lldb would not recognise that it was inside the inlined function:

(lldb) ni
Process 1792462 stopped
* thread #1, name = 'a.out', stop reason = instruction step over
    frame #0: 0x00400558 a.out`main(argc=1, argv=0xfffef3d4) at calling.cpp:11:5
   8   	
   9   	int main (int argc, char **argv) {
   10  	    inline_value = 0;    // Stop here and step over to set up stepping over.
-> 11  	    inline_trivial_1 (); // At inline_trivial_1 called from main.
   12  	    return 0;
   13  	}
(lldb) dis
a.out`main:
    0x40052c <+0>:  push   {r11, lr}
    0x400530 <+4>:  mov    r11, sp
    0x400534 <+8>:  sub    sp, sp, #12
    0x400538 <+12>: movw   r2, #0x0
    0x40053c <+16>: str    r2, [r11, #-0x4]
    0x400540 <+20>: str    r0, [sp, #0x4]
    0x400544 <+24>: str    r1, [sp]
    0x400548 <+28>: movw   r0, #0x0
    0x40054c <+32>: ldr    r1, [pc, #0x14] ; <+60> at calling.cpp
    0x400550 <+36>: add    r1, pc, r1
    0x400554 <+40>: str    r0, [r1]
->  0x400558 <+44>: nop    
    0x40055c <+48>: movw   r0, #0x0
    0x400560 <+52>: mov    sp, r11
    0x400564 <+56>: pop    {r11, pc}
    0x400568 <+60>: andeq  r0, r1, r4, ror #21
(lldb) bt
* thread #1, name = 'a.out', stop reason = instruction step over
  * frame #0: 0x00400558 a.out`main(argc=1, argv=0xfffef3d4) at calling.cpp:11:5
    frame #1: 0xf7c8d7d6 libc.so.6`__libc_start_call_main(main=(a.out`main at calling.cpp:9), argc=1, argv=0xfffef3d4) at libc_start_call_main.h:58:16
    frame #2: 0xf7c8d886 libc.so.6`__libc_start_main_impl(main=(a.out`main at calling.cpp:9), argc=0, argv=0xf7d8e000, init=<unavailable>, fini=0x00000000, rtld_fini=(ld-linux-armhf.so.3`_dl_fini + 1 at dl-fini.c:51:20), stack_end=0xfffef3d4) at libc-start.c:392:3
    frame #3: 0x00400458 a.out`_start + 40

If I add a second nop, it will realise it's in the inlined function when it gets to the second nop.

smallp-o-p pushed a commit to smallp-o-p/llvm-project that referenced this pull request Nov 3, 2024
The test is currently passing everywhere but this 32-bit arm ubuntu bot.
I don't have an easy way to debug this, so I'm skipping the test on that
platform till we get a chance to figure this out.
NoumanAmir657 pushed a commit to NoumanAmir657/llvm-project that referenced this pull request Nov 4, 2024
The test is currently passing everywhere but this 32-bit arm ubuntu bot.
I don't have an easy way to debug this, so I'm skipping the test on that
platform till we get a chance to figure this out.
@DavidSpickett
Copy link
Collaborator

Test was fixed by #114628.

jimingham added a commit to swiftlang/llvm-project that referenced this pull request Nov 7, 2024
The test is currently passing everywhere but this 32-bit arm ubuntu bot.
I don't have an easy way to debug this, so I'm skipping the test on that
platform till we get a chance to figure this out.

(cherry picked from commit a218f0f)
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.

3 participants