[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 published by the Free
+   Software Foundation; either version 2 of

[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-01 Thread Frank Ch. Eigler
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?

- FChE



[PATCH] Fix deref-of-null in handle_file_note()

2024-07-01 Thread Maks Mishin
After having been assigned to a NULL value at dwfl_segment_report_module.c:200,
pointer 'retval' is dereferenced at dwfl_segment_report_module.c:208 by calling 
function 'strcmp'.

Found by RASU JSC.

Signed-off-by: Maks Mishin 
---
 libdwfl/dwfl_segment_report_module.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libdwfl/dwfl_segment_report_module.c 
b/libdwfl/dwfl_segment_report_module.c
index dc34e0ae..976d7b79 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -205,7 +205,8 @@ handle_file_note (GElf_Addr module_start, GElf_Addr 
module_end,
return NULL;
   if (mix == firstix)
retval = fptr;
-  if (firstix < mix && mix <= lastix && strcmp (fptr, retval) != 0)
+  if (retval != NULL)
+if (firstix < mix && mix <= lastix && strcmp (fptr, retval) != 0)
return NULL;
   fptr = fnext + 1;
 }
-- 
2.30.2



[PATCH] size: Fix deref-of-null in handle_ar() function

2024-07-01 Thread Maks Mishin
Pointer, returned from function 'elf_getarhdr' at size.c:362,
may be NULL and is dereferenced at size.c:367.

Signed-off-by: Maks Mishin 
---
 src/size.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/src/size.c b/src/size.c
index ff8ca075..d6bce203 100644
--- a/src/size.c
+++ b/src/size.c
@@ -361,6 +361,16 @@ handle_ar (int fd, Elf *elf, const char *prefix, const 
char *fname)
   /* The the header for this element.  */
   Elf_Arhdr *arhdr = elf_getarhdr (subelf);
 
+  if (arhdr == NULL)
+  {
+printf ("cannot get archive header in '%s': %s\n",
+  fname, elf_errmsg (-1));
+elf_end (subelf);
+elf_end (elf);
+close (fd);
+return 1;
+  }
+
   if (elf_kind (subelf) == ELF_K_ELF)
handle_elf (subelf, new_prefix, arhdr->ar_name);
   else if (likely (elf_kind (subelf) == ELF_K_AR))
-- 
2.30.2



[PATCH] unstrip: Fix deref-of-null in copy_elided_sections()

2024-07-01 Thread Maks Mishin
Pointer `symstrdata` is dereferenced at unstrip.c:1977 without checking for 
NULL.

Signed-off-by: Maks Mishin 
---
 src/unstrip.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/unstrip.c b/src/unstrip.c
index d70053de..87bd12de 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -1974,8 +1974,11 @@ more sections in stripped file than debug file -- 
arguments reversed?"));
}
}
 
+if (symstrdata != NULL)
+  {
   if (dwelf_strtab_finalize (symstrtab, symstrdata) == NULL)
-   error_exit (0, "Not enough memory to create symbol table");
+ error_exit (0, "Not enough memory to create symbol table");
+  }
 
   elf_flagdata (symstrdata, ELF_C_SET, ELF_F_DIRTY);
 
-- 
2.30.2



Re: [PATCH] size: Fix deref-of-null in handle_ar() function

2024-07-01 Thread Sam James
Maks Mishin  writes:

> Pointer, returned from function 'elf_getarhdr' at size.c:362,
> may be NULL and is dereferenced at size.c:367.
>

Your other patch has "Found by RASU JSC." but the rest don't. Are they
all found by it? If so, please say that.

(Also, consider sending the fixes as a series if they're related/from
the same analyser tool batch.)

> Signed-off-by: Maks Mishin 
> ---
>  src/size.c | 10 ++
>  1 file changed, 10 insertions(+)
>
> diff --git a/src/size.c b/src/size.c
> index ff8ca075..d6bce203 100644
> --- a/src/size.c
> +++ b/src/size.c
> @@ -361,6 +361,16 @@ handle_ar (int fd, Elf *elf, const char *prefix, const 
> char *fname)
>/* The the header for this element.  */
>Elf_Arhdr *arhdr = elf_getarhdr (subelf);
>  
> +  if (arhdr == NULL)
> +  {
> +printf ("cannot get archive header in '%s': %s\n",
> +  fname, elf_errmsg (-1));
> +elf_end (subelf);
> +elf_end (elf);
> +close (fd);
> +return 1;
> +  }
> +
>if (elf_kind (subelf) == ELF_K_ELF)
>   handle_elf (subelf, new_prefix, arhdr->ar_name);
>else if (likely (elf_kind (subelf) == ELF_K_AR))


[PATCH] readelf: Fix memory leak in print_hash_info()

2024-07-01 Thread Maks Mishin
Signed-off-by: Maks Mishin 
---
 src/readelf.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/readelf.c b/src/readelf.c
index c945b371..48035264 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3597,6 +3597,7 @@ print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, 
size_t shstrndx,
 {
   error (0, 0, _("invalid sh_link value in section %zu"),
 elf_ndxscn (scn));
+  free (counts);
   return;
 }
 
-- 
2.30.2



[PATCH] sparc_attrs: Fix string overflow

2024-07-01 Thread Maks Mishin
A string is copied into the buffer 's' of size 577 without checking its length 
first at sparc_attrs.c:95.

Found by RASU JSC.

Signed-off-by: Maks Mishin 
---
 backends/sparc_attrs.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/backends/sparc_attrs.c b/backends/sparc_attrs.c
index 974e8fb0..104d4ed3 100644
--- a/backends/sparc_attrs.c
+++ b/backends/sparc_attrs.c
@@ -32,6 +32,7 @@
 
 #include 
 #include 
+#include 
 
 #define BACKEND sparc_
 #include "libebl_CPU.h"
@@ -92,6 +93,7 @@ sparc_check_object_attribute (Ebl *ebl __attribute__ 
((unused)),
   {
 if (*s != '\0')
   s = strcat (s, ",");
+assert (strlen(s) + strlen(caps[cap]) < 577);
 s = strcat (s, caps[cap]);
   }
   
-- 
2.30.2