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)
