diff --git a/cmake/BuildLibCORO.cmake b/cmake/BuildLibCORO.cmake index 3a9c95426a1fd75b0bb00a04ccdcc593b7932f30..860aabd5e3b50117cb93855aced943373f295a60 100644 --- a/cmake/BuildLibCORO.cmake +++ b/cmake/BuildLibCORO.cmake @@ -4,6 +4,8 @@ macro(libcoro_build) set(coro_src ${PROJECT_SOURCE_DIR}/third_party/coro/coro.c ) + set_source_files_properties(${coro_src} PROPERTIES + COMPILE_FLAGS -fomit-frame-pointer) add_library(coro STATIC ${coro_src}) @@ -20,4 +22,3 @@ macro(libcoro_build) unset(coro_src) endmacro(libcoro_build) - diff --git a/cmake/compiler.cmake b/cmake/compiler.cmake index c0b3b4703a2e5819c7b857baf5ad6e1fffa6bc1b..fb1a70fa0d9b7b83655dd0bdf43ce60b99d16b1b 100644 --- a/cmake/compiler.cmake +++ b/cmake/compiler.cmake @@ -179,17 +179,6 @@ endif() add_compile_flags("C;CXX" "-fexceptions" "-funwind-tables") -# We must set -fno-omit-frame-pointer here, since we rely -# on frame pointer when getting a backtrace, and it must -# be used consistently across all object files. -# The same reasoning applies to -fno-stack-protector switch. - -if (ENABLE_BACKTRACE) - add_compile_flags("C;CXX" - "-fno-omit-frame-pointer" - "-fno-stack-protector") -endif() - # In C a global variable without a storage specifier (static/extern) and # without an initialiser is called a ’tentative definition’. The # language permits multiple tentative definitions in the single diff --git a/third_party/coro/coro.c b/third_party/coro/coro.c index ca490dc268a9d8816bf4165dfcea3765e05aca11..5028e3c1466fecfa2b46b64c7e93db7a76290b25 100644 --- a/third_party/coro/coro.c +++ b/third_party/coro/coro.c @@ -40,6 +40,8 @@ #include "coro.h" +#include "trivia/config.h" + #include <stddef.h> #include <string.h> @@ -103,13 +105,36 @@ coro_init (void) coro_transfer (new_coro, create_coro); -#if __GCC_HAVE_DWARF2_CFI_ASM && __amd64 - asm (".cfi_undefined rip"); -#endif - - func ((void *)arg); - - /* the new coro returned. bad. just abort() for now */ + __asm__ volatile( +#ifdef ENABLE_BACKTRACE + /* + * Call-chain ends here: we need to invalidate this frame's return + * address to make unwinding stop here. + */ + + /* Clearing rbp is insufficient: undefine rip value's location — see: https://github.com/libunwind/libunwind/blob/ec171c9ba7ea3abb2a1383cee2988a7abd483a1f/src/x86_64/Gstep.c#L91-L92 */ + ".cfi_undefined rip\n" + /* Undefine rbp value's location — ibid. */ + ".cfi_undefined rbp\n" + /* Undefine rbp-relative return address location, see: https://github.com/libunwind/libunwind/blob/ec171c9ba7ea3abb2a1383cee2988a7abd483a1f/src/dwarf/Gparser.c#L877 */ + ".cfi_return_column rbp\n" +#endif /* ENABLE_BACKTRACE */ + /* Clear rbp to conform to the x86_64 ABI, see: https://github.com/libunwind/libunwind/blob/ec171c9ba7ea3abb2a1383cee2988a7abd483a1f/src/x86_64/Gstep.c#L144-L148 */ + "\txorq %%rbp, %%rbp\n" + "\tmovq %0, %%rdi\n" + "\tcallq *%1\n" + : + : "rm" (arg), "rm" (func), "m" (*arg) + : "rbp", "rax", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r10", "r11", + "xmm0","xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", + "xmm8","xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", +#ifdef __AVX512F__ + "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", + "xmm23", "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", + "xmm30", "xmm31", "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", +#endif /* __AVX512F__ */ + "mm0","mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm6", "st", + "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"); abort (); } # endif @@ -320,13 +345,21 @@ trampoline (int sig) ".fnend\n" #elif __aarch64__ - +#ifdef ENABLE_BACKTRACE ".cfi_startproc\n" - "\tmov x30, #0\n" - "\tsub sp, sp, #16\n" - "\tstr x30, [sp, #0]\n" - ".cfi_def_cfa_offset 16\n" - ".cfi_offset 30, -16\n" + /* + * Call-chain ends here: we need to invalidate this frame's return + * address to make unwinding stop here. + */ + + /* + * Detection of call-chain end on AARCH64 ABI inherently relies on CFI, + * see: https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#623the-frame-pointer. + * Simply undefine x29 and x30 register values' locations. + */ + ".cfi_undefined x29\n" + ".cfi_undefined x30\n" +#endif /* ENABLE_BACKTRACE */ "\tmov x0, x20\n" "\tblr x19\n" # ifdef __APPLE__ @@ -334,8 +367,9 @@ trampoline (int sig) # else "\tb abort\n" # endif +#ifdef ENABLE_BACKTRACE ".cfi_endproc\n" - +#endif /* ENABLE_BACKTRACE */ #else #error unsupported architecture #endif