[Bug tools/32864] "eu-readelf: bad dynamic symbol" error on ELF without DT_VERSYM

2025-04-10 Thread amerey at redhat dot com
https://sourceware.org/bugzilla/show_bug.cgi?id=32864

Aaron Merey  changed:

   What|Removed |Added

 CC||amerey at redhat dot com

--- Comment #2 from Aaron Merey  ---
Thanks for the detailed bug report. I've posted a patch to elfutils-devel based
on your sample patch.

https://sourceware.org/pipermail/elfutils-devel/2025q2/008084.html

-- 
You are receiving this mail because:
You are on the CC list for the bug.

[PATCH] src/readelf.c: Access symbol and version data only if available

2025-04-10 Thread Aaron Merey
handle_dynamic_symtab can attempt to read symbol and version data from
file offset 0 if the associated DT_ tags aren't found.

Fix this by only reading symbol and version data when non-zero file
offsets have been found.

https://sourceware.org/bugzilla/show_bug.cgi?id=32864

Suggested-by: Constantine Bytensky 
Signed-off-by: Aaron Merey 
---
 src/readelf.c | 50 +++---
 1 file changed, 31 insertions(+), 19 deletions(-)

diff --git a/src/readelf.c b/src/readelf.c
index 5b0e7b47..0452977f 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3047,18 +3047,25 @@ handle_dynamic_symtab (Ebl *ebl)
   Elf_Data *verdef_data = NULL;
   Elf_Data *verneed_data = NULL;
 
-  symdata = elf_getdata_rawchunk (
-  ebl->elf, offs[i_symtab],
-  gelf_fsize (ebl->elf, ELF_T_SYM, syments, EV_CURRENT), ELF_T_SYM);
-  symstrdata = elf_getdata_rawchunk (ebl->elf, offs[i_strtab], addrs[i_strsz],
- ELF_T_BYTE);
-  versym_data = elf_getdata_rawchunk (
-  ebl->elf, offs[i_versym], syments * sizeof (Elf64_Half), ELF_T_HALF);
+  if (offs[i_symtab] != 0)
+symdata = elf_getdata_rawchunk (
+   ebl->elf, offs[i_symtab],
+   gelf_fsize (ebl->elf, ELF_T_SYM, syments, EV_CURRENT), ELF_T_SYM);
+
+  if (offs[i_strtab] != 0)
+symstrdata = elf_getdata_rawchunk (ebl->elf, offs[i_strtab], 
addrs[i_strsz],
+  ELF_T_BYTE);
+
+  if (offs[i_versym] != 0)
+versym_data = elf_getdata_rawchunk (
+   ebl->elf, offs[i_versym], syments * sizeof (Elf64_Half), ELF_T_HALF);
 
   /* Get the verneed_data without vernaux.  */
-  verneed_data = elf_getdata_rawchunk (
-  ebl->elf, offs[i_verneed], addrs[i_verneednum] * sizeof (Elf64_Verneed),
-  ELF_T_VNEED);
+  if (offs[i_verneed] != 0)
+verneed_data = elf_getdata_rawchunk (
+   ebl->elf, offs[i_verneed], addrs[i_verneednum] * sizeof (Elf64_Verneed),
+   ELF_T_VNEED);
+
   size_t vernauxnum = 0;
   size_t vn_next_offset = 0;
 
@@ -3071,14 +3078,18 @@ handle_dynamic_symtab (Ebl *ebl)
 }
 
   /* Update the verneed_data to include the vernaux.  */
-  verneed_data = elf_getdata_rawchunk (
-  ebl->elf, offs[i_verneed],
-  (addrs[i_verneednum] + vernauxnum) * sizeof (GElf_Verneed), ELF_T_VNEED);
+  if (offs[i_verneed] != 0)
+verneed_data = elf_getdata_rawchunk (
+   ebl->elf, offs[i_verneed],
+   (addrs[i_verneednum] + vernauxnum) * sizeof (GElf_Verneed),
+   ELF_T_VNEED);
 
   /* Get the verdef_data without verdaux.  */
-  verdef_data = elf_getdata_rawchunk (
-  ebl->elf, offs[i_verdef], addrs[i_verdefnum] * sizeof (Elf64_Verdef),
-  ELF_T_VDEF);
+  if (offs[i_verdef] != 0)
+verdef_data = elf_getdata_rawchunk (
+   ebl->elf, offs[i_verdef], addrs[i_verdefnum] * sizeof (Elf64_Verdef),
+   ELF_T_VDEF);
+
   size_t verdauxnum = 0;
   size_t vd_next_offset = 0;
 
@@ -3091,9 +3102,10 @@ handle_dynamic_symtab (Ebl *ebl)
 }
 
   /* Update the verdef_data to include the verdaux.  */
-  verdef_data = elf_getdata_rawchunk (
-  ebl->elf, offs[i_verdef],
-  (addrs[i_verdefnum] + verdauxnum) * sizeof (GElf_Verdef), ELF_T_VDEF);
+  if (offs[i_verdef] != 0)
+verdef_data = elf_getdata_rawchunk (
+   ebl->elf, offs[i_verdef],
+   (addrs[i_verdefnum] + verdauxnum) * sizeof (GElf_Verdef), ELF_T_VDEF);
 
   unsigned int nsyms = (unsigned int)syments;
   process_symtab (ebl, nsyms, 0, 0, 0, symdata, versym_data, symstrdata,
-- 
2.49.0



Re: [PATCH v2] libdwfl: resolve all paths relative to sysroot

2025-04-10 Thread Aaron Merey
Hi Michal,

On Tue, Apr 1, 2025 at 2:56 PM Michal Sekletar  wrote:
>
> Whenever possible, resolve all symlinks as if the sysroot path were a
> chroot environment. This prevents potential interactions with files from
> the host filesystem.
>
> Signed-off-by: Michal Sekletar 
> ---
>  configure.ac |  26 ++
>  libdwfl/dwfl_segment_report_module.c |  39 +--
>  libdwfl/link_map.c   |  32 +-
>  tests/run-sysroot.sh |  32 ++
>  tests/testfile-sysroot-link.tar.bz2  | Bin 0 -> 2334030 bytes
>  5 files changed, 120 insertions(+), 9 deletions(-)
>  create mode 100644 tests/testfile-sysroot-link.tar.bz2
>
> diff --git a/configure.ac b/configure.ac
> index 1679a17d..27ea7153 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -283,6 +283,32 @@ case "$CFLAGS" in
>  ;;
>  esac
>
> +AC_CACHE_CHECK(
> +  [for openat2 with RESOLVE_IN_ROOT support],
> +  [eu_cv_openat2_RESOLVE_IN_ROOT],
> +  [AC_LINK_IFELSE(
> +[AC_LANG_PROGRAM(
> +  [[#define _GNU_SOURCE
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +  ]], [[
> +struct open_how how = { .flags = O_RDONLY|O_DIRECTORY, .resolve = 
> RESOLVE_IN_ROOT };
> +int dfd = open (".", O_PATH);
> +return syscall (SYS_openat2, dfd, ".", &how, sizeof(how)) < 0;
> +  ]]
> +)],
> +[eu_cv_openat2_RESOLVE_IN_ROOT=yes],
> +[eu_cv_openat2_RESOLVE_IN_ROOT=no]
> +  )]
> +)
> +AS_IF([test "x$eu_cv_openat2_RESOLVE_IN_ROOT" = xyes],
> +  [AC_DEFINE([HAVE_OPENAT2_RESOLVE_IN_ROOT], [1], [Define if openat2 is 
> available])]
> +)
> +
>  dnl enable debugging of branch prediction.
>  AC_ARG_ENABLE([debugpred],
>  AS_HELP_STRING([--enable-debugpred],[build binaries with support to debug 
> branch prediction]),
> diff --git a/libdwfl/dwfl_segment_report_module.c 
> b/libdwfl/dwfl_segment_report_module.c
> index 32f44af8..ee723114 100644
> --- a/libdwfl/dwfl_segment_report_module.c
> +++ b/libdwfl/dwfl_segment_report_module.c
> @@ -37,6 +37,12 @@
>  #include 
>  #include 
>
> +#if HAVE_OPENAT2_RESOLVE_IN_ROOT
> +#include 
> +#include 
> +#include 
> +#endif
> +
>  #include 
>
>
> @@ -784,18 +790,35 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const 
> char *name,
>  sysroot if it is set.  */
>if (dwfl->sysroot && !executable)
>  {
> - int r;
> - char *n;
> +#ifdef HAVE_OPENAT2_RESOLVE_IN_ROOT
> + int sysrootfd;
> + struct open_how how = {
> +   .flags = O_RDONLY,
> +   .resolve = RESOLVE_IN_ROOT,
> + };
> +
> + sysrootfd = open (dwfl->sysroot, O_DIRECTORY|O_PATH);
> + if (sysrootfd < 0)
> +   return -1;
>
> - r = asprintf (&n, "%s%s", dwfl->sysroot, name);
> - if (r > 0)
> + fd = syscall (SYS_openat2, sysrootfd, name, &how, sizeof(how));
> + close (sysrootfd);
> +
> + if (fd < 0 && errno == ENOSYS)
> +#endif
> {
> - fd = open (n, O_RDONLY);
> - free (n);
> + int r;
> + char *n;
> + r = asprintf (&n, "%s%s", dwfl->sysroot, name);
> + if (r > 0)
> +   {
> + fd = open (n, O_RDONLY);
> + free (n);
> +   }
> }
> -}
> +   }
>else
> - fd = open (name, O_RDONLY);
> +   fd = open (name, O_RDONLY);
>
>if (fd >= 0)
> {
> diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
> index 8ab14862..c52ed041 100644
> --- a/libdwfl/link_map.c
> +++ b/libdwfl/link_map.c
> @@ -34,6 +34,12 @@
>
>  #include 
>
> +#if HAVE_OPENAT2_RESOLVE_IN_ROOT
> +#include 
> +#include 
> +#include 
> +#endif
> +
>  /* This element is always provided and always has a constant value.
> This makes it an easy thing to scan for to discern the format.  */
>  #define PROBE_TYPE AT_PHENT
> @@ -418,7 +424,30 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t 
> elfdata,
>   /* This code is mostly inlined dwfl_report_elf.  */
>   char *sysroot_name = NULL;
>   const char *sysroot = dwfl->sysroot;
> + int fd;
> +
> +#ifdef HAVE_OPENAT2_RESOLVE_IN_ROOT
> + if (sysroot)
> +   {
> + int sysrootfd;
> +
> + struct open_how how = {
> +   .flags = O_RDONLY,
> +   .resolve = RESOLVE_IN_ROOT,
> + };
>
> + sysrootfd = open (sysroot, O_DIRECTORY|O_PATH);
> + if (sysrootfd < 0)
> +   return -1;
> +
> + fd = syscall (SYS_openat2, sysrootfd, name, &how, sizeof(how));
> + close (sysrootfd);
> +
> + /* Fallback to regular open() is openat2 is not available. */
> + if (fd < 0 && errno == ENOSYS)
> +   fd = open (name, O_RDONLY);
> +   }

Re: [PATCH] libdw: Add Nim language and dwarf_srclang tests

2025-04-10 Thread Aaron Merey
Hi Mark,

On Wed, Apr 2, 2025 at 8:50 AM Mark Wielaard  wrote:
>
> DW_LANG_Nim and DW_LNAME_Nim were added to the DWARF languages.
>
> While adding them, and the default lower bounds, I noticed DW_LANG_V
> and DW_LANG_Algol68 where missing in srclang_to_language an internal
> helper function.
>
> Testing through the public api is not that easy since you need a
> Dwarf_Die with the right attributes. So this patch adds a way to
> compile an individual source file with an optional main function that
> can directly access the internal/static functions.
>
> Note that it is almost generic. But even though using .SECONDEXPANSION
> I couldn't figure out how to create the equivalent of a rule starting
> with %_check$(EXEEXT) target. So for now the rule has to repeated for
> every new _check TEST. And there needs to be a line to tell make dist
> to not expect the fake source: nodist_src_check_SOURCES = src_check.c
>
> The new test pointed out that there were a few more bugs with
> DW_LANG_Dylan and DW_LNAME_Mojo. Also fix those.
>
> * libdw/dwarf.h: Add DW_LANG_Nim and DW_LNAME_Nim.
> * libdw/Makefile.am: Add check_PROGRAMS and TESTS for
> dwarf_srclang_check.
> * libdw/dwarf_default_lower_bound.c
> (dwarf_default_lower_bound): Add DW_LANG_Nim.
> (dwarf_language_lower_bound): Add DW_LNAME_Nim.
> * libdw/dwarf_srclang.c (srclang_to_language): Handle
> DW_LANG_Dylan, DW_LANG_V, DW_LANG_Algol68 and DW_LANG_Nim.
> (language_to_srclang): Fix DW_LNAME_Mojo. Add DW_LNAME_Nim.
> (test_lang): New function guarded by MAIN_CHECK.
> (main): Likewise.
>
> Signed-off-by: Mark Wielaard 

LGTM. The optional main function approach opens up a lot of
possibilities for testing static functions throughout all elfutils
libraries.

Aaron