[PATCH 1/2] libdwfl: specify optional sysroot to search for shared libraries and binaries

2024-07-01 Thread Michal Sekletar
From: Luke Diamand 

When searching the list of modules in a core file, if the core was
generated on a different system to the current one, we need to look
in a sysroot for the various shared objects.

For example, we might be looking at a core file from an ARM system
using elfutils running on an x86 host.

This change adds a new function, dwfl_set_sysroot(), which then
gets used when searching for libraries and binaries.

Signed-off-by: Luke Diamand 
Signed-off-by: Michal Sekletar 
---
 libdw/libdw.map  |  5 +++
 libdwfl/Makefile.am  |  1 +
 libdwfl/core-file.c  |  2 +-
 libdwfl/dwfl_end.c   |  1 +
 libdwfl/dwfl_segment_report_module.c | 20 +-
 libdwfl/dwfl_set_sysroot.c   | 57 
 libdwfl/libdwfl.h|  6 +++
 libdwfl/libdwflP.h   |  3 +-
 libdwfl/link_map.c   | 19 +-
 9 files changed, 109 insertions(+), 5 deletions(-)
 create mode 100644 libdwfl/dwfl_set_sysroot.c

diff --git a/libdw/libdw.map b/libdw/libdw.map
index 3c5ce8dc..552588a9 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -378,3 +378,8 @@ ELFUTILS_0.191 {
   global:
 dwarf_cu_dwp_section_info;
 } ELFUTILS_0.188;
+
+ELFUTILS_0.192 {
+  global:
+dwfl_set_sysroot;
+} ELFUTILS_0.191;
diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am
index 6b26cd51..57c89604 100644
--- a/libdwfl/Makefile.am
+++ b/libdwfl/Makefile.am
@@ -67,6 +67,7 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c 
dwfl_version.c \
dwfl_module_return_value_location.c \
dwfl_module_register_names.c \
dwfl_segment_report_module.c \
+   dwfl_set_sysroot.c \
link_map.c core-file.c open.c image-header.c \
dwfl_frame.c frame_unwind.c dwfl_frame_pc.c \
linux-pid-attach.c linux-core-attach.c dwfl_frame_regs.c \
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
index 89527d23..3135f884 100644
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -559,7 +559,7 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char 
*executable)
   ndx = 0;
   do
 {
-  int seg = dwfl_segment_report_module (dwfl, ndx, NULL,
+  int seg = dwfl_segment_report_module (dwfl, ndx, NULL, executable,
&dwfl_elf_phdr_memory_callback, elf,
core_file_read_eagerly, elf,
elf->maximum_size,
diff --git a/libdwfl/dwfl_end.c b/libdwfl/dwfl_end.c
index a1812407..7b5ac8a1 100644
--- a/libdwfl/dwfl_end.c
+++ b/libdwfl/dwfl_end.c
@@ -48,6 +48,7 @@ dwfl_end (Dwfl *dwfl)
   free (dwfl->lookup_addr);
   free (dwfl->lookup_module);
   free (dwfl->lookup_segndx);
+  free (dwfl->sysroot);
 
   Dwfl_Module *next = dwfl->modulelist;
   while (next != NULL)
diff --git a/libdwfl/dwfl_segment_report_module.c 
b/libdwfl/dwfl_segment_report_module.c
index dc34e0ae..bd360769 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -288,6 +288,7 @@ read_portion (struct read_state *read_state,
 
 int
 dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
+   const char *executable,
Dwfl_Memory_Callback *memory_callback,
void *memory_callback_arg,
Dwfl_Module_Callback *read_eagerly,
@@ -778,7 +779,24 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const 
char *name,
   name = file_note_name;
   name_is_final = true;
   bool invalid = false;
-  fd = open (name, O_RDONLY);
+
+  /* We were not handed specific executable hence try to look for it in 
sysroot if
+ it is set.  */
+  if (dwfl->sysroot && !executable)
+{
+ 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);
+
   if (fd >= 0)
{
  Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
diff --git a/libdwfl/dwfl_set_sysroot.c b/libdwfl/dwfl_set_sysroot.c
new file mode 100644
index ..309ccd5d
--- /dev/null
+++ b/libdwfl/dwfl_set_sysroot.c
@@ -0,0 +1,57 @@
+/* Return one of the sources lines of a CU.
+   Copyright (C) 2024 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+   Software Foundation; either version 3 of the License, or (at
+   your option) any later version
+
+   or
+
+ * the GNU General Public License as pub

[PATCH 2/2] eu-stack: add support for sysroot option

2024-07-01 Thread Michal Sekletar
From: Luke Diamand 

Use the dwfl_set_sysroot() function to set the sysroot to be
used when analysing a core:

e.g.
   $ eu-stack --core core --sysroot /path/to/sysroot -e crashing_prog

Signed-off-by: Luke Diamand 
Signed-off-by: Michal Sekletar 
---
 src/stack.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/src/stack.c b/src/stack.c
index f4c5ba8c..da2e66a8 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -73,6 +73,7 @@ static int core_fd = -1;
 static Elf *core = NULL;
 static const char *exec = NULL;
 static char *debuginfo_path = NULL;
+static const char *sysroot = NULL;
 
 static const Dwfl_Callbacks proc_callbacks =
   {
@@ -559,6 +560,10 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
   show_modules = true;
   break;
 
+case 'S':
+  sysroot = arg;
+  break;
+
 case ARGP_KEY_END:
   if (core == NULL && exec != NULL)
argp_error (state,
@@ -592,6 +597,8 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
  dwfl = dwfl_begin (&core_callbacks);
  if (dwfl == NULL)
error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+ if (sysroot && dwfl_set_sysroot (dwfl, sysroot) < 0)
+   error (EXIT_BAD, 0, "dwfl_set_sysroot");
  if (dwfl_core_file_report (dwfl, core, exec) < 0)
error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
}
@@ -675,6 +682,8 @@ main (int argc, char **argv)
N_("Show at most MAXFRAMES per thread (default 256, use 0 for 
unlimited)"), 0 },
   { "list-modules", 'l', NULL, 0,
N_("Show module memory map with build-id, elf and debug files 
detected"), 0 },
+  { "sysroot", 'S', "sysroot", 0,
+  N_("Set the sysroot to search for libraries referenced from the core file"), 
0 },
   { NULL, 0, NULL, 0, NULL, 0 }
 };
 
-- 
2.39.3 (Apple Git-146)



Re: [PATCH 1/2] libdwfl: specify optional sysroot to search for shared libraries and binaries

2024-07-02 Thread Michal Sekletar
On Mon, Jul 1, 2024 at 7:06 PM Frank Ch. Eigler  wrote:
>
> Hi -
>
> > [...]  For example, we might be looking at a core file from an ARM
> > system using elfutils running on an x86 host. [...]
>
> Makes sense.  By the way, to what extent would debuginfod (serving
> files from that sysroot) work for this same use case?

Hi Frank,

Frankly I don't know. I am not that interested in this cross-arch use case
so I didn't even test it myself. I am interested in being able to generate
stack traces from containerized applications. Since containers and host
share the kernel they have to be the same arch and debuginfod would
work without any issue in that case.

Michal

>
> - FChE


Re: [PATCH 1/2] libdwfl: specify optional sysroot to search for shared libraries and binaries

2024-07-02 Thread Michal Sekletar
On Tue, Jul 2, 2024 at 1:04 PM Dmitry V. Levin  wrote:
>
> On Mon, Jul 01, 2024 at 06:56:21PM +0200, Michal Sekletar wrote:
> [...]
> > --- a/libdwfl/link_map.c
> > +++ b/libdwfl/link_map.c
> > @@ -416,8 +416,22 @@ report_r_debug (uint_fast8_t elfclass,
uint_fast8_t elfdata,
> >if (name != NULL)
> >   {
> > /* This code is mostly inlined dwfl_report_elf.  */
> > -   // XXX hook for sysroot
> > -   int fd = open (name, O_RDONLY);
> > +   int rc;
> > +   char *path_name;
> > +   const char *sysroot = dwfl->sysroot;
> > +
> > +   /* Don't use the sysroot if the path is already inside it.  */
> > +   bool name_in_sysroot = sysroot && (strncmp(name, sysroot,
strlen(sysroot)) == 0);
>
> This seems to be a good candidate for startswith(), e.g.

Makes sense. Will be fixed in the next version.

>
> bool name_in_sysroot = sysroot && startswith(name, sysroot);
>
> Is sysroot guaranteed to end with '/'?  If not, then sysroot being
> a prefix doesn't always imply that the path is inside sysroot.

sysroot (dwfl->sysroot) is a result of realpath(). I just did a bunch of
tests and it seems that realpath does not append trailing "/". So you are
right, prefix doesn't always imply placement within sysroot. I will fix
this in the next version.

>
> > +
> > +   if (!name_in_sysroot && sysroot)
> > + rc = asprintf(&path_name, "%s/%s", sysroot, name);
> > +   else
> > + rc = asprintf(&path_name, "%s", name);
>
> Do we need the last asprintf(), or could we use "name" directly?
>
> In fact, besides this open(), "name" is used later in this function as an
> argument to __libdwfl_report_elf().  Does that invocation also has to be
> updated?
>
> Could "name" be re-purposed a bit in case of sysroot?  Just an idea,
> completely untested:
>
> char *sysroot_name = NULL;
> ...
> if (sysroot && !name_in_sysroot)
>   {
> if (asprintf(&sysroot_name, "%s/%s", sysroot, name) < 0)
>   return ...;
> name = sysroot_name;
>   }
> ...
> free(sysroot_name);

This might work. I will give it a try.

Michal
>
>
> --
> ldv


[PATCH v2 1/3] libdwfl: specify optional sysroot to search for shared libraries and binaries

2024-07-02 Thread Michal Sekletar
From: Luke Diamand 

When searching the list of modules in a core file, if the core was
generated on a different system to the current one, we need to look
in a sysroot for the various shared objects.

For example, we might be looking at a core file from an ARM system
using elfutils running on an x86 host.

This change adds a new function, dwfl_set_sysroot(), which then
gets used when searching for libraries and binaries.

Signed-off-by: Luke Diamand 
Signed-off-by: Michal Sekletar 
---
 libdw/libdw.map  |  5 ++
 libdwfl/Makefile.am  |  1 +
 libdwfl/core-file.c  |  2 +-
 libdwfl/dwfl_end.c   |  1 +
 libdwfl/dwfl_segment_report_module.c | 20 ++-
 libdwfl/dwfl_set_sysroot.c   | 80 
 libdwfl/libdwfl.h|  6 +++
 libdwfl/libdwflP.h   |  3 +-
 libdwfl/link_map.c   | 16 +-
 9 files changed, 130 insertions(+), 4 deletions(-)
 create mode 100644 libdwfl/dwfl_set_sysroot.c

diff --git a/libdw/libdw.map b/libdw/libdw.map
index 3c5ce8dc..552588a9 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -378,3 +378,8 @@ ELFUTILS_0.191 {
   global:
 dwarf_cu_dwp_section_info;
 } ELFUTILS_0.188;
+
+ELFUTILS_0.192 {
+  global:
+dwfl_set_sysroot;
+} ELFUTILS_0.191;
diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am
index 6b26cd51..57c89604 100644
--- a/libdwfl/Makefile.am
+++ b/libdwfl/Makefile.am
@@ -67,6 +67,7 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c 
dwfl_version.c \
dwfl_module_return_value_location.c \
dwfl_module_register_names.c \
dwfl_segment_report_module.c \
+   dwfl_set_sysroot.c \
link_map.c core-file.c open.c image-header.c \
dwfl_frame.c frame_unwind.c dwfl_frame_pc.c \
linux-pid-attach.c linux-core-attach.c dwfl_frame_regs.c \
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
index 89527d23..3135f884 100644
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -559,7 +559,7 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char 
*executable)
   ndx = 0;
   do
 {
-  int seg = dwfl_segment_report_module (dwfl, ndx, NULL,
+  int seg = dwfl_segment_report_module (dwfl, ndx, NULL, executable,
&dwfl_elf_phdr_memory_callback, elf,
core_file_read_eagerly, elf,
elf->maximum_size,
diff --git a/libdwfl/dwfl_end.c b/libdwfl/dwfl_end.c
index a1812407..7b5ac8a1 100644
--- a/libdwfl/dwfl_end.c
+++ b/libdwfl/dwfl_end.c
@@ -48,6 +48,7 @@ dwfl_end (Dwfl *dwfl)
   free (dwfl->lookup_addr);
   free (dwfl->lookup_module);
   free (dwfl->lookup_segndx);
+  free (dwfl->sysroot);
 
   Dwfl_Module *next = dwfl->modulelist;
   while (next != NULL)
diff --git a/libdwfl/dwfl_segment_report_module.c 
b/libdwfl/dwfl_segment_report_module.c
index dc34e0ae..2b050d64 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -288,6 +288,7 @@ read_portion (struct read_state *read_state,
 
 int
 dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
+   const char *executable,
Dwfl_Memory_Callback *memory_callback,
void *memory_callback_arg,
Dwfl_Module_Callback *read_eagerly,
@@ -778,7 +779,24 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const 
char *name,
   name = file_note_name;
   name_is_final = true;
   bool invalid = false;
-  fd = open (name, O_RDONLY);
+
+  /* We were not handed specific executable hence try to look for it in 
sysroot if
+ it is set.  */
+  if (dwfl->sysroot && !executable)
+{
+ 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);
+
   if (fd >= 0)
{
  Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
diff --git a/libdwfl/dwfl_set_sysroot.c b/libdwfl/dwfl_set_sysroot.c
new file mode 100644
index ..344d4ae5
--- /dev/null
+++ b/libdwfl/dwfl_set_sysroot.c
@@ -0,0 +1,80 @@
+/* Return one of the sources lines of a CU.
+   Copyright (C) 2024 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+   Software Foundation; either version 3 of the License, or (at
+   your option) any later version
+
+   or
+
+ * the GNU General Public License as published 

[PATCH v2 2/3] eu-stack: add support for sysroot option

2024-07-02 Thread Michal Sekletar
From: Luke Diamand 

Use the dwfl_set_sysroot() function to set the sysroot to be
used when analysing a core:

e.g.
   $ eu-stack --core core --sysroot /path/to/sysroot -e crashing_prog

Signed-off-by: Luke Diamand 
Signed-off-by: Michal Sekletar 
---
 src/stack.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/src/stack.c b/src/stack.c
index f4c5ba8c..79c9af9c 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -73,6 +73,7 @@ static int core_fd = -1;
 static Elf *core = NULL;
 static const char *exec = NULL;
 static char *debuginfo_path = NULL;
+static const char *sysroot = NULL;
 
 static const Dwfl_Callbacks proc_callbacks =
   {
@@ -559,6 +560,10 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
   show_modules = true;
   break;
 
+case 'S':
+  sysroot = arg;
+  break;
+
 case ARGP_KEY_END:
   if (core == NULL && exec != NULL)
argp_error (state,
@@ -592,6 +597,8 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
  dwfl = dwfl_begin (&core_callbacks);
  if (dwfl == NULL)
error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+ if (sysroot && dwfl_set_sysroot (dwfl, sysroot) < 0)
+   error (EXIT_BAD, 0, "dwfl_set_sysroot: %m");
  if (dwfl_core_file_report (dwfl, core, exec) < 0)
error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
}
@@ -675,6 +682,8 @@ main (int argc, char **argv)
N_("Show at most MAXFRAMES per thread (default 256, use 0 for 
unlimited)"), 0 },
   { "list-modules", 'l', NULL, 0,
N_("Show module memory map with build-id, elf and debug files 
detected"), 0 },
+  { "sysroot", 'S', "sysroot", 0,
+  N_("Set the sysroot to search for libraries referenced from the core file"), 
0 },
   { NULL, 0, NULL, 0, NULL, 0 }
 };
 
-- 
2.39.3 (Apple Git-146)



Re: [PATCH 1/2] libdwfl: specify optional sysroot to search for shared libraries and binaries

2024-07-02 Thread Michal Sekletar
On Tue, Jul 2, 2024 at 1:04 PM Dmitry V. Levin  wrote:

> On Mon, Jul 01, 2024 at 06:56:21PM +0200, Michal Sekletar wrote:
> [...]
> > --- a/libdwfl/link_map.c
> > +++ b/libdwfl/link_map.c
> > @@ -416,8 +416,22 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t
> elfdata,
> >if (name != NULL)
> >   {
> > /* This code is mostly inlined dwfl_report_elf.  */
> > -   // XXX hook for sysroot
> > -   int fd = open (name, O_RDONLY);
> > +   int rc;
> > +   char *path_name;
> > +   const char *sysroot = dwfl->sysroot;
> > +
> > +   /* Don't use the sysroot if the path is already inside it.  */
> > +   bool name_in_sysroot = sysroot && (strncmp(name, sysroot,
> strlen(sysroot)) == 0);
>
> This seems to be a good candidate for startswith(), e.g.
>
> bool name_in_sysroot = sysroot && startswith(name, sysroot);
>
> Is sysroot guaranteed to end with '/'?  If not, then sysroot being
> a prefix doesn't always imply that the path is inside sysroot.
>
> > +
> > +   if (!name_in_sysroot && sysroot)
> > + rc = asprintf(&path_name, "%s/%s", sysroot, name);
> > +   else
> > + rc = asprintf(&path_name, "%s", name);
>
> Do we need the last asprintf(), or could we use "name" directly?
>
> In fact, besides this open(), "name" is used later in this function as an
> argument to __libdwfl_report_elf().  Does that invocation also has to be
> updated?
>
> Could "name" be re-purposed a bit in case of sysroot?  Just an idea,
> completely untested:
>
> char *sysroot_name = NULL;
> ...
> if (sysroot && !name_in_sysroot)
>   {
> if (asprintf(&sysroot_name, "%s/%s", sysroot, name) < 0)
>   return ...;
> name = sysroot_name;
>   }
> ...
> free(sysroot_name);
>

I've sent out v2 where I tried to incorporate the feedback. Also I've added
a test case.

Michal


>
>
> --
> ldv
>
>


Re: [PATCH v2 1/3] libdwfl: specify optional sysroot to search for shared libraries and binaries

2024-07-03 Thread Michal Sekletar
On Wed, Jul 3, 2024 at 4:38 PM Dmitry V. Levin  wrote:

> On Tue, Jul 02, 2024 at 07:30:58PM +0200, Michal Sekletar wrote:
> [...]
> > +int
> > +dwfl_set_sysroot (Dwfl *dwfl, const char *sysroot)
> > +{
> > +  if (!sysroot)
> > +{
> > +  free (dwfl->sysroot);
> > +  dwfl->sysroot = NULL;
> > +  return 0;
> > +}
> > +
> > +  char *r, *s;
> > +  r = realpath (sysroot, NULL);
> > +  if (!r)
> > +return -1;
> > +
> > +  int rc;
> > +  struct stat sb;
> > +
> > +  rc = stat (r, &sb);
> > +  if (rc < 0 || !S_ISDIR (sb.st_mode))
> > +{
> > +  errno = EINVAL;
> > +  return -1;
> > +}
> > +
> > +  rc = asprintf (&s, "%s/", r);
>
> There is a case when realpath() returns a path ending with '/':
> when the path is "/".  I'm mentioning this just in case, not sure whether
> sysroot == "/" makes any sense at all, and whether this needs a special

attention.
>

I think that should be fine, //sysroot should be equivalent to /sysroot,
IOW, multiple slashes shouldn't cause any issues.

Michal


>
> --
> ldv
>
>


Re: [PATCH 1/2] libdwfl: specify optional sysroot to search for shared libraries and binaries

2024-07-08 Thread Michal Sekletar
On Fri, Jul 5, 2024 at 12:58 AM Aaron Merey  wrote:

> Hi Michal,
>
> On Tue, Jul 2, 2024 at 1:34 PM Michal Sekletar 
> wrote:
> >
> > I've sent out v2 where I tried to incorporate the feedback. Also I've
> added a test case.
>
> Thanks for adding the test case.  The patches LGTM and I've pushed all
> three.
>
> I made a few trivial changes to indentation and to prevent some lines
> from exceeding 80 characters.  From dwfl_set_sysroot.c I also removed
> #includes for limits.h, stdlib.h and errno.h since they are already
> included by the other header files.
>

Hi Aaron,

Thank you for applying the series and for followup fixlets!

Michal


>
> Aaron
>
>


Re: [PATCH v2 3/3] tests: add test for eu-stack --sysroot

2024-07-15 Thread Michal Sekletar
On Fri, Jul 12, 2024 at 5:38 PM Aaron Merey  wrote:
>
> Hi Ying,
>
> On Wed, Jul 10, 2024 at 2:06 PM Aaron Merey  wrote:
> >
> > On Wed, Jul 10, 2024 at 4:33 AM Ying Huang 
wrote:
> > >
> > > + testrun diff /tmp/tmp.bCCbATKu43/stack.out -
> > > + built_testrun diff /tmp/tmp.bCCbATKu43/stack.out -
> > > +
LD_LIBRARY_PATH=/home/huangying/elf/elfutils_main/libdw:/home/huangying/elf/elfutils_main/backends:/home/huangying/elf/elfutils_main/libelf:/home/huangying/elf/elfutils_main/libasm:/home/huangying/elf/elfutils_main/debuginfod
> > > + diff /tmp/tmp.bCCbATKu43/stack.out -
> > > 4,5c4,5
> > > < #1  0xe5663f20
> > > < #2  0xe5667a98
> > > ---
> > > > #1  0xe5663f20 kill_shell
> > > > #2  0xe5667a98 termsig_handler.part.0
> > > + rm -rf -- /tmp/tmp.bCCbATKu43
> > > FAIL run-sysroot.sh (exit status: 1)
> > >
> > >
> > > There are two lines where the function name cannot be parsed.
> >
> > I took a look at this but I'm still not sure what's going on.  I ran
> > the run-sysroot.sh testcase by hand on the extracted contents of
> > testfile-sysroot.tar.bz2.  eu-stack's /proc/PID/fd contained the
> > correct binaries located under the sysroot.  The testcase passes
> > on my Fedora 40 x86_64 machine as well as on all elfutils buildbots.
> >
> > It's also strange that those two particular stack frames from
> > /bin/bash are missing the function name yet the other /bin/bash
> > frames include proper function names.
> >
> > I'll look into this some more.
>
> This issue turned out to be related to .gnu_debugdata.  The 2 missing
> symbols you reported are contained in this section.  It's LZMA-compressed
> so if elfutils isn't built with LZMA support then the section isn't read.

Hi Aaron,

Thank you for the investigation and fix!

Cheers,
Michal

>
>
> I did some testing on Debian 6.1.94-1 (2024-06-21) x86_64. LZMA/xz wasn't
> pre-installed and I was able to reproduce the test failure.  I pushed a
> commit (39e962f063b5e) that modifies run-sysroot.sh to remove these two
> frames from the backtrace being tested, so that the result doesn't depend
> on LZMA support.




>
>
> Aaron


[PATCH] libdwfl: resolve all paths relative to sysroot

2025-03-19 Thread Michal Sekletar
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 | 17 +
 libdwfl/dwfl_segment_report_module.c | 21 +
 libdwfl/link_map.c   | 27 ++-
 3 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 3298f7fc..22f7258a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -283,6 +283,23 @@ case "$CFLAGS" in
 ;;
 esac
 
+AC_MSG_CHECKING([for openat2 with RESOLVE_IN_ROOT support])
+AC_LINK_IFELSE(
+  [AC_LANG_PROGRAM([[
+#include 
+#include 
+#include 
+#include 
+#include 
+  ]], [[
+struct open_how how = { .flags = O_RDONLY|O_DIRECTORY, .resolve = 
RESOLVE_IN_ROOT };
+return syscall (SYS_openat2, AT_FDCWD, ".", &how, sizeof(how)) >= 0 ? 
EXIT_SUCCESS : EXIT_FAILURE;
+  ]])],
+  [AC_DEFINE([HAVE_OPENAT2_RESOLVE_IN_ROOT], [1], [Define if openat2 is 
available])
+   AC_MSG_RESULT(yes)],
+  [AC_MSG_RESULT(no)]
+)
+
 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..53b938b9 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,6 +790,19 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const 
char *name,
 sysroot if it is set.  */
   if (dwfl->sysroot && !executable)
 {
+#if 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;
+ fd = syscall (SYS_openat2, sysrootfd, name, &how, sizeof(how));
+ close (sysrootfd);
+#else
  int r;
  char *n;
 
@@ -793,6 +812,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char 
*name,
  fd = open (n, O_RDONLY);
  free (n);
}
+
+#endif
 }
   else
  fd = open (name, O_RDONLY);
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 8ab14862..761e9b03 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,25 @@ 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;
 
+#if 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);
+   }
+#else
  /* Don't use the sysroot if the path is already inside it.  */
  bool name_in_sysroot = sysroot && startswith (name, sysroot);
 
@@ -430,7 +454,8 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
  name = sysroot_name;
}
 
- int fd = open (name, O_RDONLY);
+ fd = open (name, O_RDONLY);
+#endif
  if (fd >= 0)
{
  Elf *elf;
-- 
2.39.5 (Apple Git-154)