libelf: Explicitly update section data after (de)compression.
authorMark Wielaard <mark@klomp.org>
Fri, 9 Nov 2018 08:18:22 +0000 (08:18 +0000)
committerMark Wielaard <mark@klomp.org>
Fri, 9 Nov 2018 16:34:30 +0000 (17:34 +0100)
We need to explictly trigger a section data reload after updating the
ELF section rawdata to make sure it gets written out to disk on an
elf_update. Doing this showed one bug/inefficiently when the underlying
file has a different endianness. In that case for debug sections we
would convert by allocating a new buffer and just copying over the
raw data into a new buffer. This is not really necessary and would
hide any relocations done on the rawdata by libdwfl.

Added a couple of new ppc64 big endian testfiles that show the issue.

Signed-off-by: Mark Wielaard <mark@klomp.org>
libelf/ChangeLog
libelf/elf_compress.c
libelf/elf_getdata.c
tests/ChangeLog
tests/Makefile.am
tests/run-readelf-zdebug-rel.sh
tests/run-strip-reloc.sh
tests/testfile-debug-rel-ppc64-g.o.bz2 [new file with mode: 0644]
tests/testfile-debug-rel-ppc64-z.o.bz2 [new file with mode: 0644]
tests/testfile-debug-rel-ppc64.o.bz2 [new file with mode: 0644]

index af56503..53da9a6 100644 (file)
@@ -1,3 +1,10 @@
+2018-11-09  Mark Wielaard  <mark@klomp.org>
+
+       * elf_compress.c (__libelf_reset_rawdata): Make rawdata change
+       explicit by calling __libelf_set_data_list.
+       * elf_getdata.c (convert_data): Don't convert if type is ELF_T_BYTE
+       even if endianness is different.
+
 2018-10-18  Mark Wielaard  <mark@klomp.org>
 
        * libelf.h (Elf_Type): Add ELF_T_NHDR8.
index fd412e8..d96245d 100644 (file)
@@ -326,6 +326,12 @@ __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size, size_t align,
 
   scn->rawdata_base = buf;
   scn->flags |= ELF_F_MALLOCED;
+
+  /* Pretend we (tried to) read the data from the file and setup the
+     data (might have to convert the Chdr to native format).  */
+  scn->data_read = 1;
+  scn->flags |= ELF_F_FILEDATA;
+  __libelf_set_data_list_rdlock (scn, 1);
 }
 
 int
index 4f80aaf..2043bba 100644 (file)
@@ -146,7 +146,8 @@ convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass,
 {
   const size_t align = __libelf_type_align (eclass, type);
 
-  if (data == MY_ELFDATA)
+  /* Do we need to convert the data and/or adjust for alignment?  */
+  if (data == MY_ELFDATA || type == ELF_T_BYTE)
     {
       if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
        /* No need to copy, we can use the raw data.  */
index 23e9113..7ce3980 100644 (file)
@@ -1,3 +1,13 @@
+2018-11-09  Mark Wielaard  <mark@klomp.org>
+
+       * testfile-debug-rel-ppc64-g.o.bz2: New test file.
+       * testfile-debug-rel-ppc64-z.o.bz2: Likewise.
+       * testfile-debug-rel-ppc64.o.bz2: Likewise.
+       * Makefile.am (EXTRA_DIST): Add testfile-debug-rel-ppc64-g.o.bz2,
+       testfile-debug-rel-ppc64-z.o.bz2 and testfile-debug-rel-ppc64.o.bz2.
+       * run-strip-reloc.sh: Also test on testfile-debug-rel-ppc64.o.
+       * run-readelf-zdebug-rel.sh: Also test on testfile-debug-rel-ppc64*.o.
+
 2018-10-26  Mark Wielaard  <mark@klomp.org>
 
        * run-strip-reloc.sh: Add a test for --reloc-debug-sections-only.
index a2a381a..d3ac345 100644 (file)
@@ -412,7 +412,10 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
             testfile-riscv64.bz2 testfile-riscv64-s.bz2 \
             testfile-riscv64-core.bz2 \
             run-copyadd-sections.sh run-copymany-sections.sh \
-            run-typeiter-many.sh run-strip-test-many.sh
+            run-typeiter-many.sh run-strip-test-many.sh \
+            testfile-debug-rel-ppc64-g.o.bz2 \
+            testfile-debug-rel-ppc64-z.o.bz2 \
+            testfile-debug-rel-ppc64.o.bz2
 
 if USE_VALGRIND
 valgrind_cmd='valgrind -q --leak-check=full --error-exitcode=1'
index 3f20078..53fa42a 100755 (executable)
@@ -146,4 +146,110 @@ cat loc.out | sed -e "s/'.debug_loc' at offset 0x185/'.zdebug_loc' at offset 0x1
 
 cat loc.out | sed -e "s/at offset 0x185/at offset 0x150/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-debug-rel-z.o
 
+# Same as above, but on ppc64
+testfiles testfile-debug-rel-ppc64.o
+testfiles testfile-debug-rel-ppc64-g.o testfile-debug-rel-ppc64-z.o
+
+cat > info.out << \EOF
+
+DWARF section [ 6] '.debug_info' at offset 0x80:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 1
+           producer             (strp) "GNU C11 7.3.1 20180712 (Red Hat 7.3.1-6) -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -g -Og"
+           language             (data1) C99 (12)
+           name                 (strp) "testfile-zdebug-rel.c"
+           comp_dir             (strp) "/home/mjw"
+           low_pc               (addr) 000000000000000000
+           high_pc              (data8) 44 (0x000000000000002c)
+           stmt_list            (sec_offset) 0
+ [    2d]    subprogram           abbrev: 2
+             external             (flag_present) yes
+             name                 (strp) "main"
+             decl_file            (data1) testfile-zdebug-rel.c (1)
+             decl_line            (data1) 4
+             prototyped           (flag_present) yes
+             type                 (ref4) [    82]
+             low_pc               (addr) 000000000000000000
+             high_pc              (data8) 44 (0x000000000000002c)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+             sibling              (ref4) [    82]
+ [    4e]      formal_parameter     abbrev: 3
+               name                 (strp) "argc"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 4
+               type                 (ref4) [    82]
+               location             (sec_offset) location list [     0]
+ [    5d]      formal_parameter     abbrev: 4
+               name                 (strp) "argv"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 4
+               type                 (ref4) [    89]
+               location             (exprloc) 
+                [ 0] reg4
+ [    6a]      variable             abbrev: 5
+               name                 (string) "a"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 6
+               type                 (ref4) [    9c]
+               const_value          (sdata) 18446744073709551607 (-9)
+ [    74]      variable             abbrev: 6
+               name                 (string) "b"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 7
+               type                 (ref4) [    9c]
+               location             (sec_offset) location list [    4e]
+ [    82]    base_type            abbrev: 7
+             byte_size            (data1) 4
+             encoding             (data1) signed (5)
+             name                 (string) "int"
+ [    89]    pointer_type         abbrev: 8
+             byte_size            (data1) 8
+             type                 (ref4) [    8f]
+ [    8f]    pointer_type         abbrev: 8
+             byte_size            (data1) 8
+             type                 (ref4) [    95]
+ [    95]    base_type            abbrev: 9
+             byte_size            (data1) 1
+             encoding             (data1) unsigned_char (8)
+             name                 (strp) "char"
+ [    9c]    base_type            abbrev: 9
+             byte_size            (data1) 8
+             encoding             (data1) unsigned (7)
+             name                 (strp) "long unsigned int"
+EOF
+
+cat info.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=info testfile-debug-rel-ppc64.o
+
+cat info.out | sed -e "s/'.debug_info'/'.zdebug_info'/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=info testfile-debug-rel-ppc64-g.o
+
+cat info.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=info testfile-debug-rel-ppc64-z.o
+
+cat > loc.out << \EOF
+
+DWARF section [ 9] '.debug_loc' at offset 0x1af:
+
+ CU [     b] base: 000000000000000000
+ [     0] range 0, 4
+           [ 0] reg3
+          range 4, 14
+           [ 0] breg3 -42
+           [ 2] stack_value
+          range 14, 2c
+           [ 0] GNU_entry_value:
+                [ 0] reg3
+           [ 3] stack_value
+ [    4e] range 8, 18
+           [ 0] reg3
+EOF
+
+cat loc.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-debug-rel-ppc64.o
+
+cat loc.out | sed -e "s/'.debug_loc' at offset 0x1af/'.zdebug_loc' at offset 0x15f/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-debug-rel-ppc64-g.o
+
+cat loc.out | sed -e "s/at offset 0x1af/at offset 0x177/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-debug-rel-ppc64-z.o
+
 exit 0
index 6e54ab4..6f299ab 100755 (executable)
@@ -135,4 +135,8 @@ testrun ${abs_top_builddir}/src/elfcompress -o strip-compressed.o -t zlib \
 runtest strip-uncompressed.o 1
 runtest strip-compressed.o 1
 
+# See run-readelf-zdebug-rel.sh
+testfiles testfile-debug-rel-ppc64.o
+runtest testfile-debug-rel-ppc64.o 1
+
 exit $status
diff --git a/tests/testfile-debug-rel-ppc64-g.o.bz2 b/tests/testfile-debug-rel-ppc64-g.o.bz2
new file mode 100644 (file)
index 0000000..8c5ec99
Binary files /dev/null and b/tests/testfile-debug-rel-ppc64-g.o.bz2 differ
diff --git a/tests/testfile-debug-rel-ppc64-z.o.bz2 b/tests/testfile-debug-rel-ppc64-z.o.bz2
new file mode 100644 (file)
index 0000000..df50465
Binary files /dev/null and b/tests/testfile-debug-rel-ppc64-z.o.bz2 differ
diff --git a/tests/testfile-debug-rel-ppc64.o.bz2 b/tests/testfile-debug-rel-ppc64.o.bz2
new file mode 100644 (file)
index 0000000..8340d0c
Binary files /dev/null and b/tests/testfile-debug-rel-ppc64.o.bz2 differ