Accepting request 751829 from devel:tools:compiler
- Fix assertion failure 'refd != NULL' in write_die [swo#24169]. * dwz-fix-refd-NULL-assertion-in-write_die.patch - Fix assertion failure 'off == cu_size' in recompute_abbrevs [swo#24764]. * dwz-fix-assertion-off-cu_size-in-recompute_abbrevs.patch OBS-URL: https://build.opensuse.org/request/show/751829 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/dwz?expand=0&rev=10
This commit is contained in:
commit
2e58eea1ec
138
dwz-fix-assertion-off-cu_size-in-recompute_abbrevs.patch
Normal file
138
dwz-fix-assertion-off-cu_size-in-recompute_abbrevs.patch
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
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 <tdevries@suse.de>
|
||||||
|
|
||||||
|
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
|
55
dwz-fix-refd-NULL-assertion-in-write_die.patch
Normal file
55
dwz-fix-refd-NULL-assertion-in-write_die.patch
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
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 <tdevries@suse.de>
|
||||||
|
|
||||||
|
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)
|
13
dwz.changes
13
dwz.changes
@ -1,3 +1,16 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Nov 28 12:56:34 UTC 2019 - Tom de Vries <tdevries@suse.com>
|
||||||
|
|
||||||
|
- 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 <tdevries@suse.com>
|
||||||
|
|
||||||
|
- Fix assertion failure 'off == cu_size' in recompute_abbrevs
|
||||||
|
[swo#24764].
|
||||||
|
* dwz-fix-assertion-off-cu_size-in-recompute_abbrevs.patch
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Tue Nov 5 09:55:50 UTC 2019 - Tom de Vries <tdevries@suse.com>
|
Tue Nov 5 09:55:50 UTC 2019 - Tom de Vries <tdevries@suse.com>
|
||||||
|
|
||||||
|
4
dwz.spec
4
dwz.spec
@ -75,6 +75,8 @@ NoSource: 0
|
|||||||
|
|
||||||
Patch1: dwz-update-version-copyright-message.patch
|
Patch1: dwz-update-version-copyright-message.patch
|
||||||
Patch2: dwz-fix-die-no-multifile-propagation.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}
|
%if %{build_main}
|
||||||
%description
|
%description
|
||||||
@ -105,6 +107,8 @@ This package contains the testsuite results from DWZ.
|
|||||||
%setup -q -n dwz
|
%setup -q -n dwz
|
||||||
%patch1 -p1
|
%patch1 -p1
|
||||||
%patch2 -p1
|
%patch2 -p1
|
||||||
|
%patch3 -p1
|
||||||
|
%patch4 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
make %{?_smp_mflags} CFLAGS="%{optflags}"
|
make %{?_smp_mflags} CFLAGS="%{optflags}"
|
||||||
|
Loading…
Reference in New Issue
Block a user