Skip to content

prologue_end since LLVM20 misleads gdb into setting flawed breakpoints #139549

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

Closed
jmorse opened this issue May 12, 2025 · 4 comments
Closed

prologue_end since LLVM20 misleads gdb into setting flawed breakpoints #139549

jmorse opened this issue May 12, 2025 · 4 comments
Assignees

Comments

@jmorse
Copy link
Member

jmorse commented May 12, 2025

While working on the reproducer from #135937, I discovered that gdb really doesn't like the new placement of prologue_end since #107849 and related patches. The code:

 1  int printf(const char *, ...);
 2  int a, c;
 3  unsigned b = 5;
 4  int d() {
 5    if (b)
 6      return b;
 7    c = 8;  // Dead code here
 8  }
 9  int main() {
10    d();
11    printf("%X\n", a);
12  }

Compiled with clang 3b4f9c5 -g -O2 produces this code at the beginning of main:

0000000000001160 <main>:
    1160:       83 3d c9 2e 00 00 00    cmpl   $0x0,0x2ec9(%rip)        # 4030 <b>
    1167:       75 0a                   jne    1173 <main+0x13>
    1169:       c7 05 c5 2e 00 00 08    movl   $0x8,0x2ec5(%rip)        # 4038 <c>
    1170:       00 00 00

Which has this linetable:

0x0000000000001160      5      7      0   0             0  is_stmt prologue_end
0x0000000000001169      7      5      0   0             0  is_stmt
0x0000000000001174     11     18      0   0             0  is_stmt

i.e., the first line is part of d that's been inlined, and the prologue immediately ends. LLDB is happy with this, the SCE debugger is happy with this, however gdb:

(gdb) start
Temporary breakpoint 1 at 0x1169: file /tmp/wat.c, line 10.
[runs to completion]

places the initial breakpoint for 'main' on the line entry /after/ prologue_end, which is past the first branch instruction. As a result, the path taken through main isn't completely covered by that breakpoint, and the program never stops. This is undesirable. The gdb version string I have locally is GNU gdb (Ubuntu 12.1-0ubuntu1~22.04.2) 12.1.

DWARF5 describes the prologue_end flag thusly:

A boolean indicating that the current address is one (of possibly many) where execution should be suspended for a breakpoint at the entry of a function

Which I feel naturally means that the address to suspend execution is that address where prologue_end is. i.e. 0x1160 in this example. gdb would appear to have an interpretation that I'm unfamiliar with.

Next steps are, I believe:

  • If someone has a different interpretation of prologue_end, or can explain why gdb behaves in this way, please do tell me!,
  • Otherwise I'll try to replicate with the latest version of gdb,
  • And if it replicates, I'll report to gdb to see what they think the correct behaviour should be.
@jmorse jmorse self-assigned this May 12, 2025
@llvmbot
Copy link
Member

llvmbot commented May 12, 2025

@llvm/issue-subscribers-debuginfo

Author: Jeremy Morse (jmorse)

While working on the reproducer from #135937, I discovered that gdb really doesn't like the new placement of `prologue_end` since #107849 and related patches. The code:
 1  int printf(const char *, ...);
 2  int a, c;
 3  unsigned b = 5;
 4  int d() {
 5    if (b)
 6      return b;
 7    c = 8;  // Dead code here
 8  }
 9  int main() {
10    d();
11    printf("%X\n", a);
12  }

Compiled with clang 3b4f9c5 -g -O2 produces this code at the beginning of main:

0000000000001160 &lt;main&gt;:
    1160:       83 3d c9 2e 00 00 00    cmpl   $0x0,0x2ec9(%rip)        # 4030 &lt;b&gt;
    1167:       75 0a                   jne    1173 &lt;main+0x13&gt;
    1169:       c7 05 c5 2e 00 00 08    movl   $0x8,0x2ec5(%rip)        # 4038 &lt;c&gt;
    1170:       00 00 00

Which has this linetable:

0x0000000000001160      5      7      0   0             0  is_stmt prologue_end
0x0000000000001169      7      5      0   0             0  is_stmt
0x0000000000001174     11     18      0   0             0  is_stmt

i.e., the first line is part of d that's been inlined, and the prologue immediately ends. LLDB is happy with this, the SCE debugger is happy with this, however gdb:

(gdb) start
Temporary breakpoint 1 at 0x1169: file /tmp/wat.c, line 10.
[runs to completion]

places the initial breakpoint for 'main' on the line entry /after/ prologue_end, which is past the first branch instruction. As a result, the path taken through main isn't completely covered by that breakpoint, and the program never stops. This is undesirable. The gdb version string I have locally is GNU gdb (Ubuntu 12.1-0ubuntu1~22.04.2) 12.1.

DWARF5 describes the prologue_end flag thusly:

A boolean indicating that the current address is one (of possibly many) where execution should be suspended for a breakpoint at the entry of a function

Which I feel naturally means that the address to suspend execution is that address where prologue_end is. i.e. 0x1160 in this example. gdb would appear to have an interpretation that I'm unfamiliar with.

Next steps are, I believe:

  • If someone has a different interpretation of prologue_end, or can explain why gdb behaves in this way, please do tell me!,
  • Otherwise I'll try to replicate with the latest version of gdb,
  • And if it replicates, I'll report to gdb to see what they think the correct behaviour should be.

@walkerkd
Copy link
Collaborator

I agree with your interpretation of prologue_end, but have no idea why gdb would interpret it differently.

@dwblaikie
Copy link
Collaborator

Guess it's something to do with the instruction being branching in some way? There's certainly going to be many common cases where there is a zero-length prologue, and I'd expect gdb handles most of them fine, eg:

int f2(int x) {
  return x + 2;
}
Address            Line   Column File   ISA Discriminator OpIndex Flags
------------------ ------ ------ ------ --- ------------- ------- -------------
0x0000000000001130      3     12      0   0             0       0  is_stmt prologue_end
0x0000000000001133      3      3      0   0             0       0
0x0000000000001134      3      3      0   0             0       0  end_sequence

and gdb breaking on f2 seems fine breaking at 0x1130

@jmorse
Copy link
Member Author

jmorse commented May 15, 2025

It looks like this is fixed with the latest version of gdb (or, a much more recent version). The one I've now got locally has the version string GNU gdb (GDB) 15.0.50.20240129-git and will successfully place the breakpoint at the first instruction of the function.

I suppose there's nothing to do here so I'll close the ticket.

@jmorse jmorse closed this as completed May 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants