[PATCH] strip, unstrip: Handle SHT_GROUP correctly.

2018-10-13 Thread Mark Wielaard
The usage of annobin in Fedora showed a couple of bugs when using
eu-strip and eu-unstrip on ET_REL files that contain multiple group
sections.

When stripping we should not remove the SHF_GROUP flag from sections
even if the group section itself might be removed. Either the section
itself gets removed, and so the flag doesn't matter. Or it gets moved
together with the group section into the debug file, and then it still
needs to have the flag set. Also we would "renumber" the section group
flag field (which isn't a section index, and so shouldn't be changed).

Often the group sections have the exact same name (".group"), flags
(none) and sometimes the same sizes. Which makes matching them hard.
Extract the group signature and compare those when comparing two
group sections.

Signed-off-by: Mark Wielaard 
---
 src/ChangeLog|  12 +++
 src/strip.c  |  12 +--
 src/unstrip.c|  60 ---
 tests/ChangeLog  |   6 
 tests/Makefile.am|   1 +
 tests/run-annobingroup.sh|  33 +
 tests/testfile-annobingroup-x86_64.o.bz2 | Bin 0 -> 1437 bytes
 7 files changed, 116 insertions(+), 8 deletions(-)
 create mode 100644 tests/testfile-annobingroup-x86_64.o.bz2

diff --git a/src/ChangeLog b/src/ChangeLog
index 6a702ee..eb5e8ba 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,15 @@
+2018-10-12  Mark Wielaard  
+
+   * strip.c (handle_elf): Don't remove SHF_GROUP flag from sections.
+   Skip group section flag when renumbering section indexes.
+   * unstrip.c (struct section): Add sig field.
+   (compare_unalloc_sections): Take and use sig1 and sig2 as arguments.
+   (compare_sections): Pass signatures to compare_unalloc_sections.
+   (get_group_sig): New function.
+   (find_alloc_sections_prelink): Set signature.
+   (copy_elided_sections): Likewise and pass them on.
+   (find_unalloc_section): Take and pass signatures.
+
 2018-09-13  Mark Wielaard  
 
* readelf.c (print_shdr): Get number of section with elf_getshdrnum.
diff --git a/src/strip.c b/src/strip.c
index 4a3db1b..da639b9 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -792,9 +792,13 @@ handle_elf (int fd, Elf *elf, const char *prefix, const 
char *fname,
 
  if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
{
- /* The section group section will be removed.  */
+ /* The section group section might be removed.
+Don't remove the SHF_GROUP flag.  The section is
+either also removed, in which case the flag doesn't matter.
+Or it moves with the group into the debug file, then
+it will be reconnected with the new group and should
+still have the flag set.  */
  shdr_info[cnt].group_idx = 0;
- shdr_info[cnt].shdr.sh_flags &= ~SHF_GROUP;
}
}
 
@@ -1368,7 +1372,9 @@ handle_elf (int fd, Elf *elf, const char *prefix, const 
char *fname,
&& shdr_info[cnt].data->d_buf != NULL);
 
Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
-   for (size_t inner = 0;
+   /* First word is the section group flag.
+  Followed by section indexes, that need to be renumbered.  */
+   for (size_t inner = 1;
 inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
 ++inner)
  if (grpref[inner] < shnum)
diff --git a/src/unstrip.c b/src/unstrip.c
index e6f0947..03a0346 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -696,6 +696,7 @@ struct section
 {
   Elf_Scn *scn;
   const char *name;
+  const char *sig;
   Elf_Scn *outscn;
   Dwelf_Strent *strent;
   GElf_Shdr shdr;
@@ -720,7 +721,8 @@ compare_alloc_sections (const struct section *s1, const 
struct section *s2,
 
 static int
 compare_unalloc_sections (const GElf_Shdr *shdr1, const GElf_Shdr *shdr2,
- const char *name1, const char *name2)
+ const char *name1, const char *name2,
+ const char *sig1, const char *sig2)
 {
   /* Sort by sh_flags as an arbitrary ordering.  */
   if (shdr1->sh_flags < shdr2->sh_flags)
@@ -734,6 +736,10 @@ compare_unalloc_sections (const GElf_Shdr *shdr1, const 
GElf_Shdr *shdr2,
   if (shdr1->sh_size > shdr2->sh_size)
 return 1;
 
+  /* Are they both SHT_GROUP sections? Then compare signatures.  */
+  if (sig1 != NULL && sig2 != NULL)
+return strcmp (sig1, sig2);
+
   /* Sort by name as last resort.  */
   return strcmp (name1, name2);
 }
@@ -751,7 +757,8 @@ compare_sections (const void *a, const void *b, bool rel)
   return ((s1->shdr.sh_flags & SHF_ALLOC)
  ? compare_alloc_sections (s1, s2, rel)
  : compare_unalloc_sections (&s1->shdr, &s2->shdr,
- 

[PATCH] readelf: Handle multiple .debug_macro sections and decode header flag.

2018-10-13 Thread Mark Wielaard
In object files there could be multiple .debug_macro sections.
These are COMDAT sections used as imports. Note that the output for
DW_MACRO_import isn't ideal since the offset is printed against the
start of the .debug_macro section, but it doesn't show which one.
We currently don't have that information and no interface yet for
libdw users.

Also decode the macro header flag byte for convenience.

Signed-off-by: Mark Wielaard 
---
 src/ChangeLog  |   4 +
 src/readelf.c  |  31 ++-
 tests/ChangeLog|  10 +
 tests/run-readelf-macro.sh |   4 +-
 tests/run-readelf-macros.sh| 435 +
 tests/run-readelf-zdebug.sh|   2 +-
 tests/testfile-macros-object.o.bz2 | Bin 0 -> 5718 bytes
 7 files changed, 480 insertions(+), 6 deletions(-)
 create mode 100755 tests/run-readelf-macros.sh
 create mode 100644 tests/testfile-macros-object.o.bz2

diff --git a/src/ChangeLog b/src/ChangeLog
index 6a702ee..d594eb4 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,9 @@
 2018-09-13  Mark Wielaard  
 
+   * readelf.c (print_debug_macro_section): Use elf_getdata. Print
+   decoded flag string.
+2018-09-13  Mark Wielaard  
+
* readelf.c (print_shdr): Get number of section with elf_getshdrnum.
(print_phdr): Likewise.
 
diff --git a/src/readelf.c b/src/readelf.c
index bddcd70..366e2c3 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -9702,8 +9702,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod 
__attribute__ ((unused)),
  (uint64_t) shdr->sh_offset);
   putc_unlocked ('\n', stdout);
 
-  Elf_Data *data = (dbg->sectiondata[IDX_debug_macro]
-   ?: elf_rawdata (scn, NULL));
+  Elf_Data *data =  elf_getdata (scn, NULL);
   if (unlikely (data == NULL))
 {
   error (0, 0, gettext ("cannot get macro information section data: %s"),
@@ -9772,7 +9771,33 @@ print_debug_macro_section (Dwfl_Module *dwflmod 
__attribute__ ((unused)),
   if (readp + 1 > readendp)
goto invalid_data;
   const unsigned char flag = *readp++;
-  printf (gettext (" Flag:   0x%" PRIx8 "\n"), flag);
+  printf (gettext (" Flag:   0x%" PRIx8), flag);
+  if (flag != 0)
+   {
+ printf (" (");
+ if ((flag & 0x01) != 0)
+   {
+ printf ("offset_size");
+ if ((flag & 0xFE) !=  0)
+   printf (", ");
+   }
+ if ((flag & 0x02) != 0)
+   {
+ printf ("debug_line_offset");
+ if ((flag & 0xFC) !=  0)
+   printf (", ");
+   }
+ if ((flag & 0x04) != 0)
+   {
+ printf ("operands_table");
+ if ((flag & 0xF8) !=  0)
+   printf (", ");
+   }
+ if ((flag & 0xF8) != 0)
+   printf ("unknown");
+ printf (")");
+   }
+  printf ("\n");
 
   unsigned int offset_len = (flag & 0x01) ? 8 : 4;
   printf (gettext (" Offset length:  %" PRIu8 "\n"), offset_len);
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 04eeb4a..a78cc7c 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,13 @@
+2018-10-12  Mark Wielaard  
+
+   * run-readelf-zdebug.sh: Adjust flags output.
+   * run-readelf-macro.sh: Likewise.
+   * run-readelf-macros.sh: New test.
+   * testfile-macros-object.o.bz2: New test file.
+   * Makefile.am (TESTS): Add run-readelf-macros.sh.
+   (EXTRA_DIST): Add run-readelf-macros.sh and
+   testfile-macros-object.o.bz2.
+
 2018-09-18  Mark Wielaard  
 
* backtrace-dwarf.c (thread_callback): Only error when
diff --git a/tests/run-readelf-macro.sh b/tests/run-readelf-macro.sh
index 8693203..8b17f7d 100755
--- a/tests/run-readelf-macro.sh
+++ b/tests/run-readelf-macro.sh
@@ -65,7 +65,7 @@ DWARF section [32] '.debug_macro' at offset 0x2480:
 
  Offset: 0x0
  Version:4
- Flag:   0x2
+ Flag:   0x2 (debug_line_offset)
  Offset length:  4
  .debug_line offset: 0x0
 
@@ -329,7 +329,7 @@ DWARF section [32] '.debug_macro' at offset 0x2480:
 
  Offset: 0x5bc
  Version:4
- Flag:   0x2
+ Flag:   0x2 (debug_line_offset)
  Offset length:  4
  .debug_line offset: 0x47
 
diff --git a/tests/run-readelf-macros.sh b/tests/run-readelf-macros.sh
new file mode 100755
index 000..cc311b7
--- /dev/null
+++ b/tests/run-readelf-macros.sh
@@ -0,0 +1,435 @@
+#! /bin/sh
+# Copyright (C) 2018 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
+# M

Re: [PATCH] Handle ADD/SUB relocations

2018-10-13 Thread Mark Wielaard
Hi Andreas,

On Tue, 2018-10-02 at 14:46 +0200, Andreas Schwab wrote:
> This adds support for ADD and SUB relocations as seen on RISC-V.

Sorry this took 2 weeks. I should have reviewed it immediately because
it looks just perfect. I pushed it to master.

Thanks,

Mark