Leaf functions are problematic for backtraces as they lack the frame pointer setup epilogue. If such a function causes a fault, the original caller won't be part of the backtrace. That's problematic if, for example, memcpy() is failing because it got passed a bad pointer. The generated backtrace will look like this, providing no clue what the issue may be: STACK: @401b31 4001ad 0x0000000000401b31: memcpy at lib/string.c:136 (discriminator 3) for (i = 0; i < n; ++i) > a[i] = b[i]; 0x00000000004001ac: gdt32_end at x86/cstart64.S:127 lea __environ(%rip), %rdx > call main mov %eax, %edi By abusing profiling, we can force the compiler to emit a frame pointer setup epilogue even for leaf functions, making the above backtrace change like this: STACK: @401c21 400512 4001ad 0x0000000000401c21: memcpy at lib/string.c:136 (discriminator 3) for (i = 0; i < n; ++i) > a[i] = b[i]; 0x0000000000400511: main at x86/hypercall.c:91 (discriminator 24) > memcpy((void *)~0xbadc0de, (void *)0xdeadbeef, 42); 0x00000000004001ac: gdt32_end at x86/cstart64.S:127 lea __environ(%rip), %rdx > call main mov %eax, %edi Above backtrace includes the failing memcpy() call, making it much easier to spot the bug. Enable "fake profiling" if supported by the compiler to get better backtraces. The runtime overhead should be negligible for the gained debugability as the profiling call is actually a NOP. Signed-off-by: Mathias Krause --- Makefile | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Makefile b/Makefile index 9dc5d2234e2a..470da8f5e625 100644 --- a/Makefile +++ b/Makefile @@ -95,6 +95,17 @@ CFLAGS += $(wmissing_parameter_type) CFLAGS += $(wold_style_declaration) CFLAGS += -Woverride-init -Wmissing-prototypes -Wstrict-prototypes +ifneq ($(KEEP_FRAME_POINTER),) +# Fake profiling to force the compiler to emit a frame pointer setup also in +# leaf function (-mno-omit-leaf-frame-pointer doesn't work, unfortunately). +# +# Note: +# We need to defer the cc-option test until -fno-pic or -no-pie have been +# added to CFLAGS as -mnop-mcount needs it. The lazy evaluation of CFLAGS +# during compilation makes this do "The Right Thing." +fomit_frame_pointer += $(call cc-option, -pg -mnop-mcount, "") +endif + autodepend-flags = -MMD -MP -MF $(dir $*).$(notdir $*).d LDFLAGS += -nostdlib $(no_pie) -z noexecstack -- 2.30.2