Skip to content

debugging: define ElfW when the target has no <link.h> - #2154

Open
vasko-110 wants to merge 1 commit into
abseil:masterfrom
vasko-110:elf-mem-image-has-link-h
Open

debugging: define ElfW when the target has no <link.h>#2154
vasko-110 wants to merge 1 commit into
abseil:masterfrom
vasko-110:elf-mem-image-has-link-h

Conversation

@vasko-110

@vasko-110 vasko-110 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #2153.

Per review: instead of disabling ABSL_HAVE_ELF_MEM_IMAGE on targets without a dynamic loader, define ElfW ourselves when <link.h> is missing. newlib ships <elf.h>, so that is enough to build.

Two details differ from the snippet in the review. __SIZEOF_POINTER__ == 8 replaces the architecture list, which covers ppc64/s390x/mips64/loongarch64 as well. And the FreeBSD branch keeps defined(__FreeBSD__): __ELF_NATIVE_CLASS is a glibc macro, and by the time we reach this block glibc's <link.h> has already defined ElfW, so it would never fire — while FreeBSD would silently lose __ElfN.

The platform deny-list is untouched.

Verified: elf_mem_image.cc and vdso_support.cc compile under arm-none-eabi-g++, and the host is unchanged — ElfW still comes from <link.h> there.

Comment thread absl/debugging/internal/elf_mem_image.h Outdated
!defined(__asmjs__) && !defined(__wasm__) && !defined(__HAIKU__) && \
!defined(__sun) && !defined(__VXWORKS__) && !defined(__hexagon__) && \
!defined(__XTENSA__)
!defined(__XTENSA__) && __has_include(<link.h>)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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```

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
#endif

Two 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?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think either making it work for bare metal, or going your original route with some cleanup (instead of lumping on more complexity) would be preferable. I don't have a strong preference between those, but I'd rather not add this catch-all and leave this list of platforms that presumably don't have link.h either

@vasko-110 vasko-110 Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

Went with your approach. I can't test VxWorks/Hexagon/Xtensa/wasm/Haiku here, so pruning their guards would have been guesswork — this way the list doesn't need to change at all.

Kept two things from my last comment: __SIZEOF_POINTER__ == 8 instead of the arch list, and defined(__FreeBSD__) for the __ElfN branch.

@mkruskal-google mkruskal-google self-assigned this Sep 7, 2026
ABSL_HAVE_ELF_MEM_IMAGE is enabled for every __ELF__ target except an
explicit deny-list, and the header then includes <link.h>
unconditionally. __ELF__ describes the object format, not the presence of
a dynamic loader: bare-metal ELF toolchains produce ELF objects and ship
no <link.h>. On arm-none-eabi with newlib the include is reached and the
build fails with a fatal error.

newlib does provide <elf.h>, so include that when <link.h> is missing and
define ElfW from the target's pointer size. This generalizes the existing
FreeBSD case, which already defines ElfW itself.

Platforms that do have <link.h> are unaffected: it defines ElfW, so the
fallback block is skipped.
@vasko-110
vasko-110 force-pushed the elf-mem-image-has-link-h branch from 9c7fb0b to ba01560 Compare September 8, 2026 10:07
@vasko-110 vasko-110 changed the title debugging: guard ABSL_HAVE_ELF_MEM_IMAGE on <link.h> availability debugging: define ElfW when the target has no <link.h> Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: ABSL_HAVE_ELF_MEM_IMAGE assumes every ELF target ships <link.h>

2 participants