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]

Reply via email to