From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 70242 invoked by alias); 27 Apr 2019 19:40:22 -0000 Mailing-List: contact dwz-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Post: List-Help: List-Subscribe: Sender: dwz-owner@sourceware.org Received: (qmail 70233 invoked by uid 89); 27 Apr 2019 19:40:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.100.3 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.6 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_PASS autolearn=ham version=3.3.1 spammy=dies, cc1, Theres, introduces X-Spam-Status: No, score=-25.6 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_PASS autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on sourceware.org X-Spam-Level: X-HELO: mx1.suse.de X-Virus-Scanned: by amavisd-new at test-mx.suse.de Subject: Re: [PATCH][low-mem] Fix DW_OP_GNU_parameter_ref handling in read_exprloc From: Tom de Vries To: dwz@sourceware.org, jakub@redhat.com References: <20190214093832.GA22005@delia> Message-ID: Date: Tue, 01 Jan 2019 00:00:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.5.1 MIME-Version: 1.0 In-Reply-To: <20190214093832.GA22005@delia> Content-Type: multipart/mixed; boundary="------------EB4B47F4F5301DC839C10CAF" Content-Language: en-US X-SW-Source: 2019-q2/txt/msg00041.txt.bz2 This is a multi-part message in MIME format. --------------EB4B47F4F5301DC839C10CAF Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Content-length: 726 On 14-02-19 10:38, Tom de Vries wrote: > Hi, > > Function read_exprloc contains a loop that marks all parents of a > DW_OP_GNU_parameter_ref reference with CK_BAD. The loop however has no > private loop variable, so the ref variable, initially pointing to the > referenced DIE, ends up after the loop pointing to the root parent of the > reference instead. Consequently, the code after the loop, intended to be > executed for the referenced DIE, is instead executed for the root parent of > the referenced DIE. > > Fix this by moving the loop alap. > This updated patch introduces a private loop variable instead. Also, the rationale now contains a more elaborate analysis of the PR. Committed as below. Thanks, - Tom --------------EB4B47F4F5301DC839C10CAF Content-Type: text/x-patch; name="0001-low-mem-Fix-DW_OP_GNU_parameter_ref-handling-in-read_exprloc.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename*0="0001-low-mem-Fix-DW_OP_GNU_parameter_ref-handling-in-read_ex"; filename*1="prloc.patch" Content-length: 3403 [low-mem] Fix DW_OP_GNU_parameter_ref handling in read_exprloc When dwz-ing a cc1 build with bootstrap-lto in low-mem mode, we run into: ... $ dwz -l0 cc1 dwz: dwz.c:8558: adjust_exprloc: \ Assertion `refd != NULL && !refd->die_remove' failed. Aborted (core dumped) ... This abort is triggered as follows. There's a DIE 0x27a408: ... <2><27a408>: Abbrev Number: 6 (DW_TAG_formal_parameter) <27a409> DW_AT_abstract_origin: <0x648e6c6> <27a40d> DW_AT_location : 0x540585 (location list) <27a411> DW_AT_GNU_locviews: 0x540583 ... which refers to location list 0x540585: ... 00540583 v000000000000001 v000000000000000 location view pair 00540585 v000000000000001 v000000000000000 views at 00540583 for: 00000000005884a2 00000000005884b7 (DW_OP_GNU_parameter_ref: \ <0x267c92>; DW_OP_stack_value) 0054059d ... which contains a DWARF op referring to the DIE at 0x267c92 (listed here with parent 0x267c89): ... <2><267c89>: Abbrev Number: 56 (DW_TAG_subprogram) <267c8a> DW_AT_abstract_origin: <0x648e6b5> <267c8e> DW_AT_sibling : <0x267c98> <3><267c92>: Abbrev Number: 21 (DW_TAG_formal_parameter) <267c93> DW_AT_abstract_origin: <0x648e6c6> ... When invoking read_exprloc for DIE 0x27a408 and ref DIE 0x267c92, we execute: ... if (ref->die_ck_state == CK_KNOWN) { ref->die_ck_state = CK_BAD; while (!ref->die_root && ref->die_parent->die_ck_state == CK_KNOWN) { ref = ref->die_parent; ref->die_ck_state = CK_BAD; } } else ref->die_ck_state = CK_BAD; ... and end up in the while loop, after which the ref variable has been updated to 0x267c89. Subsequently, we execute a low-mem specific bit: ... if (unlikely (low_mem)) { ref->die_referenced = 1; /* As .debug_loc adjustment is done after write_info finishes, we need to keep the referenced DIEs around uncollapsed. */ if (need_adjust) ref->die_intercu_referenced = 1; } ... but fail to mark the referenced DIE 0x267c92 with die_referenced, and instead mark its parent 0x267c89. Consequently, since nothing else references 0x267c92, it's removed from the off_htab during remove_unneeded, and when we try to find it in off_htab during adjust_exprloc: ... refd = off_htab_lookup (refcu, refcu->cu_offset + addr); assert (refd != NULL && !refd->die_remove); ... we abort because refd == NULL. Fix this by using a private loop variable in the while loop. 2019-04-27 Tom de Vries PR dwz/24195 * dwz.c (read_exprloc): Use private loop variable in while loop. --- dwz.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/dwz.c b/dwz.c index 2c0e4c4..b968fef 100644 --- a/dwz.c +++ b/dwz.c @@ -1540,12 +1540,15 @@ read_exprloc (DSO *dso, dw_die_ref die, unsigned char *ptr, size_t len, ref->die_op_call2_referenced = 1; if (ref->die_ck_state == CK_KNOWN) { + dw_die_ref d; ref->die_ck_state = CK_BAD; - while (!ref->die_root - && ref->die_parent->die_ck_state == CK_KNOWN) + + d = ref; + while (!d->die_root + && d->die_parent->die_ck_state == CK_KNOWN) { - ref = ref->die_parent; - ref->die_ck_state = CK_BAD; + d = d->die_parent; + d->die_ck_state = CK_BAD; } } else --------------EB4B47F4F5301DC839C10CAF--