[PATCH] libdw: Handle DW_OP_GNU_uninit in dwarf_getlocation

2023-02-10 Thread Mark Wielaard
dwarf_getlocation would return an error when it saw a
DW_OP_GNU_uninit. Handle it by simply recognizing as a no argument
operation.

DW_OP_GNU_uninit is emitted by GCC as a marker to flag the location
expression as referring to an uninitialized value.

Signed-off-by: Mark Wielaard 
---
 libdw/ChangeLog   | 5 +
 libdw/dwarf_getlocation.c | 1 +
 tests/ChangeLog   | 4 
 tests/varlocs.c   | 6 ++
 4 files changed, 16 insertions(+)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 71e96c88..9bea831e 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2023-02-10  Mark Wielaard  
+
+   * dwarf_getlocation.c (__libdw_intern_expression): Handle
+   DW_OP_GNU_uninit.
+
 2023-01-22  Mark Wielaard  
 
* dwarf_getscopes.c (pc_record): Return nscopes when done.
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index d0d78163..553fdc98 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -396,6 +396,7 @@ __libdw_intern_expression (Dwarf *dbg, bool 
other_byte_order,
case DW_OP_form_tls_address:
case DW_OP_GNU_push_tls_address:
case DW_OP_stack_value:
+   case DW_OP_GNU_uninit:
  /* No operand.  */
  break;
 
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 974a3a4f..fd261bc6 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2023-02-10  Mark Wielaard  
+
+   * varlocs.c (print_expr): Handle DW_OP_GNU_uninit.
+
 2023-02-03  Mark Wielaard  
 
* run-addr2line-C-test.sh: Check ELFUTILS_DISABLE_DEMANGLE.
diff --git a/tests/varlocs.c b/tests/varlocs.c
index d2c13767..8e563fd3 100644
--- a/tests/varlocs.c
+++ b/tests/varlocs.c
@@ -251,6 +251,12 @@ print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, 
Dwarf_Addr addr, int depth)
   printf ("%s", opname);
   break;
 
+case DW_OP_GNU_uninit:
+  /* No arguments. Special. It means the expression describes
+an value which hasn't been initialized (yet).  */
+  printf ("%s", opname);
+  break;
+
 case DW_OP_call_frame_cfa:
   /* No arguments. Special. Pushes Call Frame Address as computed
 by CFI data (dwarf_cfi_addrframe will fetch that info (either from
-- 
2.39.1



[PATCH] PR28873 - Implement eu-readelf -D

2023-02-10 Thread Di Chen via Elfutils-devel
>From bdc19de94bff8f8812611b9ba8c0116a650d0fb5 Mon Sep 17 00:00:00 2001
From: Di Chen 
Date: Fri, 13 Jan 2023 20:12:43 +0800
Subject: [PATCH] readelf: display dynamic symtab without section headers

This commit adds a new option "-D/--use-dynamic" to support printing the
dynamic symbol table from the PT_DYNAMIC segment. By using the
PT_DYNAMIC segment, eu-readelf can go through the contents of dynamic
section entries and the values of each tag. From that, we can get the
address and size of the dynamic symbol table, the address of the string
table, etc.

By using the new option "-D/--use-dynamic", eu-readelf can list the
symbols without section headers.

Example:
  $ ./src/readelf -Ds a.out
  0:   0 NOTYPE  LOCAL  DEFAULTUNDEF
  1:   0 FUNCGLOBAL DEFAULTUNDEF
__libc_start_main@GLIBC_2.34 (2)
  2:   0 NOTYPE  WEAK   DEFAULTUNDEF
__gmon_start__

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

Signed-off-by: Di Chen 
---
 src/readelf.c | 289 --
 1 file changed, 283 insertions(+), 6 deletions(-)

diff --git a/src/readelf.c b/src/readelf.c
index 451f8400..9e1e9b73 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -307,7 +307,8 @@ static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr
*ehdr, Elf_Scn *scn,
 static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
  GElf_Shdr *shdr);
 static bool print_symtab (Ebl *ebl, int type);
-static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
+static bool handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
+static bool handle_dynamic_symtab (Ebl *ebl);
 static void print_verinfo (Ebl *ebl);
 static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
 static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
@@ -327,7 +328,9 @@ enum dyn_idx
 {
   i_strsz,
   i_verneed,
+  i_verneednum,
   i_verdef,
+  i_verdefnum,
   i_versym,
   i_symtab,
   i_strtab,
@@ -1042,7 +1045,7 @@ process_elf_file (Dwfl_Module *dwflmod, int fd)
 symtab_printed |= print_symtab (ebl, SHT_DYNSYM);
   if (print_version_info)
 print_verinfo (ebl);
-  if (print_symbol_table)
+  if (print_symbol_table && !use_dynamic_segment)
 symtab_printed |= print_symtab (ebl, SHT_SYMTAB);

   if ((print_symbol_table || print_dynsym_table)
@@ -2442,6 +2445,12 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr,
Elf_Scn *scn, GElf_Shdr *shdr)
 static bool
 print_symtab (Ebl *ebl, int type)
 {
+  /* Use the dynamic section info to display symbol tables.  */
+  if (use_dynamic_segment && type == SHT_DYNSYM)
+  {
+ return handle_dynamic_symtab(ebl);
+  }
+
   /* Find the symbol table(s).  For this we have to search through the
  section table.  */
   Elf_Scn *scn = NULL;
@@ -2480,16 +2489,275 @@ print_symtab (Ebl *ebl, int type)
 _("cannot get section [%zd] header: %s"),
 elf_ndxscn (scn), elf_errmsg (-1));
 }
-  handle_symtab (ebl, scn, shdr);
-  symtab_printed = true;
+  symtab_printed = handle_symtab (ebl, scn, shdr);
  }
 }

   return symtab_printed;
 }

+static bool
+handle_dynamic_symtab (Ebl *ebl)
+{
+  GElf_Phdr *phdr = NULL;
+  /* phnum is a static variable which already fetched in function
process_elf_file.  */
+  for (size_t i = 0; i < phnum; ++i) {
+GElf_Phdr phdr_mem;
+phdr = gelf_getphdr(ebl->elf, i, &phdr_mem);
+if (phdr->p_type == PT_DYNAMIC) {
+  break;
+}
+  }
+  if (phdr == NULL)
+ return false;

-static void
+  GElf_Addr addrs[i_max] = {0,};
+  GElf_Off offs[i_max] = {0,};
+  get_dynscn_addrs(ebl->elf, phdr, addrs);
+  find_offsets(ebl->elf, 0, i_max, addrs, offs);
+
+  size_t syments;
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr(ebl->elf, &ehdr_mem);
+
+  if (offs[i_hash] != 0) {
+/* In the original format, .hash says the size of .dynsym.  */
+
+size_t entsz = SH_ENTSIZE_HASH(ehdr);
+Elf_Data *data =
+elf_getdata_rawchunk(ebl->elf, offs[i_hash] + entsz, entsz,
+ (entsz == 4 ? ELF_T_WORD : ELF_T_XWORD));
+if (data != NULL)
+  syments = (entsz == 4 ? *(const GElf_Word *)data->d_buf
+: *(const GElf_Xword *)data->d_buf);
+  }
+  if (offs[i_gnu_hash] != 0 && syments == 0) {
+/* In the new format, we can derive it with some work.  */
+
+const struct {
+  Elf32_Word nbuckets;
+  Elf32_Word symndx;
+  Elf32_Word maskwords;
+  Elf32_Word shift2;
+} * header;
+
+Elf_Data *data = elf_getdata_rawchunk(ebl->elf, offs[i_gnu_hash],
+  sizeof *header, ELF_T_WORD);
+if (data != NULL) {
+  header = data->d_buf;
+  Elf32_Word nbuckets = header->nbuckets;
+  Elf32_Word symndx = header->symndx;
+  GElf_Off buckets_at = (offs[i_gnu_hash] + sizeof *header +
+ (gelf_getclass(ebl->elf) * sizeof(Elf32_Word)
*
+  header->maskwords));
+
+  //

Re: [PATCH v2 4/7] x86_64_return_value_location: Support lvalue and rvalue references

2023-02-10 Thread Frank Ch. Eigler via Elfutils-devel
Hi -

> $ cat 1.cpp
> int &foo() { throw; }
> int &&bar() { throw; }
> $ g++ -g 1.cpp -c
> and then running
> 
> $ LD_LIBRARY_PATH=../libelf:../libdw ./funcretval -e 1.o
> 
> What would be a good way to integrate such a testcase?
> Currently all tests are built with gcc, is it okay to add one
> built with g++? [...]

Sure.


- FChE