Re: PR30000 - introduce new srcfiles tool

2023-10-23 Thread Aaron Merey
Hi Housam,

On Thu, Sep 28, 2023 at 11:00 AM Housam Alamour via Elfutils-devel
 wrote:
>
> Here is the new srcfiles tool ready for review.

Thanks for working on this.

I was not able to apply the patch from your email due to some line
breaks that your email client may have inserted.  `git format-patch` and
`git send-email` are useful for emailing patches with the right format.
However I was able to test the patch using your try-pr3 git branch.

> diff --git a/doc/srcfiles.1 b/doc/srcfiles.1
> new file mode 100644
> index ..245c2d27
> --- /dev/null
> +++ b/doc/srcfiles.1

srcfile.1 does not install since it's missing from doc/Makefile.am.

> @@ -0,0 +1,125 @@
> +.\" Copyright 2023 Red Hat Inc.
> +.\" Mon 2023-Sept 23 Housam Alamour 
> +.\" Contact elfutils-devel@sourceware.org to correct errors or typos.
> +.TH EU-SRCFILES 1 "2023-Sept-25" "elfutils"
> +
> +.de SAMPLE
> +.br
> +.RS 0
> +.nf
> +.nh
> +\fB
> +..
> +.de ESAMPLE
> +\fP
> +.hy
> +.fi
> +.RE
> +..
> +
> +.SH "NAME"
> +eu-srcfiles \- Lists the source files of a dwarf/elf file.

DWARF and ELF are usually capitalized.

> +
> +.SH "SYNOPSIS"
> +eu-srcfiles [\fB\-0\fR|\fB\-\-null\fR] [\fB\-c\fR|\fB\-\-cu\-only\fR]
> [\fB\-v\fR|\fB\-\-verbose\fR] INPUT

This description of the arg format differs from `eu-srcfiles --help`

$ eu-srcfiles --help
Usage: eu-srcfiles [OPTION...] [FILE]
[...]

The --help description implies that `eu-srcfiles ./prog` should work
for some executable named prog but this is not the case.
The man page is correct that I have to include -e or --core for this
to work and that '-e a.out' is used as a default file name.

> +
> +.SH "DESCRIPTION"
> +\fBeu-srcfiles\fR lists the source files of a given \s-1dwarf/elf\s0
> +file.  This list is based on a search of the dwarf debuginfo, which
> +may be automatically fetched by debuginfod if applicable.  The target
> +file may be an executable, a coredump, a process, or even the running
> +kernel.  The default is the file 'a.out'.  The source file names are
> +made unique and printed to standard output.
> +
> +.SH "OPTIONS"
> +The long and short forms of options, shown here as alternatives, are
> +equivalent.
> +
> +.SS "Input Options"
> +
> +Only one INPUT option may be used.  The default is '-e a.out'.

There are some input options, such as -k, that are listed in --help but
not included in the man page.

> diff --git a/src/srcfiles.cxx b/src/srcfiles.cxx
> new file mode 100644
> index ..c948269d
> [...]
> +int
> +main (int argc, char *argv[])
> +{
> +  int remaining;
> +
> +  /* Parse and process arguments.  This includes opening the modules.  */
> +  argp_children[0].argp = dwfl_standard_argp ();
> +  argp_children[0].group = 1;
> +
> +  Dwfl *dwfl = NULL;
> +  (void) argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
> +  assert (dwfl != NULL);
> +  // Process all loaded modules - probably just one, except if -K or -p is
> used.

The use of /* */ and // for comments is inconsistent.  Although to be
fair it's inconsistent in parts of elfutils too!

> diff --git a/tests/run-srcfiles-self.sh b/tests/run-srcfiles-self.sh
> new file mode 100755
> index ..075ff7d2
> --- /dev/null
> +++ b/tests/run-srcfiles-self.sh
> @@ -0,0 +1,45 @@
> +#! /bin/sh
> +# Copyright (C) 2023 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 the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# elfutils is distributed in the hope that it will be useful, but
> +# WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see .
> +
> +. $srcdir/test-subr.sh
> +
> +# Test different command line combinations on the srcfiles binary itself.
> +ET_EXEC="${abs_top_builddir}/src/srcfiles"
> +ET_PID=$$
> +
> +SRC_NAME="srcfiles.cxx"
> +
> +for null_arg in --null ""; do
> +  for verbose_arg in --verbose ""; do
> +testrun $ET_EXEC $null_arg $verbose_arg -p $ET_PID > /dev/null
> +
> +# Ensure that the output contains srclines.cxx
> +cu_only=$(testrun $ET_EXEC $null_arg $verbose_arg -c -e $ET_EXEC)
> +default=$(testrun $ET_EXEC $null_arg $verbose_arg -e $ET_EXEC)
> +result1=$(echo "$cu_only" | grep "$SRC_NAME")
> +result2=$(echo "$default" | grep "$SRC_NAME")
> +if [ -z "$result1" ] || [-z "$result2"]; then
> +  exit 1
> +fi
> +
> +# Ensure that the output with the cu-only option contains less source
> files
> +if [ "$cu_only" -gt "$default" ]; then
> +  exit 1
> +fi
> +  done
> +done
> +

These tests pass for me on F38 x86_64.

It looks like this only tests whether 

Re: [PATCH] Fixed formatting of man page and --help options and added additional test case to ensure the correct source file is output.

2023-10-24 Thread Aaron Merey
On Tue, Oct 24, 2023 at 1:35 PM Housam Alamour  wrote:
>
> Hello,
> Here are the requested changes.

Thanks Housam. I made a couple tweaks to the testcases, squashed this
patch into "PR 3: debuginfod-find should have a source-list verb"
and merged it into the main branch.

Aaron



[PATCH] readelf: Support .gdb_index version 9

2023-10-31 Thread Aaron Merey
Hi,

I'd like to merge this patch before the next release.  Unless anyone objects
I'll merge it by Friday Nov 3.

Commit message:

Version 9 adds a "shortcut table" to the index.  The shortcut table contains
the name and language of the main function, if it exists.

A testcase added in this patch uses an executable written with Fortran.
This is because gdb does not currently populate the shortcut table of
C/C++ programs (see sourceware PR30996).

Signed-off-by: Aaron Merey 
---
 src/readelf.c   |  66 +++-
 tests/Makefile.am   |   3 +-
 tests/run-readelf-gdb_index.sh  |  95 +++-
 tests/testfilegdbindex9-no-maininfo.bz2 | Bin 0 -> 3502 bytes
 tests/testfilegdbindex9.bz2 | Bin 0 -> 4266 bytes
 5 files changed, 159 insertions(+), 5 deletions(-)
 create mode 100755 tests/testfilegdbindex9-no-maininfo.bz2
 create mode 100755 tests/testfilegdbindex9.bz2

diff --git a/src/readelf.c b/src/readelf.c
index db31ad09..a28f6236 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -11539,8 +11539,9 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
   // hash used for generating the table.  Version 6 contains symbols
   // for inlined functions, older versions didn't.  Version 7 adds
   // symbol kinds.  Version 8 just indicates that it correctly includes
-  // TUs for symbols.
-  if (vers < 4 || vers > 8)
+  // TUs for symbols.  Version 9 adds shortcut table for information
+  // regarding the main function.
+  if (vers < 4 || vers > 9)
 {
   printf (_("  unknown version, cannot parse section\n"));
   return;
@@ -11578,6 +11579,17 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl 
*ebl,
   if (unlikely (readp + 4 > dataend))
 goto invalid_data;
 
+  uint32_t shortcut_off = 0;
+  if (vers >= 9)
+{
+  shortcut_off = read_4ubyte_unaligned (dbg, readp);
+  printf (_(" shortcut offset: %#" PRIx32 "\n"), shortcut_off);
+
+  readp += 4;
+  if (unlikely (readp + 4 > dataend))
+   goto invalid_data;
+}
+
   uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
   printf (_(" constant offset: %#" PRIx32 "\n"), const_off);
 
@@ -11675,8 +11687,19 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl 
*ebl,
   if (const_off >= data->d_size)
 goto invalid_data;
 
+  const unsigned char *shortcut_start = NULL;
+  if (vers >= 9)
+{
+  if (shortcut_off >= data->d_size)
+   goto invalid_data;
+
+  shortcut_start = data->d_buf + shortcut_off;
+  nextp = shortcut_start;
+}
+  else
+nextp = const_start;
+
   readp = data->d_buf + sym_off;
-  nextp = const_start;
   size_t sym_nr = (nextp - readp) / 8;
 
   printf (_("\n Symbol table at offset %#" PRIx32
@@ -11750,6 +11773,43 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl 
*ebl,
}
   n++;
 }
+
+  if (vers < 9)
+return;
+
+  if (unlikely (shortcut_start == NULL))
+goto invalid_data;
+
+  readp = shortcut_start;
+  nextp = const_start;
+  size_t shortcut_nr = (nextp - readp) / 4;
+
+  if (unlikely (shortcut_nr != 2))
+goto invalid_data;
+
+  printf (_("\nShortcut table at offset %#" PRIx32 " contains %zu slots:\n"),
+ shortcut_off, shortcut_nr);
+
+  uint32_t lang = read_4ubyte_unaligned (dbg, readp);
+  readp += 4;
+
+  printf (_("Language of main: %s\n"), dwarf_lang_name (lang));
+  printf (_("Name of main: "));
+
+  if (lang != 0)
+{
+  uint32_t name = read_4ubyte_unaligned (dbg, readp);
+  readp += 4;
+  const unsigned char *sym = const_start + name;
+
+  if (unlikely ((size_t) (dataend - const_start) < name
+   || memchr (sym, '\0', dataend - sym) == NULL))
+   goto invalid_data;
+
+  printf ("%s\n", sym);
+}
+  else
+printf ("\n");
 }
 
 /* Returns true and sets split DWARF CU id if there is a split compile
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ef5b6bb5..e8bc9058 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -421,7 +421,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 run-readelf-Dd.sh \
 testfile-s390x-hash-both.bz2 \
 run-readelf-gdb_index.sh testfilegdbindex5.bz2 \
-testfilegdbindex7.bz2 \
+testfilegdbindex7.bz2 testfilegdbindex9.bz2 \
+testfilegdbindex9-no-maininfo.bz2 \
 run-readelf-s.sh testfilebazdbg.bz2 testfilebazdyn.bz2 \
 testfilebazmin.bz2 testfilebazdbg.debug.bz2 testfilebazmdb.bz2 \
 testfilebaztab.bz2 testfilebasmin.bz2 testfilebaxmin.bz2 \
diff --git a/tests/run-readelf-gdb_index.sh b/tests/run-readelf-gdb_index.sh
index fcbc3c57..95367ef8 100755
--- a/tests/run-readelf-gdb_index.sh
+++ b/tests/run-readelf-gdb_index.sh
@@ -63

[COMMITTED][PATCH] debuginfod-client.c: Don't print empty line in header_callback

2023-11-01 Thread Aaron Merey
libcurl passes an empty line to header_callback indicating the end
of the response's HTTP headers.

Currently this empty line is printed to the debuginfod_client's
verbose_fd with a "header" prefix:

$ echo $DEBUGINFOD_URLS
https://debuginfod.fedoraproject.org/
$ debuginfod-find -vv debuginfo e2bbf033b548021c37866429f12a99bd33bd6e8d
[...]
header x-fedora-requestid: ZULLx0PPA8nmj8c8Hw-RtAACgAE
header server: Apache
header
[...]

Prevent this unnecessary line of output by only printing non-empty
lines in header_callback.

Signed-off-by: Aaron Merey 
---
 debuginfod/debuginfod-client.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
index 6882cb19..dcf05031 100644
--- a/debuginfod/debuginfod-client.c
+++ b/debuginfod/debuginfod-client.c
@@ -568,7 +568,9 @@ header_callback (char * buffer, size_t size, size_t 
numitems, void * userdata)
   struct handle_data *data = (struct handle_data *) userdata;
   if (size != 1)
 return 0;
-  if (data->client && data->client->verbose_fd >= 0)
+  if (data->client
+  && data->client->verbose_fd >= 0
+  && numitems > 2)
 dprintf (data->client->verbose_fd, "header %.*s", (int)numitems, buffer);
   // Some basic checks to ensure the headers received are of the expected 
format
   if (strncasecmp(buffer, "X-DEBUGINFOD", 11)
-- 
2.41.0



[COMMITTED][Bug libdw/30980] dwfl_offline_section_address: replace asserts with early return

2023-11-01 Thread Aaron Merey
dwfl_offline_section_address asserts that the current module is ET_REL.

A possibly corrupt .gnu_debuglink can cause an abort by calling
dwfl_offline_section_address on an ET_DYN module.

Prevent this abort and similar ones by replacing
dwfl_offline_section_address initial asserts with an early return.

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

Signed-off-by: Aaron Merey 

---
 libdwfl/offline.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/libdwfl/offline.c b/libdwfl/offline.c
index e090b42b..52539fe3 100644
--- a/libdwfl/offline.c
+++ b/libdwfl/offline.c
@@ -50,10 +50,11 @@ dwfl_offline_section_address (Dwfl_Module *mod,
  const GElf_Shdr *shdr __attribute__ ((unused)),
  Dwarf_Addr *addr)
 {
-  assert (mod->e_type == ET_REL);
-  assert (shdr->sh_addr == 0);
-  assert (shdr->sh_flags & SHF_ALLOC);
-  assert (shndx != 0);
+  if (mod->e_type != ET_REL
+  || shdr->sh_addr != 0
+  || !(shdr->sh_flags & SHF_ALLOC)
+  || shndx == 0)
+return -1;
 
   if (mod->debug.elf == NULL)
 /* We are only here because sh_addr is zero even though layout is complete.
-- 
2.41.0



Re: ☠ Buildbot (Sourceware): elfutils - failed test (failure) (master)

2023-11-01 Thread Aaron Merey
This fedora-s390x buildbot failure is probably spurious.

The testsuite passed on the s390x trybot.  I also ran the testsuite
on a different F38 s390x machine and again it passed.

Aaron

On Wed, Nov 1, 2023 at 9:36 PM  wrote:
>
> A new failure has been detected on builder elfutils-fedora-s390x while 
> building elfutils.
>
> Full details are available at:
> https://builder.sourceware.org/buildbot/#builders/43/builds/240
>
> Build state: failed test (failure)
> Revision: a34c5faad861efdd26d1c52b4f8d9d4077e03131
> Worker: fedora-s390x
> Build Reason: (unknown)
> Blamelist: Aaron Merey 
>
> Steps:
>
> - 0: worker_preparation ( success )
>
> - 1: set package name ( success )
>
> - 2: git checkout ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/2/logs/stdio
>
> - 3: autoreconf ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/3/logs/stdio
>
> - 4: configure ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/4/logs/stdio
> - config.log: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/4/logs/config_log
>
> - 5: get version ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/5/logs/stdio
> - property changes: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/5/logs/property_changes
>
> - 6: make ( warnings )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/6/logs/stdio
> - warnings (3): 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/6/logs/warnings__3_
>
> - 7: make check ( failure )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/7/logs/stdio
> - test-suite.log: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/7/logs/test-suite_log
>
> - 8: prep ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/8/logs/stdio
>
> - 9: build bunsen.cpio.gz ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/9/logs/stdio
>
> - 10: fetch bunsen.cpio.gz ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/10/logs/stdio
>
> - 11: unpack bunsen.cpio.gz ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/11/logs/stdio
>
> - 12: pass .bunsen.source.gitname ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/12/logs/stdio
>
> - 13: pass .bunsen.source.gitdescribe ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/13/logs/stdio
>
> - 14: pass .bunsen.source.gitbranch ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/14/logs/stdio
>
> - 15: pass .bunsen.source.gitrepo ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/15/logs/stdio
>
> - 16: upload to bunsen ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/16/logs/stdio
>
> - 17: clean up ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/17/logs/stdio
>
> - 18: make distclean ( success )
> Logs:
> - stdio: 
> https://builder.sourceware.org/buildbot/#builders/43/builds/240/steps/18/logs/stdio
>



Re: [PATCH] readelf: Support .gdb_index version 9

2023-11-02 Thread Aaron Merey
On Thu, Nov 2, 2023 at 10:20 AM Frank Ch. Eigler  wrote:
>
> > BTW the description of the gdb_index at the top
> > https://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
> > doesn't resolve anymore. It is now
> > https://sourceware.org/gdb/current/onlinedocs/gdb.html/Index-Section-Format.html
>
> Added another httpd redirect to make the first link work too.

Thanks Frank.

On Thu, Nov 2, 2023 at 8:54 AM Mark Wielaard  wrote:
>
> > +  printf (_("\nShortcut table at offset %#" PRIx32 " contains %zu 
> > slots:\n"),
> > +   shortcut_off, shortcut_nr);
>
> That is a fancy way to print "contains 2 slots" :)

My intention was to require fewer changes to the code if the shortcut
table was extended in a future version.  But yes at the moment this is
slightly excessive!

>
> > +  uint32_t lang = read_4ubyte_unaligned (dbg, readp);
> > +  readp += 4;
> > +
> > +  printf (_("Language of main: %s\n"), dwarf_lang_name (lang));
>
> Note that dwarf_lang_name calls string_or_unknown with false for
> print_unknown_num so it might make sense to either flip that to true
> (but there is probably a reason it doesn't print the hex num) or to
> always add the hex num after the name so the user doesn't just get ???
> on an unknown DWARF_LANG constant.

Binutils readelf includes the language hex number for unknown languages
and we should too.  I will add the hex number to the output when the
language is unknown.

>
> > +  printf (_("Name of main: "));
> > +
> > +  if (lang != 0)
> > +{
> > +  uint32_t name = read_4ubyte_unaligned (dbg, readp);
> > +  readp += 4;
> > +  const unsigned char *sym = const_start + name;
> > +
> > +  if (unlikely ((size_t) (dataend - const_start) < name
> > + || memchr (sym, '\0', dataend - sym) == NULL))
> > + goto invalid_data;
>
> Good end of string check.
> BTW. DW_LANG constants are going away with DWARF6:
> https://dwarfstd.org/languages-v6.html

Interesting.  If gdb continues to support .gdb_index then we may end up
extending the shortcut table to include the new DW_AT_language_version.

> > +Shortcut table at offset 0x207c contains 2 slots:
> > +Language of main: ???
> > +Name of main: 
> > +EOF
>
> This seems an unfortunate example. Why is the language unknown?
> But maybe it is a nice example to show why you should at least print
> the hex num of the language?

Currently gdb only populates the shortcut table when it can find
DW_AT_main_subprogram or DW_AT_calling_convention with value
DW_CC_program.  gcc doesn't emit this for C/C++ programs so their
shortcut tables all have language and name set to 0.
See https://sourceware.org/bugzilla/show_bug.cgi?id=30996

I will change this testcase to include the hex number of the language.

Aaron



[PATCH] libdwfl: Correctly handle corefile non-contiguous segments

2023-11-12 Thread Aaron Merey
It is possible for segments of different shared libaries to be interleaved
in memory such that the segments of one library are located in between
non-contiguous segments of another library.

For example, this can be seen with firefox on RHEL 7.9 where multiple
shared libraries could be mapped in between ld-2.17.so segments:

  [...]
  7f0972082000-7f09720a4000  139264  /usr/lib64/ld-2.17.so
  7f09720a4000-7f09720a5000  4096/memfd:mozilla-ipc 
(deleted)
  7f09720a5000-7f09720a7000  8192/memfd:mozilla-ipc 
(deleted)
  7f09720a7000-7f09720a9000  8192/memfd:mozilla-ipc 
(deleted)
  7f0972134000-7f0972136000  8192
/usr/lib64/firefox/libmozwayland.so
  7f0972136000-7f0972137000 2000 4096
/usr/lib64/firefox/libmozwayland.so
  7f0972137000-7f0972138000 3000 4096
/usr/lib64/firefox/libmozwayland.so
  7f0972138000-7f0972139000 3000 4096
/usr/lib64/firefox/libmozwayland.so
  7f097213a000-7f0972147000  53248   
/usr/lib64/firefox/libmozsqlite3.so
  7f0972147000-7f097221e000 d000 880640  
/usr/lib64/firefox/libmozsqlite3.so
  7f097221e000-7f0972248000 000e4000 172032  
/usr/lib64/firefox/libmozsqlite3.so
  7f0972248000-7f0972249000 0010e000 4096
/usr/lib64/firefox/libmozsqlite3.so
  7f0972249000-7f097224c000 0010e000 12288   
/usr/lib64/firefox/libmozsqlite3.so
  7f097224c000-7f097225 00111000 16384   
/usr/lib64/firefox/libmozsqlite3.so
  7f097225-7f0972253000  12288   
/usr/lib64/firefox/liblgpllibs.so
  [...]
  7f09722a3000-7f09722a4000 00021000 4096/usr/lib64/ld-2.17.so
  7f09722a4000-7f09722a5000 00022000 4096/usr/lib64/ld-2.17.so

dwfl_segment_report_module did not account for the possibility of
interleaving non-contiguous segments, resulting in premature closure
of modules as well as failing to report modules.

Fix this by removing segment skipping in dwfl_segment_report_module.
When dwfl_segment_report_module reported a module, it would return
the index of the segment immediately following the end address of the
current module.  Since there's a chance that other modules might fall
within this address range, dwfl_segment_report_module instead returns
the index of the next segment.

This patch also fixes premature module closure that can occur in
dwfl_segment_report_module when interleaving non-contiguous segments
are found.  Previously modules with start and end addresses that overlap
with the current segment would have their build-id compared the build-id
associated with the current segment.  If there was a mismatch, that module
would be closed.  Avoid closing modules in this case when mismatching
build-ids correspond to distinct modules.

A couple caveats should be mentioned.  First, start and end addresses
of reported modules cannot be assumed to contain segments from only
that module.  This has always been the case however.

Second, the testcases in this patch use a firefox corefile that is
fairly large.  The .bz2 corefile is about 47M.  A clean elfutils repo
is currently about 42M, so this corefile more than doubles the size of
the elfutils repo.  I looked for a much smaller process with
interleaving non-contiguous shared library sections but was not able
to find one.  I've included the corefile and tests in this patch but
they can be removed if we'd prefer to not approx. double the size of
the repo.

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

Signed-off-by: Aaron Merey 
---
 libdwfl/dwfl_segment_report_module.c |  37 +--
 tests/Makefile.am|   5 +-
 tests/run-unstrip-noncontig.sh   | 155 +++
 tests/testcore-noncontig.bz2 | Bin 0 -> 49146091 bytes
 4 files changed, 184 insertions(+), 13 deletions(-)
 create mode 100755 tests/run-unstrip-noncontig.sh
 create mode 100644 tests/testcore-noncontig.bz2

diff --git a/libdwfl/dwfl_segment_report_module.c 
b/libdwfl/dwfl_segment_report_module.c
index 3ef62a7d..09ee37b3 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -737,17 +737,34 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const 
char *name,
&& invalid_elf (module->elf, module->disk_file_has_build_id,
&build_id))
  {
-   elf_end (module->elf);
-   close (module->fd);
-   module->elf = NULL;
-   module->fd = -1;
+   /* If MODULE's build-id doesn't match the disk file's
+  build-id, close ELF only if MODULE and ELF refer to
+  different builds of files with the same name.  This
+  prevents premature closure of the correct ELF in cases
+  where segments of a module are non-contiguous in

Re: [PATCH] libdwfl: Correctly handle corefile non-contiguous segments

2023-11-13 Thread Aaron Merey
BTW this patch won't apply as-is. I removed the firefox corefile since
I'd rather not send a >50M email to this list :)

See branch users/amerey/try-pr30975 if you want to run the code.

Aaron

On Sun, Nov 12, 2023 at 3:16 PM Aaron Merey  wrote:
>
> It is possible for segments of different shared libaries to be interleaved
> in memory such that the segments of one library are located in between
> non-contiguous segments of another library.
>
> For example, this can be seen with firefox on RHEL 7.9 where multiple
> shared libraries could be mapped in between ld-2.17.so segments:
>
>   [...]
>   7f0972082000-7f09720a4000  139264  /usr/lib64/ld-2.17.so
>   7f09720a4000-7f09720a5000  4096/memfd:mozilla-ipc 
> (deleted)
>   7f09720a5000-7f09720a7000  8192/memfd:mozilla-ipc 
> (deleted)
>   7f09720a7000-7f09720a9000  8192/memfd:mozilla-ipc 
> (deleted)
>   7f0972134000-7f0972136000  8192
> /usr/lib64/firefox/libmozwayland.so
>   7f0972136000-7f0972137000 2000 4096
> /usr/lib64/firefox/libmozwayland.so
>   7f0972137000-7f0972138000 3000 4096
> /usr/lib64/firefox/libmozwayland.so
>   7f0972138000-7f0972139000 3000 4096
> /usr/lib64/firefox/libmozwayland.so
>   7f097213a000-7f0972147000  53248   
> /usr/lib64/firefox/libmozsqlite3.so
>   7f0972147000-7f097221e000 d000 880640  
> /usr/lib64/firefox/libmozsqlite3.so
>   7f097221e000-7f0972248000 000e4000 172032  
> /usr/lib64/firefox/libmozsqlite3.so
>   7f0972248000-7f0972249000 0010e000 4096
> /usr/lib64/firefox/libmozsqlite3.so
>   7f0972249000-7f097224c000 0010e000 12288   
> /usr/lib64/firefox/libmozsqlite3.so
>   7f097224c000-7f097225 00111000 16384   
> /usr/lib64/firefox/libmozsqlite3.so
>   7f097225-7f0972253000  12288   
> /usr/lib64/firefox/liblgpllibs.so
>   [...]
>   7f09722a3000-7f09722a4000 00021000 4096/usr/lib64/ld-2.17.so
>   7f09722a4000-7f09722a5000 00022000 4096/usr/lib64/ld-2.17.so
>
> dwfl_segment_report_module did not account for the possibility of
> interleaving non-contiguous segments, resulting in premature closure
> of modules as well as failing to report modules.
>
> Fix this by removing segment skipping in dwfl_segment_report_module.
> When dwfl_segment_report_module reported a module, it would return
> the index of the segment immediately following the end address of the
> current module.  Since there's a chance that other modules might fall
> within this address range, dwfl_segment_report_module instead returns
> the index of the next segment.
>
> This patch also fixes premature module closure that can occur in
> dwfl_segment_report_module when interleaving non-contiguous segments
> are found.  Previously modules with start and end addresses that overlap
> with the current segment would have their build-id compared the build-id
> associated with the current segment.  If there was a mismatch, that module
> would be closed.  Avoid closing modules in this case when mismatching
> build-ids correspond to distinct modules.
>
> A couple caveats should be mentioned.  First, start and end addresses
> of reported modules cannot be assumed to contain segments from only
> that module.  This has always been the case however.
>
> Second, the testcases in this patch use a firefox corefile that is
> fairly large.  The .bz2 corefile is about 47M.  A clean elfutils repo
> is currently about 42M, so this corefile more than doubles the size of
> the elfutils repo.  I looked for a much smaller process with
> interleaving non-contiguous shared library sections but was not able
> to find one.  I've included the corefile and tests in this patch but
> they can be removed if we'd prefer to not approx. double the size of
> the repo.
>
> https://sourceware.org/bugzilla/show_bug.cgi?id=30975
>
> Signed-off-by: Aaron Merey 
> ---
>  libdwfl/dwfl_segment_report_module.c |  37 +--
>  tests/Makefile.am|   5 +-
>  tests/run-unstrip-noncontig.sh   | 155 +++
>  tests/testcore-noncontig.bz2 | Bin 0 -> 49146091 bytes
>  4 files changed, 184 insertions(+), 13 deletions(-)
>  create mode 100755 tests/run-unstrip-noncontig.sh
>  create mode 100644 tests/testcore-noncontig.bz2
>
> diff --git a/libdwfl/dwfl_segment_report_module.c 
> b/libdwfl/dwfl_segment_report_module.c
> index 3ef62a7d..09ee37b3 100644
> --- a/libdwfl/dwfl_segment_report_module.c
> +++ b/libdwfl/dwfl_segment_report_module.c
> @@ -737,17 +737,34 @@ dwfl_segment_report_m

Re: [PATCH] elfutils: PR 30991 srcfiles tarball feature

2023-11-13 Thread Aaron Merey
Hi Housam,

Thanks for working on this.  This is a useful feature that I can
definitely see myself using!

On Wed, Nov 8, 2023 at 11:49 AM Housam Alamour  wrote:
>
> * srclines.cxx: Introduce new option that places all the
> source files associated with a specified dwarf/elf file
> into a zip file and sends it to stdout.
>
> * run-srcfiles-self.sh: Added test-case for the new zip feature.
>
> * srcfiles.1, NEWS: Added documentation for the new zip feature
>
> Example:
> % ./src/srcfiles -z -e /bin/ls > output.zip
>
> https://sourceware.org/bugzilla/show_bug.cgi?id=30991
>
> Signed-off-by: Housam Alamour 
> ---
>  NEWS   |   4 +
>  configure.ac   |  15 +++
>  doc/srcfiles.1 |  20 +++-
>  src/Makefile.am|   2 +-
>  src/srcfiles.cxx   | 193 ++---
>  tests/run-srcfiles-self.sh |  40 +++-
>  6 files changed, 251 insertions(+), 23 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index 53c717eb..388a3b63 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -1,5 +1,9 @@
>  Version 0.190
>
> +srcfiles: added srcfiles tool that lists all the source files of a given
> +  DWARF/ELF file. May also be used to create fetch the source files 
> and
> +  place them into a zip.

A srcfiles entry was already added to NEWS.  You can make a new "Version
0.191" section and mention just the zip feature.

> +
>  readelf: Support readelf -Ds, --use-dynamic --symbol.
>
>  debuginfod: Schema change (reindexing required, sorry!) for a 60%
> diff --git a/configure.ac b/configure.ac
> index 29ed32fe..3bfd2097 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -880,6 +880,21 @@ AC_ARG_ENABLE(debuginfod-urls,
>  AC_SUBST(DEBUGINFOD_URLS, $default_debuginfod_urls)
>  AC_CONFIG_FILES([config/profile.sh config/profile.csh])
>
> +dnl Check if libarchive is available to determine if the
> +dnl srcfiles --zip option should be enabled or disabled
> +AC_CACHE_CHECK([whether libarchive is available],
> +ac_cv_have_libarchive,
> +[AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
> +#include 
> +]])],
> +ac_cv_have_libarchive=yes,
> +ac_cv_have_libarchive=no)])
> +AS_IF([test "x$ac_cv_have_libarchive" = "xyes"],
> +[
> +AC_DEFINE([HAVE_LIBARCHIVE], [1], [Define to 1 if libarchive is 
> available])
> +])
> +AM_CONDITIONAL([HAVE_LIBARCHIVE], [test "x$ac_cv_have_libarchive" = "xyes"])
> +

There's already a check for libarchive for debuginfod. Let's do just one
check and use the result for both debuginfod and srcfiles.

>  AC_OUTPUT
>
>  AC_MSG_NOTICE([
> diff --git a/doc/srcfiles.1 b/doc/srcfiles.1
> index 6149c21b..6157045b 100644
> --- a/doc/srcfiles.1
> +++ b/doc/srcfiles.1
> @@ -21,15 +21,18 @@
>  eu-srcfiles \- Lists the source files of a DWARF/ELF file.
>
>  .SH "SYNOPSIS"
> -eu-srcfiles [\fB\-0\fR|\fB\-\-null\fR] [\fB\-c\fR|\fB\-\-cu\-only\fR] 
> [\fB\-v\fR|\fB\-\-verbose\fR] INPUT
> +eu-srcfiles [\fB\-0\fR|\fB\-\-null\fR] [\fB\-c\fR|\fB\-\-cu\-only\fR] 
> [\fB\-v\fR|\fB\-\-verbose\fR] [\fB\-z\fR|\fB\-\-zip\fR] INPUT
>
>  .SH "DESCRIPTION"
> -\fBeu-srcfiles\fR lists the source files of a given \s-DWARF/ELF\s0
> +\fBeu-srcfiles\fR lists all the source files of a given DWARF/ELF
>  file.  This list is based on a search of the DWARF debuginfo, which
>  may be automatically fetched by debuginfod if applicable.  The target
>  file may be an executable, a coredump, a process, or even the running
>  kernel.  The default is the file 'a.out'.  The source file names are
> -made unique and printed to standard output.
> +made unique and printed to standard output. The source files can be
> +placed in a zip file that is sent to stdout.
> +
> +Note that all occurrences of '/./' and '/../' in the path name are 
> canonicalized.
>
>  .SH "INPUT OPTIONS"
>  The long and short forms of options, shown here as alternatives, are
> @@ -78,7 +81,7 @@ Print program version.
>
>  .TP
>  \fB\-0, \-\-null\fR
> -Separate items by a null instead of a newline.
> +Separate items by a null instead of a newline. Cannot be used with the zip 
> option becuase it raises errors when unzipping.
>
>  .TP
>  \fB\-c, \-\-cu\-only\fR
> @@ -88,6 +91,10 @@ Only list the CU names.
>  \fB\-v, \-\-verbose\fR
>  Increase verbosity of logging messages.
>
> +.TP
> +\fB\-z, \-\-zip\fR
> +Zip all the source files and send to stdout. Cannot be used with the null 
> option becuase it raises errors when unzipping.
> +

I wouldn't bother mentioning "because it raises errors..." and instead just
say "Cannot be used with --null".

>
>  .SH EXAMPLES
>
> @@ -119,6 +126,11 @@ List the source files of a kernel image.
>  eu-srcfiles -e /boot/vmlinuz-`uname -r`
>  .ESAMPLE
>
> +Zip all the source files for a binary.
> +.SAMPLE
> +eu-srcfiles -z -e /bin/ls > ls.zip
> +.ESAMPLE
> +
>
>  .SH "AUTHOR"
>  Written by Housam Alamour.
> diff --git a/src/Makefile.am b/src/Makefile.am
> index d3d9d408..3853c152 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -85,7 +85,

Re: [PATCH] elfutils: PR 30991 srcfiles tarball feature

2023-11-14 Thread Aaron Merey
Hi Housam,

On Mon, Nov 13, 2023 at 8:49 PM Aaron Merey  wrote:
>
> On Wed, Nov 8, 2023 at 11:49 AM Housam Alamour  wrote:
> > +/* Read the file contents and write it to the zip file */
> > +fd = open(file_path.c_str(), O_RDONLY);
> > +if (!fd)
> > +{
> > +  cerr << "Error: Failed to open the file: " << file_path << endl;
> > +  continue;
> > +}
> [...]
> As for error messages, right now we don't actually print "Failed to
> open...". open returns -1 on error, but we only print when fd == 0.
> So we want to print an error message when fd == -1 instead.
>
> There are other sources of error messages that we could include, like
> stat and read. libarchive and debuginfod_find_source provide error codes
> too.
>
> IMO if -v is given we should print detailed error messages whenever
> a file can't be acquired.  Errno and strerror are useful for this.  Otherwise
> if -v isn't given then we can simply print the "Failed to open file" message.

I came up with a slightly better way to handle error messages after giving
this some more thought.  How about if -v isn't given, then print no messages
re. file availability, error or otherwise.  And if -v is given then we print
a detailed message for each file either confirming its availability or giving
the reason it couldn't be acquired.

This approach is less noisy when files can't be found for mundane reasons but
it also provides comprehensive details on each file when the user asks for it.

Aaron



Re: [PATCH] libdwfl: Correctly handle corefile non-contiguous segments

2023-11-14 Thread Aaron Merey
Hi Mark,

On Tue, Nov 14, 2023 at 9:03 AM Mark Wielaard  wrote:
>
> > A couple caveats should be mentioned.  First, start and end addresses
> > of reported modules cannot be assumed to contain segments from only
> > that module.  This has always been the case however.
>
> There is dwfl_addrmodule/dwfl_addrsegment to find the module that
> covers a specific address. Defined in libdwfl/segment.c. I think this
> should handle this by checking the closes load address. But I have not
> tested it.
>
> Normally only kernel modules (.ko ET_REL files) have multiple segments.
> So it might make sense to double check none of this impacts systemtap.

I'll look into this.

> > Second, the testcases in this patch use a firefox corefile that is
> > fairly large.  The .bz2 corefile is about 47M.  A clean elfutils repo
> > is currently about 42M, so this corefile more than doubles the size of
> > the elfutils repo.  I looked for a much smaller process with
> > interleaving non-contiguous shared library sections but was not able
> > to find one.  I've included the corefile and tests in this patch but
> > they can be removed if we'd prefer to not approx. double the size of
> > the repo.
>
> I really appreciate the testcase, but it really is too big. It is 736M
> bunzip2ed (which would happen on any make check). I think this makes
> the repo and the build/check a little too heavy. Also we try to include
> instructions to recreate any binary test files and that isn't really
> possible in this case.

Agreed, this isn't a great testcase.  I'm not sure if there's a way to
force the linker to create segments that reproduce the bug on a much
smaller process, but I'll see if I can write something by hand with
libelf.  Or maybe GNU poke can be of use here?  I'll take a look.

Aaron



[PATCH v2] libdwfl: Correctly handle corefile non-contiguous segments

2023-11-17 Thread Aaron Merey
v1: https://sourceware.org/pipermail/elfutils-devel/2023q4/006644.html

v2 changes:

The size of the uncompressed testcore-noncontig has been reduced from
736M to 54K.

dwfl_addrsegment tests have been added to verify correct handling of
non-contiguous segments.
---
 libdwfl/dwfl_segment_report_module.c |  37 ++-
 tests/.gitignore |   1 +
 tests/Makefile.am|   8 ++--
 tests/dwfl-core-noncontig.c  |  67 +++
 tests/run-dwfl-core-noncontig.sh |  63 +
 tests/testcore-noncontig.bz2 | Bin 0 -> 54684 bytes
 6 files changed, 162 insertions(+), 14 deletions(-)
 create mode 100644 tests/dwfl-core-noncontig.c
 create mode 100755 tests/run-dwfl-core-noncontig.sh
 create mode 100644 tests/testcore-noncontig.bz2

diff --git a/libdwfl/dwfl_segment_report_module.c 
b/libdwfl/dwfl_segment_report_module.c
index 3ef62a7d..09ee37b3 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -737,17 +737,34 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const 
char *name,
&& invalid_elf (module->elf, module->disk_file_has_build_id,
&build_id))
  {
-   elf_end (module->elf);
-   close (module->fd);
-   module->elf = NULL;
-   module->fd = -1;
+   /* If MODULE's build-id doesn't match the disk file's
+  build-id, close ELF only if MODULE and ELF refer to
+  different builds of files with the same name.  This
+  prevents premature closure of the correct ELF in cases
+  where segments of a module are non-contiguous in memory.  */
+   if (name != NULL && module->name[0] != '\0'
+   && strcmp (basename (module->name), basename (name)) == 0)
+ {
+   elf_end (module->elf);
+   close (module->fd);
+   module->elf = NULL;
+   module->fd = -1;
+ }
  }
-   if (module->elf != NULL)
+   else if (module->elf != NULL)
  {
-   /* Ignore this found module if it would conflict in address
-  space with any already existing module of DWFL.  */
+   /* This module has already been reported.  */
skip_this_module = true;
  }
+   else
+ {
+   /* Only report this module if we haven't already done so.  */
+   for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL;
+mod = mod->next)
+ if (mod->low_addr == module_start
+ && mod->high_addr == module_end)
+   skip_this_module = true;
+ }
  }
   if (skip_this_module)
goto out;
@@ -781,10 +798,6 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const 
char *name,
}
 }
 
-  /* Our return value now says to skip the segments contained
- within the module.  */
-  ndx = addr_segndx (dwfl, segment, module_end, true);
-
   /* Examine its .dynamic section to get more interesting details.
  If it has DT_SONAME, we'll use that as the module name.
  If it has a DT_DEBUG, then it's actually a PIE rather than a DSO.
@@ -929,6 +942,8 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char 
*name,
   ndx = -1;
   goto out;
 }
+  else
+ndx++;
 
   /* We have reported the module.  Now let the caller decide whether we
  should read the whole thing in right now.  */
diff --git a/tests/.gitignore b/tests/.gitignore
index b9aa22ba..5bebb2c4 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -49,6 +49,7 @@
 /dwfl-report-elf-align
 /dwfl-report-offline-memory
 /dwfl-report-segment-contiguous
+/dwfl-core-noncontig
 /dwfllines
 /dwflmodtest
 /dwflsyms
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7fb8efb1..9f8f7698 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -42,7 +42,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames 
sectiondump \
  dwfl-bug-addr-overflow arls dwfl-bug-fd-leak \
  dwfl-addr-sect dwfl-bug-report early-offscn \
  dwfl-bug-getmodules dwarf-getmacros dwarf-ranges addrcfi \
- dwarfcfi \
+ dwfl-core-noncontig dwarfcfi \
  test-flag-nobits dwarf-getstring rerequest_tag \
  alldts typeiter typeiter2 low_high_pc \
  test-elf_cntl_gelf_getshdr dwflsyms dwfllines \
@@ -212,7 +212,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile 
test-nlist \
$(asm_TESTS) run-disasm-bpf.sh run-low_high_pc-dw-form-indirect.sh \
run-nvidia-extended-linemap-libdw.sh 
run-nvidia-extended-linemap-readelf.sh \
run-readelf-dw-form-indirect.sh run-strip-largealign.sh \
-   run-

Re: [PATCH v2] libdwfl: Correctly handle corefile non-contiguous segments

2023-11-21 Thread Aaron Merey
Hi Mark,

On Tue, Nov 21, 2023 at 7:48 AM Mark Wielaard  wrote:
> >
> > The size of the uncompressed testcore-noncontig has been reduced from
> > 736M to 54K.
>
> Uncompressed it is 580K. Still a bit large, but much more reasonable.
> We even have a couple of larger test files in the repo. Thanks.
> And in theory it can be replicated.

Sorry about that, I didn't mean to mix compressed and uncompressed sizes.

> > dwfl_addrsegment tests have been added to verify correct handling of
> > non-contiguous segments.
>
> BTW. Adding extra comments after the --- makes it easier to post a
> commit as you will apply it because comments after the --- will be
> ignored by git am.
>
> Please restore the original commit message before pushing.
> The description of the issue was really good.

Done.

> > +  /* First segment of non-contiguous module following the address space 
> > gap.  */
> > +  seg = dwfl_addrsegment (dwfl, 0x7f14e47ad000, NULL);
> > +  assert (seg == 40);
>
> OK. This does make sense if you have seen the eu-readelf -l testcore-
> noncontig output. Maybe that should be there in a comment?

Done.

> All looks good. Maybe add the suggested comment about looking at the
> program headers to undestand the testscase and please restore the
> original commit message before applying.

Pushed as commit 2f38fa57942f95.

Thanks,
Aaron



[PATCH 1/2] libdw: Use INTUSE with dwarf_get_units

2023-12-06 Thread Aaron Merey
Add INTDECL for dwarf_get_units and call dwarf_get_units with INTUSE.

Signed-off-by: Aaron Merey 
---
 libdw/dwarf_get_units.c   |  1 +
 libdw/dwarf_next_lines.c  |  8 +--
 libdw/libdwP.h| 91 +--
 libdw/libdw_find_split_unit.c |  4 +-
 4 files changed, 52 insertions(+), 52 deletions(-)

diff --git a/libdw/dwarf_get_units.c b/libdw/dwarf_get_units.c
index 6215bf4b..407ed2ba 100644
--- a/libdw/dwarf_get_units.c
+++ b/libdw/dwarf_get_units.c
@@ -129,3 +129,4 @@ dwarf_get_units (Dwarf *dwarf, Dwarf_CU *cu, Dwarf_CU 
**next_cu,
 
   return 0;
 }
+INTDEF(dwarf_get_units)
diff --git a/libdw/dwarf_next_lines.c b/libdw/dwarf_next_lines.c
index 9b76b47e..74854ecd 100644
--- a/libdw/dwarf_next_lines.c
+++ b/libdw/dwarf_next_lines.c
@@ -99,8 +99,8 @@ dwarf_next_lines (Dwarf *dbg, Dwarf_Off off,
   Dwarf_CU *given_cu = *cu;
   Dwarf_CU *next_cu = given_cu;
   bool found = false;
-  while (dwarf_get_units (dbg, next_cu, &next_cu, NULL, NULL,
- &cudie, NULL) == 0)
+  while (INTUSE(dwarf_get_units) (dbg, next_cu, &next_cu, NULL, NULL,
+ &cudie, NULL) == 0)
{
  if (dwarf_hasattr (&cudie, DW_AT_stmt_list))
{
@@ -131,8 +131,8 @@ dwarf_next_lines (Dwarf *dbg, Dwarf_Off off,
 tables. Need to do a linear search (but stop at the given
 CU, since we already searched those.  */
  next_cu = NULL;
- while (dwarf_get_units (dbg, next_cu, &next_cu, NULL, NULL,
- &cudie, NULL) == 0
+ while (INTUSE(dwarf_get_units) (dbg, next_cu, &next_cu, NULL, NULL,
+ &cudie, NULL) == 0
 && next_cu != given_cu)
{
  Dwarf_Attribute attr;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index aef42267..5aca9082 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -414,6 +414,49 @@ struct Dwarf_CU
   void *endp;
 };
 
+/* Aliases to avoid PLTs.  */
+INTDECL (dwarf_aggregate_size)
+INTDECL (dwarf_attr)
+INTDECL (dwarf_attr_integrate)
+INTDECL (dwarf_begin)
+INTDECL (dwarf_begin_elf)
+INTDECL (dwarf_child)
+INTDECL (dwarf_default_lower_bound)
+INTDECL (dwarf_dieoffset)
+INTDECL (dwarf_diename)
+INTDECL (dwarf_end)
+INTDECL (dwarf_entrypc)
+INTDECL (dwarf_errmsg)
+INTDECL (dwarf_formaddr)
+INTDECL (dwarf_formblock)
+INTDECL (dwarf_formref_die)
+INTDECL (dwarf_formsdata)
+INTDECL (dwarf_formstring)
+INTDECL (dwarf_formudata)
+INTDECL (dwarf_getabbrevattr_data)
+INTDECL (dwarf_getalt)
+INTDECL (dwarf_getarange_addr)
+INTDECL (dwarf_getarangeinfo)
+INTDECL (dwarf_getaranges)
+INTDECL (dwarf_getlocation_die)
+INTDECL (dwarf_getsrcfiles)
+INTDECL (dwarf_getsrclines)
+INTDECL (dwarf_get_units)
+INTDECL (dwarf_hasattr)
+INTDECL (dwarf_haschildren)
+INTDECL (dwarf_haspc)
+INTDECL (dwarf_highpc)
+INTDECL (dwarf_lowpc)
+INTDECL (dwarf_nextcu)
+INTDECL (dwarf_next_unit)
+INTDECL (dwarf_offdie)
+INTDECL (dwarf_peel_type)
+INTDECL (dwarf_ranges)
+INTDECL (dwarf_setalt)
+INTDECL (dwarf_siblingof)
+INTDECL (dwarf_srclang)
+INTDECL (dwarf_tag)
+
 #define ISV4TU(cu) ((cu)->version == 4 && (cu)->sec_idx == IDX_debug_types)
 
 /* Compute the offset of a CU's first DIE from the CU offset.
@@ -1061,8 +1104,8 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
   if (cu == NULL && dbg != NULL)
 {
   Dwarf_CU *first_cu;
-  if (dwarf_get_units (dbg, NULL, &first_cu,
-  NULL, NULL, NULL, NULL) == 0)
+  if (INTUSE(dwarf_get_units) (dbg, NULL, &first_cu,
+  NULL, NULL, NULL, NULL) == 0)
cu = first_cu;
 }
 
@@ -1379,48 +1422,4 @@ void __libdw_set_debugdir (Dwarf *dbg);
 char * __libdw_filepath (const char *debugdir, const char *dir,
 const char *file)
   internal_function;
-
-
-/* Aliases to avoid PLTs.  */
-INTDECL (dwarf_aggregate_size)
-INTDECL (dwarf_attr)
-INTDECL (dwarf_attr_integrate)
-INTDECL (dwarf_begin)
-INTDECL (dwarf_begin_elf)
-INTDECL (dwarf_child)
-INTDECL (dwarf_default_lower_bound)
-INTDECL (dwarf_dieoffset)
-INTDECL (dwarf_diename)
-INTDECL (dwarf_end)
-INTDECL (dwarf_entrypc)
-INTDECL (dwarf_errmsg)
-INTDECL (dwarf_formaddr)
-INTDECL (dwarf_formblock)
-INTDECL (dwarf_formref_die)
-INTDECL (dwarf_formsdata)
-INTDECL (dwarf_formstring)
-INTDECL (dwarf_formudata)
-INTDECL (dwarf_getabbrevattr_data)
-INTDECL (dwarf_getalt)
-INTDECL (dwarf_getarange_addr)
-INTDECL (dwarf_getarangeinfo)
-INTDECL (dwarf_getaranges)
-INTDECL (dwarf_getlocation_die)
-INTDECL (dwarf_getsrcfiles)
-INTDECL (dwarf_getsrclines)
-INTDECL (dwarf_hasattr)
-INTDECL (dwarf_haschildren)
-INTDECL (dwarf_haspc)
-INTDECL (dwarf_highpc)
-INTDECL (dwarf_lowpc)
-INTDECL (dwarf_nextcu)
-INTDECL (dwarf_next_unit)
-INTDECL (dwarf_offdie)
-INTDECL (dwarf_peel_type)
-INTDECL (dwarf_ranges)
-INTDECL (dwarf_

[PATCH 0/2] dwarf_getaranges: Build aranges list from CUs

2023-12-06 Thread Aaron Merey
Patch 1/2 is a prepatory patch that modifies dwarf_get_units calls
with INTUSE.

Aaron Merey (2):
  libdw: Use INTUSE with dwarf_get_units
  dwarf_getaranges: Build aranges list from CUs instead of
.debug_aranges

 libdw/dwarf_get_units.c   |   1 +
 libdw/dwarf_getaranges.c  | 215 --
 libdw/dwarf_next_lines.c  |   8 +-
 libdw/libdwP.h|  91 +++---
 libdw/libdw_find_split_unit.c |   4 +-
 5 files changed, 104 insertions(+), 215 deletions(-)

-- 
2.43.0



[PATCH 2/2] dwarf_getaranges: Build aranges list from CUs instead of .debug_aranges

2023-12-06 Thread Aaron Merey
No longer use .debug_aranges to build the aranges list since it could be
absent or incomplete.

Instead build the aranges list by iterating over each CU and recording
each address range.

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

Signed-off-by: Aaron Merey 

---

This patch's method of building the aranges list is slower than simply
reading .debug_aranges.  On my machine, running eu-stack on a 2.9G
firefox core file takes about 8.7 seconds with this patch applied,
compared to about 3.3 seconds without this patch.

Ideally we could assume that .debug_aranges is complete if it is present
and build the aranges list via CU iteration only when .debug_aranges
is absent.  This would let us save time on gcc-compiled binaries, which
include complete .debug_aranges by default.

However the DWARF spec appears to permit partially complete
.debug_aranges [1].  We could improve performance by starting with a
potentially incomplete list built from .debug_aranges.  If a lookup
fails then search the CUs for missing aranges and add to the list
when found.

This approach would complicate the dwarf_get_aranges interface.  The
list it initially provides could no longer be assumed to be complete.
The number of elements in the list could change during calls to
dwarf_getarange{info, _addr}.  This would invalidate the naranges value
set by dwarf_getaranges.  The current API doesn't include a way to
communicate to the caller when narages changes and by how much.

Due to these complications I think it's better to simply ignore
.debug_aranges altogether and build the aranges table via CU iteration,
as is done in this patch.

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=22288#c5

 libdw/dwarf_getaranges.c | 215 ++-
 1 file changed, 52 insertions(+), 163 deletions(-)

diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c
index 27439d37..8676f93b 100644
--- a/libdw/dwarf_getaranges.c
+++ b/libdw/dwarf_getaranges.c
@@ -33,7 +33,6 @@
 #endif
 
 #include 
-#include 
 #include "libdwP.h"
 #include 
 
@@ -68,174 +67,51 @@ dwarf_getaranges (Dwarf *dbg, Dwarf_Aranges **aranges, 
size_t *naranges)
   return 0;
 }
 
-  if (dbg->sectiondata[IDX_debug_aranges] == NULL)
-{
-  /* No such section.  */
-  *aranges = NULL;
-  if (naranges != NULL)
-   *naranges = 0;
-  return 0;
-}
-
-  if (dbg->sectiondata[IDX_debug_aranges]->d_buf == NULL)
-return -1;
-
   struct arangelist *arangelist = NULL;
   unsigned int narangelist = 0;
 
-  const unsigned char *readp = dbg->sectiondata[IDX_debug_aranges]->d_buf;
-  const unsigned char *readendp
-= readp + dbg->sectiondata[IDX_debug_aranges]->d_size;
-
-  while (readp < readendp)
+  Dwarf_CU *cu = NULL;
+  while (INTUSE(dwarf_get_units) (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
 {
-  const unsigned char *hdrstart = readp;
-
-  /* Each entry starts with a header:
-
-1. A 4-byte or 12-byte length containing the length of the
-set of entries for this compilation unit, not including the
-length field itself. [...]
-
-2. A 2-byte version identifier containing the value 2 for
-DWARF Version 2.1.
-
-3. A 4-byte or 8-byte offset into the .debug_info section. [...]
-
-4. A 1-byte unsigned integer containing the size in bytes of
-an address (or the offset portion of an address for segmented
-addressing) on the target system.
-
-5. A 1-byte unsigned integer containing the size in bytes of
-a segment descriptor on the target system.  */
-  if (unlikely (readp + 4 > readendp))
-   goto invalid;
-
-  Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
-  unsigned int length_bytes = 4;
-  if (length == DWARF3_LENGTH_64_BIT)
-   {
- if (unlikely (readp + 8 > readendp))
-   goto invalid;
-
- length = read_8ubyte_unaligned_inc (dbg, readp);
- length_bytes = 8;
-   }
-  else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
-&& length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
-   goto invalid;
-
-  const unsigned char *endp = readp + length;
-  if (unlikely (endp > readendp))
-   goto invalid;
-
-  if (unlikely (readp + 2 > readendp))
-   goto invalid;
-
-  unsigned int version = read_2ubyte_unaligned_inc (dbg, readp);
-  if (version != 2)
-   {
-   invalid:
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
-   fail:
- while (arangelist != NULL)
-   {
- struct arangelist *next = arangelist->next;
- free (arangelist);
- arangelist = next;
-   }
- return -1;
-   }
-
-  Dwarf_Word offset = 0;
-  if (__libdw_read_offset_inc (dbg,
-  I

[PATCH v2] dwarf_getaranges: Build aranges list from CUs instead of .debug_aranges

2023-12-11 Thread Aaron Merey
No longer use .debug_aranges to build the aranges list since it could be
absent or incomplete.

Instead build the aranges list by iterating over each CU and recording
each address range.

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

Signed-off-by: Aaron Merey 
---

v2 adds a test for generating aranges from a binary with no
.debug_aranges.

This patch's method of building the aranges list is slower than simply
reading .debug_aranges.  On my machine, running eu-stack on a 2.9G
firefox core file takes about 8.7 seconds with this patch applied,
compared to about 3.3 seconds without this patch.

Ideally we could assume that .debug_aranges is complete if it is present
and build the aranges list via CU iteration only when .debug_aranges
is absent.  This would let us save time on gcc-compiled binaries, which
include complete .debug_aranges by default.

However the DWARF spec appears to permit partially complete
.debug_aranges [1].  We could improve performance by starting with a
potentially incomplete list built from .debug_aranges.  If a lookup
fails then search the CUs for missing aranges and add to the list
when found.

This approach would complicate the dwarf_get_aranges interface.  The
list it initially provides could no longer be assumed to be complete.
The number of elements in the list could change during calls to
dwarf_getarange{info, _addr}.  This would invalidate the naranges value
set by dwarf_getaranges.  The current API doesn't include a way to
communicate to the caller when narages changes and by how much.

Due to these complications I think it's better to simply ignore
.debug_aranges altogether and build the aranges table via CU iteration,
as is done in this patch.

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=22288#c5

 libdw/dwarf_getaranges.c | 215 ++-
 tests/run-get-aranges.sh |  48 +
 2 files changed, 100 insertions(+), 163 deletions(-)

diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c
index 27439d37..8676f93b 100644
--- a/libdw/dwarf_getaranges.c
+++ b/libdw/dwarf_getaranges.c
@@ -33,7 +33,6 @@
 #endif
 
 #include 
-#include 
 #include "libdwP.h"
 #include 
 
@@ -68,174 +67,51 @@ dwarf_getaranges (Dwarf *dbg, Dwarf_Aranges **aranges, 
size_t *naranges)
   return 0;
 }
 
-  if (dbg->sectiondata[IDX_debug_aranges] == NULL)
-{
-  /* No such section.  */
-  *aranges = NULL;
-  if (naranges != NULL)
-   *naranges = 0;
-  return 0;
-}
-
-  if (dbg->sectiondata[IDX_debug_aranges]->d_buf == NULL)
-return -1;
-
   struct arangelist *arangelist = NULL;
   unsigned int narangelist = 0;
 
-  const unsigned char *readp = dbg->sectiondata[IDX_debug_aranges]->d_buf;
-  const unsigned char *readendp
-= readp + dbg->sectiondata[IDX_debug_aranges]->d_size;
-
-  while (readp < readendp)
+  Dwarf_CU *cu = NULL;
+  while (INTUSE(dwarf_get_units) (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
 {
-  const unsigned char *hdrstart = readp;
-
-  /* Each entry starts with a header:
-
-1. A 4-byte or 12-byte length containing the length of the
-set of entries for this compilation unit, not including the
-length field itself. [...]
-
-2. A 2-byte version identifier containing the value 2 for
-DWARF Version 2.1.
-
-3. A 4-byte or 8-byte offset into the .debug_info section. [...]
-
-4. A 1-byte unsigned integer containing the size in bytes of
-an address (or the offset portion of an address for segmented
-addressing) on the target system.
-
-5. A 1-byte unsigned integer containing the size in bytes of
-a segment descriptor on the target system.  */
-  if (unlikely (readp + 4 > readendp))
-   goto invalid;
-
-  Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
-  unsigned int length_bytes = 4;
-  if (length == DWARF3_LENGTH_64_BIT)
-   {
- if (unlikely (readp + 8 > readendp))
-   goto invalid;
-
- length = read_8ubyte_unaligned_inc (dbg, readp);
- length_bytes = 8;
-   }
-  else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
-&& length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
-   goto invalid;
-
-  const unsigned char *endp = readp + length;
-  if (unlikely (endp > readendp))
-   goto invalid;
-
-  if (unlikely (readp + 2 > readendp))
-   goto invalid;
-
-  unsigned int version = read_2ubyte_unaligned_inc (dbg, readp);
-  if (version != 2)
-   {
-   invalid:
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
-   fail:
- while (arangelist != NULL)
-   {
- struct arangelist *next = arangelist->next;
- free (arangelist);
- arangelist = next;
-   }
- return -1;

Re: [PATCH 1/2] libdw: Use INTUSE with dwarf_get_units

2023-12-22 Thread Aaron Merey
On Thu, Dec 21, 2023 at 6:56 PM Mark Wielaard  wrote:
>
> On Wed, Dec 06, 2023 at 08:35:03PM -0500, Aaron Merey wrote:
> > Add INTDECL for dwarf_get_units and call dwarf_get_units with INTUSE.
>
> This is obviously OK. Although it is a bit of a micro-optimization.

Thanks, pushed as commit c1058da5a

Aaron



Re: [PATCH] PR 30991: srcfiles tarball feature

2024-01-22 Thread Aaron Merey
Hi Housam,

This is a very cool feature.  Thanks again for working on this!

On Fri, Jan 19, 2024 at 11:47 AM Housam Alamour  wrote:
>
> * srcfiles.cxx: Introduce new --zip option that places all the
> source files associated with a specified dwarf/elf file
> into a zip file and sends it to stdout. Files may be
> fetched from debuginfod (if applicable) or locally as
> a backup.
> Added -b option to disable the backup of checking
> for files locally in -z mode.
>
> * run-srcfiles-self.sh: Added test-case for the new zip
> feature that archives the source files of the srcfiles
> tool and checks archive integrity. An additional test
> ensures that if debuginfod is enabled, the files are
> fetched and archived properly while maintaing integrity.

Should be 'maintaining'.

>
> * debuginfod-subr.sh: On very slow/remote storage, it can
> take O(minute) to finish indexing the entire elfutils
> build tree, so a wait_ready4 shell function is one
> way to let a longer debuginfod wait operation work.
>
> * srcfiles.1, NEWS: Added documentation for the new zip feature.
>
> * configure.ac: Simplify check for libarchive for srcfiles.cxx
> by integrating it into the same check for debuginfod.
>
> * Makefile.am: build with local copy of debuginfod-client.
>
> Example:
> % ./src/srcfiles -z -e /bin/ls > output.zip
>
> https://sourceware.org/bugzilla/show_bug.cgi?id=30991
>
> Signed-off-by: Housam Alamour 
> ---
>  NEWS   |   8 +
>  configure.ac   |   5 +-
>  debuginfod/debuginfod.cxx  |   2 -
>  doc/srcfiles.1 |  26 +++-
>  src/Makefile.am|   9 +-
>  src/srcfiles.cxx   | 307 -
>  tests/debuginfod-subr.sh   |  14 +-
>  tests/run-srcfiles-self.sh |  77 +-
>  8 files changed, 394 insertions(+), 54 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index 0420d3b8..3391d6a1 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -1,3 +1,8 @@
> +Version 0.191 (after 0.189)
> +
> +srcfiles: Can now fetch the source files of a DWARF/ELF file and
> +  place them into a zip.
> +
>  Version 0.190 "Woke!"
>
>  CONTRIBUTING: Switch from real name policy to known identity policy.
> @@ -9,6 +14,9 @@ libelf: Add RELR support.
>
>  libdw: Recognize .debug_[ct]u_index sections
>
> +srcfiles: added srcfiles tool that lists all the source files of a given
> +  DWARF/ELF file.
> +
>  readelf: Support readelf -Ds, --use-dynamic --symbol.
>   Support .gdb_index version 9
>
> diff --git a/configure.ac b/configure.ac
> index af5b6bf7..ddb79b83 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -841,7 +841,7 @@ AM_CONDITIONAL([LIBDEBUGINFOD],[test 
> "x$enable_libdebuginfod" = "xyes" || test "
>  AM_CONDITIONAL([DUMMY_LIBDEBUGINFOD],[test "x$enable_libdebuginfod" = 
> "xdummy"])
>  AC_CHECK_HEADERS([execinfo.h])
>
> -# Look for libmicrohttpd, libarchive, sqlite for debuginfo server
> +# Look for libmicrohttpd, libarchive, sqlite for debuginfo server and 
> srcfiles tool
>  # minimum versions as per rhel7.
>  AC_ARG_ENABLE([debuginfod],AS_HELP_STRING([--enable-debuginfod], [Build 
> debuginfod server]))
>  AS_IF([test "x$enable_debuginfod" != "xno"], [
> @@ -853,11 +853,12 @@ AS_IF([test "x$enable_debuginfod" != "xno"], [
>AC_MSG_ERROR([need libdebuginfod (or dummy), use --disable-debuginfod 
> to disable.])
>  fi
>  enable_debuginfod=yes # presume success
> +AC_DEFINE([HAVE_LIBARCHIVE], [1], [Define to 1 if libarchive is 
> available]) # presume success
>  PKG_PROG_PKG_CONFIG
>  PKG_CHECK_MODULES([libmicrohttpd],[libmicrohttpd >= 
> 0.9.33],[],[enable_debuginfod=no])
>  PKG_CHECK_MODULES([oldlibmicrohttpd],[libmicrohttpd < 
> 0.9.51],[old_libmicrohttpd=yes],[old_libmicrohttpd=no])
>  PKG_CHECK_MODULES([sqlite3],[sqlite3 >= 
> 3.7.17],[],[enable_debuginfod=no])
> -PKG_CHECK_MODULES([libarchive],[libarchive >= 
> 3.1.2],[],[enable_debuginfod=no])
> +PKG_CHECK_MODULES([libarchive],[libarchive >= 
> 3.1.2],[],[enable_debuginfod=no], AC_DEFINE([HAVE_LIBARCHIVE], [0], [Define 
> to 0 if libarchive is not available]))
>  if test "x$enable_debuginfod" = "xno"; then
>AC_MSG_ERROR([dependencies not found, use --disable-debuginfod to 
> disable.])
>  fi
> diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx
> index 524be948..6b21f46f 100644
> --- a/debuginfod/debuginfod.cxx
> +++ b/debuginfod/debuginfod.cxx
> @@ -2996,8 +2996,6 @@ dwarf_extract_source_paths (Elf *elf, set& 
> debug_sourcefiles)
>
>if (comp_dir[0] == '\0' && cuname[0] != '/')
>  {
> -  // This is a common symptom for dwz-compressed debug files,
> -  // where the altdebug file cannot be resolved.
>if (verbose > 3)
>  obatched(clog) << "skipping cu=" << cuname << " due to empty 
> comp_dir" << endl;
>continue;
> diff --git a/doc/srcfiles.1 b/doc/srcfiles.1
> index 6149c21b..a7cde664 100644
> --

Re: [PATCH] libdwfl: Remove asserts from library code

2024-01-28 Thread Aaron Merey
Hi Di,

Thanks for the patch.

On Sun, Dec 24, 2023 at 2:35 AM Di Chen  wrote:
>
> From 33d436aefb6b63a159943bd24eb432b8cfb8b369 Mon Sep 17 00:00:00 2001
> From: Di Chen 
> Date: Sun, 24 Dec 2023 11:44:48 +0800
> Subject: [PATCH] libdwfl: Remove asserts from library code
>
> It would be better for elfutils library functions to return an error
> code instead of aborting because of a failed assert.
>
> This commit works on removing the asserts under libdwfl. There are two
> ways handling the removing:
>
>   1) Replace the asserts with if statements.
>
>   2) Replace the asserts with eu_static_assert.
>
> Asserts are heavily used across all elfutils libraries, and it's
> impossibe to implement the removing in one commit. So let's gradually
> remove the asserts in the later coming commits.

Agreed.

>
> https://sourceware.org/bugzilla/show_bug.cgi?id=31027
>
> Signed-off-by: Di Chen 
> ---
>  libdwfl/dwfl_frame.c | 14 +-
>  libdwfl/dwfl_frame_pc.c  |  3 ++-
>  libdwfl/dwfl_frame_regs.c|  7 +--
>  libdwfl/dwfl_module_build_id.c   |  3 ++-
>  libdwfl/dwfl_module_getdwarf.c   |  3 ++-
>  libdwfl/dwfl_module_getsrc_file.c|  3 ++-
>  libdwfl/dwfl_module_register_names.c |  3 ++-
>  libdwfl/dwfl_segment_report_module.c |  2 +-
>  8 files changed, 25 insertions(+), 13 deletions(-)
>
> diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c
> index 5ee71dd4..18150e2a 100644
> --- a/libdwfl/dwfl_frame.c
> +++ b/libdwfl/dwfl_frame.c
> @@ -85,12 +85,14 @@ free_states (Dwfl_Frame *state)
>  static Dwfl_Frame *
>  state_alloc (Dwfl_Thread *thread)
>  {
> -  assert (thread->unwound == NULL);
> +  if (thread->unwound != NULL)
> +return NULL;
>Ebl *ebl = thread->process->ebl;
>size_t nregs = ebl_frame_nregs (ebl);
>if (nregs == 0)
>  return NULL;
> -  assert (nregs < sizeof (((Dwfl_Frame *) NULL)->regs_set) * 8);
> +  if (nregs >= sizeof (((Dwfl_Frame *) NULL)->regs_set) * 8)
> +return NULL;

All of these assert removals look good, but it may be helpful if we also
set an error code with __libdwfl_seterrno, at least in the dwfl_frame*.c
functions being modified in this patch.

I think the INVALID_REGISTER error can be used when nregs is too big.
However for 'thread->unwound != NULL' it's not clear to me exactly
which DWFL_ERROR we should use.  The NO_UNWIND error seems applicable
but its description reads "Unwinding not supported for this architecture".
Arch support isn't necessarily the problem here.

Maybe we should add another DWFL_ERROR for these cases, something like
"BAD_FRAME"?  Then we can use this error code when a frame is missing
or its pc_state is corrupt.

>Dwfl_Frame *state = malloc (sizeof (*state) + sizeof (*state->regs) * 
> nregs);
>if (state == NULL)
>  return NULL;
> @@ -283,8 +285,9 @@ dwfl_getthreads (Dwfl *dwfl, int (*callback) (Dwfl_Thread 
> *thread, void *arg),
>   }
>int err = callback (&thread, arg);
>if (err != DWARF_CB_OK)
> - return err;
> -  assert (thread.unwound == NULL);
> +return err;
> +  if (thread.unwound != NULL)
> +return -1;
>  }
>/* NOTREACHED */
>  }
> @@ -450,7 +453,8 @@ dwfl_thread_getframes (Dwfl_Thread *thread,
>__libdwfl_seterrno (err);
>return -1;
>  }
> -  assert (state->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED);
> +  if (state->pc_state != DWFL_FRAME_STATE_PC_UNDEFINED)
> +return -1;
>free_states (state);
>return 0;
>  }
> diff --git a/libdwfl/dwfl_frame_pc.c b/libdwfl/dwfl_frame_pc.c
> index 296c815b..b9991e9a 100644
> --- a/libdwfl/dwfl_frame_pc.c
> +++ b/libdwfl/dwfl_frame_pc.c
> @@ -35,7 +35,8 @@
>  bool
>  dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation)
>  {
> -  assert (state->pc_state == DWFL_FRAME_STATE_PC_SET);
> +  if (state->pc_state != DWFL_FRAME_STATE_PC_SET)
> +return false;
>*pc = state->pc;
>ebl_normalize_pc (state->thread->process->ebl, pc);
>if (isactivation)
> diff --git a/libdwfl/dwfl_frame_regs.c b/libdwfl/dwfl_frame_regs.c
> index a4bd3884..064f5e8a 100644
> --- a/libdwfl/dwfl_frame_regs.c
> +++ b/libdwfl/dwfl_frame_regs.c
> @@ -37,8 +37,11 @@ dwfl_thread_state_registers (Dwfl_Thread *thread, int 
> firstreg,
>   unsigned nregs, const Dwarf_Word *regs)
>  {
>Dwfl_Frame *state = thread->unwound;
> -  assert (state && state->unwound == NULL);
> -  assert (state->initial_frame);
> +  if (state == NULL || state->unwound != NULL || !state->initial_frame)
> +{
> +__libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
> +return false;

Need two more spaces of indentation here.

> +}
>for (unsigned regno = firstreg; regno < firstreg + nregs; regno++)
>  if (! __libdwfl_frame_reg_set (state, regno, regs[regno - firstreg]))
>{
> diff --git a/libdwfl/dwfl_module_build_id.c b/libdwfl/dwfl_module_build_id.c
> index 0c198f23..4dcc046e 100644
> --- a/libdwfl/dwfl_module_build_id.c
> +++ b/libdwfl/dwfl_module_build_id.c

Re: [PATCH] srcfiles.cxx: Addressed all patch review notes. typos, formatting, documentation, show -z and -b option even if libarchive is not available (and adjust test script accordingly), show sourc

2024-01-29 Thread Aaron Merey
Hi Housam,

On Fri, Jan 26, 2024 at 4:01 PM Housam Alamour  wrote:
>
> +/* Definitions of arguments for argp functions.  */
>  static const struct argp_option options[] =
>  {
>{ NULL, 0, NULL, OPTION_DOC, N_("Output options:"), 1 },
> @@ -89,58 +89,50 @@ static const struct argp_option options[] =
>{ "verbose", 'v', NULL, 0,
>  N_ ("Increase verbosity of logging messages."), 0 },
>{ "cu-only", 'c', NULL, 0, N_ ("Only list the CU names."), 0 },
> -  #ifdef HAVE_LIBARCHIVE
> -  { "zip", 'z', NULL, 0, N_ ("Zip all the source files and send to stdout."
> -"Cannot be used with the null option"), 0 },
> -#ifdef ENABLE_LIBDEBUGINFOD
> -{ "no-backup", 'b', NULL, 0, N_ ("Disables local source file search when 
> "
> -  "debuginfod fails to fetch files. This option is only applicable"
> -  "when fetching and zipping files."), 0 },
> -#endif
> -  #endif
> +  { "zip", 'z', NULL, 0, N_ ("Zip all the source files and send to stdout. "
> +"By default, priority is given to fetching source files from "
> +"debuginfod over local source files"), 0 },
> +  { "no-backup", 'b', NULL, 0, N_ ("Disables local source file search when "
> +"debuginfod fails to fetch files.  This option is only applicable "
> +"when fetching and zipping files."), 0 },
>{ NULL, 0, NULL, 0, NULL, 0 }
>  };

I originally suggested keeping -z/-b as valid options even when
srcfiles isn't built with libarchive/libdebuginfod support, but later on
IRC we decided to keep -z/-b conditional on building srcfiles with
the necessary support. I think these #ifdef might have been removed
by mistake.

Also when you post a revised patch, it's a bit easier for me if you just
post the current definitive patch with all commits squashed.  I'll just diff
your patches if I want to compare changes since the last revision!

Aaron



[PATCH] unstrip: Call adjust_relocs no more than once per section.

2024-02-05 Thread Aaron Merey
During symtab merging, adjust_relocs might be called multiple times on
some SHT_REL/SHT_RELA sections.  In these cases it is possible for a
relocation's symbol index to be correctly mapped from X to Y during the
first call to adjust_relocs but then wrongly remapped from Y to Z during
the second call.

Fix this by adjusting relocation symbol indices just once per section.

Also add stable sorting for symbols during symtab merging so that the
symbol order in the output file's symtab does not depend on undefined
behaviour in qsort.

Note that adjust_relocs still might be called a second time on a section
during add_new_section_symbols.  However since add_new_section_symbols
generates its own distinct symbol index map, this should not trigger the
bug described above.

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

Signed-off-by: Aaron Merey 
---

I added some tests to run-unstrip-test.sh to verify that strip+unstrip
does not alter the symbols referred to by relocations.  I tried to use
eu-elfcmp for this purpose.  However for a pair of i386 ET_REL binaries
I did some testing with, eu-elfcmp skips checking the SHT_REL/SHT_RELA
sections because the sh_flags do not contain SHF_ALLOC (the flags only
contain SHF_INFO_LINK in this case).

I'm not sure if this eu-elfcmp behaviour is intentional or if eu-elfcmp
should start comparing REL/RELA sections even if they aren't allocated.

 src/unstrip.c|  81 
 tests/.gitignore |   1 +
 tests/Makefile.am|   3 +-
 tests/elf-print-reloc-syms.c | 144 +++
 tests/run-unstrip-test.sh|   8 ++
 5 files changed, 221 insertions(+), 16 deletions(-)
 create mode 100644 tests/elf-print-reloc-syms.c

diff --git a/src/unstrip.c b/src/unstrip.c
index d5bd1821..f37d6c58 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -598,21 +598,30 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const 
GElf_Shdr *shdr,
 /* Adjust all the relocation sections in the file.  */
 static void
 adjust_all_relocs (Elf *elf, Elf_Scn *symtab, const GElf_Shdr *symshdr,
-  size_t map[], size_t map_size)
+  size_t map[], size_t map_size, bool *scn_filter)
 {
   size_t new_sh_link = elf_ndxscn (symtab);
   Elf_Scn *scn = NULL;
   while ((scn = elf_nextscn (elf, scn)) != NULL)
 if (scn != symtab)
   {
+   if (scn_filter != NULL)
+ {
+   size_t ndx = elf_ndxscn (scn);
+
+   /* Skip relocations that were already mapped during adjust_relocs
+  for the stripped symtab.  This is to avoid mapping a relocation's
+  symbol index from X to Y during the first adjust_relocs and then
+  wrongly remapping it from Y to Z during the second call.  */
+   if (scn_filter[ndx])
+ continue;
+ }
+
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
-   /* Don't redo SHT_GROUP, groups are in both the stripped and debug,
-  it will already have been done by adjust_relocs for the
-  stripped_symtab.  */
-   if (shdr->sh_type != SHT_NOBITS && shdr->sh_type != SHT_GROUP
-   && shdr->sh_link == new_sh_link)
+
+   if (shdr->sh_type != SHT_NOBITS && shdr->sh_link == new_sh_link)
  adjust_relocs (scn, scn, shdr, map, map_size, symshdr);
   }
 }
@@ -697,7 +706,7 @@ add_new_section_symbols (Elf_Scn *old_symscn, size_t 
old_shnum,
 }
 
   /* Adjust any relocations referring to the old symbol table.  */
-  adjust_all_relocs (elf, symscn, shdr, symndx_map, nsym - 1);
+  adjust_all_relocs (elf, symscn, shdr, symndx_map, nsym - 1, NULL);
 
   return symdata;
 }
@@ -874,6 +883,7 @@ collect_symbols (Elf *outelf, bool rel, Elf_Scn *symscn, 
Elf_Scn *strscn,
   s->shndx = shndx;
   s->info.info = sym->st_info;
   s->info.other = sym->st_other;
+  s->duplicate = NULL;
 
   if (scnmap != NULL && shndx != SHN_UNDEF && shndx < SHN_LORESERVE)
s->shndx = scnmap[shndx - 1];
@@ -903,8 +913,7 @@ collect_symbols (Elf *outelf, bool rel, Elf_Scn *symscn, 
Elf_Scn *strscn,
   if (s1->value > s2->value) \
 return 1
 
-/* Compare symbols with a consistent ordering,
-   but one only meaningful for equality.  */
+/* Symbol comparison used to sort symbols in preparation for deduplication.  */
 static int
 compare_symbols (const void *a, const void *b)
 {
@@ -915,6 +924,38 @@ compare_symbols (const void *a, const void *b)
   CMP (size);
   CMP (shndx);
 
+  int res = s1->compare - s2->compare;
+  if (res != 0)
+return res;
+
+  res = strcmp (s1->name, s2->name);
+  if (res != 0)
+return res;
+
+  /* Duplicates still have distinct positions in the symbol index ma

Re: [PATCH] PR 30991: srcfiles tarball feature

2024-02-05 Thread Aaron Merey
Thanks Housam, pushed as commit 75fb8c0152.

Aaron

On Fri, Feb 2, 2024 at 10:51 AM Housam Alamour  wrote:
>
> * srcfiles.cxx: Introduce new --zip option that places all the
> source files associated with a specified dwarf/elf file
> into a zip file and sends it to stdout. Files may be
> fetched from debuginfod (if applicable) or locally as
> a backup.
> Added -b option to disable the backup of checking
> for files locally in -z mode.
>
> * run-srcfiles-self.sh: Added test-case for the new zip
> feature that archives the source files of the srcfiles
> tool and checks archive integrity. An additional test
> ensures that if debuginfod is enabled, the files are
> fetched and archived properly while maintaing integrity.
>
> * debuginfod-subr.sh: On very slow/remote storage, it can
> take O(minute) to finish indexing the entire elfutils
> build tree, so a wait_ready4 shell function is one
> way to let a longer debuginfod wait operation work.
>
> * srcfiles.1, NEWS: Added documentation for the new zip feature.
>
> * configure.ac: Simplify check for libarchive for srcfiles.cxx
> by integrating it into the same check for debuginfod.
>
> * Makefile.am: build with local copy of debuginfod-client.
>
> Example:
> % ./src/srcfiles -z -e /bin/ls > output.zip
>
> https://sourceware.org/bugzilla/show_bug.cgi?id=30991
>
> Signed-off-by: Housam Alamour 
> ---
>  NEWS   |   8 +
>  configure.ac   |   5 +-
>  debuginfod/debuginfod.cxx  |   2 -
>  doc/srcfiles.1 |  33 +++-
>  src/Makefile.am|   9 +-
>  src/srcfiles.cxx   | 305 +
>  tests/debuginfod-subr.sh   |  14 +-
>  tests/run-srcfiles-self.sh |  74 -
>  8 files changed, 400 insertions(+), 50 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index 0420d3b8..3391d6a1 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -1,3 +1,8 @@
> +Version 0.191 (after 0.189)
> +
> +srcfiles: Can now fetch the source files of a DWARF/ELF file and
> +  place them into a zip.
> +
>  Version 0.190 "Woke!"
>
>  CONTRIBUTING: Switch from real name policy to known identity policy.
> @@ -9,6 +14,9 @@ libelf: Add RELR support.
>
>  libdw: Recognize .debug_[ct]u_index sections
>
> +srcfiles: added srcfiles tool that lists all the source files of a given
> +  DWARF/ELF file.
> +
>  readelf: Support readelf -Ds, --use-dynamic --symbol.
>   Support .gdb_index version 9
>
> diff --git a/configure.ac b/configure.ac
> index af5b6bf7..ddb79b83 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -841,7 +841,7 @@ AM_CONDITIONAL([LIBDEBUGINFOD],[test 
> "x$enable_libdebuginfod" = "xyes" || test "
>  AM_CONDITIONAL([DUMMY_LIBDEBUGINFOD],[test "x$enable_libdebuginfod" = 
> "xdummy"])
>  AC_CHECK_HEADERS([execinfo.h])
>
> -# Look for libmicrohttpd, libarchive, sqlite for debuginfo server
> +# Look for libmicrohttpd, libarchive, sqlite for debuginfo server and 
> srcfiles tool
>  # minimum versions as per rhel7.
>  AC_ARG_ENABLE([debuginfod],AS_HELP_STRING([--enable-debuginfod], [Build 
> debuginfod server]))
>  AS_IF([test "x$enable_debuginfod" != "xno"], [
> @@ -853,11 +853,12 @@ AS_IF([test "x$enable_debuginfod" != "xno"], [
>AC_MSG_ERROR([need libdebuginfod (or dummy), use --disable-debuginfod 
> to disable.])
>  fi
>  enable_debuginfod=yes # presume success
> +AC_DEFINE([HAVE_LIBARCHIVE], [1], [Define to 1 if libarchive is 
> available]) # presume success
>  PKG_PROG_PKG_CONFIG
>  PKG_CHECK_MODULES([libmicrohttpd],[libmicrohttpd >= 
> 0.9.33],[],[enable_debuginfod=no])
>  PKG_CHECK_MODULES([oldlibmicrohttpd],[libmicrohttpd < 
> 0.9.51],[old_libmicrohttpd=yes],[old_libmicrohttpd=no])
>  PKG_CHECK_MODULES([sqlite3],[sqlite3 >= 
> 3.7.17],[],[enable_debuginfod=no])
> -PKG_CHECK_MODULES([libarchive],[libarchive >= 
> 3.1.2],[],[enable_debuginfod=no])
> +PKG_CHECK_MODULES([libarchive],[libarchive >= 
> 3.1.2],[],[enable_debuginfod=no], AC_DEFINE([HAVE_LIBARCHIVE], [0], [Define 
> to 0 if libarchive is not available]))
>  if test "x$enable_debuginfod" = "xno"; then
>AC_MSG_ERROR([dependencies not found, use --disable-debuginfod to 
> disable.])
>  fi
> diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx
> index 524be948..6b21f46f 100644
> --- a/debuginfod/debuginfod.cxx
> +++ b/debuginfod/debuginfod.cxx
> @@ -2996,8 +2996,6 @@ dwarf_extract_source_paths (Elf *elf, set& 
> debug_sourcefiles)
>
>if (comp_dir[0] == '\0' && cuname[0] != '/')
>  {
> -  // This is a common symptom for dwz-compressed debug files,
> -  // where the altdebug file cannot be resolved.
>if (verbose > 3)
>  obatched(clog) << "skipping cu=" << cuname << " due to empty 
> comp_dir" << endl;
>continue;
> diff --git a/doc/srcfiles.1 b/doc/srcfiles.1
> index 6149c21b..c6338315 100644
> --- a/doc/srcfiles.1
> +++ b/doc/srcfiles.1
> @@ -21,15 

Re: [PATCH] unstrip: Call adjust_relocs no more than once per section.

2024-02-06 Thread Aaron Merey
Hi Mark,

On Tue, Feb 6, 2024 at 10:36 AM Mark Wielaard  wrote:
>
> So it looks like elfcmp explicitly checks ebl_section_strip_p and
> doesn't compare sections that are strippable. Maybe we should add an
> eu-elfcmp --all-sections flag?
>
> We should probably also check that it handles the new SHT_RELR sections
> correctly. I see it only checks for SHT_REL and SHT_RELA in the code.
> Although RELR is really simple and doesn't have symbol references. So
> it is probably fine.

I added a PR for this: https://sourceware.org/bugzilla/show_bug.cgi?id=31345

> >  adjust_all_relocs (Elf *elf, Elf_Scn *symtab, const GElf_Shdr *symshdr,
> > -size_t map[], size_t map_size)
> > +size_t map[], size_t map_size, bool *scn_filter)
> >  {
>
> Maybe bool scn_filter[] since it really is an array?

Done.

> Looks good in general. Just clean up in the new testcase and run it
> with testrun.

Done. Pushed as commit 2f9b180cc1.

Aaron



[PATCH] Handle DW_AT_decl_file 0

2024-02-09 Thread Aaron Merey
Modify dwarf_decl_file to support DW_AT_decl_file with value 0.

Because of inconsistencies in the DWARF 5 spec, it is ambiguous whether
DW_AT_decl_file value 0 is a valid .debug_line file table index for the
main source file or if it means that there is no source file specified.

dwarf_decl_file interprets DW_AT_decl_file 0 as meaning no source file
is specified.  This works with DWARF 5 produced by gcc, which duplicates
the main source file name at index 0 and 1 of the file table and avoids
using DW_AT_decl_file 0.

However clang uses DW_AT_decl_file 0 for the main source index with no
duplication at another index.  In this case dwarf_decl_file will be
unable to find the file name of the main file.

This patch changes dwarf_decl_file to treat DW_AT_decl_file 0 as a normal
index into the file table, allowing it to work with DWARF 5 debuginfo
produced by clang.

As for earlier DWARF versions which exclusively use DW_AT_decl_file 0
to indicate that no source file is specified, dwarf_decl_file will now
return the name "???" if called on a DIE with DW_AT_decl_file 0.

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

Signed-off-by: Aaron Merey 
---
 libdw/dwarf_decl_file.c  |  25 ++---
 tests/Makefile.am|   3 ++-
 tests/run-allfcts.sh |  17 +
 tests/testfile-dwarf5-line-clang.bz2 | Bin 0 -> 2764 bytes
 4 files changed, 29 insertions(+), 16 deletions(-)
 create mode 100755 tests/testfile-dwarf5-line-clang.bz2

diff --git a/libdw/dwarf_decl_file.c b/libdw/dwarf_decl_file.c
index 75662a33..07b69f8d 100644
--- a/libdw/dwarf_decl_file.c
+++ b/libdw/dwarf_decl_file.c
@@ -31,7 +31,6 @@
 # include 
 #endif
 
-#include 
 #include 
 #include "libdwP.h"
 
@@ -48,13 +47,6 @@ dwarf_decl_file (Dwarf_Die *die)
   &idx) != 0)
 return NULL;
 
-  /* Zero means no source file information available.  */
-  if (idx == 0)
-{
-  __libdw_seterrno (DWARF_E_NO_ENTRY);
-  return NULL;
-}
-
   /* Get the array of source files for the CU.  */
   struct Dwarf_CU *cu = attr_mem.cu;
   if (cu->lines == NULL)
@@ -63,20 +55,23 @@ dwarf_decl_file (Dwarf_Die *die)
   size_t nlines;
 
   /* Let the more generic function do the work.  It'll create more
-data but that will be needed in an real program anyway.  */
+data but that will be needed in a real program anyway.  */
   (void) INTUSE(dwarf_getsrclines) (&CUDIE (cu), &lines, &nlines);
-  assert (cu->lines != NULL);
 }
 
-  if (cu->lines == (void *) -1l)
+  if (cu->lines == NULL || cu->lines == (void *) -1l)
 {
-  /* If the file index is not zero, there must be file information
-available.  */
-  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+  /* Line table could not be found.  */
   return NULL;
 }
 
-  assert (cu->files != NULL && cu->files != (void *) -1l);
+ if (cu->files == NULL || cu->files == (void *) -1l)
+{
+  /* If the line table was found then then the file table should
+have also been found.  */
+  __libdw_seterrno (DWARF_E_UNKNOWN_ERROR);
+  return NULL;
+}
 
   if (idx >= cu->files->nfiles)
 {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 13bd9d56..b075e3c3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -634,7 +634,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 testfile-largealign.o.bz2 run-strip-largealign.sh \
 run-funcretval++11.sh \
 test-ar-duplicates.a.bz2 \
-run-dwfl-core-noncontig.sh testcore-noncontig.bz2
+run-dwfl-core-noncontig.sh testcore-noncontig.bz2 \
+testfile-dwarf5-line-clang.bz2
 
 
 if USE_VALGRIND
diff --git a/tests/run-allfcts.sh b/tests/run-allfcts.sh
index 9c0a55d8..1d4766fe 100755
--- a/tests/run-allfcts.sh
+++ b/tests/run-allfcts.sh
@@ -170,4 +170,21 @@ testrun_compare ${abs_builddir}/allfcts testfile-lto-gcc9 
<<\EOF
 /home/mark/src/tests/testfile-lto-main.c:6:main
 EOF
 
+# = dwarf5-line.c =
+# int
+# main (int argc, char ** argv)
+# {
+#   return 0;
+# }
+
+# Using clang version 17.0.4 (Fedora 17.0.4-1.fc39)
+# clang -gdwarf-5 -O0 -o testfile-dwarf5-line-clang dwarf5-line.c
+
+testfiles testfile-dwarf5-line-clang
+
+# Check that dwarf_decl_file can handle .debug_line file table index 0
+testrun_compare ${abs_builddir}/allfcts testfile-dwarf5-line-clang <<\EOF
+/home/amerey/test/dwarf5-line.c:2:main
+EOF
+
 exit 0
diff --git a/tests/testfile-dwarf5-line-clang.bz2 
b/tests/testfile-dwarf5-line-clang.bz2
new file mode 100755
index 
..ab62b707bd7371268d6e685a2f86a1a3a868b0a9
GIT binary patch
literal 2764
zcmV;-3N!UWT4*^jL0KkKS?3bM4FC%f|NsC0|Nrmr|NH;%|NsBz|NsC0Y46D+q(klP
z_GEV7|6kwvWB?5S00E!|h!aMdntDLhJSItiq3U^0)f#B@ntFzs
z000kAWYa*NhhJXR4jD~;!41flWFeaKAGyq761dR-6)G8o+yQEuT0j3w

Re: [PATCH] Handle DW_AT_decl_file 0

2024-02-12 Thread Aaron Merey
Hi Mark,

On Mon, Feb 12, 2024 at 12:31 PM Mark Wielaard  wrote:
> >(void) INTUSE(dwarf_getsrclines) (&CUDIE (cu), &lines, &nlines);
> > -  assert (cu->lines != NULL);
> >  }
>
> I see why would like to get rid of asserts in the code base.
> But I believe the assert is valid. dwarf_getsrclines will check whether
> cu->lines is NULL, in which case it tries to load the line table. It
> then sets cu->lines to the newly parsed line table, or to -1 to
> indicate there was an error parsing (or no) line table.
> >
> > -  if (cu->lines == (void *) -1l)
> > +  if (cu->lines == NULL || cu->lines == (void *) -1l)
> >  {
> > -  /* If the file index is not zero, there must be file information
> > -  available.  */
> > -  __libdw_seterrno (DWARF_E_INVALID_DWARF);
> > +  /* Line table could not be found.  */
> >return NULL;
> >  }
>
> Which means this is a change in behavior. Now if there was no line
> table, or a problem parsing it, then no error is set, but NULL is
> returned anyway. Which means using dwarf_errno or dwarf_errmsg after
> dwarf_decl_file returns NULL doesn't work reliably anymore. Are you
> sure libdw errno shouldn't be set to DWARF_E_INVALID_DWARF?

My thinking was to rely on dwarf_getsrclines setting the libdw errno
if an error occurred.  If we always use DWARF_E_INVALID_DWARF then we
might overwrite an error code that describes the failure more specifically.

If we want to ensure that the libdw errno is set whenever we reach this
condition, we could check if dwarf_getsrclines set the errno. If it did,
then just leave that errno set. If it didn't, then set errno to
DWARF_E_INVALID_DWARF.

>> > -  assert (cu->files != NULL && cu->files != (void *) -1l);
> > + if (cu->files == NULL || cu->files == (void *) -1l)
> > +{
> > +  /* If the line table was found then then the file table should
> > +  have also been found.  */
> > +  __libdw_seterrno (DWARF_E_UNKNOWN_ERROR);
> > +  return NULL;
> > +}
> >
>
> I think if you are going to replace the assert here, then it should
> (also) be DWARF_E_INVALID_DWARF. It means a decl_file was given, but
> there is no file table. Which IMHO is invalid. Just like in the case
> below:
>
> >
> >if (idx >= cu->files->nfiles)
> >  {
>
> Here we also set DWARF_E_INVALID_DWARF because the decl_file number is
> larger than the number of files in the file table.

Ok, fixed.

> > --- a/tests/run-allfcts.sh
> > +++ b/tests/run-allfcts.sh
> > @@ -170,4 +170,21 @@ testrun_compare ${abs_builddir}/allfcts 
> > testfile-lto-gcc9 <<\EOF
> >  /home/mark/src/tests/testfile-lto-main.c:6:main
> >  EOF
> >
> > +# = dwarf5-line.c =
> > +# int
> > +# main (int argc, char ** argv)
> > +# {
> > +#   return 0;
> > +# }
> > +
> > +# Using clang version 17.0.4 (Fedora 17.0.4-1.fc39)
> > +# clang -gdwarf-5 -O0 -o testfile-dwarf5-line-clang dwarf5-line.c
>
> Does it need to be -O0? Not that I really object. Just hoping to get a
> slightly smaller binary/testfile with -O1 or -O2.

It doesn't need to be -O0.  I'll just leave out -O altogether.

Aaron



Re: [PATCH] Handle DW_AT_decl_file 0

2024-02-12 Thread Aaron Merey
Hi Mark,

On Mon, Feb 12, 2024 at 4:14 PM Mark Wielaard  wrote:
>
> On Mon, Feb 12, 2024 at 01:16:30PM -0500, Aaron Merey wrote:
> > On Mon, Feb 12, 2024 at 12:31 PM Mark Wielaard  wrote:
> > > >(void) INTUSE(dwarf_getsrclines) (&CUDIE (cu), &lines, &nlines);
> > > > -  assert (cu->lines != NULL);
> > > >  }
> > >
> > > I see why would like to get rid of asserts in the code base.
> > > But I believe the assert is valid. dwarf_getsrclines will check whether
> > > cu->lines is NULL, in which case it tries to load the line table. It
> > > then sets cu->lines to the newly parsed line table, or to -1 to
> > > indicate there was an error parsing (or no) line table.
> > > >
> > > > -  if (cu->lines == (void *) -1l)
> > > > +  if (cu->lines == NULL || cu->lines == (void *) -1l)
> > > >  {
> > > > -  /* If the file index is not zero, there must be file information
> > > > -  available.  */
> > > > -  __libdw_seterrno (DWARF_E_INVALID_DWARF);
> > > > +  /* Line table could not be found.  */
> > > >return NULL;
> > > >  }
> > >
> > > Which means this is a change in behavior. Now if there was no line
> > > table, or a problem parsing it, then no error is set, but NULL is
> > > returned anyway. Which means using dwarf_errno or dwarf_errmsg after
> > > dwarf_decl_file returns NULL doesn't work reliably anymore. Are you
> > > sure libdw errno shouldn't be set to DWARF_E_INVALID_DWARF?
> >
> > My thinking was to rely on dwarf_getsrclines setting the libdw errno
> > if an error occurred.  If we always use DWARF_E_INVALID_DWARF then we
> > might overwrite an error code that describes the failure more specifically.
>
> Ah, yes. That makes sense. But because of caching dwarf_getsrclines
> only sets an error on first try.
>
> > If we want to ensure that the libdw errno is set whenever we reach this
> > condition, we could check if dwarf_getsrclines set the errno. If it did,
> > then just leave that errno set. If it didn't, then set errno to
> > DWARF_E_INVALID_DWARF.
>
> Good idea. Or we could (also) cache the error in the cu
> (files_libdwerr?), that is what e.g. dwfl_module_getdwarf does
> (see mod->dwerr). But I think either solution is more like a
> redesign/factoring. And you might consider doing it separate from this
> bug fix.
>
> If you have time, you could then also look into this
> (performance/caching) issue:
> https://sourceware.org/bugzilla/show_bug.cgi?id=27405
> "libdw_get_srcfiles should not imply srclines"

Ok I'll look at PR27405.  I've removed the error handling changes from
this patch.  I also recompiled the testfile without -O0. It didn't end up
improving the size of the testfile but the -O0 was unnecessary either way.

Pushed as commit add63e0317b6e.

Aaron



Preparing for the 0.191 release on Friday March 1

2024-02-14 Thread Aaron Merey
Hi everyone,

We are planning to do the 0.191 release on Friday March 1.

Since the 0.190 release last November, there have been 31 commits.
Among these are some important bug fixes and new features.

If your patch is still under review [1] or you have other patches
you'd like merged before the release, please let us know.

Aaron

[1] https://patchwork.sourceware.org/project/elfutils/list/



Re: [PATCH v2] dwarf_getaranges: Build aranges list from CUs instead of .debug_aranges

2024-02-19 Thread Aaron Merey
Hi Mark,

On Tue, Feb 13, 2024 at 8:28 AM Mark Wielaard  wrote:
>
> > This patch's method of building the aranges list is slower than simply
> > reading .debug_aranges.  On my machine, running eu-stack on a 2.9G
> > firefox core file takes about 8.7 seconds with this patch applied,
> > compared to about 3.3 seconds without this patch.
>
> That is significant. 2.5 times slower.
> Did you check with perf or some other profiler where exactly the extra
> time goes. Does the new method find more aranges (and so produces
> "better" backtraces)?

I took another look at the performance and realized I made a silly
mistake when I originally tested this.  My build that was 2.5x slower
was compiled with -O0 but I tested it against an -O2 build.  Oops!

With the optimization level set to -O2 in all cases, the runtime of
'eu-stack -s' on the original 2.9G firefox core file is only about
9% slower: 3.6 seconds with the patch applied compared to 3.3
seconds without the patch.

As for the number of aranges found, there is a difference for libxul.so:
250435 with the patch compared to 254832 without.  So 4397 fewer aranges
are found when using the new CU iteration method.  I'll dig into this and
see if there is a problem or if it's just due to some redundancy in
libxul's .debug_aranges.  FWIW there was no change to the aranges counts
for the other modules searched during this eu-stack firefox corefile test.

>
> > Ideally we could assume that .debug_aranges is complete if it is present
> > and build the aranges list via CU iteration only when .debug_aranges
> > is absent.  This would let us save time on gcc-compiled binaries, which
> > include complete .debug_aranges by default.
>
> Right. This why the question is if the firefox case sees more/less
> aranges. If I remember correctly it is build with gcc and rustc, and
> rustc might not produce .debug_aranges.
>
> > However the DWARF spec appears to permit partially complete
> > .debug_aranges [1].  We could improve performance by starting with a
> > potentially incomplete list built from .debug_aranges.  If a lookup
> > fails then search the CUs for missing aranges and add to the list
> > when found.
> >
> > This approach would complicate the dwarf_get_aranges interface.  The
> > list it initially provides could no longer be assumed to be complete.
> > The number of elements in the list could change during calls to
> > dwarf_getarange{info, _addr}.  This would invalidate the naranges value
> > set by dwarf_getaranges.  The current API doesn't include a way to
> > communicate to the caller when narages changes and by how much.
> >
> > Due to these complications I think it's better to simply ignore
> > .debug_aranges altogether and build the aranges table via CU iteration,
> > as is done in this patch.
>
> Might it be an idea to leave dwarf_getaranges as it is and introduce a
> new (internal) function to get "dynamic" ranges? It looks like what
> programs (like eu-stack and eu-addr2line) really use is dwarf_addrdie
> and dwfl_module_addrdie. These are currently build on dwarf_getaranges,
> but could maybe use a new interface?

IMO this depends on what users expect from dwarf_getaranges.  Do they
want the exact contents of .debug_aranges (whether or not it's complete)
or should dwarf_getaranges go beyond .debug_aranges to ensure the most
complete results?

The comment for dwarf_getaranges in libdw.h simply reads "Return list
address ranges".  Since there's no mention of .debug_aranges specifically,
I think it's fair if dwarf_getaranges does whatever it can to ensure
comprehensive results.  In which case dwarf_getaranges should probably
dynamically generate aranges.

Aaron



Re: [PATCH v2] dwarf_getaranges: Build aranges list from CUs instead of .debug_aranges

2024-02-21 Thread Aaron Merey
Hi Mark,

On Tue, Feb 20, 2024 at 5:23 PM Mark Wielaard  wrote:
>
> > As for the number of aranges found, there is a difference for libxul.so:
> > 250435 with the patch compared to 254832 without.  So 4397 fewer aranges
> > are found when using the new CU iteration method.  I'll dig into this and
> > see if there is a problem or if it's just due to some redundancy in
> > libxul's .debug_aranges.  FWIW there was no change to the aranges counts
> > for the other modules searched during this eu-stack firefox corefile test.
>
> A quick way to see where the differences are is using
> eu-readelf --debug-dump=decodedaranges before/after your patch.
>
> This is opposite to what I expected. I had expected there to be more,
> instead of less ranges. The difference is less than 2%. But still
> interesting to know what/why.
>
> Were there any differences in the backtraces? If not, then those
> ranges might not actually have been mapping to code.

The backtraces were identical.  I took a closer look at this and the
difference is due to clang including DW_AT_location addresses in
.debug_aranges.  This patch just looks for DW_AT_{high,low}_pc and
DW_AT_ranges (via dwarf_ranges) when generating the aranges list,
so these DW_AT_location addresses aren't included.

According to David Blaikie [1], "GCC does not include globals in
debug_aranges, so they probably can't be relied upon unfortunately
(unfortunate that Clang pays the cost when it emits them, but consumers
can't rely on them)".

Since consumers already can't assume that .debug_aranges includes
DW_AT_location addresses, I think it's reasonable for us to not include
them when dynamically generating aranges.  Especially since there could
be a noticeable performance cost to doing so.

A separate issue I saw is that some entries in .debug_aranges with
a decoded start address of "00" wouldn't always
have matching entries in .debug_ranges.  This resulted in some dynamic
aranges not matching their corresponding .debug_aranges entry.

For example, the following decoded arange is in libxul's .debug_aranges:

start: 00, length:13, CU DIE offset: 95189496

In the .debug_info for this CU, there is a corresponding subprogram with
low_pc 0 and high_pc 13.

However in the .debug_ranges entry for this CU, there is no range starting
at address 0 with size of at least 13.  The closest range list entry is:

range 1, 1
+0x0001 <__ehdr_start+0x1>..
+00 

When we dynamically generate aranges this results in the following
decoded arange:

start: 0x0001, length: 0, CU DIE offset: 95189496

So the start address is off by 1 and the length doesn't match the
.debug_aranges entry.  In some similar cases there wouldn't even be
a corresponding "range 1, 1" entry in .debug_ranges.  I'm not yet sure
what's going on here.

>
> > > Might it be an idea to leave dwarf_getaranges as it is and introduce a
> > > new (internal) function to get "dynamic" ranges? It looks like what
> > > programs (like eu-stack and eu-addr2line) really use is dwarf_addrdie
> > > and dwfl_module_addrdie. These are currently build on dwarf_getaranges,
> > > but could maybe use a new interface?
> >
> > IMO this depends on what users expect from dwarf_getaranges.  Do they
> > want the exact contents of .debug_aranges (whether or not it's complete)
> > or should dwarf_getaranges go beyond .debug_aranges to ensure the most
> > complete results?
> >
> > The comment for dwarf_getaranges in libdw.h simply reads "Return list
> > address ranges".  Since there's no mention of .debug_aranges specifically,
> > I think it's fair if dwarf_getaranges does whatever it can to ensure
> > comprehensive results.  In which case dwarf_getaranges should probably
> > dynamically generate aranges.
>
> You might be right that no user really cares. But as seen in the
> eu-readelf code, it might also be that people expected it to map to
> the ranges from .debug_aranges.
>
> So I would be happier if we just kept the dwarf_getaranges code as
> is. And just change the code in dwarf_addrdie and dwfl_module_addrdie.
>
> We could then also introduce a new public function, dwarf_getdieranges
> (?) that does the new thing. But it doesn't have to be public on the
> first try as long as dwarf_addrdie and dwfl_module_addrdie work. (We
> might want to change the interface of dwarf_getdieranges so it can be
> "lazy" for example.)

Ok this approach seems like the most flexible.  Users can have both
.debug_aranges and CU-based aranges plus we don't have to change the
semantics of dwarf_getaranges.  I'll submit a revised patch for this.

Aaron

[1] https://reviews.llvm.org/D123538#inline-1188522



Re: [PATCH v2] dwarf_getaranges: Build aranges list from CUs instead of .debug_aranges

2024-02-22 Thread Aaron Merey
Hi Frank,

On Thu, Feb 22, 2024 at 10:35 AM Frank Ch. Eigler  wrote:
>
> > > We could then also introduce a new public function, dwarf_getdieranges
> > > (?) that does the new thing. But it doesn't have to be public on the
> > > first try as long as dwarf_addrdie and dwfl_module_addrdie work. (We
> > > might want to change the interface of dwarf_getdieranges so it can be
> > > "lazy" for example.)
> >
> > Ok this approach seems like the most flexible.  Users can have both
> > .debug_aranges and CU-based aranges plus we don't have to change the
> > semantics of dwarf_getaranges.  [...]
>
> Another option is to generate the .debug_aranges automatically, but
> only if it is absent from the input dwarf file.  (An eu-readelf user
> can tell if it was synthetic or not, if it matters.)

I'd like to be able to do this but .debug_aranges might be incomplete
even if the section is present in the input file.  This would require
us to parse CUs anyways in order to verify the section's completeness.

I'll defer to David Blaikie [1] again: "consumers shouldn't rely on the
presence of .debug_aranges, or them being complete (DWARF doesn't
require/guarantee this - and Clang doesn't emit aranges by default, for
instance). Each contribution to .debug_aranges says which CU it covers
and any CUs not covered should be parsed/assumed to contain things
covering other addresses."

Aaron

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=22288#c5



[PATCH] Add __libdw_getdieranges

2024-02-26 Thread Aaron Merey
__libdw_getdieranges builds an aranges list by iterating over CUs and
recording each address range.

__libdw_getdieranges provides an alternative to relying on .debug_aranges
for address ranges, since this section might be absent or incomplete.

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

Signed-off-by: Aaron Merey 
---

Once this function's interface is refined it can be added to the public
libdw API.  We might add some form of lazy loading, for example.

I mentioned [1] that there are some clang-compiled shared libraries
where some subprograms starting at address 0 don't have a corresponding
entry in .debug_ranges (for a CU that contains DW_AT_ranges). These
address ranges with no corresponding entry in .debug_ranges won't be
included in the aranges generated by this patch's CU iteration approach.

[1] https://sourceware.org/pipermail/elfutils-devel/2024q1/006832.html

 libdw/dwarf_addrdie.c|   2 +-
 libdw/dwarf_getaranges.c | 190 ++-
 libdw/libdwP.h   |  13 ++-
 libdwfl/cu.c |   8 +-
 tests/run-getsrc-die.sh  |   5 ++
 5 files changed, 169 insertions(+), 49 deletions(-)

diff --git a/libdw/dwarf_addrdie.c b/libdw/dwarf_addrdie.c
index 3a08ab75..48a1aaea 100644
--- a/libdw/dwarf_addrdie.c
+++ b/libdw/dwarf_addrdie.c
@@ -41,7 +41,7 @@ dwarf_addrdie (Dwarf *dbg, Dwarf_Addr addr, Dwarf_Die *result)
   size_t naranges;
   Dwarf_Off off;
 
-  if (INTUSE(dwarf_getaranges) (dbg, &aranges, &naranges) != 0
+  if (__libdw_getdieranges (dbg, &aranges, &naranges) != 0
   || INTUSE(dwarf_getarangeinfo) (INTUSE(dwarf_getarange_addr) (aranges,
addr),
  NULL, NULL, &off) != 0)
diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c
index 27439d37..41fe96d0 100644
--- a/libdw/dwarf_getaranges.c
+++ b/libdw/dwarf_getaranges.c
@@ -33,7 +33,6 @@
 #endif
 
 #include 
-#include 
 #include "libdwP.h"
 #include 
 
@@ -54,6 +53,149 @@ compare_aranges (const void *a, const void *b)
   return 0;
 }
 
+/* Convert ARANGELIST into Dwarf_Aranges and store at ARANGES.  */
+static bool
+finalize_aranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges,
+ struct arangelist *arangelist, unsigned int narangelist)
+{
+  /* Allocate the array for the result.  */
+  void *buf = libdw_alloc (dbg, Dwarf_Aranges,
+  sizeof (Dwarf_Aranges)
+  + narangelist * sizeof (Dwarf_Arange), 1);
+
+  /* First use the buffer for the pointers, and sort the entries.
+ We'll write the pointers in the end of the buffer, and then
+ copy into the buffer from the beginning so the overlap works.  */
+  eu_static_assert (sizeof (Dwarf_Arange) >= sizeof (Dwarf_Arange *));
+  struct arangelist **sortaranges
+= (buf + sizeof (Dwarf_Aranges)
+   + ((sizeof (Dwarf_Arange) - sizeof sortaranges[0]) * narangelist));
+
+  /* The list is in LIFO order and usually they come in clumps with
+ ascending addresses.  So fill from the back to probably start with
+ runs already in order before we sort.  */
+  unsigned int i = narangelist;
+  while (i-- > 0)
+{
+  sortaranges[i] = arangelist;
+  arangelist = arangelist->next;
+}
+
+  /* Something went wrong if narangelist is less then the actual length
+ of arangelist. */
+  if (arangelist != NULL)
+{
+  __libdw_seterrno (DWARF_E_UNKNOWN_ERROR);
+  return false;
+}
+
+  /* Sort by ascending address.  */
+  qsort (sortaranges, narangelist, sizeof sortaranges[0], &compare_aranges);
+
+  /* Now that they are sorted, put them in the final array.
+ The buffers overlap, so we've clobbered the early elements
+ of SORTARANGES by the time we're reading the later ones.  */
+  *aranges = buf;
+  (*aranges)->dbg = dbg;
+  (*aranges)->naranges = narangelist;
+  if (naranges != NULL)
+*naranges = narangelist;
+  for (i = 0; i < narangelist; ++i)
+{
+  struct arangelist *elt = sortaranges[i];
+  (*aranges)->info[i] = elt->arange;
+  free (elt);
+}
+
+  return true;
+}
+
+int
+__libdw_getdieranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges)
+{
+  if (dbg == NULL)
+return -1;
+
+  if (dbg->dieranges != NULL)
+{
+  *aranges = dbg->dieranges;
+  if (naranges != NULL)
+   *naranges = dbg->dieranges->naranges;
+  return 0;
+}
+
+  struct arangelist *arangelist = NULL;
+  unsigned int narangelist = 0;
+
+  Dwarf_CU *cu = NULL;
+  while (INTUSE(dwarf_get_units) (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
+{
+  Dwarf_Addr base;
+  Dwarf_Addr low;
+  Dwarf_Addr high;
+
+  Dwarf_Die cudie = CUDIE (cu);
+
+  /* Skip CUs that only contain type information.  */
+  if (!INTUSE(dwarf

[PATCH v2] Add __libdw_getdieranges

2024-02-27 Thread Aaron Merey
__libdw_getdieranges builds an aranges list by iterating over each
CU and recording each address range.

This function is an alternative to dwarf_getaranges.  dwarf_getaranges
attempts to read address ranges from .debug_aranges, which might be
absent or incomplete.

This patch replaces dwarf_getaranges with __libdw_getdieranges in
dwarf_addrdie and dwfl_module_addrdie.  The existing tests in
run-getsrc-die.sh are also rerun with .debug_aranges removed from
the testfiles.

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

Signed-off-by: Aaron Merey 
---

v2 addresses feedback from Mark's review:
https://sourceware.org/pipermail/elfutils-devel/2024q1/006853.html

Avoid calling free on arangelist when it's possibly corrupt.
Run tests in run-getsrc-die.sh twice, once with .debug_aranges
present in the testfile and once with the section removed.

 libdw/dwarf_addrdie.c|   2 +-
 libdw/dwarf_getaranges.c | 186 ++-
 libdw/libdwP.h   |  13 ++-
 libdwfl/cu.c |   8 +-
 tests/run-getsrc-die.sh  |  22 -
 5 files changed, 179 insertions(+), 52 deletions(-)

diff --git a/libdw/dwarf_addrdie.c b/libdw/dwarf_addrdie.c
index 3a08ab75..48a1aaea 100644
--- a/libdw/dwarf_addrdie.c
+++ b/libdw/dwarf_addrdie.c
@@ -41,7 +41,7 @@ dwarf_addrdie (Dwarf *dbg, Dwarf_Addr addr, Dwarf_Die *result)
   size_t naranges;
   Dwarf_Off off;
 
-  if (INTUSE(dwarf_getaranges) (dbg, &aranges, &naranges) != 0
+  if (__libdw_getdieranges (dbg, &aranges, &naranges) != 0
   || INTUSE(dwarf_getarangeinfo) (INTUSE(dwarf_getarange_addr) (aranges,
addr),
  NULL, NULL, &off) != 0)
diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c
index 27439d37..7a3cd36b 100644
--- a/libdw/dwarf_getaranges.c
+++ b/libdw/dwarf_getaranges.c
@@ -33,7 +33,6 @@
 #endif
 
 #include 
-#include 
 #include "libdwP.h"
 #include 
 
@@ -54,6 +53,147 @@ compare_aranges (const void *a, const void *b)
   return 0;
 }
 
+/* Convert ARANGELIST into Dwarf_Aranges and store at ARANGES.  */
+static bool
+finalize_aranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges,
+ struct arangelist *arangelist, unsigned int narangelist)
+{
+  /* Allocate the array for the result.  */
+  void *buf = libdw_alloc (dbg, Dwarf_Aranges,
+  sizeof (Dwarf_Aranges)
+  + narangelist * sizeof (Dwarf_Arange), 1);
+
+  /* First use the buffer for the pointers, and sort the entries.
+ We'll write the pointers in the end of the buffer, and then
+ copy into the buffer from the beginning so the overlap works.  */
+  eu_static_assert (sizeof (Dwarf_Arange) >= sizeof (Dwarf_Arange *));
+  struct arangelist **sortaranges
+= (buf + sizeof (Dwarf_Aranges)
+   + ((sizeof (Dwarf_Arange) - sizeof sortaranges[0]) * narangelist));
+
+  /* The list is in LIFO order and usually they come in clumps with
+ ascending addresses.  So fill from the back to probably start with
+ runs already in order before we sort.  */
+  unsigned int i = narangelist;
+  while (i-- > 0)
+{
+  sortaranges[i] = arangelist;
+  arangelist = arangelist->next;
+}
+
+  /* Something went wrong if narangelist is less then the actual length
+ of arangelist. */
+  if (arangelist != NULL)
+{
+  __libdw_seterrno (DWARF_E_UNKNOWN_ERROR);
+  return false;
+}
+
+  /* Sort by ascending address.  */
+  qsort (sortaranges, narangelist, sizeof sortaranges[0], &compare_aranges);
+
+  /* Now that they are sorted, put them in the final array.
+ The buffers overlap, so we've clobbered the early elements
+ of SORTARANGES by the time we're reading the later ones.  */
+  *aranges = buf;
+  (*aranges)->dbg = dbg;
+  (*aranges)->naranges = narangelist;
+  if (naranges != NULL)
+*naranges = narangelist;
+  for (i = 0; i < narangelist; ++i)
+{
+  struct arangelist *elt = sortaranges[i];
+  (*aranges)->info[i] = elt->arange;
+  free (elt);
+}
+
+  return true;
+}
+
+int
+__libdw_getdieranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges)
+{
+  if (dbg == NULL)
+return -1;
+
+  if (dbg->dieranges != NULL)
+{
+  *aranges = dbg->dieranges;
+  if (naranges != NULL)
+   *naranges = dbg->dieranges->naranges;
+  return 0;
+}
+
+  struct arangelist *arangelist = NULL;
+  unsigned int narangelist = 0;
+
+  Dwarf_CU *cu = NULL;
+  while (INTUSE(dwarf_get_units) (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
+{
+  Dwarf_Addr base;
+  Dwarf_Addr low;
+  Dwarf_Addr high;
+
+  Dwarf_Die cudie = CUDIE (cu);
+
+  /* Skip CUs that only contain type information.  */
+  if (!INTUSE(dwarf_hasattr) (&cudie, DW_AT_low_pc)
+   

[COMMITTED] tests/run-getsrc-die.sh: Skip tests if objcopy fails

2024-02-29 Thread Aaron Merey
run-getsrc-die.sh uses objcopy to remove .debug_aranges from testfiles.
Depending how objcopy is built, it may fail to recognize the format of
the testfiles.  Skip the remaining tests if objcopy fails.

Signed-off-by: Aaron Merey 
---
 tests/run-getsrc-die.sh | 36 
 1 file changed, 20 insertions(+), 16 deletions(-)

diff --git a/tests/run-getsrc-die.sh b/tests/run-getsrc-die.sh
index 54c7ad8c..6740e5d9 100755
--- a/tests/run-getsrc-die.sh
+++ b/tests/run-getsrc-die.sh
@@ -22,23 +22,17 @@
 # which uses dwfl_module_getsrc. This test uses dwarf_addrdie and
 # dwarf_getsrc_die
 testfiles testfile testfile-inlines testfile-lex-inlines
-tempfiles testfile-no-aranges testfile-inlines-no-aranges
-tempfiles testfile-lex-inlines-no-aranges good.out getsrc_die.out
+tempfiles testfile-no-aranges testfile-inlines-no-aranges getsrc_die.out
+tempfiles testfile-lex-inlines-no-aranges good1.out good2.out good3.out
 
-# Each test should also pass with no .debug_aranges present.
-objcopy --remove-section .debug_aranges testfile testfile-no-aranges
-objcopy --remove-section .debug_aranges testfile-inlines 
testfile-inlines-no-aranges
-objcopy --remove-section .debug_aranges testfile-lex-inlines 
testfile-lex-inlines-no-aranges
-
-cat > good.out <<\EOF
+cat > good1.out <<\EOF
 /home/drepper/gnu/new-bu/build/ttt/f.c:3
 /home/drepper/gnu/new-bu/build/ttt/b.c:4
 EOF
 
-cat good.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die testfile 
0x08048468 0x0804845c
-cat good.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die 
testfile-no-aranges 0x08048468 0x0804845c
+cat good1.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die testfile 
0x08048468 0x0804845c
 
-cat > good.out <<\EOF
+cat > good2.out <<\EOF
 /tmp/x.cpp:5
 /tmp/x.cpp:6
 /tmp/x.cpp:10
@@ -51,17 +45,27 @@ cat > good.out <<\EOF
 /tmp/x.cpp:5
 EOF
 
-cat good.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die 
testfile-inlines 0x05a0 0x05a1 0x05b0 
0x05b1 0x05c0 0x05d0 0x05e0 
0x05e1 0x05f1 0x05f2
-cat good.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die 
testfile-inlines-no-aranges 0x05a0 0x05a1 
0x05b0 0x05b1 0x05c0 0x05d0 
0x05e0 0x05e1 0x05f1 0x05f2
+cat good2.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die 
testfile-inlines 0x05a0 0x05a1 0x05b0 
0x05b1 0x05c0 0x05d0 0x05e0 
0x05e1 0x05f1 0x05f2
 
-cat > good.out <<\EOF
+cat > good3.out <<\EOF
 /tmp/x.cpp:5
 /tmp/x.cpp:5
 /tmp/x.cpp:5
 /tmp/x.cpp:5
 EOF
 
-cat good.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die 
testfile-lex-inlines 0x0680 0x0681 0x0690 
0x0691
-cat good.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die 
testfile-lex-inlines-no-aranges 0x0680 0x0681 
0x0690 0x0691
+cat good3.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die 
testfile-lex-inlines 0x0680 0x0681 0x0690 
0x0691
+
+# Each test should also pass with no .debug_aranges present.  If objcopy cannot
+# strip the testfiles then skip the remaining tests.
+objcopy --remove-section .debug_aranges testfile testfile-no-aranges || exit 0
+objcopy --remove-section .debug_aranges testfile-inlines 
testfile-inlines-no-aranges || exit 0
+objcopy --remove-section .debug_aranges testfile-lex-inlines 
testfile-lex-inlines-no-aranges || exit 0
+
+cat good1.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die 
testfile-no-aranges 0x08048468 0x0804845c
+
+cat good2.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die 
testfile-inlines-no-aranges 0x05a0 0x05a1 
0x05b0 0x05b1 0x05c0 0x05d0 
0x05e0 0x05e1 0x05f1 0x05f2
+
+cat good3.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die 
testfile-lex-inlines-no-aranges 0x0680 0x0681 
0x0690 0x0691
 
 exit 0
-- 
2.43.0



elfutils 0.191 released

2024-03-01 Thread Aaron Merey
ELFUTILS 0.191 "Bug fixes in C major" - https://elfutils.org/

A new release of elfutils is available at:
ftp://sourceware.org/pub/elfutils/0.191/
or https://sourceware.org/elfutils/ftp/0.191/

Visit us on the Libera.Chat irc channel #elfutils

* NEWS *

libdw: dwarf_addrdie now supports binaries lacking a .debug_aranges
   section.

Improved support for DWARF package files.  Add new function
   dwarf_cu_dwp_section_info.

debuginfod: Caching eviction logic improvements to improve retention
   of small/frequent/slow files such as Fedora's vdso.debug.

srcfiles: Can now fetch the source files of a DWARF/ELF file and
   place them into a zip.

* GIT SHORTLOG *

Aaron Merey (9):
  libdwfl: Correctly handle corefile non-contiguous segments
  libdw: Use INTUSE with dwarf_get_units
  debuginfod.cxx: Restore comment
  Revert "debuginfod.cxx: Restore comment"
  unstrip: Call adjust_relocs no more than once per section.
  Handle DW_AT_decl_file 0
  Add __libdw_getdieranges
  tests/run-getsrc-die.sh: Skip tests if objcopy fails
  Prepare for 0.191

Aleksei Vetrov (4):
  libdw: check offset dwarf_formstring in all cases
  libdwfl: handle duplicate ELFs when reporting archives
  tests: Add test for duplicate entries in archive
  libelf: check decompressed ZSTD size

Frank Ch. Eigler (4):
  doc/debuginfod.8: clarify source file handling
  PR31248: debuginfod_find_*: lseek to the front on returned fds
  debuginfod.8 man page: tweak -U explanation
  PR31265 - rework debuginfod archive-extract fdcache

Housam Alamour (1):
  PR 30991: srcfiles tarball feature

Khem Raj (1):
  Add helper function for basename

Mark Wielaard (17):
  elfutils.spec: Add eu-srcfiles and add new make rpmbuild target
  backends: Fix arm_machine_flag_name version string.
  rpmbuild: fix Makefile rules
  libelf: Fix possible memory leak in elf_getdata_rawchunk
  libelf: Fix elf_begin.c build on 32bit arches.
  tests: Restructure run-debuginfod-response-headers.sh
  readelf: Don't print average number of tests when no tests are done
  tests: Don't redirect output to /dev/null in run-native-test.sh
  libdwfl: Add some extra space to buffer to read kernel image header
  libelf: Treat elf_memory as if using ELF_C_READ_MMAP
  srcfiles: Fix --enable-gcov (BUILD_STATIC) build
  NEWS: Update version number and remove duplicate 0.190 entry
  libdw: Update dwarf_cu_dwp_section_info documentation
  libebl: ebl_object_note print 32bit annobin address ranges correctly
  readelf: Use unsigned loop variables in handle_verneed and
handle_verdef
  libdw: Initialize tu_offset in __libdw_package_index
      GPG-KEY: Add key for Aaron Merey

Omar Sandoval (6):
  libdw: Parse DWARF package file index sections
  libdw: Try .dwp file in __libdw_find_split_unit()
  libdw: Handle split DWARF in dwarf_decl_file
  libdw: Refactor dwarf_next_lines and fix skipped CU
  libdw: Apply DWARF package file section offsets where appropriate
  libdw: Handle overflowed DW_SECT_INFO offsets in DWARF package file
indexes

Paul Pluzhnikov (2):
  Fix computations with (potentially) NULL pointer
  Minor: include  for uintptr_t

Sergei Trofimovich (1):
  tests: fix build against upcoming
`gcc-14` (`-Werror=calloc-transposed-args`)

Xi Ruoyao (2):
  libelf: Sync elf.h from glibc
  backends: Update list of LoongArch relocations
-BEGIN PGP PUBLIC KEY BLOCK-
 
mQENBGXb21kBCADCyOpVSfJ6XHVp8+dspYCgkSwr26IF+SXHzt9dVyMChAKJIXib
ty8NA/Huh3ZRNzFXdFM09yoYiglnYu3+r1rniliP1L1w3y0tDNxlvlLmVhM5WAfA
IyZ9tI8X1XIfRLYsX70UM3jDvyoXkEQkjhQKDHrgBdBTNARHlHVykj44xD2TCwao
vV0gFu2EmCN8TsMWLdQ1VymtYd/UFB6znlLzSglzzx4OYKyla6anbWqKxvB3siIH
Pf/ULBh0JNTluH39kk486yE9Lh1z9H8FoVlUWcXvlr0rmPPQDl9se02bkd4rA/gD
kRQmlUXxJIJCNYZiQ7k0nZSYQY6JzhY1szBLABEBAAG0H0Fhcm9uIE1lcmV5IDxh
bWVyZXlAcmVkaGF0LmNvbT6JAVEEEwEIADsWIQRsK2MVY7jTMFeNPLR0/T+id55w
cwUCZdvbWQIbAwULCQgHAgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRB0/T+id55w
cxHiCAC9evJD8CqSPOfuKFa2iITLoSM2ORdpsp5Wla9OpAV5GnUNKbR7KCLoG7OQ
3Tth9qdHqrCIUigvj2xzcaovdyVRpDLBFG5cbrBB7Jqly0ptJhFUtx8wbDBammZq
7ZAsLFP582ILqlLjcTIOUNk4ABuTDN9FIdewgWXMW7GPp5euJ4ucos2glySwLbC4
+6kZ1guYYbO3S9YWWyImP2Guf4KVi5kTF0USTklvszJLvwJNkYknQhxnDcWLeOPJ
P4hOdHlwJSsaXcKyOn//FdMXRGDcknKcn43e03esXjflvz8HyXz4VbjEqDpOHS9i
l/NOw6+C7+wcAvHDu583cMbuI7hziEYEEBEIAAYFAmXiB7IACgkQVZbdDOm/ZT2Q
fwCfQSmNDkHu3ZxwvWs+mOFaYR3PGRAAnieQMVnPZd8kgGkVO/GNIJIBeuA7iF0E
EBECAB0WIQRBoMESdLHof+KOTFPj134flRYZkQUCZeIIBAAKCRDj134flRYZkX4N
AJ0Q8p1f7lmWgiHaHmD3DtuJ7uhWHACgk84evo0UsqVNi/4xHZ0wpVvxx+S5AQ0E
ZdvbWQEIAKgzEcJMUfFgsUGwMO/I4mwjvB7+Jx90lSYjS3uM7E3jnYhu/en42skl
nYEMxMR9EWUF6RZ78QiUvD/Ik6fP0YrMuTRBnZ7ZOd5zLPbgDIAOVeiVxFRwGOzj
z01V/plDlz+zCQkS1tOPgpGKCzTol7/M9ks9AHqKE6DWrrk1LbER2qDyE6XMAe5b
LNqdmtfJ2uf2XPThGGz0ujJ0MdistoRMechX9qBIBaLwxuA5edx+3iu6MdjMCeua
yV+Yb4ePG+9IY3OmdC/3wNpJYOQvS

Re: [PATCH] Getter and setter for Dwfl's offline_next_address

2024-03-15 Thread Aaron Merey
Hi Martin,

On Wed, Mar 6, 2024 at 2:23 PM Martin Rodriguez Reboredo
 wrote:
>
> diff --git a/tests/dwfl-offline-address.c b/tests/dwfl-offline-address.c
> new file mode 100644
> index ..9a33b95a
> --- /dev/null
> +++ b/tests/dwfl-offline-address.c
> @@ -0,0 +1,43 @@
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include ELFUTILS_HEADER(dwfl)
> +#include 
> +#include "system.h"
> +
> +#define OFFLINE_REDZONE 0x1
> +
> +static const Dwfl_Callbacks offline_callbacks =
> +  {
> +.find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
> +.section_address = INTUSE(dwfl_offline_section_address),
> +  };
> +
> +int
> +main (int argc, char **argv)
> +{
> +  Dwfl *dwfl = dwfl_begin (&offline_callbacks);
> +  assert (dwfl != NULL);
> +
> +  if (dwfl_get_offline_next_address (dwfl) != OFFLINE_REDZONE)
> +{
> +  dwfl_end (dwfl);
> +  return 1;
> +}
> +
> +  int result = 0;
> +  dwfl_set_offline_next_address (dwfl, 0);
> +  if (dwfl_get_offline_next_address (dwfl) != 0)
> + result = 1;
> +
> +  dwfl_end (dwfl);
> +
> +  return result;
> +}

This test needs to be run under a testrun command in a tests/run-*.sh script
in order to have the result recorded by 'make check'.

Also there are a few places in libdwfl/ and src/ where we manually set
dwfl->offline_next_address.  We could use the setter here instead.

Aaron



Re: [PATCH] riscv: Partial implementation of flatten_aggregate

2024-03-20 Thread Aaron Merey
Hi Mark,

On Wed, Mar 20, 2024 at 11:03 AM Mark Wielaard  wrote:
>
> dwfl_module_return_value_location would fail on riscv for functions
> which return a (small) struct. This patch implements the simplest
> cases of flatten_aggregate in backends/riscv_retval.c. It just handles
> structs containing one or two members of the same base type which fit
> completely or in pieces in one or two general or floating point
> registers.
>
> It also adds a specific test case run-funcretval-struct.sh containing
> small structs of ints, longs, floats and doubles. All these testscases
> now work for riscv. There is already a slightly more extensive
> testcase for this in tests/run-funcretval.sh but that only has a
> testcase for aarch64.

This patch LGTM.  I'm not able to test it myself on riscv but I see that
for the first time a build has successfully passed on the elfutils riscv
trybot [1].

Aaron

[1] https://builder.sourceware.org/buildbot/#/builders/273



[PATCH] config/profile.fish.in: Prevent bracketed variables and unmatched wildcard errors

2024-03-26 Thread Aaron Merey
Fish does not support bracketed variables in scripts.  Remove brackets
from the variable ${prefix} in profile.fish before installation to
prevent this error.

Fish also raises an error for unmatched wildcards, except for special
cases like the set command.  Use a wildcard to match .urls files using
the set command instead of cat to prevent an unmatched wildcard error
when no .urls files are found.

Signed-off-by: Aaron Merey 
---
 config/Makefile.am | 1 +
 config/profile.fish.in | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/config/Makefile.am b/config/Makefile.am
index ae14e625..fd41997f 100644
--- a/config/Makefile.am
+++ b/config/Makefile.am
@@ -41,6 +41,7 @@ pkgconfig_DATA += libdebuginfod.pc
 install-data-local:
$(INSTALL_DATA) profile.sh -D 
$(DESTDIR)$(sysconfdir)/profile.d/debuginfod.sh
$(INSTALL_DATA) profile.csh -D 
$(DESTDIR)$(sysconfdir)/profile.d/debuginfod.csh
+   sed -i 's/{prefix}/prefix/g' profile.fish
$(INSTALL_DATA) profile.fish -D 
$(DESTDIR)$(datadir)/fish/vendor_conf.d/debuginfod.fish
mkdir -p $(DESTDIR)$(sysconfdir)/debuginfod
if [ -n "@DEBUGINFOD_URLS@" ]; then \
diff --git a/config/profile.fish.in b/config/profile.fish.in
index 00e9ca59..c0a234db 100644
--- a/config/profile.fish.in
+++ b/config/profile.fish.in
@@ -7,7 +7,8 @@
 if not set --query DEBUGINFOD_URLS
 # Use local variables so we don't need to manually unset them
 set --local prefix "@prefix@"
-set --local DEBUGINFOD_URLS (cat /dev/null 
"@sysconfdir@/debuginfod"/*.urls 2>/dev/null | string replace '\n' ' ')
+set --local files "@sysconfdir@/debuginfod/"*.urls
+set --local DEBUGINFOD_URLS (cat /dev/null $files 2>/dev/null | string 
replace '\n' ' ')
 if test -n "$DEBUGINFOD_URLS"
 set --global --export DEBUGINFOD_URLS "$DEBUGINFOD_URLS"
 end
-- 
2.43.0



Elfutils Code of Conduct

2024-03-28 Thread Aaron Merey
Hi all,

I'd like to propose a formal code of conduct for elfutils.  Elfutils
already has a brief, informal code of conduct.  The CONTRIBUTING
document in the elfutils source directory states that:

   committers/maintainers who repeatedly ignore the above guidelines,
   are hostile or offensive towards other committers or contributors,
   and don't correct their behavior after being asked by other committers
   will be removed as maintainer/committer.

I'd like to replace this with a more formal code of conduct that applies
to anyone participating in the elfutils community and better describes the
types of behaviors that are either encouraged or unwelcome.  The code of
conduct should also outline how complaints will be handled and who is
responsible for enforcement.

The Contributor Covenant [1] is a code of conduct that I believe satisfies
these goals.  Mark has already recommended that elfutils adopt the
Contributor Covenant [2].  It is also used by a variety of open source
projects including Golang, Curl and the Linux kernel.

This code of conduct includes a committee to handle any complaints or
concerns that fall under the code.  Mark and I have offered to be on this
committee.  If anyone else would like to be a member of the elfutils code
of conduct committee, please let us know!

I've included the text of Contributor Covenant v2.1 below with changes
to the following sections:

Enforcement Responsibilities: Clarified who is a "community leader".
Scope: Used examples specific to elfutils.
Enforcement: Mention our code of conduct committee and names of members.

Any other comments or questions regarding an elfutils code of conduct are
also welcome.

Aaron

[1] https://www.contributor-covenant.org/
[2] 
https://inbox.sourceware.org/elfutils-devel/63f6aa114966e0d49d18497c336afa8d3965e24d.ca...@klomp.org/#t

---

# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in
our community a harassment-free experience for everyone, regardless of
age, body size, visible or invisible disability, ethnicity, sex
characteristics, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance,
race, caste, color, religion, or sexual identity and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political
  attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders (i.e. regular contributors and/or those with elfutils
git commit access) are responsible for clarifying and enforcing our standards
of acceptable behavior and will take appropriate and fair corrective action
in response to any behavior that they deem inappropriate, threatening,
offensive, or harmful.

Community leaders have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, and will communicate reasons
for moderation decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, such as the
elfutils IRC channel, website, mailing list and bug reports. It also
applies when an individual is officially representing the community
in public spaces. Examples of representing our community include acting
as an appointed representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may
be reported to the elfutils code of conduct committee at
elfutils-cond...@sourceware.org.

The current members of the elfutils code of conduct committee are:
Mark Wielaard
Aaron Merey

All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security
of the reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in
determining the consequences for any action the

[PATCH] libdw: dwarf_getsrcfiles should not imply dwarf_getsrclines

2024-03-28 Thread Aaron Merey
dwarf_getsrcfiles causes line data to be read in addition to file data.
This is wasteful for programs which only need file or directory names.
Debuginfod server is one such example.

Fix this by moving the srcfile handling in read_srclines into a separate
function read_srcfiles.

read_srclines also no longer handles DW_LNE_define_file due to lack of
use and to simplify the separation of srcfile and srcline reading.

* libdw/dwarf_getsrcfiles.c (dwarf_getsrcfiles): Replace
dwarf_getsrclines and __libdw_getsrclines with
__libdw_getsrcfiles.
* libdw/dwarf_getsrclines.c (read_line_header): New function.
(read_srcfiles): New function.
(read_srclines): Move file reading into read_srcfiles.
Remove DW_LNE_define_file handling.  Add parameter so
that previously read srcfiles can be used if available.
(__libdw_getsrclines): Call read_srcfiles if linesp is
NULL.  Pass previously read srcfiles to read_srclines
if available.
(__libdw_getsrcfiles): New function.
* libdw/dwarf_macro_getsrcfiles.c (dwarf_macro_getsrcfiles):
Replace __libdw_getsrclines with __libdw_getsrcfiles.
* libdw/libdwP.h (__libdw_getsrcfiles): New declaration.
* tests/get-files.c: Verify that dwarf_getsrcfiles does
not cause srclines to be read.
* tests/get-lines.c: Verify that srclines can be read
after srcfiles have been read.

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

Signed-off-by: Aaron Merey 
---
 libdw/dwarf_getsrcfiles.c   |  24 +-
 libdw/dwarf_getsrclines.c   | 506 ++--
 libdw/dwarf_macro_getsrcfiles.c |   4 +-
 libdw/libdwP.h  |  10 +
 tests/get-files.c   |   8 +
 tests/get-lines.c   |  20 +-
 6 files changed, 346 insertions(+), 226 deletions(-)

diff --git a/libdw/dwarf_getsrcfiles.c b/libdw/dwarf_getsrcfiles.c
index cd2e5b5a..24e4b7d2 100644
--- a/libdw/dwarf_getsrcfiles.c
+++ b/libdw/dwarf_getsrcfiles.c
@@ -70,10 +70,9 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, 
size_t *nfiles)
{
  /* We are only interested in the files, the lines will
 always come from the skeleton.  */
- res = __libdw_getsrclines (cu->dbg, dwp_off,
+ res = __libdw_getsrcfiles (cu->dbg, dwp_off,
 __libdw_getcompdir (cudie),
-cu->address_size, NULL,
-&cu->files);
+cu->address_size, &cu->files);
}
}
  else
@@ -89,12 +88,19 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, 
size_t *nfiles)
}
   else
{
- Dwarf_Lines *lines;
- size_t nlines;
-
- /* Let the more generic function do the work.  It'll create more
-data but that will be needed in an real program anyway.  */
- res = INTUSE(dwarf_getsrclines) (cudie, &lines, &nlines);
+ /* The die must have a statement list associated.  */
+ Dwarf_Attribute stmt_list_mem;
+ Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, 
DW_AT_stmt_list,
+  &stmt_list_mem);
+
+ Dwarf_Off debug_line_offset;
+ if (__libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
+  NULL, &debug_line_offset) == NULL)
+   return -1;
+
+ res = __libdw_getsrcfiles (cu->dbg, debug_line_offset,
+__libdw_getcompdir (cudie),
+cu->address_size, &cu->files);
}
 }
   else if (cu->files != (void *) -1l)
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index 69e10c7b..4eda13f4 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -77,6 +77,28 @@ compare_lines (const void *a, const void *b)
 : 0;
 }
 
+/* Decoded .debug_line program header.  */
+struct line_header
+{
+  /* Header entries */
+  Dwarf_Word unit_length;
+  unsigned int length;
+  uint_fast16_t version;
+  size_t line_address_size;
+  size_t segment_selector_size;
+  Dwarf_Word header_length;
+  const unsigned char *header_start;
+  uint_fast8_t minimum_instr_len;
+  uint_fast8_t max_ops_per_instr;
+  uint_fast8_t default_is_stmt;
+  int_fast8_t line_base;
+  uint_fast8_t line_range;
+  uint_fast8_t opcode_base;
+  const uint8_t *standard_opcode_lengths;
+  unsigned int debug_str_offset;  /* CUBIN only */
+  size_t files_start;
+};
+
 struct line_state
 {
   Dwarf_Word addr;
@@ -155,127 +177,81 @@ add_new_line (struct line_state *state, struct linelist 
*new_line)
   return false;
 }
 
+/* Cache the .debug_line header.  Return 0 if sucessful,

[PATCH] libdw: dwarf_getsrcfiles should not imply dwarf_getsrclines

2024-04-09 Thread Aaron Merey
dwarf_getsrcfiles causes line data to be read in addition to file data.
This is wasteful for programs which only need file or directory names.
Debuginfod server is one such example.

Fix this by moving the srcfile reading in read_srclines into a separate
function read_srcfiles.  This change improves debuginfod server's max
resident set size by up to 75% during rpm indexing.

* libdw/dwarf_getsrcfiles.c (dwarf_getsrcfiles): Replace
dwarf_getsrclines and __libdw_getsrclines with
__libdw_getsrcfiles.
* libdw/dwarf_getsrclines.c (read_line_header): New function.
(read_srcfiles): New function.
(read_srclines): Move srcfile reading into read_srcfiles.
Add parameter to use cached srcfiles if available.
Also merge srcfiles with any files from DW_LNE_define_file.
(__libdw_getsrclines): Changed to call get_lines_or_files.
(__libdw_getsrcfiles): New function.  Calls get_lines_or_files.
(get_lines_or_files): New function based on the old
__libdw_getsrclines.  Call read_srcfiles if linesp is NULL,
otherwise call read_srclines.  Pass previously read srcfiles
to read_srclines if available.
* libdw/dwarf_macro_getsrcfiles.c (dwarf_macro_getsrcfiles):
Replace __libdw_getsrclines with __libdw_getsrcfiles.
* libdw/libdwP.h (__libdw_getsrcfiles): New declaration.
* tests/.gitignore: Add new test binary.
* tests/get-files.c: Verify that dwarf_getsrcfiles does
not cause srclines to be read.
* tests/get-lines.c: Verify that srclines can be read
after srcfiles have been read.
* tests/Makefile.am: Add new testfiles.
* tests/get-files-define-file.c: Print file names before
and after reading DW_LNE_define_file.
* tests/run-get-files.sh: Add get-files-define-file test.
* tests/testfile-define-file.bz2: New testfile.  Copy of
testfile36.debug but with a line program consisting of two
DW_LNE_define_file opcodes.

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

Signed-off-by: Aaron Merey 
---

v2 changes:
Restored support for DW_LNE_define_file.

Added DW_LNE_define_file testcase and testfile.

Added new function get_lines_or_files which is based on the old
__libdw_getsrclines.  __libdw_getsrclines and __libdw_getsrcfiles now
call get_lines_or_files.

Mentioned max resident set size improvement in the commit message.  I
did not mention a 5% speed up to rpm indexing that I have previously
talked about since I could not reliably reproduce it with v2 of the patch.
I suspect that speed up may have been due to the smaller max RSS reducing
swapping during that round of testing.

 libdw/dwarf_getsrcfiles.c   |  24 +-
 libdw/dwarf_getsrclines.c   | 661 ++--
 libdw/dwarf_macro_getsrcfiles.c |   4 +-
 libdw/libdwP.h  |  10 +
 tests/.gitignore|   1 +
 tests/Makefile.am   |   6 +-
 tests/get-files-define-file.c   | 162 
 tests/get-files.c   |   8 +
 tests/get-lines.c   |  20 +-
 tests/run-get-files.sh  |  65 +++-
 tests/testfile-define-file.bz2  | Bin 0 -> 24910 bytes
 11 files changed, 734 insertions(+), 227 deletions(-)
 create mode 100644 tests/get-files-define-file.c
 create mode 100644 tests/testfile-define-file.bz2

diff --git a/libdw/dwarf_getsrcfiles.c b/libdw/dwarf_getsrcfiles.c
index cd2e5b5a..24e4b7d2 100644
--- a/libdw/dwarf_getsrcfiles.c
+++ b/libdw/dwarf_getsrcfiles.c
@@ -70,10 +70,9 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, 
size_t *nfiles)
{
  /* We are only interested in the files, the lines will
 always come from the skeleton.  */
- res = __libdw_getsrclines (cu->dbg, dwp_off,
+ res = __libdw_getsrcfiles (cu->dbg, dwp_off,
 __libdw_getcompdir (cudie),
-cu->address_size, NULL,
-&cu->files);
+cu->address_size, &cu->files);
}
}
  else
@@ -89,12 +88,19 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, 
size_t *nfiles)
}
   else
{
- Dwarf_Lines *lines;
- size_t nlines;
-
- /* Let the more generic function do the work.  It'll create more
-data but that will be needed in an real program anyway.  */
- res = INTUSE(dwarf_getsrclines) (cudie, &lines, &nlines);
+ /* The die must have a statement list associated.  */
+ Dwarf_Attribute stmt_list_mem;
+ Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, 
DW_AT_stmt_list,
+  &stmt_list_mem);
+
+ Dwarf_Off debug_li

Re: [PATCH] libdw: dwarf_getsrcfiles should not imply dwarf_getsrclines

2024-04-10 Thread Aaron Merey
Hi Mark,

On Wed, Apr 10, 2024 at 3:48 PM Mark Wielaard  wrote:
> > v2 changes:
> > Restored support for DW_LNE_define_file.
>
> Great. And sorry I first suggested to just drop it and then said I
> would like it back. This was more work than I though.

No problem, better if we support this just in case.

> This one line uses tabs for indentation, all others spaces.
> [...]
> And this last block uses tabs again.
> [...]
> Here tabs again, then the rest spaces.
> [...]
> So inconsistent indentation, but the code looks good.

Fixed the indentation.

> > -  /* Pass the file data structure to the caller.  */
> > -  if (filesp != NULL)
> > -*filesp = files;
> > +  const char **newdirs = (void *) &newfiles->info[nnewfiles];
> > +  const char **prevdirs = (void *) &prevfiles->info[nprevfiles];
> > +
> > +  /* Copy prevdirs to newdirs.  */
> > +  for (size_t n = 0; n < ndirs; n++)
> > + newdirs[n] = prevdirs[n];
>
> Again slightly off indentation.
> But I also don't fully follow the prevdirs/newdirs copying.
> Why is this? No newdirs are defined here, are there?
> Maybe I don't understand the data-structure used here.

The directories are the same but we still need to copy them so that
dwarf_getsrcdirs can find newfiles' dir names.

Dwarf_Files is an unusual structure since it doesn't contain a member
specifically for the array of dirnames.  Instead they're stored at
the end of the Dwarf_Fileinfo array member.

> So testfile-define-file is actually testfile36.debug but with a new
> line program? How did you edit/insert that one?

I used xxd to create a hexdump of testfile36.debug and modified the line
program by hand with a text editor.  I converted the modified hexdump
back to a binary with xxd -r.

I chose testfile36.debug because its .debug_line includes multiple
directory and file names.  It also contains a single short line program
that was easy to replace with two DW_LNE_define_file opcodes without
corrupting things.

Aaron



Re: [PATCH] libdw: dwarf_getsrcfiles should not imply dwarf_getsrclines

2024-04-11 Thread Aaron Merey
On Thu, Apr 11, 2024 at 5:55 AM Mark Wielaard  wrote:
>
> All looks good BTW. Please do push (if possible with the above change).

Thanks Mark, pushed as commit d4b0848be5f575ff9464fee12ce7be416e4fb392

Aaron



[COMMITTED] tests/.gitignore: Use correct spelling for get-files-define-file

2024-04-17 Thread Aaron Merey
Replace get-files-define_file with get-files-define-file.

Signed-off-by: Aaron Merey 
---
 tests/.gitignore | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/.gitignore b/tests/.gitignore
index 4937f0d1..30f5800b 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -75,7 +75,7 @@
 /funcscopes
 /get-aranges
 /get-files
-/get-files-define_file
+/get-files-define-file
 /get-lines
 /get-pubnames
 /get-units-invalid
-- 
2.43.0



Re: [PATCH] config/profile.fish.in: Prevent bracketed variables and unmatched wildcard errors

2024-04-17 Thread Aaron Merey
On Wed, Mar 27, 2024 at 10:06 AM Mark Wielaard  wrote:
>
> Not knowing fish this looks OK to me.  We might want a testcase like
> the one that was just added for config/profile.sh to make sure we ship
> something that runs correctly.  Could be something as simple as:
>
> type fish 2>/dev/null || (echo "no fish installed"; exit 77)
> fish ${abs_top_builddir}/config/profile.fish

On Sat, Mar 30, 2024 at 7:32 AM Frederik “Freso” S. Olesen
 wrote:
>
> On Wed, Mar 27, 2024 at 03:06:48PM +0100, Mark Wielaard wrote:
> > Adding Freso to the CC since he is the original author of the fish
> > support.
>
> Looks good to me! I don’t want to claim any specific authorship
> or special knowledge of it. I basically just adapted the existing
> bash/.sh profile script for local use and then retrofitted that
> for upstream submission. I’m happy that other fish users are
> contributing to improving it! :)

Thanks, pushed as commit eeea53b41b12dc9633ce6a3b1eb5c7d0ba0e057f
with Mark's testcase added.

Aaron



[PATCH] Fix 'make coverage' when used with lcov version 2.0+

2024-05-06 Thread Aaron Merey
Starting with version 2.0, various lcov warnings now trigger an error
exit.  This results in 'make coverage' terminating before completion.

Fix this by invoking lcov and genhtml with --ignore-errors to prevent
the error exit when version 2.0+ is in use.

Manually tested by running elfutils-htdocs/update-coverage.sh with
lcov 1.14 and 2.0.

Signed-off-by: Aaron Merey 
---
 Makefile.am  | 30 +-
 configure.ac |  4 
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index c9d59d4a..a1f0b0c3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -77,6 +77,7 @@ coverage-clean:
 coverage: $(COVERAGE_OUTPUT_INDEX_HTML)
@echo 'file://$(abs_builddir)/$(COVERAGE_OUTPUT_INDEX_HTML)'
 
+if LCOV_OLD
 $(COVERAGE_OUTPUT_INDEX_HTML): $(COVERAGE_OUTPUT_FILE)
LC_ALL=C $(GENHTML) \
--legend \
@@ -89,7 +90,23 @@ $(COVERAGE_OUTPUT_INDEX_HTML): $(COVERAGE_OUTPUT_FILE)
--prefix='$(realpath $(abs_builddir)/..)' \
--output-directory='$(COVERAGE_OUTPUT_DIRECTORY)' \
$<
+else
+$(COVERAGE_OUTPUT_INDEX_HTML): $(COVERAGE_OUTPUT_FILE)
+   LC_ALL=C $(GENHTML) \
+   --legend \
+   --show-details \
+   --ignore-errors empty,negative \
+   --rc=genhtml_branch_coverage=1 \
+   --title='$(COVERAGE_TITLE)' \
+   --prefix='$(abspath $(abs_srcdir))' \
+   --prefix='$(realpath $(abs_srcdir))' \
+   --prefix='$(abspath $(abs_builddir)/..)' \
+   --prefix='$(realpath $(abs_builddir)/..)' \
+   --output-directory='$(COVERAGE_OUTPUT_DIRECTORY)' \
+   $<
+endif
 
+if LCOV_OLD
 $(COVERAGE_OUTPUT_FILE):
$(LCOV) \
--capture \
@@ -99,7 +116,18 @@ $(COVERAGE_OUTPUT_FILE):
--gcov-tool='$(GCOV)' \
--output-file='$@' \
$(LCOV_DIRS_ARGS)
-
+else
+$(COVERAGE_OUTPUT_FILE):
+   $(LCOV) \
+   --capture \
+   --no-external \
+   --no-checksum \
+   --ignore-errors empty,negative \
+   --rc=lcov_branch_coverage=1 \
+   --gcov-tool='$(GCOV)' \
+   --output-file='$@' \
+   $(LCOV_DIRS_ARGS)
+endif
 endif
 
 # Tell version 3.79 and up of GNU make to not build goals in this
diff --git a/configure.ac b/configure.ac
index a279bb52..2aa728bd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -322,6 +322,10 @@ if test "$use_gcov" = yes; then
 fi
 AM_CONDITIONAL(GCOV, test "$use_gcov" = yes)
 
+# Check if lcov/genhtml supports ignoring additional errors.
+AM_CONDITIONAL([LCOV_OLD],
+  [test "$LCOV" = "lcov" && lcov --version | grep -E -q "version 0|version 1"])
+
 AC_ARG_ENABLE([sanitize-undefined],
   AS_HELP_STRING([--enable-sanitize-undefined],
  [Use gcc undefined behaviour sanitizer]),
-- 
2.43.0



Re: [PATCH] Fix 'make coverage' when used with lcov version 2.0+

2024-05-08 Thread Aaron Merey
On Mon, May 6, 2024 at 4:45 PM Aaron Merey  wrote:
>
> Starting with version 2.0, various lcov warnings now trigger an error
> exit.  This results in 'make coverage' terminating before completion.
>
> Fix this by invoking lcov and genhtml with --ignore-errors to prevent
> the error exit when version 2.0+ is in use.
>
> Manually tested by running elfutils-htdocs/update-coverage.sh with
> lcov 1.14 and 2.0.
>
> Signed-off-by: Aaron Merey 
> ---
>  Makefile.am  | 30 +-
>  configure.ac |  4 
>  2 files changed, 33 insertions(+), 1 deletion(-)

Pushed as commit ca8ad4648197

Aaron



Re: [rfc] [patch] PR28204: debuginfod ima signature verification

2024-05-09 Thread Aaron Merey
Hi Frank,

I've pointed out a couple nits below, but otherwise the patch LGTM.
I've also attached a diff for handling DEBUGINFOD_IMA_CERT_PATH in
profile.fish.in that should apply on top of this patch.

I know there's already been a lot of discussion re. ima:permissive and
I'm weighing in rather late, but FWIW I do support including it.
Currently individual ELF sections cannot be downloaded when
ima:enforcing is active.  With ima:permissive we could support proper
section queries while also being able to perform some amount of
ima verification.

On Tue, Apr 16, 2024 at 6:15 PM Frank Ch. Eigler  wrote:
>
> Hi -
>
> The following is the candidate patch for the basic functionality.
> It's been corrected for whitespace & error codes, given more complete
> docs and commit message.  See also the users/fche/try-bz2824f branch.
>
>
> debuginfod: PR28204 - RPM IMA per-file signature verification
>
> Recent versions of Fedora/RHEL include per-file cryptographic
> signatures in RPMs, not just an overall RPM signature.  This work
> extends debuginfod client & server to extract, transfer, and verify
> those signatures.  These allow clients to assure users that the
> downloaded files have not been corrupted since their original
> packaging.  Downloads that fail the test are rejected.
>
> Clients may select a desired level of enforcement for sets of URLs in
> the DEBUGINFOD_URLS by inserting special markers ahead of them:
>
> ima:ignore   pay no attention to absence or presence of signatures
> ima:enforcingrequire every file to be correctly signed
>
> The default is ima:ignore mode.  In ima:enforcing mode, section
> queries are forced to be entire-file downloads, as it is not
> possible to crypto-verify just sections.
>
> IMA signatures are verified against a set of signing certificates.
> These are normally published by distributions.  The environment
> variable $DEBUGINFOD_IMA_CERT_PATH contains a colon-separated path for
> finding DER or PEM formatted certificates / public keys.  These
> certificates are assumed trusted.  The profile.d scripts transcribe
> /etc/debuginfod/*.certdir files into that variable.
>
> As for implementation:
>
> * configure.ac: Add --enable-default-ima-cert-path=PATH parameter.
>   Check for libimaevm (using headers only).
>
> * config/Makefile.am: Install defaults into /etc files.
> * config/profile.{csh,sh}.in: Process defaults into env variables.
> * config/elfutils.spec.in: Add more buildrequires.
>
> * debuginfod/debuginfod.cxx (handle_buildid_r_match): Added extraction of 
> the
>   per-file IMA signature for the queried file and store in http header.
>   (find_globbed_koji_filepath): New function.
>   (parse_opt): New flag --koji-sigcache.
> * debuginfod/debuginfod-client.c (debuginfod_query_server): Added policy 
> for
>   validating IMA signatures
>   (debuginfod_validate_imasig): New function, with friends.
> * debuginfod/debuginfod.h.in: Added DEBUGINFOD_IMA_CERT_PATH_ENV_VAR.
> * debuginfod/Makefile.am: Add linker flags for rpm and crypto.
>
> * doc/debuginfod-client-config.7: Document DEBUGINFOD_IMA_CERT_PATH,
>   update DEBUGINFOD_URLS.
> * doc/debuginfod.8: Document --koji-sigcache.
> * doc/debuginfod-find.1, doc/debuginfod_find_debuginfo.3: Update SECURITY.
>
> * tests/run-debuginfod-ima-verification.sh: New test.
> * tests/debuginfod-ima: Some new files for the tests.
> * tests/Makefile.am: run/distribute them.
>
> Signed-off-by: Ryan Goldberg 
> Signed-off-by: Frank Ch. Eigler 
>
> diff --git a/config/Makefile.am b/config/Makefile.am
> index ae14e625b726..5a28e66d4408 100644
> --- a/config/Makefile.am
> +++ b/config/Makefile.am
> @@ -46,12 +46,16 @@ pkgconfig_DATA += libdebuginfod.pc
> if [ -n "@DEBUGINFOD_URLS@" ]; then \
> echo "@DEBUGINFOD_URLS@" > 
> $(DESTDIR)$(sysconfdir)/debuginfod/elfutils.urls; \
> fi
> +   if [ -n "@DEBUGINFOD_IMA_CERT_PATH@" ]; then \
> +   echo "@DEBUGINFOD_IMA_CERT_PATH@" > 
> $(DESTDIR)$(sysconfdir)/debuginfod/elfutils.certpath; \
> +   fi
>
>  uninstall-local:
> rm -f $(DESTDIR)$(sysconfdir)/profile.d/debuginfod.sh
> rm -f $(DESTDIR)$(sysconfdir)/profile.d/debuginfod.csh
> rm -f $(DESTDIR)$(datadir)/fish/vendor_conf.d/debuginfod.fish
> rm -f $(DESTDIR)$(sysconfdir)/debuginfod/elfutils.urls
> +   rm -f $(DESTDIR)$(sysconfdir)/debuginfod/elfutils.certpath
> -rmdir $(DESTDIR)$(sysconfdir)/debuginfod
>  endif
>
> diff --git a/config/elfutils.spec.in b/config/elfutils.spec.in
> index 4d802a25ad5f..460729972420 100644
> --- a/config/elfutils.spec.in
> +++ b/config/elfutils.spec.in
> @@ -43,6 +43,12 @@ BuildRequires: curl
>  # For run-debuginfod-response-headers.sh test case
>  BuildRequires: socat
>
> +# For debuginfod rpm IMA verification
> +BuildRequires: rpm-devel
> +Buil

[COMMITTED] Makefile.am: Avoid code duplication

2024-05-09 Thread Aaron Merey
On Thu, May 9, 2024 at 6:59 PM Dmitry V. Levin  wrote:
>
> On Thu, May 09, 2024 at 06:08:05PM -0400, Frank Ch. Eigler wrote:
> > Hi -
> >
> > On Fri, May 10, 2024 at 12:53:39AM +0300, Dmitry V. Levin wrote:
> > > > Pushed as commit ca8ad4648197
> > >
> > > What's the purpose of sending proposed patches to the mailing list
> > > if reviews are silently ignored?
> >
> > Please be collegial and don't exaggerate.
>
> The fact is that the review was silently ignored, which is, from my point
> of view, an extraordinary event, and I hereby raise the question why it
> was ignored, and request that the issue pointed out in the review to be
> properly addressed.

Apologies Dmitry, your review was mistakenly caught in my mail client's
spam filter and I did not see it until now.

I agree that we can avoid some code duplication here. I'm going to push
the following patch as obvious:

---
 Makefile.am | 33 ++---
 1 file changed, 6 insertions(+), 27 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index a1f0b0c3..69af63ac 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -78,24 +78,16 @@ coverage: $(COVERAGE_OUTPUT_INDEX_HTML)
@echo 'file://$(abs_builddir)/$(COVERAGE_OUTPUT_INDEX_HTML)'
 
 if LCOV_OLD
-$(COVERAGE_OUTPUT_INDEX_HTML): $(COVERAGE_OUTPUT_FILE)
-   LC_ALL=C $(GENHTML) \
-   --legend \
-   --show-details \
-   --rc=genhtml_branch_coverage=1 \
-   --title='$(COVERAGE_TITLE)' \
-   --prefix='$(abspath $(abs_srcdir))' \
-   --prefix='$(realpath $(abs_srcdir))' \
-   --prefix='$(abspath $(abs_builddir)/..)' \
-   --prefix='$(realpath $(abs_builddir)/..)' \
-   --output-directory='$(COVERAGE_OUTPUT_DIRECTORY)' \
-   $<
+ignore_errors =
 else
+ignore_errors = --ignore-errors empty,negative
+endif
+
 $(COVERAGE_OUTPUT_INDEX_HTML): $(COVERAGE_OUTPUT_FILE)
LC_ALL=C $(GENHTML) \
--legend \
--show-details \
-   --ignore-errors empty,negative \
+   $(ignore_errors) \
--rc=genhtml_branch_coverage=1 \
--title='$(COVERAGE_TITLE)' \
--prefix='$(abspath $(abs_srcdir))' \
@@ -104,30 +96,17 @@ $(COVERAGE_OUTPUT_INDEX_HTML): $(COVERAGE_OUTPUT_FILE)
--prefix='$(realpath $(abs_builddir)/..)' \
--output-directory='$(COVERAGE_OUTPUT_DIRECTORY)' \
$<
-endif
 
-if LCOV_OLD
 $(COVERAGE_OUTPUT_FILE):
$(LCOV) \
--capture \
--no-external \
--no-checksum \
+   $(ignore_errors) \
--rc=lcov_branch_coverage=1 \
--gcov-tool='$(GCOV)' \
--output-file='$@' \
$(LCOV_DIRS_ARGS)
-else
-$(COVERAGE_OUTPUT_FILE):
-   $(LCOV) \
-   --capture \
-   --no-external \
-   --no-checksum \
-   --ignore-errors empty,negative \
-   --rc=lcov_branch_coverage=1 \
-   --gcov-tool='$(GCOV)' \
-   --output-file='$@' \
-   $(LCOV_DIRS_ARGS)
-endif
 endif
 
 # Tell version 3.79 and up of GNU make to not build goals in this
-- 
2.43.0



Re: [PATCH] ar: Replace one alloca use by xmalloc

2024-05-10 Thread Aaron Merey
Hi Mark,

On Tue, Apr 30, 2024 at 10:39 AM Mark Wielaard  wrote:
>
> This alloca use is inside a lexical block and is used to replace one
> element of argv. Use a function local variable, xmalloc and free to
> make memory usage pattern more clear.
>
> * src/ar.c (main): Move newp char pointer declaration up.
> Use xmalloc to allocate space. free at end of main.
>
> Signed-off-by: Mark Wielaard 

LGTM. This patch shouldn't change anything except possibly help
some static analyzers detect correct memory usage.

Aaron

> ---
>  src/ar.c | 6 +-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/src/ar.c b/src/ar.c
> index e6d6d58f2b3b..fcb8bfb90a9f 100644
> --- a/src/ar.c
> +++ b/src/ar.c
> @@ -41,6 +41,7 @@
>  #include 
>  #include 
>
> +#include "libeu.h"
>  #include "arlib.h"
>
>
> @@ -154,10 +155,11 @@ main (int argc, char *argv[])
>
>/* For historical reasons the options in the first parameter need
>   not be preceded by a dash.  Add it now if necessary.  */
> +  char *newp = NULL;
>if (argc > 1 && argv[1][0] != '-')
>  {
>size_t len = strlen (argv[1]) + 1;
> -  char *newp = alloca (len + 1);
> +  newp = (char *) xmalloc (len + 1);
>newp[0] = '-';
>memcpy (&newp[1], argv[1], len);
>argv[1] = newp;
> @@ -271,6 +273,8 @@ MEMBER parameter required for 'a', 'b', and 'i' 
> modifiers"));
>break;
>  }
>
> +  free (newp);
> +
>return status;
>  }
>
> --
> 2.44.0
>



[COMMITTED] config/Makefile.am: Modify profile.fish in all-local

2024-05-10 Thread Aaron Merey
Fish shell scripts do not support bracketed variables.
config/Makefile.am removes brackets from a variable in
config/fish.profile in order to prevent an error when running the
script.

Currently the brackets are removed during make install.  This causes
testsuite failures if make check is run before make install.

Fix this by removing the brackets in all-local instead of
install-data-local.

Signed-off-by: Aaron Merey 
---
 config/Makefile.am | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/config/Makefile.am b/config/Makefile.am
index e42aacee..2dcbe94e 100644
--- a/config/Makefile.am
+++ b/config/Makefile.am
@@ -38,10 +38,12 @@ pkgconfig_DATA = libelf.pc libdw.pc
 if LIBDEBUGINFOD
 pkgconfig_DATA += libdebuginfod.pc
 
+all-local:
+   sed -i 's/{prefix}/prefix/g' profile.fish
+
 install-data-local:
$(INSTALL_DATA) profile.sh -D 
$(DESTDIR)$(sysconfdir)/profile.d/debuginfod.sh
$(INSTALL_DATA) profile.csh -D 
$(DESTDIR)$(sysconfdir)/profile.d/debuginfod.csh
-   sed -i 's/{prefix}/prefix/g' profile.fish
$(INSTALL_DATA) profile.fish -D 
$(DESTDIR)$(datadir)/fish/vendor_conf.d/debuginfod.fish
mkdir -p $(DESTDIR)$(sysconfdir)/debuginfod
if [ -n "@DEBUGINFOD_URLS@" ]; then \
-- 
2.43.0



[PATCH] Update code of conduct

2024-05-28 Thread Aaron Merey
Adopt a new code of conduct based on the Contributor's Covenant.

See the new CONDUCT file for more information.

Signed-off-by: Aaron Merey 
---
 CONDUCT | 134 
 CONTRIBUTING|   3 +-
 Makefile.am |   2 +-
 NEWS|   3 +
 config/elfutils.spec.in |   2 +-
 5 files changed, 141 insertions(+), 3 deletions(-)
 create mode 100644 CONDUCT

diff --git a/CONDUCT b/CONDUCT
new file mode 100644
index ..2d0b8589
--- /dev/null
+++ b/CONDUCT
@@ -0,0 +1,134 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in
+our community a harassment-free experience for everyone, regardless of
+age, body size, visible or invisible disability, ethnicity, sex
+characteristics, gender identity and expression, level of experience,
+education, socio-economic status, nationality, personal appearance,
+race, caste, color, religion, or sexual identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+  and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+  overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+  advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political
+  attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+  address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Enforcement Responsibilities
+
+Community leaders (i.e. regular contributors and/or those with elfutils
+git commit access) are responsible for clarifying and enforcing our standards
+of acceptable behavior and will take appropriate and fair corrective action
+in response to any behavior that they deem inappropriate, threatening,
+offensive, or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, and will communicate reasons
+for moderation decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, such as the
+elfutils IRC channel, website, mailing list and bug reports. It also
+applies when an individual is officially representing the community
+in public spaces. Examples of representing our community include acting
+as an appointed representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may
+be reported to the elfutils code of conduct committee at
+elfutils-cond...@sourceware.org.
+
+The current members of the elfutils code of conduct committee are:
+Mark Wielaard
+Aaron Merey
+
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security
+of the reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in
+determining the consequences for any action they deem in violation of
+this Code of Conduct:
+
+### 1. Correction
+
+Community Impact: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+Consequence: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+Community Impact: A violation through a single incident or series of
+actions.
+
+Consequence: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, for a specified period of time.
+This includes avoiding interactions in community spaces as well as external
+channels like social media. Violating these terms may lead to a temporary
+or permanent ban.
+
+### 3. Temporary Ban
+
+Community Impact: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+Consequence: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public
+or private interaction with the people involved, including u

Re: [patch] debuginfod metadata extension

2024-06-03 Thread Aaron Merey
Hi Frank,

LGTM, please go ahead and merge the patch with these changes.

Aaron

On Sat, Jun 1, 2024 at 11:26 AM Frank Ch. Eigler  wrote:
>
> Hi -
>
> > Thanks for the patch, some suggestions below.
>
> Thanks, adding the following 'git diff -w' to the patch you reviewed:
>
> > [...]
> > I was experimenting with metadata queries to a local server that indexed
> > a single rpm (binutils-2.41-8.fc40.x86_64.rpm). The following commands
> > produced JSON with empty "results":
> >
> > debuginfod-find metadata glob '*'
> > debuginfod-find metadata glob '/usr*'
> > debuginfod-find metadata glob '/usr/bin*'
> >
> > Using the glob '/usr/bin/*' did produce results with complete metadata.
> >
> > I haven't looked into the cause but this seems like a bug.  I'd expect
> > the first 3 globs to return at least as many results as the 4th. If this is
> > intentional behaviour then I think it should be documented.
>
> This is intentional.  When you use glob patterns like '*' or '/usr*'
> in the shell, you don't get recursive path name lists either.
> Addressed in the documentation via reference to shell /
> fnmatch(FNM_PATHNAME).
>
>
> diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
> index c75abadf7dce..3d6f8d8c4bea 100644
> --- a/debuginfod/debuginfod-client.c
> +++ b/debuginfod/debuginfod-client.c
> @@ -72,7 +72,7 @@ int debuginfod_find_section (debuginfod_client *c, const 
> unsigned char *b,
>  int s, const char *scn, char **p)
>   { return -ENOSYS; }
>  int debuginfod_find_metadata (debuginfod_client *c,
> -  const char *k, char *v, char **p) { return 
> -ENOSYS; }
> +  const char *k, const char *v, char **p) { 
> return -ENOSYS; }
>  void debuginfod_set_progressfn(debuginfod_client *c,
>debuginfod_progressfn_t fn) { }
>  void debuginfod_set_verbose_fd(debuginfod_client *c, int fd) { }
> @@ -858,22 +858,12 @@ init_server_urls(char* url_subdir, const char* type,
>char *server_url = strtok_r(server_urls, url_delim, &strtok_saveptr);
>/* Count number of URLs.  */
>int n = 0;
> -  assert (0 == strcmp(url_subdir, "buildid") || 0 == strcmp(url_subdir, 
> "metadata"));
>
>while (server_url != NULL)
>  {
> -  int r;
> -  char *tmp_url;
> -  if (strlen(server_url) > 1 && server_url[strlen(server_url)-1] == '/')
> -r = asprintf(&tmp_url, "%s%s", server_url, url_subdir);
> -  else
> -r = asprintf(&tmp_url, "%s/%s", server_url, url_subdir);
> -
> -  if (r == -1)
> -return -ENOMEM;
> -
> -  // When we encounted a (well-formed) token off the form ima:foo, we 
> update the policy
> -  // under which results from that server will be ima verified
> +  // When we encountered a (well-formed) token off the form
> +  // ima:foo, we update the policy under which results from that
> +  // server will be ima verified
>if (startswith(server_url, "ima:"))
>  {
>  #ifdef ENABLE_IMA_VERIFICATION
> @@ -898,6 +888,17 @@ init_server_urls(char* url_subdir, const char* type,
>goto continue_next_url;
>  }
>
> +  // Construct actual URL for libcurl
> +  int r;
> +  char *tmp_url;
> +  if (strlen(server_url) > 1 && server_url[strlen(server_url)-1] == '/')
> +r = asprintf(&tmp_url, "%s%s", server_url, url_subdir);
> +  else
> +r = asprintf(&tmp_url, "%s/%s", server_url, url_subdir);
> +
> +  if (r == -1)
> +return -ENOMEM;
> +
>/* PR 27983: If the url is duplicate, skip it */
>int url_index;
>for (url_index = 0; url_index < n; ++url_index)
> @@ -1025,7 +1026,7 @@ init_handle(debuginfod_client *client,
>
>  /*
>   * This function busy-waits on one or more curl queries to complete. This can
> - * be controled via only_one, which, if true, will find the first winner and 
> exit
> + * be controlled via only_one, which, if true, will find the first winner 
> and exit
>   * once found. If positive maxtime and maxsize dictate the maximum allowed 
> wait times
>   * and download sizes respectively. Returns 0 on success and -Posix error on 
> failure.
>   */
> @@ -1044,7 +1045,7 @@ perform_queries(CURLM *curlm, CURL **target_handle, 
> struct handle_data *data, de
>c->winning_headers = NULL;
>  }
>if (maxtime > 0 && clock_gettime(CLOCK_MONOTONIC_RAW, &start_time) == -1)
> -return errno;
> +return -errno;
>long delta = 0;
>do
>  {
> @@ -1052,7 +1053,7 @@ perform_queries(CURLM *curlm, CURL **target_handle, 
> struct handle_data *data, de
>if (maxtime > 0)
>  {
>if (clock_gettime(CLOCK_MONOTONIC_RAW, &cur_time) == -1)
> -return errno;
> +return -errno;
>delta = cur_time.tv_sec - start_time.tv_sec;
>if ( delta >  maxtime)
>  {
> @@ -1108,9 +1109,7 @@ perform_queries(CURLM *cu

Re: [PATCH] Update code of conduct

2024-06-07 Thread Aaron Merey
Pushed as commit e2a3e51ab54c4698fe09

Aaron

On Tue, May 28, 2024 at 3:34 PM Aaron Merey  wrote:
>
> Adopt a new code of conduct based on the Contributor's Covenant.
>
> See the new CONDUCT file for more information.
>
> Signed-off-by: Aaron Merey 
> ---
>  CONDUCT | 134 
>  CONTRIBUTING|   3 +-
>  Makefile.am |   2 +-
>  NEWS|   3 +
>  config/elfutils.spec.in |   2 +-
>  5 files changed, 141 insertions(+), 3 deletions(-)
>  create mode 100644 CONDUCT
>
> diff --git a/CONDUCT b/CONDUCT
> new file mode 100644
> index ..2d0b8589
> --- /dev/null
> +++ b/CONDUCT
> @@ -0,0 +1,134 @@
> +# Contributor Covenant Code of Conduct
> +
> +## Our Pledge
> +
> +We as members, contributors, and leaders pledge to make participation in
> +our community a harassment-free experience for everyone, regardless of
> +age, body size, visible or invisible disability, ethnicity, sex
> +characteristics, gender identity and expression, level of experience,
> +education, socio-economic status, nationality, personal appearance,
> +race, caste, color, religion, or sexual identity and orientation.
> +
> +We pledge to act and interact in ways that contribute to an open, welcoming,
> +diverse, inclusive, and healthy community.
> +
> +## Our Standards
> +
> +Examples of behavior that contributes to a positive environment for our
> +community include:
> +
> +* Demonstrating empathy and kindness toward other people
> +* Being respectful of differing opinions, viewpoints, and experiences
> +* Giving and gracefully accepting constructive feedback
> +* Accepting responsibility and apologizing to those affected by our mistakes,
> +  and learning from the experience
> +* Focusing on what is best not just for us as individuals, but for the
> +  overall community
> +
> +Examples of unacceptable behavior include:
> +
> +* The use of sexualized language or imagery, and sexual attention or
> +  advances of any kind
> +* Trolling, insulting or derogatory comments, and personal or political
> +  attacks
> +* Public or private harassment
> +* Publishing others' private information, such as a physical or email
> +  address, without their explicit permission
> +* Other conduct which could reasonably be considered inappropriate in a
> +  professional setting
> +
> +## Enforcement Responsibilities
> +
> +Community leaders (i.e. regular contributors and/or those with elfutils
> +git commit access) are responsible for clarifying and enforcing our standards
> +of acceptable behavior and will take appropriate and fair corrective action
> +in response to any behavior that they deem inappropriate, threatening,
> +offensive, or harmful.
> +
> +Community leaders have the right and responsibility to remove, edit, or
> +reject comments, commits, code, wiki edits, issues, and other contributions
> +that are not aligned to this Code of Conduct, and will communicate reasons
> +for moderation decisions when appropriate.
> +
> +## Scope
> +
> +This Code of Conduct applies within all community spaces, such as the
> +elfutils IRC channel, website, mailing list and bug reports. It also
> +applies when an individual is officially representing the community
> +in public spaces. Examples of representing our community include acting
> +as an appointed representative at an online or offline event.
> +
> +## Enforcement
> +
> +Instances of abusive, harassing, or otherwise unacceptable behavior may
> +be reported to the elfutils code of conduct committee at
> +elfutils-cond...@sourceware.org.
> +
> +The current members of the elfutils code of conduct committee are:
> +Mark Wielaard
> +Aaron Merey
> +
> +All complaints will be reviewed and investigated promptly and fairly.
> +
> +All community leaders are obligated to respect the privacy and security
> +of the reporter of any incident.
> +
> +## Enforcement Guidelines
> +
> +Community leaders will follow these Community Impact Guidelines in
> +determining the consequences for any action they deem in violation of
> +this Code of Conduct:
> +
> +### 1. Correction
> +
> +Community Impact: Use of inappropriate language or other behavior deemed
> +unprofessional or unwelcome in the community.
> +
> +Consequence: A private, written warning from community leaders, providing
> +clarity around the nature of the violation and an explanation of why the
> +behavior was inappropriate. A public apology may be requested.
> +
> +### 2. Warning
> +
> +Community Impact: A violation through a single incident or series of
> +actions.
> +
> +Consequence: A warning with consequences for con

[PATCH] Add man pages for some libelf functions

2024-06-13 Thread Aaron Merey
Hi,

I've attached a patch that adds man pages for a few libelf functions.
These man pages were originally generated using ChatGPT (model
GPT-4o).  I edited each man page by hand to help ensure brevity and
accuracy.

Parts of the original descriptions generated by ChatGPT have been left
as is.  I've attached the original man pages generated by ChatGPT for
comparison.

The prompt used to generate the man pages was:
  Write a linux man page for the function called  in the open
  source project called elfutils.

My goal is to eventually add man pages for all elfutils library functions.
If the man pages in this patch are acceptable then I will use the above
method to create the remaining man pages.  I will post these to
elfutils-devel in batches to avoid the need for reviewing very large
individual patches.

Aaron
From 920a9ac8875d82e8014bf5f3afa6d85dbf00b6cb Mon Sep 17 00:00:00 2001
From: Aaron Merey 
Date: Thu, 13 Jun 2024 15:20:03 -0400
Subject: [PATCH] Add man pages for some libelf functions

Add man pages for elf32_getehdr.3, elf64_getehdr.3, elf_errmsg.3,
elf_errno.3 and elf_version.3

Signed-off-by: Aaron Merey 
---
 doc/Makefile.am |  6 +-
 doc/elf32_getehdr.3 | 36 
 doc/elf64_getehdr.3 | 36 
 doc/elf_errmsg.3| 26 ++
 doc/elf_errno.3 | 24 
 doc/elf_version.3   | 23 +++
 6 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 doc/elf32_getehdr.3
 create mode 100644 doc/elf64_getehdr.3
 create mode 100644 doc/elf_errmsg.3
 create mode 100644 doc/elf_errno.3
 create mode 100644 doc/elf_version.3

diff --git a/doc/Makefile.am b/doc/Makefile.am
index 0c094af2..6a858c59 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -18,7 +18,11 @@
 ## along with this program.  If not, see <http://www.gnu.org/licenses/>.
 EXTRA_DIST = COPYING-GFDL README
 dist_man1_MANS=readelf.1 elfclassify.1 srcfiles.1
-notrans_dist_man3_MANS=elf_update.3 elf_getdata.3 elf_clone.3 elf_begin.3
+
+notrans_dist_man3_MANS = elf_update.3 elf_getdata.3 elf_clone.3 elf_begin.3 \
+	elf32_getehdr.3 elf64_getehdr.3 elf_errmsg.3 elf_errno.3 \
+	elf_version.3
+
 notrans_dist_man7_MANS=
 notrans_dist_man8_MANS=
 notrans_dist_man1_MANS=
diff --git a/doc/elf32_getehdr.3 b/doc/elf32_getehdr.3
new file mode 100644
index ..4dbb3886
--- /dev/null
+++ b/doc/elf32_getehdr.3
@@ -0,0 +1,36 @@
+.TH ELF32_GETEHDR 3
+.SH NAME
+elf32_getehdr \- retrieve the ELF header for a 32-bit ELF descriptor
+
+.SH SYNOPSIS
+.nf
+#include 
+
+Elf32_Ehdr *elf32_getehdr(Elf *elf);
+.fi
+
+.SH DESCRIPTION
+.B elf32_getehdr
+retrieves the ELF header for the given 32-bit ELF descriptor
+.I elf.
+The ELF header contains crucial metadata about the ELF file, such as the type, machine, version, entry point, program header table offset, and section header table offset.
+
+.SH PARAMETERS
+.TP
+.I elf
+Pointer to the ELF descriptor from which to retrieve the ELF header.
+
+.SH RETURN VALUE
+On success,
+.B elf32_getehdr
+returns a pointer to the
+.B Elf32_Ehdr
+structure. If the ELF descriptor is invalid or not a 32-bit ELF, it returns NULL and sets an error code retrievable by
+.BR elf_errno (3).
+
+.SH SEE ALSO
+.BR elf64_getehdr (3),
+.BR elf_begin (3)
+
+.SH REPORTING BUGS
+Report bugs to  or https://sourceware.org/bugzilla/.
diff --git a/doc/elf64_getehdr.3 b/doc/elf64_getehdr.3
new file mode 100644
index ..acf9a125
--- /dev/null
+++ b/doc/elf64_getehdr.3
@@ -0,0 +1,36 @@
+.TH ELF64_GETEHDR 3
+.SH NAME
+elf64_getehdr \- retrieve the ELF header for a 64-bit ELF descriptor
+
+.SH SYNOPSIS
+.nf
+#include 
+
+Elf64_Ehdr *elf64_getehdr(Elf *elf);
+.fi
+
+.SH DESCRIPTION
+.B elf64_getehdr
+retrieves the ELF header for the given 64-bit ELF descriptor
+.I elf.
+The ELF header contains crucial metadata about the ELF file, such as the type, machine, version, entry point, program header table offset, and section header table offset.
+
+.SH PARAMETERS
+.TP
+.I elf
+Pointer to the ELF descriptor from which to retrieve the ELF header.
+
+.SH RETURN VALUE
+On success,
+.B elf64_getehdr
+returns a pointer to the
+.B Elf64_Ehdr
+structure. If the ELF descriptor is invalid or not a 64-bit ELF, it returns NULL and sets an error code retrievable by
+.BR elf_errno (3).
+
+.SH SEE ALSO
+.BR elf64_getehdr (3),
+.BR elf_begin (3)
+
+.SH REPORTING BUGS
+Report bugs to  or https://sourceware.org/bugzilla/.
diff --git a/doc/elf_errmsg.3 b/doc/elf_errmsg.3
new file mode 100644
index ..1031b581
--- /dev/null
+++ b/doc/elf_errmsg.3
@@ -0,0 +1,26 @@
+.TH ELF_ERRMSG 3
+
+.SH NAME
+elf_errmsg \- return the error message string for a given libelf error code.
+
+.SH SYNOPSIS
+.B #include 
+
+.BI "const char *elf_errmsg(int " err ");"
+
+.SH DESCRIPTION
+The \fBelf_errmsg\fP function retrieves a human-readable string corresponding to the most recent error code set by a libelf libr

Re: [PATCH] Add man pages for some libelf functions

2024-06-19 Thread Aaron Merey
Hi Frank,

On Wed, Jun 19, 2024 at 11:52 AM Frank Ch. Eigler  wrote:
>
> By the way, in addition or instead of using tarballs for carrying this
> bulk content toward review, a git branch holding it all work about as
> well.

I've created the branch users/amerey/manpages for holding this work.
It contains man pages for all libelf functions (ATM most of these man
pages consist of chatgpt raw output). I will update the branch as this
work progresses.

Aaron



Re: [PATCH] Add man pages for some libelf functions

2024-06-26 Thread Aaron Merey
Add man pages for elf32_getehdr.3, elf64_getehdr.3, elf_errmsg.3,
elf_errno.3 and elf_version.3

Signed-off-by: Aaron Merey 
---

Hi Mark,

On Fri, Jun 21, 2024 at 9:28 AM Mark Wielaard  wrote:
> On Thu, 2024-06-13 at 16:01 -0400, Aaron Merey wrote:
> > I've attached a patch that adds man pages for a few libelf functions.
> > These man pages were originally generated using ChatGPT (model
> > GPT-4o).  I edited each man page by hand to help ensure brevity and
> > accuracy.
> >
> > Parts of the original descriptions generated by ChatGPT have been left
> > as is.  I've attached the original man pages generated by ChatGPT for
> > comparison.
>
> So the first question really is where did ChatGPT get this information
> from? I see it produces Copyright statements, but it is clear to me
> those aren't accurate. What is the copyright status of these generated
> manual pages?
>
> It looks like your edits are so extensive that you can claim your own
> copyright on them. But make sure that your Signed-off-by is really
> accurate. CONTRIBUTING says:
>
>   The sign-off is a simple line at the end of the explanation for the
>   patch, which certifies that you wrote it or otherwise have the right
>   to pass it on as a patch under an appropriate license. The rules are
>   pretty simple: if you can certify the below:
>
>         Developer's Certificate of Origin
>
>         By making a contribution to this project, I certify that:
>
>         (a) The contribution was created in whole or in part by me,
>             and I have the right to submit the contribution under each
>             license indicated in, or otherwise designated as being
>             applicable to, the file.
>
>         (b) The contribution was provided directly to me by some other
>             person who certified (a), and I have not modified it.
>
>         (c) I understand and agree that the project and the
>             contribution are public and that a record of the
>             contribution (including all personal information I submit
>             with it, including my sign-off) is maintained indefinitely
>             and may be redistributed.

I believe that my Signed-off-by really does apply to this patch, but
I am by no means an expert in copyright matters.  If you think that
my edits are sufficient to claim my own copyright here then I believe
that I'm ok to include it.

>
> I see it also sometimes generates a HISTORY section with a bogus "first
> appeared in..." line. We do have symbol versioning, so you can get some
> of this information from the libelf/libelf.maps file. But note that the
> symbol version isn't the same as the elfutils version (you can use git
> to map them). There are only 8 different versions that introduced new
> symbols.
>
> In general I wonder how useful the description text generated by
> chatgtp is. It looks very generic and I am a little worried it seems to
> happily generate "descriptions" for none-exiting libelf functions.
>
> > The prompt used to generate the man pages was:
> >   Write a linux man page for the function called  in the open
> >   source project called elfutils.
>
> I think it would be easier if you make the prompt less specific. How
> about just asking for a template that you can then fill in yourself?
>
>    Write a template man page for the function called   for the
>    libelf library in the elfutils project for the "libelf Programmer's
>    Manual"

I tried this prompt and chatgpt generated man pages very similar to
the chatgpt originals I attached to a previous email.  Personally I
find that I save time editing chatgpt descriptions compared to writing
my own from scratch (although it's not a huge difference).

I understand your concerns about chatgpt generating plausible yet false
content but if I'm editing its descriptions sufficiently then the
content should be true, I can claim copyright, and time is saved.

> > My goal is to eventually add man pages for all elfutils library functions.
> > If the man pages in this patch are acceptable then I will use the above
> > method to create the remaining man pages.  I will post these to
> > elfutils-devel in batches to avoid the need for reviewing very large
> > individual patches.
>
> Thanks. A couple of minor comments below.
>
> > From 920a9ac8875d82e8014bf5f3afa6d85dbf00b6cb Mon Sep 17 00:00:00 2001
> > From: Aaron Merey 
> > Date: Thu, 13 Jun 2024 15:20:03 -0400
> > Subject: [PATCH] Add man pages for some libelf functions
> >
> > Add man pages for elf32_getehdr.3, elf64_getehdr.3, elf_errmsg.3,
> > elf_errno.3 and elf_version.3
> >
> > Signed-off-by: Aaro

Re: [PATCH] Add man pages for some libelf functions

2024-06-28 Thread Aaron Merey
Hi Mark,

On Fri, Jun 28, 2024 at 7:36 AM Mark Wielaard  wrote:
> On Wed, 2024-06-26 at 20:22 -0400, Aaron Merey wrote:
> > >
> > > In general I wonder how useful the description text generated by
> > > chatgtp is. It looks very generic and I am a little worried it seems to
> > > happily generate "descriptions" for none-exiting libelf functions.
> > >
> > > > The prompt used to generate the man pages was:
> > > >   Write a linux man page for the function called  in the open
> > > >   source project called elfutils.
> > >
> > > I think it would be easier if you make the prompt less specific. How
> > > about just asking for a template that you can then fill in yourself?
> > >
> > >Write a template man page for the function called   for the
> > >libelf library in the elfutils project for the "libelf Programmer's
> > >Manual"
> >
> > I tried this prompt and chatgpt generated man pages very similar to
> > the chatgpt originals I attached to a previous email.  Personally I
> > find that I save time editing chatgpt descriptions compared to writing
> > my own from scratch (although it's not a huge difference).
> >
> > I understand your concerns about chatgpt generating plausible yet false
> > content but if I'm editing its descriptions sufficiently then the
> > content should be true, I can claim copyright, and time is saved.
>
> I am slightly confused because I think we are using the "template"
> prompt differently somehow. I would assume the above prompt makes it so
> that you only let chatgpt generate one template man page where you then
> insert your own descriptions because the llm only generated the general
> outline.
>
> My concern is not just that trying to pretend the llm "knows" the
> actual function makes the descriptions possibly come from input where
> the copyright holders can claim rights. But also that it will just
> invent very generic but plausible sounding specifics about a named
> function which are just not true and do miss actual specific
> (important, but maybe corner) cases.
>
> Personally I wouldn't trust any "specifics" generated by an llm chatbot
> and would not use it, except maybe to create a generic template for the
> man pages. Then it would still save time, but I wouldn't be concerned
> about the actual descriptions being bogus.

Ok I'll drop any descriptions from the chatgpt output and write them myself.

>
> > > > +.SH DESCRIPTION
> > > > +.B elf32_getehdr
> > > > +retrieves the ELF header for the given 32-bit ELF descriptor
> > > > +.I elf.
> > > > +The ELF header contains crucial metadata about the ELF file, such as 
> > > > the type, machine, version, entry point, program header table offset, 
> > > > and section header table offset.
> > >
> > > Should it list the actual Elf32_Ehdr struct from elf.h here?
> >
> > I included "See elf(5) for more information regarding the elf header"
> > to the description and added elf(5) to SEE ALSO.
> >
>
> Good idea. I assume this refers to
> https://man7.org/linux/man-pages/man5/elf.5.html
> I must admit I didn't know man-pages contained an elf.5 entry.
> We should probably also have a generic libelf.3 overview man page.
>
> > Thanks for the review, the updated patch is below.
>
> Looks good.
>
> I would leave out the history section of there is none (first appeared
> in elfutils 0.0 isn't really history imho :)
>
> One small comment on elf_version below.
>
> > diff --git a/doc/elf_version.3 b/doc/elf_version.3
> > new file mode 100644
> > index ..4d3f18d8
> > --- /dev/null
> > +++ b/doc/elf_version.3
> > @@ -0,0 +1,27 @@
> > +.TH ELF_VERSION 3 2024-06-26 "Libelf" "Libelf Programmer's Manual"
> > +
> > +.SH NAME
> > +elf_version \- set the ELF library version
> > +
> > +.SH SYNOPSIS
> > +.B #include 
> > +
> > +.BI "unsigned int elf_version(unsigned int " version ");"
> > +
> > +.SH DESCRIPTION
> > +The \fBelf_version\fP function sets the library's ELF version to the 
> > specified value. This function must be called before any other libelf 
> > functions are used.
> > +
> > +.SH PARAMETERS
> > +.TP
> > +.I version
> > +An \fIunsigned int\fP value specifying the desired ELF library version. 
> > This is should be set to \fBEV_CURRENT\fP to indicate the current version 
> > of the library. At this time the only supported \fIversion\fP values are 
> > \fBEV_CURRENT\fP and \fBEV_NONE\fP.
>
> EV_CURRENT is the only supported version.
> When given EV_NONE it won't initialize the library, but return the
> highest supported version (which is EV_CURRENT obviously).
>
> > +.SH RETURN VALUE
> > +The \fBelf_version\fP function returns \fBEV_CURRENT\fP when \fIversion\fP 
> > is supported. If the specified version is not supported, it returns 
> > \fBEV_NONE\fP.
>
> ^ If the version given is not EV_NONE.
> If the version given is EV_NONE it will return EV_CURRENT.

I reworded DESCRIPTION and RETURN VALUE to better describe this.
Pushed as commit 2f08cb4846.

Aaron



[COMMITTED] elfutils.spec.in: Package elf32_* and elf64_* man pages

2024-06-28 Thread Aaron Merey
Previously only elf_* man pages were included during rpmbuild.

Signed-off-by: Aaron Merey 
---
 config/elfutils.spec.in | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/config/elfutils.spec.in b/config/elfutils.spec.in
index 5bb4a722..0d1ec11b 100644
--- a/config/elfutils.spec.in
+++ b/config/elfutils.spec.in
@@ -302,6 +302,8 @@ fi
 %{_libdir}/libelf.so
 %{_libdir}/pkgconfig/libelf.pc
 %{_mandir}/man3/elf_*.3*
+%{_mandir}/man3/elf32_*.3*
+%{_mandir}/man3/elf64_*.3*
 
 %files libelf-devel-static
 %{_libdir}/libelf.a
-- 
2.45.2



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

2024-07-04 Thread Aaron Merey
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.

Aaron



[COMMITTED] tests/Makefile.am: Add run-sysroot.sh to EXTRA_DIST

2024-07-04 Thread Aaron Merey
Signed-off-by: Aaron Merey 
---
 tests/Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/Makefile.am b/tests/Makefile.am
index d5b2c02b..77f9b90d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -669,7 +669,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 testfile-dwp-4-cu-index-overflow.dwp.bz2 \
 testfile-dwp-cu-index-overflow.source \
 testfile-define-file.bz2 \
-testfile-sysroot.tar.bz2
+testfile-sysroot.tar.bz2 run-sysroot.sh
 
 
 if USE_VALGRIND
-- 
2.45.2



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

2024-07-10 Thread Aaron Merey
Hi Ying,

On Wed, Jul 10, 2024 at 4:33 AM Ying Huang  wrote:
>
> Hi,
>
> I did test on mips64el and x86_64, the test results all were failed as 
> follows:
>
> 1. x86-64:
>
> $ uname -a
> Linux swecovm-s01 6.1.0-17-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.69-1 
> (2023-12-30) x86_64 GNU/Linux
>
> $ cat tests/run-sysroot.sh.log
> ++ mktemp -d
> + tmpdir=/tmp/tmp.8ZyeM4XiUP
> + trap 'rm -rf -- /tmp/tmp.8ZyeM4XiUP' EXIT
> + tar xjf /swecoproj/huangying/elfutils/tests/testfile-sysroot.tar.bz2 -C 
> /tmp/tmp.8ZyeM4XiUP
> + testrun /swecoproj/huangying/elfutils/src/stack --core 
> /tmp/tmp.8ZyeM4XiUP/core.bash --sysroot /tmp/tmp.8ZyeM4XiUP/sysroot
> + built_testrun /swecoproj/huangying/elfutils/src/stack --core 
> /tmp/tmp.8ZyeM4XiUP/core.bash --sysroot /tmp/tmp.8ZyeM4XiUP/sysroot
> + 
> LD_LIBRARY_PATH=/swecoproj/huangying/elfutils/libdw:/swecoproj/huangying/elfutils/backends:/swecoproj/huangying/elfutils/libelf:/swecoproj/huangying/elfutils/libasm:/swecoproj/huangying/elfutils/debuginfod:/swecoproj/huangying/elfutils/libdw:/swecoproj/huangying/elfutils/libelf:
> + /swecoproj/huangying/elfutils/src/stack --core 
> /tmp/tmp.8ZyeM4XiUP/core.bash --sysroot /tmp/tmp.8ZyeM4XiUP/sysroot
> + testrun diff /tmp/tmp.8ZyeM4XiUP/stack.out -
> + built_testrun diff /tmp/tmp.8ZyeM4XiUP/stack.out -
> + 
> LD_LIBRARY_PATH=/swecoproj/huangying/elfutils/libdw:/swecoproj/huangying/elfutils/backends:/swecoproj/huangying/elfutils/libelf:/swecoproj/huangying/elfutils/libasm:/swecoproj/huangying/elfutils/debuginfod:/swecoproj/huangying/elfutils/libdw:/swecoproj/huangying/elfutils/libelf:
> + diff /tmp/tmp.8ZyeM4XiUP/stack.out -
> 4,5c4,5
> < #1  0xe5663f20
> < #2  0xe5667a98
> ---
> > #1  0xe5663f20 kill_shell
> > #2  0xe5667a98 termsig_handler.part.0
> + rm -rf -- /tmp/tmp.8ZyeM4XiUP
> FAIL run-sysroot.sh (exit status: 1)
>
>
> 2.mips64el:
>
> $ uname -a
> Linux Sleepygon 6.1.0-18-loongson-3 #1 SMP PREEMPT Debian 6.1.76-1 
> (2024-02-01) mips64 GNU/Linux
>
> $ cat tests/run-sysroot.sh.log
> ++ mktemp -d
> + tmpdir=/tmp/tmp.bCCbATKu43
> + trap 'rm -rf -- /tmp/tmp.bCCbATKu43' EXIT
> + tar xjf /home/huangying/elf/elfutils_main/tests/testfile-sysroot.tar.bz2 -C 
> /tmp/tmp.bCCbATKu43
> + testrun /home/huangying/elf/elfutils_main/src/stack --core 
> /tmp/tmp.bCCbATKu43/core.bash --sysroot /tmp/tmp.bCCbATKu43/sysroot
> + built_testrun /home/huangying/elf/elfutils_main/src/stack --core 
> /tmp/tmp.bCCbATKu43/core.bash --sysroot /tmp/tmp.bCCbATKu43/sysroot
> + 
> 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
> + /home/huangying/elf/elfutils_main/src/stack --core 
> /tmp/tmp.bCCbATKu43/core.bash --sysroot /tmp/tmp.bCCbATKu43/sysroot
> + 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.

Aaron



[COMMITTED] tests/run-sysroot.sh: Avoid testing output that depends on LZMA support

2024-07-11 Thread Aaron Merey
run-sysroot.sh checks whether a backtrace generated by eu-stack contains
symbol names found in binaries under a test sysroot.  Two frames in
the backtrace contain symbol names that must be read from .gnu_debugdata.

However this section can only be read if elfutils was built with LZMA
support.  If not, then the symbol names will be absent from the
backtrace.

Test the eu-stack output with these 2 frames removed in order to prevent
a test failure when LZMA support is missing.

Signed-off-by: Aaron Merey 
---
 tests/run-sysroot.sh | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/tests/run-sysroot.sh b/tests/run-sysroot.sh
index 7f7d3f06..cfdc51e9 100755
--- a/tests/run-sysroot.sh
+++ b/tests/run-sysroot.sh
@@ -17,8 +17,6 @@
 
 . $srcdir/test-subr.sh
 
-set -ex;
-
 tmpdir="$(mktemp -d)"
 trap "rm -rf -- ${tmpdir}" EXIT
 
@@ -28,13 +26,16 @@ tar xjf "${abs_srcdir}/testfile-sysroot.tar.bz2" -C 
"${tmpdir}"
 testrun "${abs_top_builddir}"/src/stack --core "${tmpdir}/core.bash" \
--sysroot "${tmpdir}/sysroot" >"${tmpdir}/stack.out"
 
+# Remove 2 stack frames with symbol names contained in .gnu_debugdata.
+# Whether or not these names appear in the output depends on if elfutils
+# was built with LZMA support.
+sed -i '4,5d' "${tmpdir}/stack.out"
+
 # check that we are able to get fully symbolized backtrace
-testrun diff "${tmpdir}/stack.out" - <<\EOF
+testrun_compare cat "${tmpdir}/stack.out" <<\EOF
 PID 431185 - core
 TID 431185:
 #0  0x8ebe5a8c kill
-#1  0xe5663f20 kill_shell
-#2  0xe5667a98 termsig_handler.part.0
 #3  0xe562b2fc execute_command
 #4  0xe561cbb4 reader_loop
 #5  0xe5611bf0 main
-- 
2.45.2



[COMMITTED] tests/run-sysroot.sh: Delete file with tempfiles

2024-07-11 Thread Aaron Merey
Signed-off-by: Aaron Merey 
---
 tests/run-sysroot.sh | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tests/run-sysroot.sh b/tests/run-sysroot.sh
index cfdc51e9..0bbd1aa4 100755
--- a/tests/run-sysroot.sh
+++ b/tests/run-sysroot.sh
@@ -31,6 +31,8 @@ testrun "${abs_top_builddir}"/src/stack --core 
"${tmpdir}/core.bash" \
 # was built with LZMA support.
 sed -i '4,5d' "${tmpdir}/stack.out"
 
+tempfiles cat.out
+
 # check that we are able to get fully symbolized backtrace
 testrun_compare cat "${tmpdir}/stack.out" <<\EOF
 PID 431185 - core
-- 
2.45.2



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

2024-07-12 Thread Aaron Merey
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.

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



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

2024-07-12 Thread Aaron Merey
On Fri, Jul 12, 2024 at 11:38 AM Aaron Merey  wrote:
>
> 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.

Sorry I should say that no LZMA-support dev package was pre-installed. xz itself
is preinstalled.

Aaron



[PATCH 0/9 v2] Fix thread-safety for elfutils

2024-07-17 Thread Aaron Merey
v1 can be found at
https://sourceware.org/pipermail/elfutils-devel/2023q3/006329.html

Heather McIntyre is the original author of v1 of these patches.
Heather and myself co-wrote v2.

Aaron Merey (9):
  libelf: Fix deadlock in __libelf_readall
  libelf: Fix deadlock in elf_cntl
  lib: Add eu_tsearch, eu_tfind, eu_tdelete and eu_tdestroy
  libdw: make dwarf_getalt thread-safe
  libdwP.h: Add locking to __libdw_dieabbrev
  libdw: Make libdw_find_split_unit thread-safe
  libdw: Make libdw_findcu thread-safe
  tests: Add eu-search tests
  configure: No longer mark --enable-thread-safety as EXPERIMENTAL

 configure.ac  |   6 +-
 lib/Makefile.am   |   5 +-
 lib/eu-config.h   |  30 +---
 lib/eu-search.c   |  85 +++
 lib/eu-search.h   |  64 +
 lib/locks.h   |  62 
 libdw/cfi.h   |   6 +-
 libdw/cie.c   |  10 +-
 libdw/dwarf_begin_elf.c   |   7 +-
 libdw/dwarf_end.c |  17 +--
 libdw/dwarf_formref_die.c |   2 +
 libdw/dwarf_getalt.c  |  18 ++-
 libdw/dwarf_getcfi.c  |   5 +-
 libdw/dwarf_getlocation.c |  24 ++--
 libdw/dwarf_getmacros.c   |   6 +-
 libdw/dwarf_getsrclines.c |   8 +-
 libdw/dwarf_setalt.c  |   4 +
 libdw/fde.c   |   6 +-
 libdw/frame-cache.c   |   8 +-
 libdw/libdwP.h|  49 +--
 libdw/libdw_find_split_unit.c |  18 ++-
 libdw/libdw_findcu.c  |  65 +
 libdwfl/cu.c  |   8 +-
 libdwfl/dwfl_module.c |   4 +-
 libdwfl/libdwflP.h|   3 +-
 libelf/common.h   |  16 +--
 libelf/elf_begin.c|   2 +
 libelf/elf_cntl.c |   7 +-
 libelf/elf_end.c  |  13 +-
 libelf/elf_getdata_rawchunk.c |  12 +-
 libelf/elf_readall.c  |   4 +-
 libelf/libelfP.h  |  10 +-
 tests/.gitignore  |   4 +
 tests/Makefile.am |  19 ++-
 tests/eu_search_cfi.c | 234 ++
 tests/eu_search_die.c | 262 ++
 tests/eu_search_lines.c   | 228 +
 tests/eu_search_macros.c  | 216 
 tests/run-eu-search-tests.sh  | 168 ++
 39 files changed, 1553 insertions(+), 162 deletions(-)
 create mode 100644 lib/eu-search.c
 create mode 100644 lib/eu-search.h
 create mode 100644 lib/locks.h
 create mode 100644 tests/eu_search_cfi.c
 create mode 100644 tests/eu_search_die.c
 create mode 100644 tests/eu_search_lines.c
 create mode 100644 tests/eu_search_macros.c
 create mode 100755 tests/run-eu-search-tests.sh

-- 
2.45.2



[PATCH 2/9 v2] libelf: Fix deadlock in elf_cntl

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* libelf/elf_cntl.c (elf_cntl): Move rwlock_wrlock, rwlock_unlock,
inside case switch statements.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
v2 changes:
Remove unnecessary locking and checking of elf->map_address

 libelf/elf_cntl.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/libelf/elf_cntl.c b/libelf/elf_cntl.c
index 04aa9132..3fbc7d97 100644
--- a/libelf/elf_cntl.c
+++ b/libelf/elf_cntl.c
@@ -48,13 +48,12 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
   return -1;
 }
 
-  rwlock_wrlock (elf->lock);
 
   switch (cmd)
 {
 case ELF_C_FDREAD:
   /* If not all of the file is in the memory read it now.  */
-  if (elf->map_address == NULL && __libelf_readall (elf) == NULL)
+  if (__libelf_readall (elf) == NULL)
{
  /* We were not able to read everything.  */
  result = -1;
@@ -64,7 +63,9 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
 
 case ELF_C_FDDONE:
   /* Mark the file descriptor as not usable.  */
+  rwlock_wrlock (elf->lock);
   elf->fildes = -1;
+  rwlock_unlock (elf->lock);
   break;
 
 default:
@@ -73,7 +74,5 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
   break;
 }
 
-  rwlock_unlock (elf->lock);
-
   return result;
 }
-- 
2.45.2



[PATCH 1/9 v2] libelf: Fix deadlock in __libelf_readall

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

Apply locking during __libelf_readall.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
v2 changes:

Add locking for all early returns in __libelf_readall.

libelf_{acquire,release}_all have been renamed to
libelf_{acquire,release}_all_children.  These functions also no longer
acquire/release the parent's lock.  This is done in order to simplify
lock management in __libelf_readall.

 libelf/common.h  | 16 
 libelf/elf_readall.c |  4 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/libelf/common.h b/libelf/common.h
index 9b2a856d..b7226ee8 100644
--- a/libelf/common.h
+++ b/libelf/common.h
@@ -92,10 +92,8 @@ allocate_elf (int fildes, void *map_address, int64_t offset, 
size_t maxsize,
 /* Acquire lock for the descriptor and all children.  */
 static void
 __attribute__ ((unused))
-libelf_acquire_all (Elf *elf)
+libelf_acquire_all_children (Elf *elf)
 {
-  rwlock_wrlock (elf->lock);
-
   if (elf->kind == ELF_K_AR)
 {
   Elf *child = elf->state.ar.children;
@@ -103,7 +101,9 @@ libelf_acquire_all (Elf *elf)
   while (child != NULL)
{
  if (child->ref_count != 0)
-   libelf_acquire_all (child);
+   libelf_acquire_all_children (child);
+
+ rwlock_wrlock(child->lock);
  child = child->next;
}
 }
@@ -112,7 +112,7 @@ libelf_acquire_all (Elf *elf)
 /* Release own lock and those of the children.  */
 static void
 __attribute__ ((unused))
-libelf_release_all (Elf *elf)
+libelf_release_all_children (Elf *elf)
 {
   if (elf->kind == ELF_K_AR)
 {
@@ -121,12 +121,12 @@ libelf_release_all (Elf *elf)
   while (child != NULL)
{
  if (child->ref_count != 0)
-   libelf_release_all (child);
+   libelf_release_all_children (child);
+
+ rwlock_unlock (child->lock);
  child = child->next;
}
 }
-
-  rwlock_unlock (elf->lock);
 }
 
 
diff --git a/libelf/elf_readall.c b/libelf/elf_readall.c
index d0f9a28c..4ef8fe97 100644
--- a/libelf/elf_readall.c
+++ b/libelf/elf_readall.c
@@ -84,7 +84,7 @@ __libelf_readall (Elf *elf)
 
   /* If this is an archive and we have derived descriptors get the
 locks for all of them.  */
-  libelf_acquire_all (elf);
+  libelf_acquire_all_children (elf);
 
   if (elf->maximum_size == ~((size_t) 0))
{
@@ -141,7 +141,7 @@ __libelf_readall (Elf *elf)
__libelf_seterrno (ELF_E_NOMEM);
 
   /* Free the locks on the children.  */
-  libelf_release_all (elf);
+  libelf_release_all_children (elf);
 }
 
   rwlock_unlock (elf->lock);
-- 
2.45.2



[PATCH 4/9 v2] libdw: make dwarf_getalt thread-safe

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* libdw/dwarf_getalt.c (dwarf_getalt): Add locking.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

v2 changes:

Write lock now applies to all of dwarf_getalt.
---
 libdw/dwarf_getalt.c | 18 --
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/libdw/dwarf_getalt.c b/libdw/dwarf_getalt.c
index 0a12dfae..3b827d0b 100644
--- a/libdw/dwarf_getalt.c
+++ b/libdw/dwarf_getalt.c
@@ -160,15 +160,27 @@ find_debug_altlink (Dwarf *dbg)
 }
 }
 
+/* find_debug_altlink() modifies "dbg->alt_dwarf".
+   dwarf_getalt() reads "main->alt_dwarf".
+   Mutual exclusion is enforced to prevent a race. */
+
 Dwarf *
 dwarf_getalt (Dwarf *main)
 {
+  rwlock_wrlock(main->dwarf_lock);
+
   /* Only try once.  */
   if (main == NULL || main->alt_dwarf == (void *) -1)
-return NULL;
+{
+  rwlock_unlock (main->dwarf_lock);
+  return NULL;
+}
 
   if (main->alt_dwarf != NULL)
-return main->alt_dwarf;
+{
+  rwlock_unlock (main->dwarf_lock);
+  return main->alt_dwarf;
+}
 
   find_debug_altlink (main);
 
@@ -176,9 +188,11 @@ dwarf_getalt (Dwarf *main)
   if (main->alt_dwarf == NULL)
 {
   main->alt_dwarf = (void *) -1;
+  rwlock_unlock (main->dwarf_lock);
   return NULL;
 }
 
+  rwlock_unlock (main->dwarf_lock);
   return main->alt_dwarf;
 }
 INTDEF (dwarf_getalt)
-- 
2.45.2



[PATCH 6/9 v2] libdw: Make libdw_find_split_unit thread-safe

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* (__libdw_find_split_unit): Add lock for cu->split.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---

v2 changes:
Locking applied to __libdw_find_split_unit instead of try_split_file.

 libdw/libdw_find_split_unit.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/libdw/libdw_find_split_unit.c b/libdw/libdw_find_split_unit.c
index 67d31a9c..eb3d88d7 100644
--- a/libdw/libdw_find_split_unit.c
+++ b/libdw/libdw_find_split_unit.c
@@ -150,9 +150,14 @@ Dwarf_CU *
 internal_function
 __libdw_find_split_unit (Dwarf_CU *cu)
 {
+  rwlock_wrlock(cu->split_lock);
+
   /* Only try once.  */
   if (cu->split != (Dwarf_CU *) -1)
-return cu->split;
+{
+  rwlock_unlock(cu->split_lock);
+  return cu->split;
+}
 
   /* We need a skeleton unit with a comp_dir and [GNU_]dwo_name attributes.
  The split unit will be the first in the dwo file and should have the
@@ -207,5 +212,6 @@ __libdw_find_split_unit (Dwarf_CU *cu)
   if (cu->split == (Dwarf_CU *) -1)
 cu->split = NULL;
 
+  rwlock_unlock(cu->split_lock);
   return cu->split;
 }
-- 
2.45.2



[PATCH 5/9 v2] libdwP.h: Add locking to __libdw_dieabbrev,

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---

v2 changes:
This replaces patch "libdw: Add locking around __libdw_dieabbrev for
dwarf_hasattr".  Mark suggested that we remove lazy abbrev reading
in order to simplify the locking of __libdw_dieabbrev.  This is
a fair bit of work so for now lets just put a write lock around all
of __libdw_dieabbrev.  The removal of lazy reading of abbrev will be
done in a future patch.

 libdw/dwarf_formref_die.c |  2 ++
 libdw/dwarf_setalt.c  |  4 
 libdw/libdwP.h| 23 +++
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c
index 48ba8194..f8a51970 100644
--- a/libdw/dwarf_formref_die.c
+++ b/libdw/dwarf_formref_die.c
@@ -92,7 +92,9 @@ dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *result)
  bool scan_debug_types = false;
  do
{
+rwlock_wrlock(attr->cu->dbg->dwarf_lock);
  cu = __libdw_intern_next_unit (attr->cu->dbg, scan_debug_types);
+rwlock_unlock(attr->cu->dbg->dwarf_lock);
  if (cu == NULL)
{
  if (scan_debug_types == false)
diff --git a/libdw/dwarf_setalt.c b/libdw/dwarf_setalt.c
index dc9b61cb..f7d70d9d 100644
--- a/libdw/dwarf_setalt.c
+++ b/libdw/dwarf_setalt.c
@@ -35,6 +35,8 @@
 void
 dwarf_setalt (Dwarf *main, Dwarf *alt)
 {
+  rwlock_wrlock(main->dwarf_lock);
+
   if (main->alt_fd != -1)
 {
   INTUSE(dwarf_end) (main->alt_dwarf);
@@ -43,5 +45,7 @@ dwarf_setalt (Dwarf *main, Dwarf *alt)
 }
 
   main->alt_dwarf = alt;
+
+  rwlock_unlock(main->dwarf_lock);
 }
 INTDEF (dwarf_setalt)
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index a4f26b82..9dce10e5 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -804,15 +804,28 @@ static inline Dwarf_Abbrev *
 __nonnull_attribute__ (1)
 __libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp)
 {
+  if (unlikely (die->cu == NULL))
+{
+  die->abbrev = DWARF_END_ABBREV;
+  return DWARF_END_ABBREV;
+}
+
+  rwlock_wrlock (die->cu->abbrev_lock);
+
   /* Do we need to get the abbreviation, or need to read after the code?  */
   if (die->abbrev == NULL || readp != NULL)
 {
   /* Get the abbreviation code.  */
   unsigned int code;
   const unsigned char *addr = die->addr;
-  if (unlikely (die->cu == NULL
-   || addr >= (const unsigned char *) die->cu->endp))
-   return die->abbrev = DWARF_END_ABBREV;
+
+  if (addr >= (const unsigned char *) die->cu->endp)
+   {
+ die->abbrev = DWARF_END_ABBREV;
+ rwlock_unlock (die->cu->abbrev_lock);
+ return DWARF_END_ABBREV;
+   }
+
   get_uleb128 (code, addr, die->cu->endp);
   if (readp != NULL)
*readp = addr;
@@ -821,7 +834,9 @@ __libdw_dieabbrev (Dwarf_Die *die, const unsigned char 
**readp)
   if (die->abbrev == NULL)
die->abbrev = __libdw_findabbrev (die->cu, code);
 }
-  return die->abbrev;
+
+  rwlock_unlock (die->cu->abbrev_lock);
+  return (Dwarf_Abbrev *) die->abbrev;
 }
 
 /* Helper functions for form handling.  */
-- 
2.45.2



[PATCH 8/9 v2] tests: Add eu-search tests

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* tests/eu_search_cfi.c: New file.
* tests/eu_search_die.c: New file.
* tests/eu_search_lines.c: New file.
* tests/eu_search_macros.c: New file.
* tests/run-eu-search-tests.sh: New test.
* tests/Makefile.am: Add USE_LOCKS condition for -pthread.
(check_PROGRAMS): Add eu_search_cfi, eu_search_die,
eu_search_lines, and eu_search_macros.
(TESTS, EXTRA_DIST): Add run-eu-search-tests.sh
(eu_search_cfi_LDADD): New variable.
(eu_search_die_LDADD): New variable.
(eu_search_lines_LDADD): New variable.
(eu_search_macros_LDADD): New variable.
(eu_search_cfi_LDFLAGS): New variable.
Add -pthread if USE_LOCKS is not defined.
(eu_search_die_LDFLAGS): Likewise.
(eu_search_lines_LDFLAGS): Likewise.
(eu_search_macros_LDFLAGS): Likewise.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 
---
v2 changes:

Rebase and add run-eu-search-tests.sh to EXTRA_DIST.

The elfutils testsuite (including the tests added in this patch) passes
for me on the sourceware buildbots.  However the buildbots do not configure
elfutils with --enable-thread-safety.  I think we should include this
configure option when the buildbots run elfutils tests.

 tests/.gitignore |   4 +
 tests/Makefile.am|  19 ++-
 tests/eu_search_cfi.c| 234 +++
 tests/eu_search_die.c| 262 +++
 tests/eu_search_lines.c  | 228 ++
 tests/eu_search_macros.c | 216 +
 tests/run-eu-search-tests.sh | 168 ++
 7 files changed, 1129 insertions(+), 2 deletions(-)
 create mode 100644 tests/eu_search_cfi.c
 create mode 100644 tests/eu_search_die.c
 create mode 100644 tests/eu_search_lines.c
 create mode 100644 tests/eu_search_macros.c
 create mode 100755 tests/run-eu-search-tests.sh

diff --git a/tests/.gitignore b/tests/.gitignore
index 30f5800b..360c13a3 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -67,6 +67,10 @@
 /elfstrtab
 /elf-print-reloc-syms
 /emptyfile
+/eu_search_cfi
+/eu_search_die
+/eu_search_lines
+/eu_search_macros
 /fillfile
 /find-prologues
 /funcretval
diff --git a/tests/Makefile.am b/tests/Makefile.am
index cfed54b7..1642d4e9 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -32,6 +32,10 @@ else
 tests_rpath = no
 endif
 
+if USE_LOCKS
+  AM_CFLAGS += -pthread
+endif
+
 check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
  showptable update1 update2 update3 update4 test-nlist \
  show-die-info get-files next-files get-lines next-lines \
@@ -64,6 +68,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames 
sectiondump \
  msg_tst system-elf-libelf-test system-elf-gelf-test \
  nvidia_extended_linemap_libdw elf-print-reloc-syms \
  cu-dwp-section-info declfiles \
+ eu_search_cfi eu_search_die eu_search_lines eu_search_macros \
  $(asm_TESTS)
 
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
@@ -216,7 +221,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile 
test-nlist \
run-readelf-dw-form-indirect.sh run-strip-largealign.sh \
run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh 
\
run-declfiles.sh \
-   run-sysroot.sh
+   run-sysroot.sh run-eu-search-tests.sh
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -669,7 +674,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 testfile-dwp-4-cu-index-overflow.dwp.bz2 \
 testfile-dwp-cu-index-overflow.source \
 testfile-define-file.bz2 \
-testfile-sysroot.tar.bz2 run-sysroot.sh
+testfile-sysroot.tar.bz2 run-sysroot.sh \
+run-eu-search-tests.sh
 
 
 if USE_VALGRIND
@@ -849,6 +855,15 @@ nvidia_extended_linemap_libdw_LDADD = $(libelf) $(libdw)
 elf_print_reloc_syms_LDADD = $(libelf)
 cu_dwp_section_info_LDADD = $(libdw)
 declfiles_LDADD = $(libdw)
+eu_search_cfi_LDFLAGS = $(if $(filter undefined,$(origin USE_LOCKS)),-pthread) 
$(AM_LDFLAGS)
+eu_search_die_LDFLAGS = $(if $(filter undefined,$(origin USE_LOCKS)),-pthread) 
$(AM_LDFLAGS)
+eu_search_lines_LDFLAGS = $(if $(filter undefined,$(origin 
USE_LOCKS)),-pthread) $(AM_LDFLAGS)
+eu_search_macros_LDFLAGS = $(if $(filter undefined,$(origin 
USE_LOCKS)),-pthread) $(AM_LDFLAGS)
+eu_search_cfi_LDADD = $(libeu) $(libelf) $(libdw)
+eu_search_die_LDADD = $(libdw)
+eu_search_lines_LDADD = $(libdw) $(libelf)
+eu_search_macros_LDADD = $(libdw)
 
 # We want to test the libelf headers against the system elf.h header.
 # Don't include any -I CPPFLAGS. Except when we install our own elf.h.
diff --git a/tests/eu_search_cfi.c b/tests/eu_search_cfi.c
new file mode 100644
index 000

[PATCH 3/9 v2] lib: Add eu_tsearch, eu_tfind, eu_tdelete and eu_tdestroy

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

Add new struct search_tree to hold tree root and lock.  Add new eu_t*
functions for ensuring synchronized tree access.

Replace tsearch, tfind, etc with eu_t* equivalents.

Move the rwlock_* macros out of eu-config.h and into a new header file
locks.h.  This was done so that the rwlock_* macros can be included
in libdwP.h without having to also include the rest of eu-config.h.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

v2 changes:

This patch replaces v1 03/16 and 14/16.
---
 lib/Makefile.am   |  5 ++-
 lib/eu-config.h   | 30 +
 lib/eu-search.c   | 85 +++
 lib/eu-search.h   | 64 ++
 lib/locks.h   | 62 +
 libdw/cfi.h   |  6 +--
 libdw/cie.c   | 10 +++--
 libdw/dwarf_begin_elf.c   |  7 +--
 libdw/dwarf_end.c | 17 +++
 libdw/dwarf_getcfi.c  |  5 ++-
 libdw/dwarf_getlocation.c | 24 +-
 libdw/dwarf_getmacros.c   |  6 +--
 libdw/dwarf_getsrclines.c |  8 ++--
 libdw/fde.c   |  6 +--
 libdw/frame-cache.c   |  8 ++--
 libdw/libdwP.h| 26 ---
 libdw/libdw_find_split_unit.c | 10 ++---
 libdw/libdw_findcu.c  | 18 
 libdwfl/cu.c  |  8 ++--
 libdwfl/dwfl_module.c |  4 +-
 libdwfl/libdwflP.h|  3 +-
 libelf/elf_begin.c|  2 +
 libelf/elf_end.c  | 13 +++---
 libelf/elf_getdata_rawchunk.c | 12 ++---
 libelf/libelfP.h  | 10 +++--
 25 files changed, 331 insertions(+), 118 deletions(-)
 create mode 100644 lib/eu-search.c
 create mode 100644 lib/eu-search.h
 create mode 100644 lib/locks.h

diff --git a/lib/Makefile.am b/lib/Makefile.am
index b3bb929f..e324c18d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -34,10 +34,11 @@ AM_CPPFLAGS += -I$(srcdir)/../libelf
 noinst_LIBRARIES = libeu.a
 
 libeu_a_SOURCES = xasprintf.c xstrdup.c xstrndup.c xmalloc.c next_prime.c \
- crc32.c crc32_file.c \
+ crc32.c crc32_file.c eu-search.c \
  color.c error.c printversion.c
 
 noinst_HEADERS = fixedsizehash.h libeu.h system.h dynamicsizehash.h list.h \
 eu-config.h color.h printversion.h bpf.h \
-atomics.h stdatomic-fbsd.h dynamicsizehash_concurrent.h
+atomics.h stdatomic-fbsd.h dynamicsizehash_concurrent.h \
+eu-search.h locks.h
 EXTRA_DIST = dynamicsizehash.c dynamicsizehash_concurrent.c
diff --git a/lib/eu-config.h b/lib/eu-config.h
index feb079db..a38d75da 100644
--- a/lib/eu-config.h
+++ b/lib/eu-config.h
@@ -29,35 +29,7 @@
 #ifndef EU_CONFIG_H
 #define EU_CONFIG_H1
 
-#ifdef USE_LOCKS
-# include 
-# include 
-# define rwlock_define(class,name) class pthread_rwlock_t name
-# define once_define(class,name)  class pthread_once_t name = PTHREAD_ONCE_INIT
-# define RWLOCK_CALL(call) \
-  ({ int _err = pthread_rwlock_ ## call; assert_perror (_err); })
-# define ONCE_CALL(call)  \
-  ({ int _err = pthread_ ## call; assert_perror (_err); })
-# define rwlock_init(lock) RWLOCK_CALL (init (&lock, NULL))
-# define rwlock_fini(lock) RWLOCK_CALL (destroy (&lock))
-# define rwlock_rdlock(lock)   RWLOCK_CALL (rdlock (&lock))
-# define rwlock_wrlock(lock)   RWLOCK_CALL (wrlock (&lock))
-# define rwlock_unlock(lock)   RWLOCK_CALL (unlock (&lock))
-# define once(once_control, init_routine)  \
-  ONCE_CALL (once (&once_control, init_routine))
-#else
-/* Eventually we will allow multi-threaded applications to use the
-   libraries.  Therefore we will add the necessary locking although
-   the macros used expand to nothing for now.  */
-# define rwlock_define(class,name) class int name
-# define rwlock_init(lock) ((void) (lock))
-# define rwlock_fini(lock) ((void) (lock))
-# define rwlock_rdlock(lock) ((void) (lock))
-# define rwlock_wrlock(lock) ((void) (lock))
-# define rwlock_unlock(lock) ((void) (lock))
-# define once_define(class,name)
-# define once(once_control, init_routine)  init_routine()
-#endif /* USE_LOCKS */
+#include 
 
 #include 
 /* gettext helper macros.  */
diff --git a/lib/eu-search.c b/lib/eu-search.c
new file mode 100644
index ..b7256eba
--- /dev/null
+++ b/lib/eu-search.c
@@ -0,0 +1,85 @@
+/* Definitions for thread-safe tsearch/tfind
+   Copyright (C) 2023 Rice University
+   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
+   Sof

[PATCH 7/9 v2] libdw: Make libdw_findcu thread-safe

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* libdw/libdw_findcu.c (__libdw_findcu): Use eu_tfind
and dwarf_lock
(__libdw_intern_next_unit): Use per-Dwarf_CU locks.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
v2 changes:
Use per-Dwarf_CU lock instead of a global lock.

 libdw/libdw_findcu.c | 47 
 1 file changed, 30 insertions(+), 17 deletions(-)

diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index 72cf261c..8acff448 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -177,6 +177,8 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
   newp->startp = data->d_buf + newp->start;
   newp->endp = data->d_buf + newp->end;
   eu_search_tree_init (&newp->locs_tree);
+  rwlock_init (newp->abbrev_lock);
+  rwlock_init (newp->split_lock);
 
   /* v4 debug type units have version == 4 and unit_type == DW_UT_type.  */
   if (debug_types)
@@ -243,27 +245,38 @@ __libdw_findcu (Dwarf *dbg, Dwarf_Off start, bool 
v4_debug_types)
   /* Maybe we already know that CU.  */
   struct Dwarf_CU fake = { .start = start, .end = 0 };
   struct Dwarf_CU **found = eu_tfind (&fake, tree, findcu_cb);
+  struct Dwarf_CU *result = NULL;
   if (found != NULL)
 return *found;
 
-  if (start < *next_offset)
-{
-  __libdw_seterrno (DWARF_E_INVALID_DWARF);
-  return NULL;
-}
+  rwlock_wrlock (dbg->dwarf_lock);
 
-  /* No.  Then read more CUs.  */
-  while (1)
-{
-  struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, v4_debug_types);
-  if (newp == NULL)
-   return NULL;
-
-  /* Is this the one we are looking for?  */
-  if (start < *next_offset || start == newp->start)
-   return newp;
-}
-  /* NOTREACHED */
+  if (start < *next_offset)
+__libdw_seterrno (DWARF_E_INVALID_DWARF);
+  else
+{   
+  /* No.  Then read more CUs.  */
+  while (1) 
+{   
+  struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg,
+v4_debug_types);
+  if (newp == NULL)
+{   
+  result = NULL;
+  break;
+}
+
+  /* Is this the one we are looking for?  */
+  if (start < *next_offset || start == newp->start)
+{
+  result = newp;
+  break;
+}
+}
+}   
+
+  rwlock_unlock (dbg->dwarf_lock);
+  return result;
 }
 
 struct Dwarf_CU *
-- 
2.45.2



[PATCH 9/9 v2] configure: No longer mark --enable-thread-safety as EXPERIMENTAL

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* configure.ac (--enable-thread-safety): Remove experimental
warning.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 
---

No changes in v2.  However PR31967 (datarace in elf_compress[_gnu])
was recently filed and this patch set does not address it.  Maybe
we should hold off on merging this patch and keep thread safety
"experimental" until PR31967 is fixed.

 configure.ac | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/configure.ac b/configure.ac
index 24e68d94..2c885c8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,12 +79,10 @@ AC_DEFINE_UNQUOTED(DEFAULT_AR_DETERMINISTIC, 
$default_ar_deterministic,
 
 AC_ARG_ENABLE([thread-safety],
 AS_HELP_STRING([--enable-thread-safety],
-   [enable thread safety of libraries EXPERIMENTAL]),
+   [enable thread safety of libraries]),
use_locks=$enableval, use_locks=no)
 AM_CONDITIONAL(USE_LOCKS, test "$use_locks" = yes)
 AS_IF([test "$use_locks" = yes], [AC_DEFINE(USE_LOCKS)])
-AS_IF([test "$use_locks" = yes],
-  [AC_MSG_WARN([thread-safety is EXPERIMENTAL tests might fail.])])
 
 AH_TEMPLATE([USE_LOCKS], [Defined if libraries should be thread-safe.])
 
@@ -939,10 +937,10 @@ AC_MSG_NOTICE([
 Symbol versioning  : ${enable_symbol_versioning}
 
   NOT RECOMMENDED FEATURES (should all be no)
-Experimental thread safety : ${use_locks}
 install elf.h  : ${install_elfh}
 
   OTHER FEATURES
+Enable thread safety   : ${use_locks}
 Deterministic archives by default  : ${default_ar_deterministic}
 Native language support: ${USE_NLS}
 Extra Valgrind annotations : ${use_vg_annotations}
-- 
2.45.2



Re: [PATCH 0/9 v2] Fix thread-safety for elfutils

2024-07-18 Thread Aaron Merey
Hi Milian,

On Thu, Jul 18, 2024 at 6:14 AM Milian Wolff  wrote:
>
> On Donnerstag, 18. Juli 2024 00:33:59 MESZ Aaron Merey wrote:
> > v1 can be found at
> > https://sourceware.org/pipermail/elfutils-devel/2023q3/006329.html
> >
> > Heather McIntyre is the original author of v1 of these patches.
> > Heather and myself co-wrote v2.
>
> Hey you all,
>
> this sounds very promising! I have some high level questions:
>
> Could you please add some documentation on the thread safety guarantees when
> elfutils was compiled with `--enable-thread-safety`?

This is definitely needed.  I've been working on adding man pages for
elfutils public library functions.  We should indicate whether each
function is MT-Safe.  We should also have man pages for libelf, libdw,
etc, themselves and these should include thread safety information and
constraints. I will prioritize this.

> For my purposes in
> maintaining profilers (heaptrack, hotspot), it would be extremely cool if we
> could eventually use multiple threads to analyze separate samples. In theory,
> I would hope that "write" operations (such as `dwfl_report_{begin,end,elf}`
> will require synchronization, but subsequent "read" operations (such as those
> needed for symbolication
> (`dwfl_{addrmodule,module_getsymtab,module_getsym_info,module_nextcu,module_info,module_address_section,
> get_debuginfod_client,...`,
> `dwarf_{tag,getscopes_die,formstring,fromudata,diename,getsrc_die,dieoffset,linesrc,lineno,getsrcfiles,attr_integrate,...`)
> or unwinding (`dwfl_{thread_state_registers,frame_pc,getthread_frames}) could
> happen in parallel. Is that the case already after this patch set?

This patch set is not entirely comprehensive.  It focuses on thread safety
in libelf and libdw (not libdwfl) and there is still at least one data race
in libelf (see https://sourceware.org/bugzilla/show_bug.cgi?id=31967).
However what you describe should be possible when this feature is more
fully implemented.

In the v1 of this patch set there is a patch which removed the
"experimental" notice from the --enable-thread-safety configure option.
I left this patch in v2 but I think that we should defer that patch and
instead keep thread safety "experimental" until it is more fully tested
and production ready.

> Generally it seems like the documentation could see some love in better
> explaining this feature.
>
> How can I query at runtime whether elfutils was compiled with thread safety
> guarantees or not, such that I can adapt my consumer side accordingly (i.e.
> enable multi-threading or not)?

libelf is compiled with pthread only when elfutils is built with
the --enable-thread-safety configure option.  So ATM I believe that
checking the libelf binary for pthread_rwlock_* symbols with
{eu-}readelf or another tool is your best option.

I should also mention that libdw is built with pthread unconditionally,
whether or not --enable-thread-safety is given.  However libelf and
libdw should always be installed and upgraded in lockstep, so if
libelf contains pthread_rwlock_* symbols then it's reasonable to
assume that libdw was also built with --enable-thread-safety.

However this is not ideal.  Maybe we should add some way to verify
thread safety to the public library API.

Aaron



[PATCH] Add man pages for some libelf functions

2024-07-18 Thread Aaron Merey
Add man pages for elf32_offscn.3, elf64_offscn.3, elf_getscn.3 and
elf_ndxscn.3.

Signed-off-by: Aaron Merey 
---
 doc/elf32_offscn.3 | 61 +
 doc/elf64_offscn.3 | 62 ++
 doc/elf_getscn.3   | 55 
 doc/elf_ndxscn.3   | 52 ++
 4 files changed, 230 insertions(+)
 create mode 100644 doc/elf32_offscn.3
 create mode 100644 doc/elf64_offscn.3
 create mode 100644 doc/elf_getscn.3
 create mode 100644 doc/elf_ndxscn.3

diff --git a/doc/elf32_offscn.3 b/doc/elf32_offscn.3
new file mode 100644
index ..5d4a657f
--- /dev/null
+++ b/doc/elf32_offscn.3
@@ -0,0 +1,61 @@
+.TH ELF32_OFFSCN 3 2024-07-18 "Libelf" "Libelf Programmer's Manual"
+
+.SH NAME
+elf32_offscn \- retrieve a section descriptor by file offset for a 32-bit ELF 
file
+
+.SH SYNOPSIS
+.B #include 
+
+.BI "Elf_Scn *elf32_offscn(Elf *" elf ", off_t " offset ");"
+
+.SH DESCRIPTION
+The
+.B elf32_offscn
+function retrieves the section descriptor for the section at the specified 
file offset in the ELF32 object referred to by
+.I elf.
+
+.SH PARAMETERS
+.TP
+.I elf
+An
+.I Elf pointer to the ELF object from which the section descriptor is to be 
retrieved.
+
+.TP
+.I offset
+An
+.I off_t
+value representing the file offset of the section whose descriptor is to be 
retrieved.
+
+.SH RETURN VALUE
+The
+.B elf32_offscn
+function returns a pointer to the
+.I Elf_Scn
+for the section at the specified offset. If an error occurs, it returns NULL 
and sets an appropriate libelf error code.
+
+.SH ATTRIBUTES
+For an explanation of the terms used in this section, see
+.BR attributes (7).
+.TS
+allbox;
+lbx lb lb
+l l l.
+Interface  Attribute   Value
+T{
+.na
+.nh
+.BR elf32_offscn ()
+T} Thread safety   MT-Safe
+.TE
+
+.SH SEE ALSO
+.BR elf64_offscn (3),
+.BR libelf (3),
+.BR elf (5),
+
+.SH REPORTING BUGS
+Report bugs to  or 
https://sourceware.org/bugzilla/.
+
+.SH HISTORY
+.B elf32_offscn
+first appeared in elfutils 0.112.
diff --git a/doc/elf64_offscn.3 b/doc/elf64_offscn.3
new file mode 100644
index ..4ab29b30
--- /dev/null
+++ b/doc/elf64_offscn.3
@@ -0,0 +1,62 @@
+.TH ELF64_OFFSCN 3 2024-07-18 "Libelf" "Libelf Programmer's Manual"
+
+.SH NAME
+elf64_offscn \- retrieve a section descriptor by file offset for a 64-bit ELF 
file
+
+.SH SYNOPSIS
+.B #include 
+
+.BI "Elf_Scn *elf64_offscn(Elf *" elf ", off_t " offset ");"
+
+.SH DESCRIPTION
+The
+.B elf64_offscn
+function retrieves the section descriptor for the section at the specified 
file offset in the ELF64 object referred to by
+.I elf.
+
+.SH PARAMETERS
+.TP
+.I elf
+An
+.I Elf
+pointer to the ELF object from which the section descriptor is to be retrieved.
+
+.TP
+.I offset
+An
+.I off_t
+value representing the file offset of the section whose descriptor is to be 
retrieved.
+
+.SH RETURN VALUE
+The
+.B elf64_offscn
+function returns a pointer to the
+.I Elf_Scn
+for the section at the specified offset. If an error occurs, it returns NULL 
and sets an appropriate libelf error code.
+
+.SH ATTRIBUTES
+For an explanation of the terms used in this section, see
+.BR attributes (7).
+.TS
+allbox;
+lbx lb lb
+l l l.
+Interface  Attribute   Value
+T{
+.na
+.nh
+.BR elf64_offscn ()
+T} Thread safety   MT-Safe
+.TE
+
+.SH SEE ALSO
+.BR elf32_offscn (3),
+.BR libelf (3),
+.BR elf (5),
+
+.SH REPORTING BUGS
+Report bugs to  or 
https://sourceware.org/bugzilla/.
+
+.SH HISTORY
+.B elf64_offscn
+first appeared in elfutils 0.112.
diff --git a/doc/elf_getscn.3 b/doc/elf_getscn.3
new file mode 100644
index ..1be13369
--- /dev/null
+++ b/doc/elf_getscn.3
@@ -0,0 +1,55 @@
+.TH ELF_GETSCN 3 2024-07-18 "Libelf" "Libelf Programmer's Manual"
+
+.SH NAME
+elf_getscn \- retrieve a descriptor for an ELF section at a specified index.
+
+.SH SYNOPSIS
+.B #include 
+
+.BI "Elf_Scn *elf_getscn(Elf *" elf ", size_t " index ");"
+
+.SH DESCRIPTION
+The .B elf_getscn function retrieves a section descriptor for the section at 
the specified index in the ELF object referred to by .I elf.
+
+.SH PARAMETERS
+.TP
+.I elf
+An
+.I Elf
+pointer to the ELF object from which the section descriptor is to be retrieved.
+
+.TP
+.I index
+A
+.I size_t
+value representing the index of the section whose descriptor is to be 
retrieved. Section indices start at 0.
+
+.SH RETURN VALUE
+The
+.B elf_getscn
+function returns a pointer to the
+.I Elf_Scn
+for the section at the specified index. If an error occurs, it returns NULL 
and sets an appropriate libelf error code.
+
+.SH ATTRIBUTES
+For an explanation of the terms used in this section, see
+.BR attributes (7).
+.TS
+allbox;
+lbx lb lb
+l l l.
+Interface  Attribute   Value
+T{
+.na
+.nh
+.BR elf_getscn ()
+T} Thread safe

[PATCH] Add man pages for some libelf functions

2024-07-18 Thread Aaron Merey
Add man pages for elf32_offscn.3, elf64_offscn.3, elf_getscn.3 and
elf_ndxscn.3.

Signed-off-by: Aaron Merey 
---

Reposting this patch with the new man pages added to doc/Makefile.am.

 doc/Makefile.am|  6 -
 doc/elf32_offscn.3 | 61 +
 doc/elf64_offscn.3 | 62 ++
 doc/elf_getscn.3   | 55 
 doc/elf_ndxscn.3   | 52 ++
 5 files changed, 235 insertions(+), 1 deletion(-)
 create mode 100644 doc/elf32_offscn.3
 create mode 100644 doc/elf64_offscn.3
 create mode 100644 doc/elf_getscn.3
 create mode 100644 doc/elf_ndxscn.3

diff --git a/doc/Makefile.am b/doc/Makefile.am
index db8526fc..86c1d82d 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -35,7 +35,11 @@ notrans_dist_man3_MANS= elf_update.3 \
elf64_getehdr.3 \
elf_errmsg.3 \
elf_errno.3 \
-   elf_version.3
+   elf_version.3 \
+   elf32_offscn.3 \
+   elf64_offscn.3 \
+   elf_getscn.3 \
+   elf_ndxscn.3
 
 # libdebuginfod man pages (also notrans)
 # Note we include them even when not building them because we want
diff --git a/doc/elf32_offscn.3 b/doc/elf32_offscn.3
new file mode 100644
index ..5d4a657f
--- /dev/null
+++ b/doc/elf32_offscn.3
@@ -0,0 +1,61 @@
+.TH ELF32_OFFSCN 3 2024-07-18 "Libelf" "Libelf Programmer's Manual"
+
+.SH NAME
+elf32_offscn \- retrieve a section descriptor by file offset for a 32-bit ELF 
file
+
+.SH SYNOPSIS
+.B #include 
+
+.BI "Elf_Scn *elf32_offscn(Elf *" elf ", off_t " offset ");"
+
+.SH DESCRIPTION
+The
+.B elf32_offscn
+function retrieves the section descriptor for the section at the specified 
file offset in the ELF32 object referred to by
+.I elf.
+
+.SH PARAMETERS
+.TP
+.I elf
+An
+.I Elf pointer to the ELF object from which the section descriptor is to be 
retrieved.
+
+.TP
+.I offset
+An
+.I off_t
+value representing the file offset of the section whose descriptor is to be 
retrieved.
+
+.SH RETURN VALUE
+The
+.B elf32_offscn
+function returns a pointer to the
+.I Elf_Scn
+for the section at the specified offset. If an error occurs, it returns NULL 
and sets an appropriate libelf error code.
+
+.SH ATTRIBUTES
+For an explanation of the terms used in this section, see
+.BR attributes (7).
+.TS
+allbox;
+lbx lb lb
+l l l.
+Interface  Attribute   Value
+T{
+.na
+.nh
+.BR elf32_offscn ()
+T} Thread safety   MT-Safe
+.TE
+
+.SH SEE ALSO
+.BR elf64_offscn (3),
+.BR libelf (3),
+.BR elf (5),
+
+.SH REPORTING BUGS
+Report bugs to  or 
https://sourceware.org/bugzilla/.
+
+.SH HISTORY
+.B elf32_offscn
+first appeared in elfutils 0.112.
diff --git a/doc/elf64_offscn.3 b/doc/elf64_offscn.3
new file mode 100644
index ..4ab29b30
--- /dev/null
+++ b/doc/elf64_offscn.3
@@ -0,0 +1,62 @@
+.TH ELF64_OFFSCN 3 2024-07-18 "Libelf" "Libelf Programmer's Manual"
+
+.SH NAME
+elf64_offscn \- retrieve a section descriptor by file offset for a 64-bit ELF 
file
+
+.SH SYNOPSIS
+.B #include 
+
+.BI "Elf_Scn *elf64_offscn(Elf *" elf ", off_t " offset ");"
+
+.SH DESCRIPTION
+The
+.B elf64_offscn
+function retrieves the section descriptor for the section at the specified 
file offset in the ELF64 object referred to by
+.I elf.
+
+.SH PARAMETERS
+.TP
+.I elf
+An
+.I Elf
+pointer to the ELF object from which the section descriptor is to be retrieved.
+
+.TP
+.I offset
+An
+.I off_t
+value representing the file offset of the section whose descriptor is to be 
retrieved.
+
+.SH RETURN VALUE
+The
+.B elf64_offscn
+function returns a pointer to the
+.I Elf_Scn
+for the section at the specified offset. If an error occurs, it returns NULL 
and sets an appropriate libelf error code.
+
+.SH ATTRIBUTES
+For an explanation of the terms used in this section, see
+.BR attributes (7).
+.TS
+allbox;
+lbx lb lb
+l l l.
+Interface  Attribute   Value
+T{
+.na
+.nh
+.BR elf64_offscn ()
+T} Thread safety   MT-Safe
+.TE
+
+.SH SEE ALSO
+.BR elf32_offscn (3),
+.BR libelf (3),
+.BR elf (5),
+
+.SH REPORTING BUGS
+Report bugs to  or 
https://sourceware.org/bugzilla/.
+
+.SH HISTORY
+.B elf64_offscn
+first appeared in elfutils 0.112.
diff --git a/doc/elf_getscn.3 b/doc/elf_getscn.3
new file mode 100644
index ..1be13369
--- /dev/null
+++ b/doc/elf_getscn.3
@@ -0,0 +1,55 @@
+.TH ELF_GETSCN 3 2024-07-18 "Libelf" "Libelf Programmer's Manual"
+
+.SH NAME
+elf_getscn \- retrieve a descriptor for an ELF section at a specified index.
+
+.SH SYNOPSIS
+.B #include 
+
+.BI "Elf_Scn *elf_getscn(Elf *" elf ", size_t " index ");"
+
+.SH DESCRIPTION
+The .B elf_getscn function retrieves a section descriptor for the 

Re: [PATCH v4 0/7] debuginfod: speed up extraction from kernel debuginfo packages by 200x

2024-07-23 Thread Aaron Merey
Hi Omar,

On Fri, Jul 19, 2024 at 2:24 PM Omar Sandoval  wrote:
>
> From: Omar Sandoval 
>
> This is v4 of my patch series optimizing debuginfod for kernel
> debuginfo.  v1 is here [1], v2 is here [2], v3 is here [3].  The only
> changes from v3 in this version are fixing a bogus maybe-uninitialized
> error on the Debian build and adding the new test files to EXTRA_DIST so
> that make distcheck passes.
>
> Thanks,
> Omar
>
> 1: https://sourceware.org/pipermail/elfutils-devel/2024q3/007191.html
> 2: https://sourceware.org/pipermail/elfutils-devel/2024q3/007208.html
> 3: https://sourceware.org/pipermail/elfutils-devel/2024q3/007243.html

Thanks for working on these patches.  I ran v4 on the sourceware buildbots.
The new testcase fails on debian-ppc64 [1], debian-i386 [2] and
fedora-s390x [3].  There was a 4th failing buildbot but AFAICT the failure
is unrelated to your patches.

Do you mind taking a look at this?  The patches otherwise LGTM and I'll
merge them once this is passing on the buildbots.

Aaron

[1] https://builder.sourceware.org/buildbot/#/builders/214/builds/190
[2] https://builder.sourceware.org/buildbot/#/builders/210/builds/194
[3] https://builder.sourceware.org/buildbot/#/builders/211/builds/185



Re: [PATCH] Add man pages for some libelf functions

2024-07-24 Thread Aaron Merey
Hi Mark,

On Sun, Jul 21, 2024 at 6:15 PM Mark Wielaard  wrote:
>
> Hi Aaron,
>
> Some small comments below.
>
> On Thu, Jul 18, 2024 at 10:03:02PM -0400, Aaron Merey wrote:
> > Add man pages for elf32_offscn.3, elf64_offscn.3, elf_getscn.3 and
> > elf_ndxscn.3.
> >
> > Signed-off-by: Aaron Merey 

Thanks for the review. I updated the patch with your suggestions and
pushed it as commit a49d5c0e6dee.

Aaron



Re: [PATCH v5 0/7] debuginfod: speed up extraction from kernel debuginfo packages by 200x

2024-07-24 Thread Aaron Merey
On Tue, Jul 23, 2024 at 6:40 PM Omar Sandoval  wrote:
>
> From: Omar Sandoval 
>
> This is v4 of my patch series optimizing debuginfod for kernel
> debuginfo.  v1 is here [1], v2 is here [2], v3 is here [3], v4 is here
> [4].  The only change from v4 in this version is adding --fdcache-mbs
> and --fdcache-mintmp to the new test to fix some sporadic test failures.
> Hopefully this version finally gets a clean test run.

Thanks Omar. I've gone ahead and merged these patches.

Aaron



[PATCH 01/10 v3] libelf: Fix deadlock in __libelf_readall

2024-08-02 Thread Aaron Merey
From: Heather McIntyre 

Apply locking during __libelf_readall.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
v3 changes:

Update comments and change order or child lock aquisition.

 libelf/common.h  | 24 ++--
 libelf/elf_readall.c |  4 ++--
 2 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/libelf/common.h b/libelf/common.h
index 9b2a856d..8e33a70e 100644
--- a/libelf/common.h
+++ b/libelf/common.h
@@ -89,30 +89,34 @@ allocate_elf (int fildes, void *map_address, int64_t 
offset, size_t maxsize,
 }
 
 
-/* Acquire lock for the descriptor and all children.  */
+/* Caller must hold a lock for ELF. If there are children then a lock
+   will be acquired for each of them (recursively).  */
 static void
 __attribute__ ((unused))
-libelf_acquire_all (Elf *elf)
+libelf_acquire_all_children (Elf *elf)
 {
-  rwlock_wrlock (elf->lock);
-
   if (elf->kind == ELF_K_AR)
 {
   Elf *child = elf->state.ar.children;
 
   while (child != NULL)
{
+ rwlock_wrlock (child->lock);
+
  if (child->ref_count != 0)
-   libelf_acquire_all (child);
+   libelf_acquire_all_children (child);
+
  child = child->next;
}
 }
 }
 
-/* Release own lock and those of the children.  */
+
+/* Caller must hold a lock for ELF. If there are children then a lock
+   will be released for each of them (recursively).  */
 static void
 __attribute__ ((unused))
-libelf_release_all (Elf *elf)
+libelf_release_all_children (Elf *elf)
 {
   if (elf->kind == ELF_K_AR)
 {
@@ -121,12 +125,12 @@ libelf_release_all (Elf *elf)
   while (child != NULL)
{
  if (child->ref_count != 0)
-   libelf_release_all (child);
+   libelf_release_all_children (child);
+
+ rwlock_unlock (child->lock);
  child = child->next;
}
 }
-
-  rwlock_unlock (elf->lock);
 }
 
 
diff --git a/libelf/elf_readall.c b/libelf/elf_readall.c
index d0f9a28c..4ef8fe97 100644
--- a/libelf/elf_readall.c
+++ b/libelf/elf_readall.c
@@ -84,7 +84,7 @@ __libelf_readall (Elf *elf)
 
   /* If this is an archive and we have derived descriptors get the
 locks for all of them.  */
-  libelf_acquire_all (elf);
+  libelf_acquire_all_children (elf);
 
   if (elf->maximum_size == ~((size_t) 0))
{
@@ -141,7 +141,7 @@ __libelf_readall (Elf *elf)
__libelf_seterrno (ELF_E_NOMEM);
 
   /* Free the locks on the children.  */
-  libelf_release_all (elf);
+  libelf_release_all_children (elf);
 }
 
   rwlock_unlock (elf->lock);
-- 
2.45.2



[PATCH 02/10 v3] libelf: Fix deadlock in elf_cntl

2024-08-02 Thread Aaron Merey
From: Heather McIntyre 

* libelf/elf_cntl.c (elf_cntl): Move rwlock_wrlock, rwlock_unlock,
inside case switch statements.  Remove unnecessary early return.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
v3 changes:
Remove unnecessary early return that would require locking to
check condition.

 libelf/elf_cntl.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/libelf/elf_cntl.c b/libelf/elf_cntl.c
index 04aa9132..da4ea999 100644
--- a/libelf/elf_cntl.c
+++ b/libelf/elf_cntl.c
@@ -42,19 +42,11 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
   if (elf == NULL)
 return -1;
 
-  if (elf->fildes == -1)
-{
-  __libelf_seterrno (ELF_E_INVALID_HANDLE);
-  return -1;
-}
-
-  rwlock_wrlock (elf->lock);
-
   switch (cmd)
 {
 case ELF_C_FDREAD:
   /* If not all of the file is in the memory read it now.  */
-  if (elf->map_address == NULL && __libelf_readall (elf) == NULL)
+  if (__libelf_readall (elf) == NULL)
{
  /* We were not able to read everything.  */
  result = -1;
@@ -64,7 +56,9 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
 
 case ELF_C_FDDONE:
   /* Mark the file descriptor as not usable.  */
+  rwlock_wrlock (elf->lock);
   elf->fildes = -1;
+  rwlock_unlock (elf->lock);
   break;
 
 default:
@@ -73,7 +67,5 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
   break;
 }
 
-  rwlock_unlock (elf->lock);
-
   return result;
 }
-- 
2.45.2



[PATCH 03/10 v3] lib: Add eu_tsearch, eu_tfind, eu_tdelete and eu_tdestroy

2024-08-02 Thread Aaron Merey
From: Heather McIntyre 

Add struct search_tree to hold tree root and lock.  Add new eu_t*
functions for ensuring synchronized tree access.

Replace tsearch, tfind, etc with eu_t* equivalents.

lib:
* Makefile.am (libeu_a_SOURCES): Add eu-search.c.
(noinst_HEADERS): Add eu-search.h and locks.h.
* eu-config.h: Move rwlock macros to locks.h.
* eu-search.c: New file containing tree search functions with
  locking.
* eu-search.h: New file.
* locks.h: New file containing rwlock macros previously in
  eu-config.h.
libdw:
* cfi.h (struct Dwarf_CFI_s): Change type of search tree members
  from void * to search_tree.
* cie.c: Replace tree search functions with eu-search equivalents.
* dwarf_begin_elf.c (valid_p): Initialize search trees.
* dwarf_end.c (cu_free): Replace tree search functions
  with eu-search equivalents.
* dwarf_getcfi.c (dwarf_getcfi): Initialize search trees.
* dwarf_getlocations.c: Replace search tree functions with
  eu-search equivalents.
  (__libdw_intern_expression): Change type of cache parameter to
  search_tree *.
* dwarf_getmacros.c: Replace tree search functions with
  eu-search equivalents.
* dwarf_getsrclines.c: Ditto.
* fde.c: Ditto.
* frame-cache.c (__libdw_destroy_frame_cache): Initialize search
  trees.
* libdwP.h (struct Dwarf): Change type of search tree members
  from void * to search_tree.
  (struct Dwarf_CU): Ditto.
  (__libdw_intern_expression): Change type of cache parameter to
  search_tree *.
* libdw_find_split_unit.c: Replace tree search functions with
  eu-search equivalents.
* libdw_findcu.c: Ditto.
libdwfl:
* cu.c: Ditto.
* libdwflP.h (struct Dwfl_Module): Replace void *lazy_cu_root
  with search_tree lazy_cu_tree.
libelf:
* elf_begin.c (file_read_elf): Initialize rawchunck_tree.
* elf_end.c (elf_end): Replace tree search function with
  eu-search equivalent.
* elf_getdata_rawchunck.c: Ditto.
* libelfP.h (struct Elf): Replace void * rawchuncks memeber with
search_tree rawchunk_tree.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---

v3 changes:

Moved most locking code to another patch in this series.
include "eu-search.h" and "locks.h" instead of 
and 

On Fri, Jul 19, 2024 at 8:51 AM Mark Wielaard  wrote:
> Is eu_tdestroy ever used now?
> It looks like everything now uses eu_search_tree_fine.
> Could still be a useful function to have, just checking.

Yes the function less_lazy in libdwfl/cu.c uses it.

> > +#define LOCKS_H 1
> > +
> > +#ifdef USE_LOCKS
> > +# include 
> > +# include 
>
> Why the assert.h include?

It's needed for assert_perror in the RWLOCK_CALL macro

> >/* We know about all the CUs now, we don't need this table.  */
> > -  tdestroy (mod->lazy_cu_root, nofree);
> > -  mod->lazy_cu_root = NULL;
> > +  eu_tdestroy (&mod->lazy_cu_tree, nofree);
> >  }
>
> OK, a eu_tdestroy here, and then there is a eu_search_tree_fini in
> __libdwfl_module_free, which will call eu_tdestroy again (on the now
> NULL tree). Is that correct? Does [eu_]tdestroy handle NULL trees?

Yes NULL is a valid (empty) tree.


 lib/Makefile.am   |  5 ++-
 lib/eu-config.h   | 30 +
 lib/eu-search.c   | 85 +++
 lib/eu-search.h   | 64 ++
 lib/locks.h   | 62 +
 libdw/cfi.h   |  6 +--
 libdw/cie.c   | 10 +++--
 libdw/dwarf_begin_elf.c   |  6 +--
 libdw/dwarf_end.c | 15 +++
 libdw/dwarf_getcfi.c  |  5 ++-
 libdw/dwarf_getlocation.c | 23 +-
 libdw/dwarf_getmacros.c   |  6 +--
 libdw/dwarf_getsrclines.c |  8 ++--
 libdw/fde.c   |  6 +--
 libdw/frame-cache.c   |  8 ++--
 libdw/libdwP.h| 16 ---
 libdw/libdw_find_split_unit.c | 10 ++---
 libdw/libdw_findcu.c  | 18 
 libdwfl/cu.c  |  8 ++--
 libdwfl/dwfl_module.c |  4 +-
 libdwfl/libdwflP.h|  3 +-
 libelf/elf_begin.c|  2 +
 libelf/elf_end.c  | 13 +++---
 libelf/elf_getdata_rawchunk.c | 12 ++---
 libelf/libelfP.h  | 10 +++--
 25 files changed, 317 insertions(+), 118 deletions(-)
 create mode 100644 lib/eu-search.c
 create mode 100644 lib/eu-search.h
 create mode 100644 lib/locks.h

diff --git a/lib/Makefile.am b/lib/Makefile.am
index b3bb929f..e324c18d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -34,10 +34,11 @@ AM_CPPFLAGS += -I$(srcdir)/../libelf
 n

[PATCH 04/10 v3] libdw: Add rwlocks for Dwarf and Dwarf_CU

2024-08-02 Thread Aaron Merey
From: Heather McIntyre 

Add dwarf_lock for Dwarf as well as abbrev_lock for Dwarf_CU.

* libdw/dwarf_begin_elf.c (dwarf_begin_elf): Init dwarf_lock.
* libdw/dwarf_end.c (cu_free): Free abbrev_lock.
(dwarf_end): Free dwarf_lock.
* libdw/libdwP.h (struct Dwarf): Define dwarf_lock.
(struct Dwarf_CU): Define abbrev_lock.
* libdw/libdw_findcu.c (__libdw_intern_next_unit): Init
  abbrev_lock.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 

---
v3 changes:
New patch added in v3 that contains rwlock changes previously in patch 3/9 v2.

 libdw/dwarf_begin_elf.c | 1 +
 libdw/dwarf_end.c   | 2 ++
 libdw/libdwP.h  | 7 +++
 libdw/libdw_findcu.c| 1 +
 4 files changed, 11 insertions(+)

diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index b4f3a83a..e4826dda 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -579,6 +579,7 @@ dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
   __libdw_seterrno (DWARF_E_NOMEM); /* no memory.  */
   return NULL;
 }
+  rwlock_init (result->dwarf_lock);
   result->mem_stacks = 0;
   result->mem_tails = NULL;
 
diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index 60a3e4fd..487d6ce7 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -68,6 +68,7 @@ cu_free (void *arg)
  && p != p->dbg->fake_addr_cu)
 {
   Dwarf_Abbrev_Hash_free (&p->abbrev_hash);
+  rwlock_fini (p->abbrev_lock);
 
   /* Free split dwarf one way (from skeleton to split).  */
   if (p->unit_type == DW_UT_skeleton
@@ -127,6 +128,7 @@ dwarf_end (Dwarf *dwarf)
   if (dwarf->mem_tails != NULL)
 free (dwarf->mem_tails);
   pthread_rwlock_destroy (&dwarf->mem_rwl);
+  rwlock_fini (dwarf->dwarf_lock);
 
   /* Free the pubnames helper structure.  */
   free (dwarf->pubnames_sets);
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index ae9386f1..c95296e9 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -264,6 +264,10 @@ struct Dwarf
  allocations for this Dwarf.  */
   pthread_rwlock_t mem_rwl;
 
+  /* The dwarf_lock is a read-write lock designed to ensure thread-safe access
+ and modification of Dwarf objects.  */
+  rwlock_define(, dwarf_lock);
+
   /* Internal memory handling.  This is basically a simplified thread-local
  reimplementation of obstacks.  Unfortunately the standard obstack
  implementation is not usable in libraries.  */
@@ -447,6 +451,9 @@ struct Dwarf_CU
  Don't access directly, call __libdw_cu_locs_base.  */
   Dwarf_Off locs_base;
 
+  /* Synchronize Dwarf_Die abbrev access.  */
+  rwlock_define(, abbrev_lock);
+
   /* Memory boundaries of this CU.  */
   void *startp;
   void *endp;
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index bfbad410..0f46d777 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -177,6 +177,7 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
   newp->startp = data->d_buf + newp->start;
   newp->endp = data->d_buf + newp->end;
   eu_search_tree_init (&newp->locs_tree);
+  rwlock_init (newp->abbrev_lock);
 
   /* v4 debug type units have version == 4 and unit_type == DW_UT_type.  */
   if (debug_types)
-- 
2.45.2



[PATCH 05/10 v3] libdw: make dwarf_getalt and dwarf_setalt thread-safe

2024-08-02 Thread Aaron Merey
From: Heather McIntyre 

* libdw/dwarf_getalt.c (dwarf_getalt): Add locking.
* libdw/dwarf_setalt.c (dwarf_setalt): Ditto.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
v3 changes:

Check for NULL argument before acquiring lock. Assign result before
releasing lock.  Include dwarf_setalt.c changes that were previously
included in patch 5/9 v2.

 libdw/dwarf_getalt.c | 31 +++
 libdw/dwarf_setalt.c |  3 +++
 2 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/libdw/dwarf_getalt.c b/libdw/dwarf_getalt.c
index 0a12dfae..26433b81 100644
--- a/libdw/dwarf_getalt.c
+++ b/libdw/dwarf_getalt.c
@@ -160,15 +160,34 @@ find_debug_altlink (Dwarf *dbg)
 }
 }
 
+/* find_debug_altlink() modifies "dbg->alt_dwarf".
+   dwarf_getalt() reads "main->alt_dwarf".
+   Mutual exclusion is enforced to prevent a race. */
+
 Dwarf *
 dwarf_getalt (Dwarf *main)
 {
-  /* Only try once.  */
-  if (main == NULL || main->alt_dwarf == (void *) -1)
+  if (main == NULL)
 return NULL;
 
+  rwlock_wrlock(main->dwarf_lock);
+
+  /* Only try once.  */
+  if (main->alt_dwarf == (void *) -1)
+{
+  rwlock_unlock (main->dwarf_lock);
+  return NULL;
+}
+
+  /* Assign result before releasing the lock.  */
+  Dwarf *result;
+
   if (main->alt_dwarf != NULL)
-return main->alt_dwarf;
+{
+  result = main->alt_dwarf;
+  rwlock_unlock (main->dwarf_lock);
+  return result;
+}
 
   find_debug_altlink (main);
 
@@ -176,9 +195,13 @@ dwarf_getalt (Dwarf *main)
   if (main->alt_dwarf == NULL)
 {
   main->alt_dwarf = (void *) -1;
+  rwlock_unlock (main->dwarf_lock);
   return NULL;
 }
 
-  return main->alt_dwarf;
+  result = main->alt_dwarf;
+  rwlock_unlock (main->dwarf_lock);
+
+  return result;
 }
 INTDEF (dwarf_getalt)
diff --git a/libdw/dwarf_setalt.c b/libdw/dwarf_setalt.c
index dc9b61cb..f98a457c 100644
--- a/libdw/dwarf_setalt.c
+++ b/libdw/dwarf_setalt.c
@@ -35,6 +35,8 @@
 void
 dwarf_setalt (Dwarf *main, Dwarf *alt)
 {
+  rwlock_wrlock (main->dwarf_lock);
+
   if (main->alt_fd != -1)
 {
   INTUSE(dwarf_end) (main->alt_dwarf);
@@ -43,5 +45,6 @@ dwarf_setalt (Dwarf *main, Dwarf *alt)
 }
 
   main->alt_dwarf = alt;
+  rwlock_unlock (main->dwarf_lock);
 }
 INTDEF (dwarf_setalt)
-- 
2.45.2



[PATCH 06/10 v3] libdwP.h: Add locking to dwarf_formref_die and __libdw_dieabbrev

2024-08-02 Thread Aaron Merey
From: Heather McIntyre 

* libdw/dwarf_formref_die.c (dwarf_formref_die): Add locking
  around call to __libdw_intern_next_unit.
* libdw/libdwP.h (__libdw_dieabbrev): Add locking.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

v3 changes:
Move dwarf_setalt.c changes to patch 5/9 v3.
Set __libdw_dieabbrev result before releasing lock.
---
 libdw/dwarf_formref_die.c |  3 +++
 libdw/libdwP.h| 25 +
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c
index 48ba8194..69d1bf1c 100644
--- a/libdw/dwarf_formref_die.c
+++ b/libdw/dwarf_formref_die.c
@@ -92,7 +92,10 @@ dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *result)
  bool scan_debug_types = false;
  do
{
+ rwlock_wrlock(attr->cu->dbg->dwarf_lock);
  cu = __libdw_intern_next_unit (attr->cu->dbg, scan_debug_types);
+ rwlock_unlock(attr->cu->dbg->dwarf_lock);
+
  if (cu == NULL)
{
  if (scan_debug_types == false)
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index c95296e9..492cfe8c 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -801,15 +801,28 @@ static inline Dwarf_Abbrev *
 __nonnull_attribute__ (1)
 __libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp)
 {
+  if (unlikely (die->cu == NULL))
+{
+  die->abbrev = DWARF_END_ABBREV;
+  return DWARF_END_ABBREV;
+}
+
+  rwlock_wrlock (die->cu->abbrev_lock);
+
   /* Do we need to get the abbreviation, or need to read after the code?  */
   if (die->abbrev == NULL || readp != NULL)
 {
   /* Get the abbreviation code.  */
   unsigned int code;
   const unsigned char *addr = die->addr;
-  if (unlikely (die->cu == NULL
-   || addr >= (const unsigned char *) die->cu->endp))
-   return die->abbrev = DWARF_END_ABBREV;
+
+  if (addr >= (const unsigned char *) die->cu->endp)
+   {
+ die->abbrev = DWARF_END_ABBREV;
+ rwlock_unlock (die->cu->abbrev_lock);
+ return DWARF_END_ABBREV;
+   }
+
   get_uleb128 (code, addr, die->cu->endp);
   if (readp != NULL)
*readp = addr;
@@ -818,7 +831,11 @@ __libdw_dieabbrev (Dwarf_Die *die, const unsigned char 
**readp)
   if (die->abbrev == NULL)
die->abbrev = __libdw_findabbrev (die->cu, code);
 }
-  return die->abbrev;
+
+  Dwarf_Abbrev *result = die->abbrev;
+  rwlock_unlock (die->cu->abbrev_lock);
+
+  return result; 
 }
 
 /* Helper functions for form handling.  */
-- 
2.45.2



[PATCH 07/10 v3] libdw: Make libdw_find_split_unit thread-safe

2024-08-02 Thread Aaron Merey
From: Heather McIntyre 

* libdw/libdwP.h (struct Dwarf_CU): Add split_lock.
* libdw/libdw_find_split_unit.c (__libdw_find_split_unit):
  Add locking.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
v3 changes:
Move Dwarf split_lock code from patch 3/9 v2 to this patch.
Assign return value before releasing lock.

 libdw/dwarf_end.c |  1 +
 libdw/libdwP.h|  3 +++
 libdw/libdw_find_split_unit.c | 15 +--
 libdw/libdw_findcu.c  |  1 +
 4 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index 487d6ce7..ee3ed74e 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -69,6 +69,7 @@ cu_free (void *arg)
 {
   Dwarf_Abbrev_Hash_free (&p->abbrev_hash);
   rwlock_fini (p->abbrev_lock);
+  rwlock_fini (p->split_lock);
 
   /* Free split dwarf one way (from skeleton to split).  */
   if (p->unit_type == DW_UT_skeleton
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 48c34871..8f942433 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -454,6 +454,9 @@ struct Dwarf_CU
   /* Synchronize Dwarf_Die abbrev access.  */
   rwlock_define(, abbrev_lock);
 
+  /* Synchronize split Dwarf access.  */
+  rwlock_define(, split_lock);
+
   /* Memory boundaries of this CU.  */
   void *startp;
   void *endp;
diff --git a/libdw/libdw_find_split_unit.c b/libdw/libdw_find_split_unit.c
index 4005793b..f4f34c5d 100644
--- a/libdw/libdw_find_split_unit.c
+++ b/libdw/libdw_find_split_unit.c
@@ -150,9 +150,18 @@ Dwarf_CU *
 internal_function
 __libdw_find_split_unit (Dwarf_CU *cu)
 {
+  /* Set result before releasing the lock.  */
+  Dwarf_CU *result;
+
+  rwlock_wrlock(cu->split_lock);
+
   /* Only try once.  */
   if (cu->split != (Dwarf_CU *) -1)
-return cu->split;
+{
+  result = cu->split;
+  rwlock_unlock(cu->split_lock);
+  return result;
+}
 
   /* We need a skeleton unit with a comp_dir and [GNU_]dwo_name attributes.
  The split unit will be the first in the dwo file and should have the
@@ -207,5 +216,7 @@ __libdw_find_split_unit (Dwarf_CU *cu)
   if (cu->split == (Dwarf_CU *) -1)
 cu->split = NULL;
 
-  return cu->split;
+  result = cu->split;
+  rwlock_unlock(cu->split_lock);
+  return result;
 }
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index 0f46d777..c74e895e 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -178,6 +178,7 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
   newp->endp = data->d_buf + newp->end;
   eu_search_tree_init (&newp->locs_tree);
   rwlock_init (newp->abbrev_lock);
+  rwlock_init (newp->split_lock);
 
   /* v4 debug type units have version == 4 and unit_type == DW_UT_type.  */
   if (debug_types)
-- 
2.45.2



[PATCH 08/10 v3] libdw: Make libdw_findcu thread-safe

2024-08-02 Thread Aaron Merey
From: Heather McIntyre 

* libdw/libdw_findcu.c (__libdw_findcu): Add locking.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
v3 changes:
Fix indentation and move rwlock_init calls to other patches in this
series.

 libdw/libdw_findcu.c | 38 +-
 1 file changed, 25 insertions(+), 13 deletions(-)

diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index c74e895e..ee5d 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -245,27 +245,39 @@ __libdw_findcu (Dwarf *dbg, Dwarf_Off start, bool 
v4_debug_types)
   /* Maybe we already know that CU.  */
   struct Dwarf_CU fake = { .start = start, .end = 0 };
   struct Dwarf_CU **found = eu_tfind (&fake, tree, findcu_cb);
+  struct Dwarf_CU *result = NULL;
   if (found != NULL)
 return *found;
 
+  rwlock_wrlock (dbg->dwarf_lock);
+
   if (start < *next_offset)
+__libdw_seterrno (DWARF_E_INVALID_DWARF);
+  else
 {
-  __libdw_seterrno (DWARF_E_INVALID_DWARF);
-  return NULL;
-}
+  /* No.  Then read more CUs.  */
+  while (1)
+   {
+ struct Dwarf_CU *newp
+   = __libdw_intern_next_unit (dbg, v4_debug_types);
 
-  /* No.  Then read more CUs.  */
-  while (1)
-{
-  struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, v4_debug_types);
-  if (newp == NULL)
-   return NULL;
+ if (newp == NULL)
+   {
+ result = NULL;
+ break;
+   }
 
-  /* Is this the one we are looking for?  */
-  if (start < *next_offset || start == newp->start)
-   return newp;
+ /* Is this the one we are looking for?  */
+ if (start < *next_offset || start == newp->start)
+   {
+ result = newp;
+ break;
+   }
+   }
 }
-  /* NOTREACHED */
+
+  rwlock_unlock (dbg->dwarf_lock);
+  return result;
 }
 
 struct Dwarf_CU *
-- 
2.45.2



[PATCH 10/10 v3] configure: No longer mark --enable-thread-safety as EXPERIMENTAL

2024-08-02 Thread Aaron Merey
From: Heather McIntyre 

* configure.ac (--enable-thread-safety): Remove experimental
warning.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 
---
No changes between v2 and v3.

PR31967 (datarace in elf_compress[_gnu]) was recently filed and this patch
set does not address it.  libdwfl requires additional locking.  I think we
should hold off on merging this patch and keep thread safety "experimental"
until these issues are fixed.

Aaron

 configure.ac | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/configure.ac b/configure.ac
index 24e68d94..2c885c8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,12 +79,10 @@ AC_DEFINE_UNQUOTED(DEFAULT_AR_DETERMINISTIC, 
$default_ar_deterministic,
 
 AC_ARG_ENABLE([thread-safety],
 AS_HELP_STRING([--enable-thread-safety],
-   [enable thread safety of libraries EXPERIMENTAL]),
+   [enable thread safety of libraries]),
use_locks=$enableval, use_locks=no)
 AM_CONDITIONAL(USE_LOCKS, test "$use_locks" = yes)
 AS_IF([test "$use_locks" = yes], [AC_DEFINE(USE_LOCKS)])
-AS_IF([test "$use_locks" = yes],
-  [AC_MSG_WARN([thread-safety is EXPERIMENTAL tests might fail.])])
 
 AH_TEMPLATE([USE_LOCKS], [Defined if libraries should be thread-safe.])
 
@@ -939,10 +937,10 @@ AC_MSG_NOTICE([
 Symbol versioning  : ${enable_symbol_versioning}
 
   NOT RECOMMENDED FEATURES (should all be no)
-Experimental thread safety : ${use_locks}
 install elf.h  : ${install_elfh}
 
   OTHER FEATURES
+Enable thread safety   : ${use_locks}
 Deterministic archives by default  : ${default_ar_deterministic}
 Native language support: ${USE_NLS}
 Extra Valgrind annotations : ${use_vg_annotations}
-- 
2.45.2



[PATCH 09/10 v3] tests: Add eu-search tests

2024-08-02 Thread Aaron Merey
From: Heather McIntyre 

* tests/eu_search_cfi.c: New file.
* tests/eu_search_die.c: New file.
* tests/eu_search_lines.c: New file.
* tests/eu_search_macros.c: New file.
* tests/run-eu-search-tests.sh: New test.
* tests/Makefile.am: Add USE_LOCKS condition for -pthread.
(check_PROGRAMS): Add eu_search_cfi, eu_search_die,
eu_search_lines, and eu_search_macros.
(TESTS): Add run-eu-search-tests.sh
(eu_search_cfi_LDADD): New variable.
(eu_search_die_LDADD): New variable.
(eu_search_lines_LDADD): New variable.
(eu_search_macros_LDADD): New variable.
(eu_search_cfi_LDFLAGS): New variable.
Add -pthread if USE_LOCKS is not defined.
(eu_search_die_LDFLAGS): Likewise.
(eu_search_lines_LDFLAGS): Likewise.
(eu_search_macros_LDFLAGS): Likewise.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
No changes between v2 and v3.

The elfutils testsuite (including the tests added in this patch) passes
for me on the sourceware buildbots.  However the buildbots do not configure
elfutils with --enable-thread-safety.  I think we should include this
configure option when the buildbots run elfutils tests.

Aaron

 tests/.gitignore |   4 +
 tests/Makefile.am|  19 ++-
 tests/eu_search_cfi.c| 234 +++
 tests/eu_search_die.c| 262 +++
 tests/eu_search_lines.c  | 228 ++
 tests/eu_search_macros.c | 216 +
 tests/run-eu-search-tests.sh | 168 ++
 7 files changed, 1129 insertions(+), 2 deletions(-)
 create mode 100644 tests/eu_search_cfi.c
 create mode 100644 tests/eu_search_die.c
 create mode 100644 tests/eu_search_lines.c
 create mode 100644 tests/eu_search_macros.c
 create mode 100755 tests/run-eu-search-tests.sh

diff --git a/tests/.gitignore b/tests/.gitignore
index 30f5800b..360c13a3 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -67,6 +67,10 @@
 /elfstrtab
 /elf-print-reloc-syms
 /emptyfile
+/eu_search_cfi
+/eu_search_die
+/eu_search_lines
+/eu_search_macros
 /fillfile
 /find-prologues
 /funcretval
diff --git a/tests/Makefile.am b/tests/Makefile.am
index cfed54b7..1642d4e9 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -32,6 +32,10 @@ else
 tests_rpath = no
 endif
 
+if USE_LOCKS
+  AM_CFLAGS += -pthread
+endif
+
 check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
  showptable update1 update2 update3 update4 test-nlist \
  show-die-info get-files next-files get-lines next-lines \
@@ -64,6 +68,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames 
sectiondump \
  msg_tst system-elf-libelf-test system-elf-gelf-test \
  nvidia_extended_linemap_libdw elf-print-reloc-syms \
  cu-dwp-section-info declfiles \
+ eu_search_cfi eu_search_die eu_search_lines eu_search_macros \
  $(asm_TESTS)
 
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
@@ -216,7 +221,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile 
test-nlist \
run-readelf-dw-form-indirect.sh run-strip-largealign.sh \
run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh 
\
run-declfiles.sh \
-   run-sysroot.sh
+   run-sysroot.sh run-eu-search-tests.sh
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -669,7 +674,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 testfile-dwp-4-cu-index-overflow.dwp.bz2 \
 testfile-dwp-cu-index-overflow.source \
 testfile-define-file.bz2 \
-testfile-sysroot.tar.bz2 run-sysroot.sh
+testfile-sysroot.tar.bz2 run-sysroot.sh \
+run-eu-search-tests.sh
 
 
 if USE_VALGRIND
@@ -849,6 +855,15 @@ nvidia_extended_linemap_libdw_LDADD = $(libelf) $(libdw)
 elf_print_reloc_syms_LDADD = $(libelf)
 cu_dwp_section_info_LDADD = $(libdw)
 declfiles_LDADD = $(libdw)
+eu_search_cfi_LDFLAGS = $(if $(filter undefined,$(origin USE_LOCKS)),-pthread) 
$(AM_LDFLAGS)
+eu_search_die_LDFLAGS = $(if $(filter undefined,$(origin USE_LOCKS)),-pthread) 
$(AM_LDFLAGS)
+eu_search_lines_LDFLAGS = $(if $(filter undefined,$(origin 
USE_LOCKS)),-pthread) $(AM_LDFLAGS)
+eu_search_macros_LDFLAGS = $(if $(filter undefined,$(origin 
USE_LOCKS)),-pthread) $(AM_LDFLAGS)
+eu_search_cfi_LDADD = $(libeu) $(libelf) $(libdw)
+eu_search_die_LDADD = $(libdw)
+eu_search_lines_LDADD = $(libdw) $(libelf)
+eu_search_macros_LDADD = $(libdw)
+
 
 # We want to test the libelf headers against the system elf.h header.
 # Don't include any -I CPPFLAGS. Except when we install our own elf.h.
diff --git a/tests/eu_search_cfi.c b/tests/eu_search_cfi.c
new file mode 100644
index ..0b63b213
--- /dev/null
+++ b/

Re: [PATCH] Prevent binaries in src from colliding with libc++ headers

2024-08-07 Thread Aaron Merey
Hi Tristan,

Thanks for the patch, some comments below.

> From 11f000782c16f05f81a15d4dba75deb082ab97e1 Mon Sep 17 00:00:00 2001
> From: Tristan Ross 
> Date: Tue, 30 Jul 2024 21:03:03 -0700
> Subject: [PATCH] Prevent binaries in src from colliding with libc++ headers
>
> Discovered with Nix and LLVM 17. Headers inside of libc++ can easily
> collide with binaries being linked in src. This results in clang trying
> to include a binary as a header.
>
> Signed-off-by: Tristan Ross 
> ---
>  ChangeLog   | 5 +
>  src/Makefile.am | 4 +++-
>  2 files changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/ChangeLog b/ChangeLog
> index 6aed95b6..5ba0680e 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,3 +1,8 @@
> +2024-07-30  Tristan Ross  
> +
> +* src/Makefile.am: Prevent collision between headers and
> +binaries in libc++.
> +

This change can be dropped, we no longer update ChangeLogs.

>  2023-03-27  Di Chen  
>
>  * NEWS: Support readelf -Ds for using dynamic segment to
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 1d592d4d..8e182c4f 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -19,7 +19,9 @@
>  include $(top_srcdir)/config/eu.am
>  DEFS += $(YYDEBUG) -DDEBUGPRED=@DEBUGPRED@ \
>  -DSRCDIR=\"$(shell cd $(srcdir);pwd)\" -DOBJDIR=\"$(shell pwd)\"
> -AM_CPPFLAGS += -I$(srcdir)/../libelf -I$(srcdir)/../libebl \
> +DEFAULT_INCLUDES = -I$(top_builddir)
> +AM_CPPFLAGS = -I$(top_srcdir)/lib -I.. \
> +-I$(srcdir)/../libelf -I$(srcdir)/../libebl \
>  -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf \
>  -I$(srcdir)/../libdwfl -I$(srcdir)/../libasm -I../debuginfod

DEFAULT_INCLUDES and AM_CPPFLAGS default to `-I. -I$(top_builddir)` and
`-I. -I$(srcdir) -I$(top_srcdir)/lib -I..` respectively.  So essentially
this change removes -I. and -I$(srcdir) from these variables.

I noticed that with this patch autoreconf now emits a warning:

src/Makefile.am:23: warning: AM_CPPFLAGS multiply defined [...]
config/eu.am:34: ... 'AM_CPPFLAGS' previously defined here
src/Makefile.am:19:   'config/eu.am' included from here

Is there a way to implement this change without triggering any
warnings during the build?

Aaron



Re: [PATCH] backends/riscv: Remove unused relocations

2024-08-07 Thread Aaron Merey
On Wed, Jul 31, 2024 at 9:03 AM Andreas Schwab  wrote:
>
> None of these relocations were ever part of any object file.  The
> GNU_VTINHERIT and GNU_VTINHERIT relocations were part of the obsolete
> --gc-sections support which was never implemented for RISC-V.  The other
> relocations are only used internally by libbfd during the relaxation pass
> and eliminated before writing the object file.
>
> * riscv_reloc.def: Remove GNU_VTINHERIT, GNU_VTENTRY, RVC_LUI,
> GPREL_I, GPREL_S, TPREL_I, TPREL_S.

Thanks Andreas, merged as commit 46c5c98ee7.

Aaron



Re: [PATCH] Prevent binaries in src from colliding with libc++ headers

2024-08-08 Thread Aaron Merey
From: Tristan Ross 

Hi Tristan

On Wed, Aug 7, 2024 at 5:07 PM Tristan ross  wrote:
>
> Gotcha on that ChangeLog thing. With the warning, I think we can just
> use `?=` in `config/eu.am` for `AM_CPPFLAGS`.

I tried this but I still got an error during autoreconf.  I tweaked
your patch below so that the AM_CPPFLAGS definition is set in a
separate file that src/Makefile.am can avoid including.  I also
removed the ChangeLog update from the patch.

Let me know if this updated patch works for you.

Thanks,
Aaron

---

Discovered with Nix and LLVM 17. Headers inside of libc++ can easily
collide with binaries being linked in src. This results in clang trying
to include a binary as a header.

Fix this by removing '-I.' and '-I$(srcdir)' from AM_CPPFLAGS and
DEFAULT_INCLUDES in src/Makefile.am.

To facilitate this config/eu.am has been refactored.  New file
config/eu-common.am contains all of the old eu.am but with the
AM_CPPFLAGS definition removed. eu.am now includes eu-common.am and
contains the old AM_CPPFLAGS definition.

eu.am functionality does not change, but src/Makefile.am can instead
include eu-common.am and define its own AM_CPPFLAGS without causing a
"multiply defined" warning during autoreconf.

Signed-off-by: Tristan Ross 
---
 config/eu-common.am | 148 
 config/eu.am| 120 +--
 src/Makefile.am |   6 +-
 3 files changed, 155 insertions(+), 119 deletions(-)
 create mode 100644 config/eu-common.am

diff --git a/config/eu-common.am b/config/eu-common.am
new file mode 100644
index ..9cc7f696
--- /dev/null
+++ b/config/eu-common.am
@@ -0,0 +1,148 @@
+## Common automake fragments for elfutils subdirectory makefiles.
+##
+## Copyright (C) 2010, 2014, 2016 Red Hat, Inc.
+## Copyright (C) 2023, Mark J. Wielaard 
+##
+## 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 the License, or (at
+## your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see .
+##
+
+DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"'
+
+# Drop the 'u' flag that automake adds by default. It is incompatible
+# with deterministic archives.
+ARFLAGS = cr
+
+# Warn about stack usage of more than 256K = 262144 bytes.
+if ADD_STACK_USAGE_WARNING
+STACK_USAGE_WARNING=-Wstack-usage=262144
+STACK_USAGE_NO_ERROR=-Wno-error=stack-usage=
+else
+STACK_USAGE_WARNING=
+STACK_USAGE_NO_ERROR=
+endif
+
+if SANE_LOGICAL_OP_WARNING
+LOGICAL_OP_WARNING=-Wlogical-op
+else
+LOGICAL_OP_WARNING=
+endif
+
+if HAVE_DUPLICATED_COND_WARNING
+DUPLICATED_COND_WARNING=-Wduplicated-cond
+else
+DUPLICATED_COND_WARNING=
+endif
+
+if HAVE_NULL_DEREFERENCE_WARNING
+NULL_DEREFERENCE_WARNING=-Wnull-dereference
+else
+NULL_DEREFERENCE_WARNING=
+endif
+
+if HAVE_IMPLICIT_FALLTHROUGH_WARNING
+# Use strict fallthrough. Only __attribute__((fallthrough)) will prevent the
+# warning
+if HAVE_IMPLICIT_FALLTHROUGH_5_WARNING
+IMPLICIT_FALLTHROUGH_WARNING=-Wimplicit-fallthrough=5
+else
+IMPLICIT_FALLTHROUGH_WARNING=-Wimplicit-fallthrough
+endif
+else
+IMPLICIT_FALLTHROUGH_WARNING=
+endif
+
+if HAVE_TRAMPOLINES_WARNING
+TRAMPOLINES_WARNING=-Wtrampolines
+else
+TRAMPOLINES_WARNING=
+endif
+
+if HAVE_NO_PACKED_NOT_ALIGNED_WARNING
+NO_PACKED_NOT_ALIGNED_WARNING=-Wno-packed-not-aligned
+else
+NO_PACKED_NOT_ALIGNED_WARNING=
+endif
+
+if HAVE_USE_AFTER_FREE3_WARNING
+USE_AFTER_FREE3_WARNING=-Wuse-after-free=3
+else
+USE_AFTER_FREE3_WARNING=
+endif
+
+AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \
+   -Wold-style-definition -Wstrict-prototypes $(TRAMPOLINES_WARNING) \
+   $(LOGICAL_OP_WARNING) $(DUPLICATED_COND_WARNING) \
+   $(NULL_DEREFERENCE_WARNING) $(IMPLICIT_FALLTHROUGH_WARNING) \
+   $(USE_AFTER_FREE3_WARNING) \
+   $(if $($(*F)_no_Werror),,-Werror) \
+   $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
+   $(if $($(*F)_no_Wstack_usage),,$(STACK_USAGE_WARNING)) \
+   $(if 
$($(*F)_no_Wpacked_not_aligned),$(NO_PACKED_NOT_ALIGNED_WARNING),) \
+   $($(*F)_CFLAGS)
+
+AM_CXXFLAGS = -std=c++11 -Wall -Wshadow \
+  $(TRAMPOLINES_WARNING) \
+  $(LOGICAL_OP_WA

Re: [PATCH] Prevent binaries in src from colliding with libc++ headers

2024-08-08 Thread Aaron Merey
Hi Tristan,

On Thu, Aug 8, 2024 at 2:19 PM Aaron Merey  wrote:
> On Wed, Aug 7, 2024 at 5:07 PM Tristan ross  wrote:
> >
> > Gotcha on that ChangeLog thing. With the warning, I think we can just
> > use `?=` in `config/eu.am` for `AM_CPPFLAGS`.
>
> I tried this but I still got an error during autoreconf.  I tweaked
> your patch below so that the AM_CPPFLAGS definition is set in a
> separate file that src/Makefile.am can avoid including.  I also
> removed the ChangeLog update from the patch.
>
> Let me know if this updated patch works for you.

Can you also provide a reproducer for the error you are seeing?

Thanks,
Aaron



Re: [PATCH] Prevent binaries in src from colliding with libc++ headers

2024-08-09 Thread Aaron Merey
Hi Tristan,

(elfutils-devel CC'ed)

On Thu, Aug 8, 2024 at 6:09 PM Tristan ross  wrote:
>
> > Can you also provide a reproducer for the error you are seeing?
>
> I think this can be reproduced if you build elfutils with Clang and Clang is 
> using libc++ (LLVM's C++ implementation). Build with like `make -j10` and 
> then you will get an error which looks like this:
>
>   CCLD nm
>   CCLD ar
>   CCLD elfcompress
>   CCLD strip
>   CCLD unstrip
> In file included from srcfiles.cxx:50:
> In file included from 
> /nix/store/649b79xp5hfmjc5a5xwq7nxw8lrwjs5y-libcxx-aarch64-unknown-linux-gnu-18.1.8-dev/include/c++/v1/iostream:44:
> In file included from 
> /nix/store/649b79xp5hfmjc5a5xwq7nxw8lrwjs5y-libcxx-aarch64-unknown-linux-gnu-18.1.8-dev/include/c++/v1/istream:170:
> In file included from 
> /nix/store/649b79xp5hfmjc5a5xwq7nxw8lrwjs5y-libcxx-aarch64-unknown-linux-gnu-18.1.8-dev/include/c++/v1/ostream:189:
> In file included from 
> /nix/store/649b79xp5hfmjc5a5xwq7nxw8lrwjs5y-libcxx-aarch64-unknown-linux-gnu-18.1.8-dev/include/c++/v1/format:195:
> In file included from 
> /nix/store/649b79xp5hfmjc5a5xwq7nxw8lrwjs5y-libcxx-aarch64-unknown-linux-gnu-18.1.8-dev/include/c++/v1/__format/container_adaptor.h:25:
> ./stack:1:1: error: expected unqualified-id

Thanks. There was discussion about this bug on IRC, it looks like it's
the same bug as https://bugs.gentoo.org/925241.  This bug was fixed in
gentoo with a simpler patch [1] than what I proposed.  I suggest we
use the gentoo patch instead.

Aaron

[1] 
https://gitweb.gentoo.org/repo/gentoo.git/tree/dev-libs/elfutils/files/elfutils-0.191-avoid-overriding-libcxx-system-header.patch?id=631d30345702f6c5aa323808f8ebbae1c0fbd5ea



Re: [PATCH] Prevent binaries in src from colliding with libc++ headers

2024-08-09 Thread Aaron Merey
(elfutils-devel CC'ed)

On Fri, Aug 9, 2024 at 10:32 AM Tristan ross  wrote:
>
> The Gentoo patch looks essentially the same as what we started with which 
> might bring that warning back. It also uses `-iquote .` but from what I've 
> seen, no files in src import with quotes. But that patch will work.

I built elfutils with the gentoo patch and there were no autoreconf warnings.

Aaron



Re: [PATCH] Prevent binaries in src from colliding with libc++ headers

2024-08-14 Thread Aaron Merey
Hi Tristan,

On Fri, Aug 9, 2024 at 10:43 AM Tristan ross  wrote:
>
> Well, that's great. Probably should use it instead since it's simpler.
>
>  日付:Fri, 09 Aug 2024 07:38:05 -0700 差出人:ame...@redhat.com 
>
> (elfutils-devel CC'ed)
>
> On Fri, Aug 9, 2024 at 10:32 AM Tristan ross  
> wrote:
> >
> > The Gentoo patch looks essentially the same as what we started with which 
> > might bring that warning back. It also uses `-iquote .` but from what I've 
> > seen, no files in src import with quotes. But that patch will work.
>
> I built elfutils with the gentoo patch and there were no autoreconf warnings.

I've merged the gentoo patch as commit b426c4db31e

Thanks,
Aaron



  1   2   3   4   >