From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gnu.wildebeest.org (wildebeest.demon.nl [212.238.236.112]) by sourceware.org (Postfix) with ESMTPS id 7A9613857C52 for ; Thu, 24 Sep 2020 16:26:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 7A9613857C52 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=klomp.org Authentication-Results: sourceware.org; spf=none smtp.mailfrom=mark@tarox.wildebeest.org Received: from tarox.wildebeest.org (tarox.wildebeest.org [172.31.17.39]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by gnu.wildebeest.org (Postfix) with ESMTPSA id CC1613000F11; Thu, 24 Sep 2020 18:26:25 +0200 (CEST) Received: by tarox.wildebeest.org (Postfix, from userid 1000) id C692D470867C; Thu, 24 Sep 2020 18:26:25 +0200 (CEST) From: Mark Wielaard To: dwz@sourceware.org Cc: Mark Wielaard Subject: [PATCH 4/4] Handle DW_FORM_implicit_const [experiment]. Date: Thu, 24 Sep 2020 18:25:57 +0200 Message-Id: <20200924162557.15870-5-mark@klomp.org> X-Mailer: git-send-email 2.18.4 In-Reply-To: <20200924162557.15870-1-mark@klomp.org> References: <20200924162557.15870-1-mark@klomp.org> X-Spam-Status: No, score=-37.0 required=5.0 tests=BAYES_00, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, KAM_LAZY_DOMAIN_SECURITY, KHOP_HELO_FCRDNS, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: dwz@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Dwz mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Sep 2020 16:26:29 -0000 This handles DW_FORM_implicit_const. This form keeps the actual data value in the abbrev. This makes things tricky because we have to decide where to keep (a reference to) the value and when to update the value if necessary. In particular DW_FORM_implicit_const might be used with a line table index for the DW_AT_decl_file or DW_AT_call_file which might be updated in multifile mode. This implementation keeps a value with each attribute (which is highly inefficient, we could allocate values at the end of the struct abbrev_attr only when there is an DW_FORM_implicit_const attribute). And updates the value late in compute_abbrevs when writing the final multifile. * dwz.c (struct abbrev_attr): Add value field. (abbrev_eq2): Handle DW_FORM_implicit_const by also comparing the value. (compute_abbrev_hash): Likewise. (read_abbrev): Read DW_FORM_implicit_const. (skip_attr_no_dw_form_indirect): Skip DW_FORM_implicit_const. (get_AT): Return pointer to value for DW_FORM_implicit_const. (get_AT_int): Return value of DW_FORM_implicit_const. (checksum_die): Get value for DW_AT_decl_file or DW_AT_call_file from DW_FORM_implicit_const, skip for others (should the value then be in the u.p1.die_hash instead?). (checksum_ref_die): Likewise. (die_eq_1): Likewise. (mark_refs): Handle DW_FORM_implicit_const. (read_debug_info): Handle DW_FORM_implicit_const, set cu_lang for compile/partial units. (build_abbrevs_for_die): Handle DW_FORM_implicit_const value. Don't update value for DW_AT_decl_file or DW_AT_call_file here. (abbrev_cmp): Also compare DW_FORM_implicit_const values. (compute_abbrevs): Update DW_AT_decl_file and DW_AT_call_file DW_FORM_implicit_const values here. (write_abbrev): Also write DW_FORM_implicit_const value. (write_die): Handle DW_FORM_implicit_const, but don't change form/value for DW_AT_decl_file and DW_AT_call_file. --- dwz.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 118 insertions(+), 27 deletions(-) diff --git a/dwz.c b/dwz.c index 8f13298..f020d15 100644 --- a/dwz.c +++ b/dwz.c @@ -848,6 +848,8 @@ struct abbrev_attr unsigned int attr; /* DW_FORM_* form code. */ unsigned int form; + /* Only for DW_FORM_implicit_const. */ + int64_t value; }; /* Internal structure for .debug_abbrev entries. */ @@ -1211,7 +1213,9 @@ abbrev_eq2 (const void *p, const void *q) return 0; for (i = 0; i < t1->nattr; i++) if (t1->attr[i].attr != t2->attr[i].attr - || t1->attr[i].form != t2->attr[i].form) + || t1->attr[i].form != t2->attr[i].form + || (t1->attr[i].form == DW_FORM_implicit_const + && t1->attr[i].value != t2->attr[i].value)) return 0; return 1; } @@ -1229,6 +1233,8 @@ compute_abbrev_hash (struct abbrev_tag *t) { t->hash = iterative_hash_object (t->attr[i].attr, t->hash); t->hash = iterative_hash_object (t->attr[i].form, t->hash); + if (t->attr[i].form == DW_FORM_implicit_const) + t->hash = iterative_hash_object (t->attr[i].value, t->hash); } } @@ -1259,7 +1265,9 @@ read_abbrev (DSO *dso, unsigned char *ptr) { nattr++; form = read_uleb128 (p); - if (form == 2 + if (form == DW_FORM_implicit_const) + skip_leb128 (p); + else if (form == 2 || (form > DW_FORM_flag_present && (form != DW_FORM_ref_sig8 || form != DW_FORM_data16 @@ -1291,6 +1299,8 @@ read_abbrev (DSO *dso, unsigned char *ptr) while ((attr = read_uleb128 (ptr)) != 0) { form = read_uleb128 (ptr); + if (form == DW_FORM_implicit_const) + t->attr[t->nattr].value = read_sleb128 (ptr); t->attr[t->nattr].attr = attr; t->attr[t->nattr++].form = form; } @@ -1691,6 +1701,7 @@ skip_attr_no_dw_form_indirect (unsigned int cu_version, uint32_t form, ptr += ptr_size; break; case DW_FORM_flag_present: + case DW_FORM_implicit_const: break; case DW_FORM_ref1: case DW_FORM_flag: @@ -1791,6 +1802,8 @@ get_AT (dw_die_ref die, enum dwarf_attribute at, enum dwarf_form *formp) if (t->attr[i].attr == at) { *formp = form; + if (form == DW_FORM_implicit_const) + return (unsigned char *) &t->attr[i].value; return ptr; } @@ -1839,6 +1852,8 @@ get_AT_int (dw_die_ref die, enum dwarf_attribute at, bool *present, case DW_FORM_ref_udata: case DW_FORM_udata: return read_uleb128 (ptr); + case DW_FORM_implicit_const: + return *(uint64_t *)ptr; /* See get_AT. */ default: *present = false; return 0; @@ -2837,6 +2852,8 @@ checksum_die (DSO *dso, dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die) case DW_FORM_data8: value = read_64 (ptr); handled = true; break; case DW_FORM_udata: value = read_uleb128 (ptr); handled = true; break; + case DW_FORM_implicit_const: + value = t->attr[i].value; handled = true; break; default: error (0, 0, "%s: Unhandled %s for %s", dso->filename, get_DW_FORM_str (form), @@ -2971,6 +2988,7 @@ checksum_die (DSO *dso, dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die) ptr += ptr_size; break; case DW_FORM_flag_present: + case DW_FORM_implicit_const: break; case DW_FORM_flag: case DW_FORM_data1: @@ -3403,6 +3421,7 @@ checksum_ref_die (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die, ptr += ptr_size; break; case DW_FORM_flag_present: + case DW_FORM_implicit_const: break; case DW_FORM_flag: case DW_FORM_data1: @@ -4095,6 +4114,7 @@ die_eq_1 (dw_cu_ref cu1, dw_cu_ref cu2, case DW_FORM_data4: value1 = read_32 (ptr1); break; case DW_FORM_data8: value1 = read_64 (ptr1); break; case DW_FORM_udata: value1 = read_uleb128 (ptr1); break; + case DW_FORM_implicit_const: value1 = t1->attr[i].value; break; default: abort (); } switch (form2) @@ -4104,6 +4124,7 @@ die_eq_1 (dw_cu_ref cu1, dw_cu_ref cu2, case DW_FORM_data4: value2 = read_32 (ptr2); break; case DW_FORM_data8: value2 = read_64 (ptr2); break; case DW_FORM_udata: value2 = read_uleb128 (ptr2); break; + case DW_FORM_implicit_const: value2 = t2->attr[j].value; break; default: abort (); } if (ignore_locus) @@ -4224,6 +4245,7 @@ die_eq_1 (dw_cu_ref cu1, dw_cu_ref cu2, ptr2 += ptr_size; break; case DW_FORM_flag_present: + case DW_FORM_implicit_const: break; case DW_FORM_flag: case DW_FORM_data1: @@ -5316,6 +5338,7 @@ mark_refs (dw_cu_ref cu, dw_die_ref top_die, dw_die_ref die, int mode) ptr += ptr_size; break; case DW_FORM_flag_present: + case DW_FORM_implicit_const: break; case DW_FORM_flag: case DW_FORM_data1: @@ -6269,6 +6292,13 @@ read_debug_info (DSO *dso, int kind, unsigned int *die_count) break; case DW_FORM_flag_present: break; + case DW_FORM_implicit_const: + if (lang_p + && (die->die_tag == DW_TAG_compile_unit + || die->die_tag == DW_TAG_partial_unit) + && t->attr[i].attr == DW_AT_language) + cu->lang = t->attr[i].value; + break; case DW_FORM_data1: if (lang_p && (die->die_tag == DW_TAG_compile_unit @@ -9785,6 +9815,8 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die, { t->attr[i].attr = reft->attr[i].attr; t->attr[i].form = reft->attr[i].form; + if (t->attr[i].form == DW_FORM_implicit_const) + t->attr[i].value = reft->attr[i].value; } t->nattr = reft->nattr; } @@ -9814,28 +9846,36 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die, case DW_FORM_data4: value = read_32 (ptr); break; case DW_FORM_data8: value = read_64 (ptr); break; case DW_FORM_udata: value = read_uleb128 (ptr); break; + case DW_FORM_implicit_const: break; default: error (0, 0, "Unhandled %s for %s", get_DW_FORM_str (form), get_DW_AT_str (reft->attr[i].attr)); return 1; } - value = line_htab_lookup (refcu, value); - if (value <= 0xff) - { - form = DW_FORM_data1; - die->die_size++; - } - else if (value <= 0xffff) + /* Note that we transform DW_FORM_implicit_const in + compute_abbrev (). */ + if (form != DW_FORM_implicit_const) { - form = DW_FORM_data2; - die->die_size += 2; + value = line_htab_lookup (refcu, value); + if (value <= 0xff) + { + form = DW_FORM_data1; + die->die_size++; + } + else if (value <= 0xffff) + { + form = DW_FORM_data2; + die->die_size += 2; + } + else + { + form = DW_FORM_data4; + die->die_size += 4; + } } else - { - form = DW_FORM_data4; - die->die_size += 4; - } + t->attr[j].value = reft->attr[i].value; t->attr[j].attr = reft->attr[i].attr; t->attr[j++].form = form; continue; @@ -9941,6 +9981,7 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die, } break; case DW_FORM_flag_present: + case DW_FORM_implicit_const: break; case DW_FORM_flag: case DW_FORM_data1: @@ -10123,7 +10164,10 @@ build_abbrevs_for_die (htab_t h, dw_cu_ref cu, dw_die_ref die, if (form == DW_FORM_block1) ptr += len; t->attr[j].attr = reft->attr[i].attr; - t->attr[j++].form = reft->attr[i].form; + t->attr[j].form = reft->attr[i].form; + if (reft->attr[i].form == DW_FORM_implicit_const) + t->attr[j].value = reft->attr[i].value; + j++; die->die_size += ptr - orig_ptr; } t->nattr = j; @@ -10348,6 +10392,13 @@ abbrev_cmp (const void *p, const void *q) return -1; if (t1->attr[i].form > t2->attr[i].form) return 1; + if (t1->attr[i].form == DW_FORM_implicit_const) + { + if (t1->attr[i].value < t2->attr[i].value) + return -1; + if (t1->attr[i].value > t2->attr[i].value) + return 1; + } } return 0; } @@ -10947,6 +10998,21 @@ compute_abbrevs (DSO *dso) { abbrev_size += size_of_uleb128 (arr[i]->attr[j].attr); abbrev_size += size_of_uleb128 (arr[i]->attr[j].form); + if (arr[i]->attr[j].form == DW_FORM_implicit_const) + { + /* If this is a shared abbrev for a file reference + attribute, update to the new file number (in the + mulifile .debug_line). Note that this might + change the abbrev size... */ + if (unlikely (wr_multifile) + && (arr[i]->attr[j].attr == DW_AT_decl_file + || arr[i]->attr[j].attr == DW_AT_call_file)) + { + uint64_t value = arr[i]->attr[j].value; + arr[i]->attr[j].value = line_htab_lookup (cu, value); + } + abbrev_size += size_of_uleb128 (arr[i]->attr[j].value); + } } abbrev_size += 2; } @@ -11037,6 +11103,8 @@ write_abbrev (void) { write_uleb128 (ptr, arr[i]->attr[j].attr); write_uleb128 (ptr, arr[i]->attr[j].form); + if (arr[i]->attr[j].form == DW_FORM_implicit_const) + write_uleb128 (ptr, arr[i]->attr[j].value); } *ptr++ = 0; *ptr++ = 0; @@ -11398,22 +11466,44 @@ write_die (unsigned char *ptr, dw_cu_ref cu, dw_die_ref die, && (reft->attr[i].attr == DW_AT_decl_file || reft->attr[i].attr == DW_AT_call_file)) { + bool update = false; switch (form) { - case DW_FORM_data1: value = read_8 (inptr); break; - case DW_FORM_data2: value = read_16 (inptr); break; - case DW_FORM_data4: value = read_32 (inptr); break; - case DW_FORM_data8: value = read_64 (inptr); break; - case DW_FORM_udata: value = read_uleb128 (inptr); break; + case DW_FORM_data1: + value = read_8 (inptr); + update = true; + break; + case DW_FORM_data2: + value = read_16 (inptr); + update = true; + break; + case DW_FORM_data4: + value = read_32 (inptr); + update = true; + break; + case DW_FORM_data8: + value = read_64 (inptr); + update = true; + break; + case DW_FORM_udata: + value = read_uleb128 (inptr); + update = true; + break; + case DW_FORM_implicit_const: + /* This gets updated in compute_abbrevs. */ + break; default: abort (); } - value = line_htab_lookup (refcu, value); - switch (t->attr[j].form) + if (update) { - case DW_FORM_data1: write_8 (ptr, value); break; - case DW_FORM_data2: write_16 (ptr, value); break; - case DW_FORM_data4: write_32 (ptr, value); break; - default: abort (); + value = line_htab_lookup (refcu, value); + switch (t->attr[j].form) + { + case DW_FORM_data1: write_8 (ptr, value); break; + case DW_FORM_data2: write_16 (ptr, value); break; + case DW_FORM_data4: write_32 (ptr, value); break; + default: abort (); + } } j++; continue; @@ -11505,6 +11595,7 @@ write_die (unsigned char *ptr, dw_cu_ref cu, dw_die_ref die, } break; case DW_FORM_flag_present: + case DW_FORM_implicit_const: break; case DW_FORM_flag: case DW_FORM_data1: -- 2.18.4