https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88432
Bug ID: 88432 Summary: Dwarf line numbering inadequate when using -fstack-protector-strong Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: debug Assignee: unassigned at gcc dot gnu.org Reporter: alahay01 at gcc dot gnu.org Target Milestone: --- Created attachment 45198 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45198&action=edit Example breaking program Using -fstack-protector-strong will cause GDB to break on the wrong line when placing a breakpoint on a function. [ Note that the GCC provided with Ubuntu will default to -fstack-protector-strong, causing all function breakpoints to break on the wrong line. This breaks roughly 50 GDB tests when run on x86 and AArch64 Ubuntu ] The issue in GDB ================= Consider the following program: 47: int main () 48: { 49: char arg2 = 2; 50: signed char arg3 = 3; (full program attached. Ignore everything in it except for main. Testcase taken from the GDB testsuite.) When compiled with -fstack-protector-strong, then running it in GDB, “breakpoint main” will stop at line 48, the "{". This is wrong, it should instead stop on line 49 – the first line of the function body. GDB figures this out by looking at the dwarf line numbers. It finds the entry for the start of the function (from other dwarf entries), and assumes that it the entry for the function prologue. It then jumps forward one entry. With stack proctector turned off we get the following. Note that the dwarf label for main points at index 2. INDEX LINE ADDRESS 0 45 0x0000000000400680 1 45 0x0000000000400680 2 48 0x0000000000400688 - main: prologue pt1 3 49 0x00000000004006ac - main: first line of function 4 50 0x00000000004006b4 - main: second line of function ...etc With stack protector on (like Ubuntu): INDEX LINE ADDRESS 0 45 0x0000000000400680 1 45 0x0000000000400680 2 48 0x0000000000400688 - main: prologue pt1 3 48 0x0000000000400698 - main: stack protector code 4 49 0x00000000004006ac - main: first line of function 5 50 0x00000000004006b4 - main: second line of function ...etc Ok, we could jump forward two entries. But then breaks with the following (with either stack protector on or off): 47: int main () 48: { char arg2 = 2; 49: signed char arg3 = 3; It will result in the same line table, with just two entries at line 48: INDEX LINE ADDRESS 0 45 0x0000000000400680 1 45 0x0000000000400680 2 48 0x0000000000400688 - main: prologue pt1 3 48 0x0000000000400698 - main: stack protector code 4 49 0x00000000004006ac - main: second line of function ...etc There is no way to tell if a repeated line is the first line of code or the stack protector. The underlying issue in GCC =========================== See the attached rtl final dump from GCC (note: aarch64 code, but that doesn't matter). With the stack protector on, GCC produces RTL for the stack protector at the beginning of the function, after the prologue. You roughly get: *function prologue rtl *NOTE_INSN_PROLOGUE_END *NOTE_INSN_FUNCTION_BEG *stack guard code (__stack_chk_guard) *rest of the function rtl The stack guard rtl is given the line number of the "{" line. When dumping line locations, notice_source_line() decides which RTL expressions should cause a dump. It will force a dump of the first expression following the end of the prologue - expecting this to be the first line of the function. This gives us: .LFB1: .loc 1 48 0. – function prologue. .cfi_startproc sub sp, sp, #176 .cfi_def_cfa_offset 176 stp x29, x30, [sp, 32] .cfi_offset 29, -144 .cfi_offset 30, -136 add x29, sp, 32 .cfi_def_cfa 29, 144 str x19, [sp, 48] .cfi_offset 19, -128 .loc 1 48 0 -- Start of stack guard code adrp x0, __stack_chk_guard add x0, x0, :lo12:__stack_chk_guard ldr x1, [x0] str x1, [x29, 136] mov x1,0 .loc 1 49 0. – first line of function mov w0, 2 strb w0, [x29, 45] .loc 1 50 0 mov w0, 3 strb w0, [x29, 46]