Hello community,

here is the log from the commit of package dwz for openSUSE:Factory checked in 
at 2019-12-07 15:11:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/dwz (Old)
 and      /work/SRC/openSUSE:Factory/.dwz.new.4691 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "dwz"

Sat Dec  7 15:11:41 2019 rev:10 rq:751829 version:0.13

Changes:
--------
--- /work/SRC/openSUSE:Factory/dwz/dwz.changes  2019-11-11 12:57:09.845485320 
+0100
+++ /work/SRC/openSUSE:Factory/.dwz.new.4691/dwz.changes        2019-12-07 
15:12:01.675824394 +0100
@@ -1,0 +2,13 @@
+Thu Nov 28 12:56:34 UTC 2019 - Tom de Vries <[email protected]>
+
+- Fix assertion failure 'refd != NULL' in write_die [swo#24169].
+  * dwz-fix-refd-NULL-assertion-in-write_die.patch
+
+-------------------------------------------------------------------
+Wed Nov 27 18:50:07 UTC 2019 - Tom de Vries <[email protected]>
+
+- Fix assertion failure 'off == cu_size' in recompute_abbrevs
+  [swo#24764].
+  * dwz-fix-assertion-off-cu_size-in-recompute_abbrevs.patch
+
+-------------------------------------------------------------------

New:
----
  dwz-fix-assertion-off-cu_size-in-recompute_abbrevs.patch
  dwz-fix-refd-NULL-assertion-in-write_die.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ dwz.spec ++++++
--- /var/tmp/diff_new_pack.UGUT3i/_old  2019-12-07 15:12:02.823824232 +0100
+++ /var/tmp/diff_new_pack.UGUT3i/_new  2019-12-07 15:12:02.827824231 +0100
@@ -75,6 +75,8 @@
 
 Patch1:         dwz-update-version-copyright-message.patch
 Patch2:         dwz-fix-die-no-multifile-propagation.patch
+Patch3:         dwz-fix-assertion-off-cu_size-in-recompute_abbrevs.patch
+Patch4:         dwz-fix-refd-NULL-assertion-in-write_die.patch
 
 %if %{build_main}
 %description
@@ -105,6 +107,8 @@
 %setup -q -n dwz
 %patch1 -p1
 %patch2 -p1
+%patch3 -p1
+%patch4 -p1
 
 %build
 make %{?_smp_mflags} CFLAGS="%{optflags}"

++++++ dwz-fix-assertion-off-cu_size-in-recompute_abbrevs.patch ++++++
Fix assertion 'off == cu_size' in recompute_abbrevs

[ Backport of master commit 331eabd. ]

With an executable from PR25024, we manage to reproduce PR24764:
...
$ dwz -l0 clang-offload-bundler-10.0.0-0.20190817snap5.fc30.x86_64.debug
dwz: dwz.c:9920: recompute_abbrevs: Assertion `off == cu_size' failed.
Aborted (core dumped)
...

The problem is that the cu_size as computed during recompute_abbrevs is not
the same as was computed before during compute_abbrevs.

I tracked down the first DIE in the CU that has a different size, at 0xdf615:
...
 <5><df615>: Abbrev Number: 65 (DW_TAG_formal_parameter)
    <df616>   DW_AT_type        : <0xe33be>
    <df618>   DW_AT_artificial  : 1
...

Using a debug patch, we can track the size of the DIE during compute_abbrevs:
...
init_new_die_offsets: intracusize: 2
init_new_die_offsets: start die_size: 0
init_new_die_offsets: add DIE code size to die_size: 1
init_new_die_offsets: add nr_refs * intracusize to die_size: 3
update_new_die_offsets: die_size: 3
update_new_die_offsets: die_size: 3
finalize_new_die_offsets: die_size: 3
...
and recompute_abbrevs:
...
init_new_die_offsets: intracusize: 3
init_new_die_offsets: start die_size: 0
init_new_die_offsets: add DIE code size to die_size: 1
init_new_die_offsets: add nr_refs * intracusize to die_size: 4
update_new_die_offsets: die_size: 4
update_new_die_offsets: die_size: 4
update_new_die_offsets: die_size: 4
finalize_new_die_offsets: die_size: 4
...

The difference starts in init_new_die_offsets, when adding intracusize, which
is different for compute_abbrevs and recompute_abbrevs (2 vs. 3).

The code in recompute_abbrevs that calculates intracusize for the relevant
init_new_die_offsets call is:
...
      /* Need to be conservatively high estimate, as update_new_die_offsets
        relies on the offsets always decreasing.  cu_size at this point is
        the size we will end up with in the end, but if cu_size is
        sufficiently close (from bottom) to some uleb128 boundary (say
        16384), init_new_die_offsets might return off above that boundary
        and then update_new_die_offsets might fail its assertions on
        reference to DIEs that crossed the uleb128 boundary.  */
      intracusize = size_of_uleb128 (2 * cu_size);

      off = init_new_die_offsets (cu->cu_die, headersz, intracusize);
...
where the '2 * cu_size' is the result of commit d16aa5e "Fix up
recompute_abbrevs if cu_size is close below an uleb128 boundary and
init_new_die_offsets would return offset above that uleb128 boundary":
...
-      intracusize = size_of_uleb128 (cu_size);
+      intracusize = size_of_uleb128 (2 * cu_size);
...

Reverting commit d16aa5e gets us an intracusize of 2 in recompute_abbrevs, and
fixes the assert.  However, doing so reintroduces the assertion that was fixed
by the commit (at least, provided commit a4668e1 "Fix assertion failure in
create_import_tree" is also reverted):
...
$ dwz -l0 inkview.debug
dwz: dwz.c:8527: update_new_die_offsets: Assertion \
  `die->u.p2.die_intracu_udata_size >= intracu_udata_size' failed.
Aborted (core dumped)
...

Fix the 'off == cu_size' assert (without introducing the regression for
inkview.debug) by:
- saving the intracusize used for the call to init_new_die_offsets in
  compute_abbrevs, and
- reusing the saved intracusize for the call to init_new_die_offsets in
  recompute_abbrevs.

Also tested with clang and CheckerOptionHandlingAnalyzerPlugin.so, for which
this PR also triggered.

2019-11-27  Tom de Vries  <[email protected]>

        PR dwz/24764
        * dwz.c (struct dw_cu): Add initial_intracusize field.
        (compute_abbrevs): Initalize initial_intracusize.
        (recompute_abbrevs): Use initial_intracusize.

---
 dwz.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/dwz.c b/dwz.c
index 7c7b401..928fefa 100644
--- a/dwz.c
+++ b/dwz.c
@@ -674,6 +674,9 @@ struct dw_cu
   unsigned int cu_chunk;
   /* Form chosen for intra-cu references.  */
   enum dwarf_form cu_intracu_form;
+  /* Intracusize argument to init_new_die_offsets.  Set in compute_abbrevs,
+     used in recompute_abbrevs.  */
+  unsigned int initial_intracusize;
 };
 
 /* Internal representation of a debugging information entry (DIE).
@@ -8405,6 +8408,7 @@ compute_abbrevs (DSO *dso)
          intracusize = i;
        }
       while (1);
+      cu->initial_intracusize = intracusize;
       off = init_new_die_offsets (cu->cu_die, headersz, intracusize);
       do
        {
@@ -9555,14 +9559,7 @@ recompute_abbrevs (dw_cu_ref cu, unsigned int cu_size)
     }
   else
     {
-      /* Need to be conservatively high estimate, as update_new_die_offsets
-        relies on the offsets always decreasing.  cu_size at this point is
-        the size we will end up with in the end, but if cu_size is
-        sufficiently close (from bottom) to some uleb128 boundary (say
-        16384), init_new_die_offsets might return off above that boundary
-        and then update_new_die_offsets might fail its assertions on
-        reference to DIEs that crossed the uleb128 boundary.  */
-      intracusize = size_of_uleb128 (2 * cu_size);
+      intracusize = cu->initial_intracusize;
 
       off = init_new_die_offsets (cu->cu_die, headersz, intracusize);
       do
++++++ dwz-fix-refd-NULL-assertion-in-write_die.patch ++++++
Fix 'refd != NULL' assertion in write_die

[ Backport of master commits 6959430 and 7cc8aae. ]

When running dwz on a file that contains invalid DW_FORM_ref_addr attributes
(which has been observed to be generated by a google go compiler) we run
either into an assert:
...
$ dwz multidictionary
dwz: dwz.c:9461: write_die: Assertion `refd != NULL' failed.
Aborted (core dumped)
...
or a segmentation fault in case of low-mem mode:
...
$ dwz -l0 multidictionary
Segmentation fault (core dumped)
...

Fix this by erroring out instead:
...
$ dwz multidictionary
dwz: Couldn't find DIE at DW_FORM_ref_addr offset 0x97
...

2019-02-05  Tom de Vries  <[email protected]>

        PR dwz/24169
        * dwz.c (write_die): Error out on invalid DW_FORM_ref_addr.

---
 dwz.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/dwz.c b/dwz.c
index 928fefa..c7db337 100644
--- a/dwz.c
+++ b/dwz.c
@@ -28,6 +28,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/mman.h>
@@ -9124,6 +9125,9 @@ write_die (unsigned char *ptr, dw_cu_ref cu, dw_die_ref 
die,
                                          ? ptr_size : 4);
                inptr += refcu->cu_version == 2 ? ptr_size : 4;
                refd = off_htab_lookup (NULL, value);
+               if (refd == NULL || refd->die_tag == 0)
+                 error (1, 0, "Couldn't find DIE at DW_FORM_ref_addr offset"
+                        " 0x%" PRIx64, value);
                assert (refd != NULL);
                refdt = refd;
                while (refdt->die_toplevel == 0)

Reply via email to