debugging: guard ABSL_HAVE_ELF_MEM_IMAGE on <link.h> availability - #2154
debugging: guard ABSL_HAVE_ELF_MEM_IMAGE on <link.h> availability#2154vasko-110 wants to merge 1 commit into
Conversation
ABSL_HAVE_ELF_MEM_IMAGE is enabled for every __ELF__ target except an explicit deny-list, and elf_mem_image.h then includes <link.h> unconditionally. __ELF__ describes the object format, not the presence of a dynamic loader, and <link.h> is a glibc/dynamic-linker header that bare-metal ELF toolchains do not ship. On arm-none-eabi with newlib the macro is defined, the include is reached, and the build fails with a fatal error. Test for the header the code actually needs instead of enumerating the platforms that lack it. The existing exclusions stay: __sun, __QNX__ and __OpenBSD__ do provide a <link.h>, with different semantics. stacktrace_config.h in the same directory already guards on __has_include(<execinfo.h>), and __has_include has been used unconditionally since 2fb2566.
| !defined(__asmjs__) && !defined(__wasm__) && !defined(__HAIKU__) && \ | ||
| !defined(__sun) && !defined(__VXWORKS__) && !defined(__hexagon__) && \ | ||
| !defined(__XTENSA__) | ||
| !defined(__XTENSA__) && __has_include(<link.h>) |
There was a problem hiding this comment.
Instead of just disabling this logic for bare-metal, we could add support like we did for FreeBSD. Something like this seems like it should work, if we also condition the include of link.h:
#ifndef ElfW
# if defined(__ELF_NATIVE_CLASS)
/* FreeBSD native infrastructure uses __ElfN */
# define ElfW(type) __ElfN(type)
# elif defined(__x86_64__) || defined(__aarch64__) || defined(__riscv) && (__riscv_xlen == 64)
/* Fallback block for 64-bit bare-metal environments */
# define ElfW(type) Elf64_##type
# else
/* Fallback block for 32-bit bare-metal environments */
# define ElfW(type) Elf32_##type
# endif
#endif```
There was a problem hiding this comment.
You're right, it builds — newlib ships <elf.h> even though it has no <link.h>, so this is enough:
#if __has_include(<link.h>)
#include <link.h> // for ElfW
#else
#include <elf.h>
#endif
#ifndef ElfW
#if defined(__FreeBSD__)
#define ElfW(type) __ElfN(type)
#elif __SIZEOF_POINTER__ == 8
#define ElfW(type) Elf64_##type
#else
#define ElfW(type) Elf32_##type
#endif
#endifTwo changes from yours. __ELF_NATIVE_CLASS is glibc's, not FreeBSD's — glibc's link.h defines ElfW before we get here, so that branch never fires, and FreeBSD would quietly lose __ElfN. And __SIZEOF_POINTER__ saves listing ppc64/s390x/mips64/loongarch64.
I'd still rather keep it off here, though. VDSOSupport::Init() needs either getauxval or /proc/self/auxv, so IsPresent() is always false on bare metal — that's 5 KB of .text and open/read/close in the link for a lookup that can't succeed.
Either way works for me, which do you prefer?
Fixes #2153.
ABSL_HAVE_ELF_MEM_IMAGEis enabled for every__ELF__target except a deny-list, and the header then includes<link.h>unconditionally.__ELF__describes the object format, not the presence of a dynamic loader, so bare-metal ELF toolchains (arm-none-eabiwith newlib) fail with a fatal error. This tests for the header the code actually needs instead.The existing exclusions are untouched:
__sun,__QNX__and__OpenBSD__do ship a<link.h>with different semantics, so they must stay listed regardless.Verified on
71330b93:elf_mem_image.ccandvdso_support.ccnow compile underarm-none-eabi-g++, and on the hostABSL_HAVE_ELF_MEM_IMAGEis still defined and both files still compile — no supported platform changes behaviour.