From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20998 invoked by alias); 11 May 2018 13:38:54 -0000 Mailing-List: contact elfutils-devel-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Post: List-Help: List-Subscribe: Sender: elfutils-devel-owner@sourceware.org Received: (qmail 20079 invoked by uid 89); 11 May 2018 13:38:53 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.99.4 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 spammy= X-Spam-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.2 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on sourceware.org X-Spam-Level: X-HELO: gnu.wildebeest.org Received: from wildebeest.demon.nl (HELO gnu.wildebeest.org) (212.238.236.112) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 11 May 2018 13:38:50 +0000 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 6A835310E0BC; Fri, 11 May 2018 15:38:46 +0200 (CEST) Received: by tarox.wildebeest.org (Postfix, from userid 1000) id E3D4D413CB3E; Fri, 11 May 2018 15:38:46 +0200 (CEST) From: Mark Wielaard To: elfutils-devel@sourceware.org Cc: Mark Wielaard Subject: [PATCH] readelf, libdw: Handle DWARF5 .debug_macro. Date: Fri, 11 May 2018 13:38:00 -0000 Message-Id: <1526045925-10193-1-git-send-email-mark@klomp.org> X-Mailer: git-send-email 1.8.3.1 X-Spam-Flag: NO X-IsSubscribed: yes X-SW-Source: 2018-q2/txt/msg00031.txt.bz2 Almost identical to GNU .debug_macro extension. Just accept and use DW_AT_macros where we accept or use DW_AT_GNU_macros. And be a little stricter in which FORMs we accept (this could have caused problems with the GNU variant too). Deals with DW_FORM_strx[1234], but not yet with imported macros through DW_MACRO_import_sup. Signed-off-by: Mark Wielaard --- libdw/ChangeLog | 8 ++++++ libdw/dwarf_formudata.c | 1 + libdw/dwarf_getmacros.c | 42 +++++++++++++++++++++-------- src/ChangeLog | 5 ++++ src/readelf.c | 70 ++++++++++++++++++------------------------------- 5 files changed, 70 insertions(+), 56 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index efdd927..e66a1ec 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,11 @@ +2018-05-11 Mark Wielaard + + * dwarf_formudata.c (dwarf_formudata): Handle DW_AT_macros as macptr. + * dwarf_getmacros.c (get_table_for_offset): Add DW_MACRO_define_sup, + DW_MACRO_undef_sup, DW_MACRO_import_sup, DW_MACRO_define_strx and + DW_MACRO_undef_strx. Add str_offsets_base_off to fake CU. Deal with + DW_AT_macros. Use libdw_valid_user_form. + 2018-05-09 Mark Wielaard * dwarf_formstring.c (__libdw_cu_str_off_base): Moved to... diff --git a/libdw/dwarf_formudata.c b/libdw/dwarf_formudata.c index 02c1694..62352ee 100644 --- a/libdw/dwarf_formudata.c +++ b/libdw/dwarf_formudata.c @@ -158,6 +158,7 @@ dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval) break; case DW_AT_GNU_macros: + case DW_AT_macros: /* macptr into .debug_macro */ if (__libdw_formptr (attr, IDX_debug_macro, DWARF_E_NO_ENTRY, NULL, diff --git a/libdw/dwarf_getmacros.c b/libdw/dwarf_getmacros.c index c456051..fd92966 100644 --- a/libdw/dwarf_getmacros.c +++ b/libdw/dwarf_getmacros.c @@ -1,7 +1,6 @@ /* Get macro information. - Copyright (C) 2002-2009, 2014 Red Hat, Inc. + Copyright (C) 2002-2009, 2014, 2017, 2018 Red Hat, Inc. This file is part of elfutils. - Written by Ulrich Drepper , 2002. This file is free software; you can redistribute it and/or modify it under the terms of either @@ -192,6 +191,8 @@ get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff, MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string); MACRO_PROTO (p_udata_strp, DW_FORM_udata, DW_FORM_strp); + MACRO_PROTO (p_udata_strsup, DW_FORM_udata, DW_FORM_strp_sup); + MACRO_PROTO (p_udata_strx, DW_FORM_udata, DW_FORM_strx); MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata); MACRO_PROTO (p_secoffset, DW_FORM_sec_offset); MACRO_PROTO (p_none); @@ -205,10 +206,11 @@ get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff, [DW_MACRO_start_file - 1] = p_udata_udata, [DW_MACRO_end_file - 1] = p_none, [DW_MACRO_import - 1] = p_secoffset, - /* When adding support for DWARF5 supplementary object files and - indirect string tables also add support for DW_MACRO_define_sup, - DW_MACRO_undef_sup, DW_MACRO_import_sup, DW_MACRO_define_strx - and DW_MACRO_undef_strx. */ + [DW_MACRO_define_sup - 1] = p_udata_strsup, + [DW_MACRO_undef_sup - 1] = p_udata_strsup, + [DW_MACRO_import_sup - 1] = p_secoffset, /* XXX - but in sup!. */ + [DW_MACRO_define_strx - 1] = p_udata_strx, + [DW_MACRO_undef_strx - 1] = p_udata_strx, }; if ((flags & 0x4) != 0) @@ -357,12 +359,18 @@ read_macros (Dwarf *dbg, int sec_index, /* A fake CU with bare minimum data to fool dwarf_formX into doing the right thing with the attributes that we put out. We pretend it is the same version as the actual table. - Version 4 for the old GNU extension, version 5 for DWARF5. */ + Version 4 for the old GNU extension, version 5 for DWARF5. + To handle DW_FORM_strx[1234] we set the .str_offsets_base + from the given CU. + XXX We will need to deal with DW_MACRO_import_sup and change + out the dbg somehow for the DW_FORM_sec_offset to make sense. */ Dwarf_CU fake_cu = { .dbg = dbg, .sec_idx = sec_index, .version = table->version, .offset_size = table->is_64bit ? 8 : 4, + .str_off_base = str_offsets_base_off (dbg, (cudie != NULL + ? cudie->cu: NULL)), .startp = (void *) startp + offset, .endp = (void *) endp, }; @@ -385,14 +393,25 @@ read_macros (Dwarf *dbg, int sec_index, for (Dwarf_Word i = 0; i < proto->nforms; ++i) { - /* We pretend this is a DW_AT_GNU_macros attribute so that + /* We pretend this is a DW_AT[_GNU]_macros attribute so that DW_FORM_sec_offset forms get correctly interpreted as - offset into .debug_macro. */ - attributes[i].code = DW_AT_GNU_macros; + offset into .debug_macro. XXX Deal with DW_MACRO_import_sup + (swap .dbg) for DW_FORM_sec_offset? */ + attributes[i].code = (fake_cu.version == 4 ? DW_AT_GNU_macros + : DW_AT_macros); attributes[i].form = proto->forms[i]; attributes[i].valp = (void *) readp; attributes[i].cu = &fake_cu; + /* We don't want forms that aren't allowed because they could + read from the "abbrev" like DW_FORM_implicit_const. */ + if (! libdw_valid_user_form (attributes[i].form)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + free (attributesp); + return -1; + } + size_t len = __libdw_form_val_len (&fake_cu, proto->forms[i], readp); if (unlikely (len == (size_t) -1)) { @@ -562,7 +581,8 @@ dwarf_getmacros (Dwarf_Die *cudie, int (*callback) (Dwarf_Macro *, void *), { /* DW_AT_GNU_macros, DW_AT_macros */ Dwarf_Word macoff; - if (get_offset_from (cudie, DW_AT_GNU_macros, &macoff) != 0) + if (get_offset_from (cudie, DW_AT_GNU_macros, &macoff) != 0 + && get_offset_from (cudie, DW_AT_macros, &macoff) != 0) return -1; offset = gnu_macros_getmacros_off (cudie->cu->dbg, macoff, callback, arg, offset, accept_0xff, diff --git a/src/ChangeLog b/src/ChangeLog index 4208b52..2a6210e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2018-05-11 Mark Wielaard + + * readelf.c (print_debug_macro_section): Use libdw_valid_user_form. + Use print_form_data for strx and sup strings. + 2018-05-09 Mark Wielaard * readelf.c (dwarf_line_content_description_string): New function. diff --git a/src/readelf.c b/src/readelf.c index ba4c1d7..967a813 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -8199,20 +8199,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), goto invalid_data; unsigned int form = *readp++; printf (" %s", dwarf_form_name (form)); - if (form != DW_FORM_data1 - && form != DW_FORM_data2 - && form != DW_FORM_data4 - && form != DW_FORM_data8 - && form != DW_FORM_sdata - && form != DW_FORM_udata - && form != DW_FORM_block - && form != DW_FORM_block1 - && form != DW_FORM_block2 - && form != DW_FORM_block4 - && form != DW_FORM_flag - && form != DW_FORM_string - && form != DW_FORM_strp - && form != DW_FORM_sec_offset) + if (! libdw_valid_user_form (form)) goto invalid_data; args--; if (args > 0) @@ -8327,26 +8314,22 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), get_uleb128 (u128, readp, readendp); if (readp + offset_len > readendp) goto invalid_data; - if (offset_len == 8) - off = read_8ubyte_unaligned_inc (dbg, readp); - else - off = read_4ubyte_unaligned_inc (dbg, readp); - // Needs support for reading from supplementary object file. - printf ("%*s#define , line %u (sup)\n", - level, "", off, u128); + printf ("%*s#define ", level, ""); + readp = print_form_data (dbg, DW_FORM_strp_sup, + readp, readendp, offset_len, + str_offsets_base); + printf (", line %u (sup)\n", u128); break; case DW_MACRO_undef_sup: get_uleb128 (u128, readp, readendp); if (readp + offset_len > readendp) goto invalid_data; - if (offset_len == 8) - off = read_8ubyte_unaligned_inc (dbg, readp); - else - off = read_4ubyte_unaligned_inc (dbg, readp); - // Needs support for reading from supplementary object file. - printf ("%*s#undef , line %u (sup)\n", - level, "", off, u128); + printf ("%*s#undef ", level, ""); + readp = print_form_data (dbg, DW_FORM_strp_sup, + readp, readendp, offset_len, + str_offsets_base); + printf (", line %u (sup)\n", u128); break; case DW_MACRO_import_sup: @@ -8356,6 +8339,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), off = read_8ubyte_unaligned_inc (dbg, readp); else off = read_4ubyte_unaligned_inc (dbg, readp); + // XXX Needs support for reading from supplementary object file. printf ("%*s#include offset 0x%" PRIx64 " (sup)\n", level, "", off); break; @@ -8364,26 +8348,22 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), get_uleb128 (u128, readp, readendp); if (readp + offset_len > readendp) goto invalid_data; - if (offset_len == 8) - off = read_8ubyte_unaligned_inc (dbg, readp); - else - off = read_4ubyte_unaligned_inc (dbg, readp); - // Needs support for reading indirect string offset table - printf ("%*s#define , line %u (strx)\n", - level, "", off, u128); + printf ("%*s#define ", level, ""); + readp = print_form_data (dbg, DW_FORM_strx, + readp, readendp, offset_len, + str_offsets_base); + printf (", line %u (strx)\n", u128); break; case DW_MACRO_undef_strx: get_uleb128 (u128, readp, readendp); if (readp + offset_len > readendp) goto invalid_data; - if (offset_len == 8) - off = read_8ubyte_unaligned_inc (dbg, readp); - else - off = read_4ubyte_unaligned_inc (dbg, readp); - // Needs support for reading indirect string offset table. - printf ("%*s#undef , line %u (strx)\n", - level, "", off, u128); + printf ("%*s#undef ", level, ""); + readp = print_form_data (dbg, DW_FORM_strx, + readp, readendp, offset_len, + str_offsets_base); + printf (", line %u (strx)\n", u128); break; default: @@ -8399,11 +8379,11 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), // Just skip the arguments, we cannot really interpret them, // but print as much as we can. unsigned int args = *op_desc++; - while (args > 0) + while (args > 0 && readp < readendp) { unsigned int form = *op_desc++; - print_form_data (dbg, form, readp, readendp, offset_len, - str_offsets_base); + readp = print_form_data (dbg, form, readp, readendp, + offset_len, str_offsets_base); args--; if (args > 0) printf (", "); -- 1.8.3.1