X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Freadelf.c;h=2954e7427a23605e957cdf20f9e184544c4b172a;hb=18a667176dd196f7bc3a9cdf1cbd87d4c7b31c7f;hp=88766889b286397ef274348262ca0537e795a8cf;hpb=6dc551eec9ecf4cfc52e5e43ee8e3624e1249b93;p=platform%2Fupstream%2Felfutils.git diff --git a/src/readelf.c b/src/readelf.c index 8876688..2954e74 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -1,28 +1,20 @@ /* Print information from ELF file in human-readable form. Copyright (C) 1999-2012 Red Hat, Inc. - This file is part of Red Hat elfutils. + This file is part of elfutils. Written by Ulrich Drepper , 1999. - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. - Red Hat elfutils is distributed in the hope that it will be useful, but + elfutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - . */ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #ifdef HAVE_CONFIG_H # include @@ -59,6 +51,8 @@ #include "../libdwfl/libdwflP.h" #include "../libdw/memory-access.h" +#include "../libdw/known-dwarf.h" + /* Name and version of program. */ static void print_version (FILE *stream, struct argp_state *state); @@ -94,7 +88,7 @@ static const struct argp_option options[] = { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL, N_("Display DWARF section content. SECTION can be one of abbrev, " "aranges, frame, gdb_index, info, loc, line, ranges, pubnames, str, " - "macinfo, or exception"), 0 }, + "macinfo, macro or exception"), 0 }, { "hex-dump", 'x', "SECTION", 0, N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 }, { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL, @@ -191,10 +185,12 @@ static enum section_e section_ranges = 512, /* .debug_ranges */ section_exception = 1024, /* .eh_frame & al. */ section_gdb_index = 2048, /* .gdb_index */ + section_macro = 4096, /* .debug_macro */ section_all = (section_abbrev | section_aranges | section_frame | section_info | section_line | section_loc | section_pubnames | section_str | section_macinfo - | section_ranges | section_exception | section_gdb_index) + | section_ranges | section_exception | section_gdb_index + | section_macro) } print_debug_sections, implicit_debug_sections; /* Select hex dumping of sections. */ @@ -403,6 +399,8 @@ parse_opt (int key, char *arg, print_debug_sections |= section_str; else if (strcmp (arg, "macinfo") == 0) print_debug_sections |= section_macinfo; + else if (strcmp (arg, "macro") == 0) + print_debug_sections |= section_macro; else if (strcmp (arg, "exception") == 0) print_debug_sections |= section_exception; else if (strcmp (arg, "gdb_index") == 0) @@ -3188,521 +3186,58 @@ format_dwarf_addr (Dwfl_Module *dwflmod, static const char * dwarf_tag_string (unsigned int tag) { - static const char *const known_tags[] = - { - [DW_TAG_array_type] = "array_type", - [DW_TAG_class_type] = "class_type", - [DW_TAG_entry_point] = "entry_point", - [DW_TAG_enumeration_type] = "enumeration_type", - [DW_TAG_formal_parameter] = "formal_parameter", - [DW_TAG_imported_declaration] = "imported_declaration", - [DW_TAG_label] = "label", - [DW_TAG_lexical_block] = "lexical_block", - [DW_TAG_member] = "member", - [DW_TAG_pointer_type] = "pointer_type", - [DW_TAG_reference_type] = "reference_type", - [DW_TAG_compile_unit] = "compile_unit", - [DW_TAG_string_type] = "string_type", - [DW_TAG_structure_type] = "structure_type", - [DW_TAG_subroutine_type] = "subroutine_type", - [DW_TAG_typedef] = "typedef", - [DW_TAG_union_type] = "union_type", - [DW_TAG_unspecified_parameters] = "unspecified_parameters", - [DW_TAG_variant] = "variant", - [DW_TAG_common_block] = "common_block", - [DW_TAG_common_inclusion] = "common_inclusion", - [DW_TAG_inheritance] = "inheritance", - [DW_TAG_inlined_subroutine] = "inlined_subroutine", - [DW_TAG_module] = "module", - [DW_TAG_ptr_to_member_type] = "ptr_to_member_type", - [DW_TAG_set_type] = "set_type", - [DW_TAG_subrange_type] = "subrange_type", - [DW_TAG_with_stmt] = "with_stmt", - [DW_TAG_access_declaration] = "access_declaration", - [DW_TAG_base_type] = "base_type", - [DW_TAG_catch_block] = "catch_block", - [DW_TAG_const_type] = "const_type", - [DW_TAG_constant] = "constant", - [DW_TAG_enumerator] = "enumerator", - [DW_TAG_file_type] = "file_type", - [DW_TAG_friend] = "friend", - [DW_TAG_namelist] = "namelist", - [DW_TAG_namelist_item] = "namelist_item", - [DW_TAG_packed_type] = "packed_type", - [DW_TAG_subprogram] = "subprogram", - [DW_TAG_template_type_parameter] = "template_type_parameter", - [DW_TAG_template_value_parameter] = "template_value_parameter", - [DW_TAG_thrown_type] = "thrown_type", - [DW_TAG_try_block] = "try_block", - [DW_TAG_variant_part] = "variant_part", - [DW_TAG_variable] = "variable", - [DW_TAG_volatile_type] = "volatile_type", - [DW_TAG_dwarf_procedure] = "dwarf_procedure", - [DW_TAG_restrict_type] = "restrict_type", - [DW_TAG_interface_type] = "interface_type", - [DW_TAG_namespace] = "namespace", - [DW_TAG_imported_module] = "imported_module", - [DW_TAG_unspecified_type] = "unspecified_type", - [DW_TAG_partial_unit] = "partial_unit", - [DW_TAG_imported_unit] = "imported_unit", - [DW_TAG_mutable_type] = "mutable_type", - [DW_TAG_condition] = "condition", - [DW_TAG_shared_type] = "shared_type", - [DW_TAG_type_unit] = "type_unit", - [DW_TAG_rvalue_reference_type] = "rvalue_reference_type", - [DW_TAG_template_alias] = "template_alias", - }; - const unsigned int nknown_tags = (sizeof (known_tags) - / sizeof (known_tags[0])); - static char buf[40]; - const char *result = NULL; - - if (likely (tag < nknown_tags)) - result = known_tags[tag]; - - if (unlikely (result == NULL)) - /* There are a few known extensions. */ - switch (tag) - { - case DW_TAG_MIPS_loop: - result = "MIPS_loop"; - break; - - case DW_TAG_format_label: - result = "format_label"; - break; - - case DW_TAG_function_template: - result = "function_template"; - break; - - case DW_TAG_class_template: - result = "class_template"; - break; - - case DW_TAG_GNU_BINCL: - result = "GNU_BINCL"; - break; - - case DW_TAG_GNU_EINCL: - result = "GNU_EINCL"; - break; - - case DW_TAG_GNU_template_template_param: - result = "GNU_template_template_param"; - break; - - case DW_TAG_GNU_template_parameter_pack: - result = "GNU_template_parameter_pack"; - break; - - case DW_TAG_GNU_formal_parameter_pack: - result = "GNU_formal_parameter_pack"; - break; - - case DW_TAG_GNU_call_site: - result = "GNU_call_site"; - break; - - case DW_TAG_GNU_call_site_parameter: - result = "GNU_call_site_parameter"; - break; - - default: - if (tag < DW_TAG_lo_user) - snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag); - else - snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag); - result = buf; - break; - } - - return result; + switch (tag) + { +#define ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME; + ALL_KNOWN_DW_TAG +#undef ONE_KNOWN_DW_TAG + default: + return NULL; + } } static const char * dwarf_attr_string (unsigned int attrnum) { - static const char *const known_attrs[] = - { - [DW_AT_sibling] = "sibling", - [DW_AT_location] = "location", - [DW_AT_name] = "name", - [DW_AT_ordering] = "ordering", - [DW_AT_subscr_data] = "subscr_data", - [DW_AT_byte_size] = "byte_size", - [DW_AT_bit_offset] = "bit_offset", - [DW_AT_bit_size] = "bit_size", - [DW_AT_element_list] = "element_list", - [DW_AT_stmt_list] = "stmt_list", - [DW_AT_low_pc] = "low_pc", - [DW_AT_high_pc] = "high_pc", - [DW_AT_language] = "language", - [DW_AT_member] = "member", - [DW_AT_discr] = "discr", - [DW_AT_discr_value] = "discr_value", - [DW_AT_visibility] = "visibility", - [DW_AT_import] = "import", - [DW_AT_string_length] = "string_length", - [DW_AT_common_reference] = "common_reference", - [DW_AT_comp_dir] = "comp_dir", - [DW_AT_const_value] = "const_value", - [DW_AT_containing_type] = "containing_type", - [DW_AT_default_value] = "default_value", - [DW_AT_inline] = "inline", - [DW_AT_is_optional] = "is_optional", - [DW_AT_lower_bound] = "lower_bound", - [DW_AT_producer] = "producer", - [DW_AT_prototyped] = "prototyped", - [DW_AT_return_addr] = "return_addr", - [DW_AT_start_scope] = "start_scope", - [DW_AT_bit_stride] = "bit_stride", - [DW_AT_upper_bound] = "upper_bound", - [DW_AT_abstract_origin] = "abstract_origin", - [DW_AT_accessibility] = "accessibility", - [DW_AT_address_class] = "address_class", - [DW_AT_artificial] = "artificial", - [DW_AT_base_types] = "base_types", - [DW_AT_calling_convention] = "calling_convention", - [DW_AT_count] = "count", - [DW_AT_data_member_location] = "data_member_location", - [DW_AT_decl_column] = "decl_column", - [DW_AT_decl_file] = "decl_file", - [DW_AT_decl_line] = "decl_line", - [DW_AT_declaration] = "declaration", - [DW_AT_discr_list] = "discr_list", - [DW_AT_encoding] = "encoding", - [DW_AT_external] = "external", - [DW_AT_frame_base] = "frame_base", - [DW_AT_friend] = "friend", - [DW_AT_identifier_case] = "identifier_case", - [DW_AT_macro_info] = "macro_info", - [DW_AT_namelist_item] = "namelist_item", - [DW_AT_priority] = "priority", - [DW_AT_segment] = "segment", - [DW_AT_specification] = "specification", - [DW_AT_static_link] = "static_link", - [DW_AT_type] = "type", - [DW_AT_use_location] = "use_location", - [DW_AT_variable_parameter] = "variable_parameter", - [DW_AT_virtuality] = "virtuality", - [DW_AT_vtable_elem_location] = "vtable_elem_location", - [DW_AT_allocated] = "allocated", - [DW_AT_associated] = "associated", - [DW_AT_data_location] = "data_location", - [DW_AT_byte_stride] = "byte_stride", - [DW_AT_entry_pc] = "entry_pc", - [DW_AT_use_UTF8] = "use_UTF8", - [DW_AT_extension] = "extension", - [DW_AT_ranges] = "ranges", - [DW_AT_trampoline] = "trampoline", - [DW_AT_call_column] = "call_column", - [DW_AT_call_file] = "call_file", - [DW_AT_call_line] = "call_line", - [DW_AT_description] = "description", - [DW_AT_binary_scale] = "binary_scale", - [DW_AT_decimal_scale] = "decimal_scale", - [DW_AT_small] = "small", - [DW_AT_decimal_sign] = "decimal_sign", - [DW_AT_digit_count] = "digit_count", - [DW_AT_picture_string] = "picture_string", - [DW_AT_mutable] = "mutable", - [DW_AT_threads_scaled] = "threads_scaled", - [DW_AT_explicit] = "explicit", - [DW_AT_object_pointer] = "object_pointer", - [DW_AT_endianity] = "endianity", - [DW_AT_elemental] = "elemental", - [DW_AT_pure] = "pure", - [DW_AT_recursive] = "recursive", - [DW_AT_signature] = "signature", - [DW_AT_main_subprogram] = "main_subprogram", - [DW_AT_data_bit_offset] = "data_bit_offset", - [DW_AT_const_expr] = "const_expr", - [DW_AT_enum_class] = "enum_class", - [DW_AT_linkage_name] = "linkage_name", - }; - const unsigned int nknown_attrs = (sizeof (known_attrs) - / sizeof (known_attrs[0])); - static char buf[40]; - const char *result = NULL; - - if (likely (attrnum < nknown_attrs)) - result = known_attrs[attrnum]; - - if (unlikely (result == NULL)) - /* There are a few known extensions. */ - switch (attrnum) - { - case DW_AT_MIPS_fde: - result = "MIPS_fde"; - break; - - case DW_AT_MIPS_loop_begin: - result = "MIPS_loop_begin"; - break; - - case DW_AT_MIPS_tail_loop_begin: - result = "MIPS_tail_loop_begin"; - break; - - case DW_AT_MIPS_epilog_begin: - result = "MIPS_epilog_begin"; - break; - - case DW_AT_MIPS_loop_unroll_factor: - result = "MIPS_loop_unroll_factor"; - break; - - case DW_AT_MIPS_software_pipeline_depth: - result = "MIPS_software_pipeline_depth"; - break; - - case DW_AT_MIPS_linkage_name: - result = "MIPS_linkage_name"; - break; - - case DW_AT_MIPS_stride: - result = "MIPS_stride"; - break; - - case DW_AT_MIPS_abstract_name: - result = "MIPS_abstract_name"; - break; - - case DW_AT_MIPS_clone_origin: - result = "MIPS_clone_origin"; - break; - - case DW_AT_MIPS_has_inlines: - result = "MIPS_has_inlines"; - break; - - case DW_AT_MIPS_stride_byte: - result = "MIPS_stride_byte"; - break; - - case DW_AT_MIPS_stride_elem: - result = "MIPS_stride_elem"; - break; - - case DW_AT_MIPS_ptr_dopetype: - result = "MIPS_ptr_dopetype"; - break; - - case DW_AT_MIPS_allocatable_dopetype: - result = "MIPS_allocatable_dopetype"; - break; - - case DW_AT_MIPS_assumed_shape_dopetype: - result = "MIPS_assumed_shape_dopetype"; - break; - - case DW_AT_MIPS_assumed_size: - result = "MIPS_assumed_size"; - break; - - case DW_AT_sf_names: - result = "sf_names"; - break; - - case DW_AT_src_info: - result = "src_info"; - break; - - case DW_AT_mac_info: - result = "mac_info"; - break; - - case DW_AT_src_coords: - result = "src_coords"; - break; - - case DW_AT_body_begin: - result = "body_begin"; - break; - - case DW_AT_body_end: - result = "body_end"; - break; - - case DW_AT_GNU_vector: - result = "GNU_vector"; - break; - - case DW_AT_GNU_guarded_by: - result = "GNU_guarded_by"; - break; - - case DW_AT_GNU_pt_guarded_by: - result = "GNU_pt_guarded_by"; - break; - - case DW_AT_GNU_guarded: - result = "GNU_guarded"; - break; - - case DW_AT_GNU_pt_guarded: - result = "GNU_pt_guarded"; - break; - - case DW_AT_GNU_locks_excluded: - result = "GNU_locks_excluded"; - break; - - case DW_AT_GNU_exclusive_locks_required: - result = "GNU_exclusive_locks_required"; - break; - - case DW_AT_GNU_shared_locks_required: - result = "GNU_shared_locks_required"; - break; - - case DW_AT_GNU_odr_signature: - result = "GNU_odr_signature"; - break; - - case DW_AT_GNU_template_name: - result = "GNU_template_name"; - break; - - case DW_AT_GNU_call_site_value: - result = "GNU_call_site_value"; - break; - - case DW_AT_GNU_call_site_data_value: - result = "GNU_call_site_data_value"; - break; - - case DW_AT_GNU_call_site_target: - result = "GNU_call_site_target"; - break; - - case DW_AT_GNU_call_site_target_clobbered: - result = "GNU_call_site_target_clobbered"; - break; - - case DW_AT_GNU_tail_call: - result = "GNU_tail_call"; - break; - - case DW_AT_GNU_all_tail_call_sites: - result = "GNU_all_tail_call_sites"; - break; - - case DW_AT_GNU_all_call_sites: - result = "GNU_all_call_sites"; - break; - - case DW_AT_GNU_all_source_call_sites: - result = "GNU_all_source_call_sites"; - break; - - default: - if (attrnum < DW_AT_lo_user) - snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"), - attrnum); - else - snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"), - attrnum); - result = buf; - break; - } - - return result; + switch (attrnum) + { +#define ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME; + ALL_KNOWN_DW_AT +#undef ONE_KNOWN_DW_AT + default: + return NULL; + } } static const char * dwarf_form_string (unsigned int form) { - static const char *const known_forms[] = - { - [DW_FORM_addr] = "addr", - [DW_FORM_block2] = "block2", - [DW_FORM_block4] = "block4", - [DW_FORM_data2] = "data2", - [DW_FORM_data4] = "data4", - [DW_FORM_data8] = "data8", - [DW_FORM_string] = "string", - [DW_FORM_block] = "block", - [DW_FORM_block1] = "block1", - [DW_FORM_data1] = "data1", - [DW_FORM_flag] = "flag", - [DW_FORM_sdata] = "sdata", - [DW_FORM_strp] = "strp", - [DW_FORM_udata] = "udata", - [DW_FORM_ref_addr] = "ref_addr", - [DW_FORM_ref1] = "ref1", - [DW_FORM_ref2] = "ref2", - [DW_FORM_ref4] = "ref4", - [DW_FORM_ref8] = "ref8", - [DW_FORM_ref_udata] = "ref_udata", - [DW_FORM_indirect] = "indirect", - [DW_FORM_sec_offset] = "sec_offset", - [DW_FORM_exprloc] = "exprloc", - [DW_FORM_flag_present] = "flag_present", - [DW_FORM_ref_sig8] = "ref_sig8", - }; - const unsigned int nknown_forms = (sizeof (known_forms) - / sizeof (known_forms[0])); - static char buf[40]; - const char *result = NULL; - - if (likely (form < nknown_forms)) - result = known_forms[form]; - - if (unlikely (result == NULL)) + switch (form) { - snprintf (buf, sizeof buf, gettext ("unknown form %#" PRIx64), - (uint64_t) form); - result = buf; +#define ONE_KNOWN_DW_FORM_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_FORM (NAME, CODE) +#define ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME; + ALL_KNOWN_DW_FORM +#undef ONE_KNOWN_DW_FORM +#undef ONE_KNOWN_DW_FORM_DESC + default: + return NULL; } - - return result; } static const char * dwarf_lang_string (unsigned int lang) { - static const char *const known[] = + switch (lang) { - [DW_LANG_C89] = "ISO C89", - [DW_LANG_C] = "C", - [DW_LANG_Ada83] = "Ada83", - [DW_LANG_C_plus_plus] = "C++", - [DW_LANG_Cobol74] = "Cobol74", - [DW_LANG_Cobol85] = "Cobol85", - [DW_LANG_Fortran77] = "Fortran77", - [DW_LANG_Fortran90] = "Fortran90", - [DW_LANG_Pascal83] = "Pascal83", - [DW_LANG_Modula2] = "Modula2", - [DW_LANG_Java] = "Java", - [DW_LANG_C99] = "ISO C99", - [DW_LANG_Ada95] = "Ada95", - [DW_LANG_Fortran95] = "Fortran95", - [DW_LANG_PL1] = "PL1", - [DW_LANG_Objc] = "Objective C", - [DW_LANG_ObjC_plus_plus] = "Objective C++", - [DW_LANG_UPC] = "UPC", - [DW_LANG_D] = "D", - }; - - if (likely (lang < sizeof (known) / sizeof (known[0]))) - return known[lang]; - else if (lang == DW_LANG_Mips_Assembler) - /* This language tag is used for assembler in general. */ - return "Assembler"; - - if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user) - { - static char buf[30]; - snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user); - return buf; +#define ONE_KNOWN_DW_LANG_DESC(NAME, CODE, DESC) case CODE: return #NAME; + ALL_KNOWN_DW_LANG +#undef ONE_KNOWN_DW_LANG_DESC + default: + return NULL; } - - return "???"; } @@ -3711,16 +3246,15 @@ dwarf_inline_string (unsigned int code) { static const char *const known[] = { - [DW_INL_not_inlined] = "not_inlined", - [DW_INL_inlined] = "inlined", - [DW_INL_declared_not_inlined] = "declared_not_inlined", - [DW_INL_declared_inlined] = "declared_inlined" +#define ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_INL +#undef ONE_KNOWN_DW_INL }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3729,35 +3263,15 @@ dwarf_encoding_string (unsigned int code) { static const char *const known[] = { - [DW_ATE_void] = "void", - [DW_ATE_address] = "address", - [DW_ATE_boolean] = "boolean", - [DW_ATE_complex_float] = "complex_float", - [DW_ATE_float] = "float", - [DW_ATE_signed] = "signed", - [DW_ATE_signed_char] = "signed_char", - [DW_ATE_unsigned] = "unsigned", - [DW_ATE_unsigned_char] = "unsigned_char", - [DW_ATE_imaginary_float] = "imaginary_float", - [DW_ATE_packed_decimal] = "packed_decimal", - [DW_ATE_numeric_string] = "numeric_string", - [DW_ATE_edited] = "edited", - [DW_ATE_signed_fixed] = "signed_fixed", - [DW_ATE_unsigned_fixed] = "unsigned_fixed", - [DW_ATE_decimal_float] = "decimal_float", +#define ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_ATE +#undef ONE_KNOWN_DW_ATE }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - if (code >= DW_ATE_lo_user && code <= DW_ATE_hi_user) - { - static char buf[30]; - snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_ATE_lo_user); - return buf; - } - - return "???"; + return NULL; } @@ -3766,15 +3280,15 @@ dwarf_access_string (unsigned int code) { static const char *const known[] = { - [DW_ACCESS_public] = "public", - [DW_ACCESS_protected] = "protected", - [DW_ACCESS_private] = "private" +#define ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_ACCESS +#undef ONE_KNOWN_DW_ACCESS }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3783,15 +3297,15 @@ dwarf_visibility_string (unsigned int code) { static const char *const known[] = { - [DW_VIS_local] = "local", - [DW_VIS_exported] = "exported", - [DW_VIS_qualified] = "qualified" +#define ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_VIS +#undef ONE_KNOWN_DW_VIS }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3800,15 +3314,15 @@ dwarf_virtuality_string (unsigned int code) { static const char *const known[] = { - [DW_VIRTUALITY_none] = "none", - [DW_VIRTUALITY_virtual] = "virtual", - [DW_VIRTUALITY_pure_virtual] = "pure_virtual" +#define ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_VIRTUALITY +#undef ONE_KNOWN_DW_VIRTUALITY }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3817,16 +3331,15 @@ dwarf_identifier_case_string (unsigned int code) { static const char *const known[] = { - [DW_ID_case_sensitive] = "sensitive", - [DW_ID_up_case] = "up_case", - [DW_ID_down_case] = "down_case", - [DW_ID_case_insensitive] = "insensitive" +#define ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_ID +#undef ONE_KNOWN_DW_ID }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3835,22 +3348,15 @@ dwarf_calling_convention_string (unsigned int code) { static const char *const known[] = { - [DW_CC_normal] = "normal", - [DW_CC_program] = "program", - [DW_CC_nocall] = "nocall", +#define ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_CC +#undef ONE_KNOWN_DW_CC }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - if (code >= DW_CC_lo_user && code <= DW_CC_hi_user) - { - static char buf[30]; - snprintf (buf, sizeof (buf), "lo_user+%u", code - DW_CC_lo_user); - return buf; - } - - return "???"; + return NULL; } @@ -3859,14 +3365,15 @@ dwarf_ordering_string (unsigned int code) { static const char *const known[] = { - [DW_ORD_row_major] = "row_major", - [DW_ORD_col_major] = "col_major" +#define ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_ORD +#undef ONE_KNOWN_DW_ORD }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; - return "???"; + return NULL; } @@ -3875,17 +3382,171 @@ dwarf_discr_list_string (unsigned int code) { static const char *const known[] = { - [DW_DSC_label] = "label", - [DW_DSC_range] = "range" +#define ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_DSC +#undef ONE_KNOWN_DW_DSC }; if (likely (code < sizeof (known) / sizeof (known[0]))) return known[code]; + return NULL; +} + + +static const char * +dwarf_locexpr_opcode_string (unsigned int code) +{ + static const char *const known[] = + { + /* Normally we can't affort building huge table of 64K entries, + most of them zero, just because there are a couple defined + values at the far end. In case of opcodes, it's OK. */ +#define ONE_KNOWN_DW_OP_DESC(NAME, CODE, DESC) ONE_KNOWN_DW_OP (NAME, CODE) +#define ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME, + ALL_KNOWN_DW_OP +#undef ONE_KNOWN_DW_OP +#undef ONE_KNOWN_DW_OP_DESC + }; + + if (likely (code < sizeof (known) / sizeof (known[0]))) + return known[code]; + + return NULL; +} + + +/* Used by all dwarf_foo_name functions. */ +static const char * +string_or_unknown (const char *known, unsigned int code, + unsigned int lo_user, unsigned int hi_user, + bool print_unknown_num) +{ + static char unknown_buf[20]; + + if (likely (known != NULL)) + return known; + + if (lo_user != 0 && code >= lo_user && code <= hi_user) + { + snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x", + code - lo_user); + return unknown_buf; + } + + if (print_unknown_num) + { + snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code); + return unknown_buf; + } + return "???"; } +static const char * +dwarf_tag_name (unsigned int tag) +{ + const char *ret = dwarf_tag_string (tag); + return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true); +} + +static const char * +dwarf_attr_name (unsigned int attr) +{ + const char *ret = dwarf_attr_string (attr); + return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true); +} + + +static const char * +dwarf_form_name (unsigned int form) +{ + const char *ret = dwarf_form_string (form); + return string_or_unknown (ret, form, 0, 0, true); +} + + +static const char * +dwarf_lang_name (unsigned int lang) +{ + const char *ret = dwarf_lang_string (lang); + return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false); +} + + +static const char * +dwarf_inline_name (unsigned int code) +{ + const char *ret = dwarf_inline_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_encoding_name (unsigned int code) +{ + const char *ret = dwarf_encoding_string (code); + return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false); +} + + +static const char * +dwarf_access_name (unsigned int code) +{ + const char *ret = dwarf_access_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_visibility_name (unsigned int code) +{ + const char *ret = dwarf_visibility_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_virtuality_name (unsigned int code) +{ + const char *ret = dwarf_virtuality_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_identifier_case_name (unsigned int code) +{ + const char *ret = dwarf_identifier_case_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_calling_convention_name (unsigned int code) +{ + const char *ret = dwarf_calling_convention_string (code); + return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false); +} + + +static const char * +dwarf_ordering_name (unsigned int code) +{ + const char *ret = dwarf_ordering_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + +static const char * +dwarf_discr_list_name (unsigned int code) +{ + const char *ret = dwarf_discr_list_string (code); + return string_or_unknown (ret, code, 0, 0, false); +} + + static void print_block (size_t n, const void *block) { @@ -3909,171 +3570,6 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, { const unsigned int ref_size = vers < 3 ? addrsize : offset_size; - static const char *const known[] = - { - [DW_OP_addr] = "addr", - [DW_OP_deref] = "deref", - [DW_OP_const1u] = "const1u", - [DW_OP_const1s] = "const1s", - [DW_OP_const2u] = "const2u", - [DW_OP_const2s] = "const2s", - [DW_OP_const4u] = "const4u", - [DW_OP_const4s] = "const4s", - [DW_OP_const8u] = "const8u", - [DW_OP_const8s] = "const8s", - [DW_OP_constu] = "constu", - [DW_OP_consts] = "consts", - [DW_OP_dup] = "dup", - [DW_OP_drop] = "drop", - [DW_OP_over] = "over", - [DW_OP_pick] = "pick", - [DW_OP_swap] = "swap", - [DW_OP_rot] = "rot", - [DW_OP_xderef] = "xderef", - [DW_OP_abs] = "abs", - [DW_OP_and] = "and", - [DW_OP_div] = "div", - [DW_OP_minus] = "minus", - [DW_OP_mod] = "mod", - [DW_OP_mul] = "mul", - [DW_OP_neg] = "neg", - [DW_OP_not] = "not", - [DW_OP_or] = "or", - [DW_OP_plus] = "plus", - [DW_OP_plus_uconst] = "plus_uconst", - [DW_OP_shl] = "shl", - [DW_OP_shr] = "shr", - [DW_OP_shra] = "shra", - [DW_OP_xor] = "xor", - [DW_OP_bra] = "bra", - [DW_OP_eq] = "eq", - [DW_OP_ge] = "ge", - [DW_OP_gt] = "gt", - [DW_OP_le] = "le", - [DW_OP_lt] = "lt", - [DW_OP_ne] = "ne", - [DW_OP_skip] = "skip", - [DW_OP_lit0] = "lit0", - [DW_OP_lit1] = "lit1", - [DW_OP_lit2] = "lit2", - [DW_OP_lit3] = "lit3", - [DW_OP_lit4] = "lit4", - [DW_OP_lit5] = "lit5", - [DW_OP_lit6] = "lit6", - [DW_OP_lit7] = "lit7", - [DW_OP_lit8] = "lit8", - [DW_OP_lit9] = "lit9", - [DW_OP_lit10] = "lit10", - [DW_OP_lit11] = "lit11", - [DW_OP_lit12] = "lit12", - [DW_OP_lit13] = "lit13", - [DW_OP_lit14] = "lit14", - [DW_OP_lit15] = "lit15", - [DW_OP_lit16] = "lit16", - [DW_OP_lit17] = "lit17", - [DW_OP_lit18] = "lit18", - [DW_OP_lit19] = "lit19", - [DW_OP_lit20] = "lit20", - [DW_OP_lit21] = "lit21", - [DW_OP_lit22] = "lit22", - [DW_OP_lit23] = "lit23", - [DW_OP_lit24] = "lit24", - [DW_OP_lit25] = "lit25", - [DW_OP_lit26] = "lit26", - [DW_OP_lit27] = "lit27", - [DW_OP_lit28] = "lit28", - [DW_OP_lit29] = "lit29", - [DW_OP_lit30] = "lit30", - [DW_OP_lit31] = "lit31", - [DW_OP_reg0] = "reg0", - [DW_OP_reg1] = "reg1", - [DW_OP_reg2] = "reg2", - [DW_OP_reg3] = "reg3", - [DW_OP_reg4] = "reg4", - [DW_OP_reg5] = "reg5", - [DW_OP_reg6] = "reg6", - [DW_OP_reg7] = "reg7", - [DW_OP_reg8] = "reg8", - [DW_OP_reg9] = "reg9", - [DW_OP_reg10] = "reg10", - [DW_OP_reg11] = "reg11", - [DW_OP_reg12] = "reg12", - [DW_OP_reg13] = "reg13", - [DW_OP_reg14] = "reg14", - [DW_OP_reg15] = "reg15", - [DW_OP_reg16] = "reg16", - [DW_OP_reg17] = "reg17", - [DW_OP_reg18] = "reg18", - [DW_OP_reg19] = "reg19", - [DW_OP_reg20] = "reg20", - [DW_OP_reg21] = "reg21", - [DW_OP_reg22] = "reg22", - [DW_OP_reg23] = "reg23", - [DW_OP_reg24] = "reg24", - [DW_OP_reg25] = "reg25", - [DW_OP_reg26] = "reg26", - [DW_OP_reg27] = "reg27", - [DW_OP_reg28] = "reg28", - [DW_OP_reg29] = "reg29", - [DW_OP_reg30] = "reg30", - [DW_OP_reg31] = "reg31", - [DW_OP_breg0] = "breg0", - [DW_OP_breg1] = "breg1", - [DW_OP_breg2] = "breg2", - [DW_OP_breg3] = "breg3", - [DW_OP_breg4] = "breg4", - [DW_OP_breg5] = "breg5", - [DW_OP_breg6] = "breg6", - [DW_OP_breg7] = "breg7", - [DW_OP_breg8] = "breg8", - [DW_OP_breg9] = "breg9", - [DW_OP_breg10] = "breg10", - [DW_OP_breg11] = "breg11", - [DW_OP_breg12] = "breg12", - [DW_OP_breg13] = "breg13", - [DW_OP_breg14] = "breg14", - [DW_OP_breg15] = "breg15", - [DW_OP_breg16] = "breg16", - [DW_OP_breg17] = "breg17", - [DW_OP_breg18] = "breg18", - [DW_OP_breg19] = "breg19", - [DW_OP_breg20] = "breg20", - [DW_OP_breg21] = "breg21", - [DW_OP_breg22] = "breg22", - [DW_OP_breg23] = "breg23", - [DW_OP_breg24] = "breg24", - [DW_OP_breg25] = "breg25", - [DW_OP_breg26] = "breg26", - [DW_OP_breg27] = "breg27", - [DW_OP_breg28] = "breg28", - [DW_OP_breg29] = "breg29", - [DW_OP_breg30] = "breg30", - [DW_OP_breg31] = "breg31", - [DW_OP_regx] = "regx", - [DW_OP_fbreg] = "fbreg", - [DW_OP_bregx] = "bregx", - [DW_OP_piece] = "piece", - [DW_OP_deref_size] = "deref_size", - [DW_OP_xderef_size] = "xderef_size", - [DW_OP_nop] = "nop", - [DW_OP_push_object_address] = "push_object_address", - [DW_OP_call2] = "call2", - [DW_OP_call4] = "call4", - [DW_OP_call_ref] = "call_ref", - [DW_OP_form_tls_address] = "form_tls_address", - [DW_OP_call_frame_cfa] = "call_frame_cfa", - [DW_OP_bit_piece] = "bit_piece", - [DW_OP_implicit_value] = "implicit_value", - [DW_OP_stack_value] = "stack_value", - [DW_OP_GNU_implicit_pointer] = "GNU_implicit_pointer", - [DW_OP_GNU_entry_value] = "GNU_entry_value", - [DW_OP_GNU_const_type] = "GNU_const_type", - [DW_OP_GNU_regval_type] = "GNU_regval_type", - [DW_OP_GNU_deref_type] = "GNU_deref_type", - [DW_OP_GNU_convert] = "GNU_convert", - [DW_OP_GNU_reinterpret] = "GNU_reinterpret", - }; - if (len == 0) { printf ("%*s(empty)\n", indent, ""); @@ -4088,6 +3584,17 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, { uint_fast8_t op = *data++; + const char *op_name = dwarf_locexpr_opcode_string (op); + if (unlikely (op_name == NULL)) + { + static char buf[20]; + if (op >= DW_OP_lo_user) + snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user); + else + snprintf (buf, sizeof buf, "??? (%#x)", op); + op_name = buf; + } + switch (op) { case DW_OP_addr:; @@ -4106,7 +3613,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, char *a = format_dwarf_addr (dwflmod, 0, addr); printf ("%*s[%4" PRIuMAX "] %s %s\n", - indent, "", (uintmax_t) offset, known[op], a); + indent, "", (uintmax_t) offset, op_name, a); free (a); offset += 1 + addrsize; @@ -4127,7 +3634,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n", indent, "", (uintmax_t) offset, - known[op], (uintmax_t) addr); + op_name, (uintmax_t) addr); offset += 1 + ref_size; break; @@ -4139,7 +3646,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, NEED (1); printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n", indent, "", (uintmax_t) offset, - known[op], *((uint8_t *) data)); + op_name, *((uint8_t *) data)); ++data; --len; offset += 2; @@ -4150,7 +3657,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n", indent, "", (uintmax_t) offset, - known[op], read_2ubyte_unaligned (dbg, data)); + op_name, read_2ubyte_unaligned (dbg, data)); CONSUME (2); data += 2; offset += 3; @@ -4161,7 +3668,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n", indent, "", (uintmax_t) offset, - known[op], read_4ubyte_unaligned (dbg, data)); + op_name, read_4ubyte_unaligned (dbg, data)); CONSUME (4); data += 4; offset += 5; @@ -4172,7 +3679,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n", indent, "", (uintmax_t) offset, - known[op], read_8ubyte_unaligned (dbg, data)); + op_name, (uint64_t) read_8ubyte_unaligned (dbg, data)); CONSUME (8); data += 8; offset += 9; @@ -4183,7 +3690,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n", indent, "", (uintmax_t) offset, - known[op], *((int8_t *) data)); + op_name, *((int8_t *) data)); ++data; --len; offset += 2; @@ -4194,7 +3701,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n", indent, "", (uintmax_t) offset, - known[op], read_2sbyte_unaligned (dbg, data)); + op_name, read_2sbyte_unaligned (dbg, data)); CONSUME (2); data += 2; offset += 3; @@ -4205,7 +3712,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n", indent, "", (uintmax_t) offset, - known[op], read_4sbyte_unaligned (dbg, data)); + op_name, read_4sbyte_unaligned (dbg, data)); CONSUME (4); data += 4; offset += 5; @@ -4216,7 +3723,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, // XXX value might be modified by relocation printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n", indent, "", (uintmax_t) offset, - known[op], read_8sbyte_unaligned (dbg, data)); + op_name, read_8sbyte_unaligned (dbg, data)); CONSUME (8); data += 8; offset += 9; @@ -4231,7 +3738,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, NEED (1); get_uleb128 (uleb, data); /* XXX check overrun */ printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n", - indent, "", (uintmax_t) offset, known[op], uleb); + indent, "", (uintmax_t) offset, op_name, uleb); CONSUME (data - start); offset += 1 + (data - start); break; @@ -4243,7 +3750,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, get_uleb128 (uleb, data); /* XXX check overrun */ get_uleb128 (uleb2, data); /* XXX check overrun */ printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n", - indent, "", (uintmax_t) offset, known[op], uleb, uleb2); + indent, "", (uintmax_t) offset, op_name, uleb, uleb2); CONSUME (data - start); offset += 1 + (data - start); break; @@ -4256,7 +3763,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, NEED (1); get_sleb128 (sleb, data); /* XXX check overrun */ printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n", - indent, "", (uintmax_t) offset, known[op], sleb); + indent, "", (uintmax_t) offset, op_name, sleb); CONSUME (data - start); offset += 1 + (data - start); break; @@ -4267,7 +3774,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, get_uleb128 (uleb, data); /* XXX check overrun */ get_sleb128 (sleb, data); /* XXX check overrun */ printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n", - indent, "", (uintmax_t) offset, known[op], uleb, sleb); + indent, "", (uintmax_t) offset, op_name, uleb, sleb); CONSUME (data - start); offset += 1 + (data - start); break; @@ -4275,7 +3782,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_call2: NEED (2); printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n", - indent, "", (uintmax_t) offset, known[op], + indent, "", (uintmax_t) offset, op_name, read_2ubyte_unaligned (dbg, data)); CONSUME (2); offset += 3; @@ -4284,7 +3791,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_call4: NEED (4); printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n", - indent, "", (uintmax_t) offset, known[op], + indent, "", (uintmax_t) offset, op_name, read_4ubyte_unaligned (dbg, data)); CONSUME (4); offset += 5; @@ -4294,7 +3801,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, case DW_OP_bra: NEED (2); printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n", - indent, "", (uintmax_t) offset, known[op], + indent, "", (uintmax_t) offset, op_name, (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data))); CONSUME (2); data += 2; @@ -4306,7 +3813,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, NEED (1); get_uleb128 (uleb, data); /* XXX check overrun */ printf ("%*s[%4" PRIuMAX "] %s: ", - indent, "", (uintmax_t) offset, known[op]); + indent, "", (uintmax_t) offset, op_name); NEED (uleb); print_block (uleb, data); data += uleb; @@ -4331,7 +3838,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX ", %+" PRId64 "\n", indent, "", (intmax_t) offset, - known[op], (uintmax_t) addr, sleb); + op_name, (uintmax_t) addr, sleb); CONSUME (data - start); offset += 1 + (data - start); break; @@ -4342,7 +3849,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, NEED (1); get_uleb128 (uleb, data); /* XXX check overrun */ printf ("%*s[%4" PRIuMAX "] %s:\n", - indent, "", (uintmax_t) offset, known[op]); + indent, "", (uintmax_t) offset, op_name); NEED (uleb); print_ops (dwflmod, dbg, indent + 6, indent + 6, vers, addrsize, offset_size, uleb, data); @@ -4359,7 +3866,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, uint8_t usize = *(uint8_t *) data++; NEED (usize); printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "] ", - indent, "", (uintmax_t) offset, known[op], uleb); + indent, "", (uintmax_t) offset, op_name, uleb); print_block (usize, data); data += usize; CONSUME (data - start); @@ -4372,7 +3879,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, get_uleb128 (uleb, data); /* XXX check overrun */ get_uleb128 (uleb2, data); /* XXX check overrun */ printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %#" PRIx64 "\n", - indent, "", (uintmax_t) offset, known[op], uleb, uleb2); + indent, "", (uintmax_t) offset, op_name, uleb, uleb2); CONSUME (data - start); offset += 1 + (data - start); break; @@ -4384,7 +3891,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, get_uleb128 (uleb, data); /* XXX check overrun */ printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n", indent, "", (uintmax_t) offset, - known[op], usize, uleb); + op_name, usize, uleb); CONSUME (data - start); offset += 1 + (data - start); break; @@ -4395,19 +3902,27 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, NEED (1); get_uleb128 (uleb, data); /* XXX check overrun */ printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n", - indent, "", (uintmax_t) offset, known[op], uleb); + indent, "", (uintmax_t) offset, op_name, uleb); CONSUME (data - start); offset += 1 + (data - start); break; + case DW_OP_GNU_parameter_ref: + /* 4 byte CU relative reference to the abstract optimized away + DW_TAG_formal_parameter. */ + NEED (4); + printf ("%*s[%4" PRIuMAX "] %s [%6" PRIxMAX "]\n", + indent, "", (uintmax_t) offset, op_name, + (uintmax_t) read_4ubyte_unaligned (dbg, data)); + CONSUME (4); + data += 4; + offset += 5; + break; + default: /* No Operand. */ - if (op < sizeof known / sizeof known[0] && known[op] != NULL) - printf ("%*s[%4" PRIuMAX "] %s\n", - indent, "", (uintmax_t) offset, known[op]); - else - printf ("%*s[%4" PRIuMAX "] %#x\n", - indent, "", (uintmax_t) offset, op); + printf ("%*s[%4" PRIuMAX "] %s\n", + indent, "", (uintmax_t) offset, op_name); ++offset; break; } @@ -4417,7 +3932,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, invalid: printf (gettext ("%*s[%4" PRIuMAX "] %s \n"), - indent, "", (uintmax_t) offset, known[op]); + indent, "", (uintmax_t) offset, op_name); break; } } @@ -4566,13 +4081,16 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { + const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ? + dbg->sectiondata[IDX_debug_abbrev]->d_size : 0); + printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n" " [ Code]\n"), elf_ndxscn (scn), section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset); Dwarf_Off offset = 0; - while (offset < dbg->sectiondata[IDX_debug_abbrev]->d_size) + while (offset < sh_size) { printf (gettext ("\nAbbreviation section at offset %" PRIu64 ":\n"), offset); @@ -4607,7 +4125,7 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), ", children: %s, tag: %s\n"), code, (int64_t) offset, has_children ? gettext ("yes") : gettext ("no"), - dwarf_tag_string (tag)); + dwarf_tag_name (tag)); size_t cnt = 0; unsigned int name; @@ -4617,7 +4135,7 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), &name, &form, &enoffset) == 0) { printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n", - dwarf_attr_string (name), dwarf_form_string (form), + dwarf_attr_name (name), dwarf_form_name (form), (uint64_t) enoffset); ++cnt; @@ -4787,9 +4305,12 @@ register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc, bits ?: &ignore, type ?: &ignore); if (n <= 0) { - snprintf (name, REGNAMESZ, "reg%u", loc->regno); + if (loc != NULL) + snprintf (name, REGNAMESZ, "reg%u", loc->regno); + else + snprintf (name, REGNAMESZ, "??? 0x%x", regno); if (bits != NULL) - *bits = loc->bits; + *bits = loc != NULL ? loc->bits : 0; if (type != NULL) *type = DW_ATE_unsigned; set = "??? unrecognized"; @@ -4797,7 +4318,7 @@ register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc, else { if (bits != NULL && *bits <= 0) - *bits = loc->bits; + *bits = loc != NULL ? loc->bits : 0; if (type != NULL && *type == DW_ATE_void) *type = DW_ATE_unsigned; @@ -5566,8 +5087,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) } char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr); printf (" %*s%-20s (%s) %s\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), a); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), a); free (a); } break; @@ -5575,14 +5096,15 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) case DW_FORM_indirect: case DW_FORM_strp: case DW_FORM_string: + case DW_FORM_GNU_strp_alt: if (cbargs->silent) break; const char *str = dwarf_formstring (attrp); if (unlikely (str == NULL)) goto attrval_out; printf (" %*s%-20s (%s) \"%s\"\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), str); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), str); break; case DW_FORM_ref_addr: @@ -5590,7 +5112,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) case DW_FORM_ref8: case DW_FORM_ref4: case DW_FORM_ref2: - case DW_FORM_ref1:; + case DW_FORM_ref1: + case DW_FORM_GNU_ref_alt: if (cbargs->silent) break; Dwarf_Die ref; @@ -5598,17 +5121,17 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) goto attrval_out; printf (" %*s%-20s (%s) [%6" PRIxMAX "]\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), (uintmax_t) dwarf_dieoffset (&ref)); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), (uintmax_t) dwarf_dieoffset (&ref)); break; case DW_FORM_ref_sig8: if (cbargs->silent) break; printf (" %*s%-20s (%s) {%6" PRIx64 "}\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), - read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp)); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), + (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp)); break; case DW_FORM_sec_offset: @@ -5633,8 +5156,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) { if (!cbargs->silent) printf (" %*s%-20s (%s) %" PRIxMAX "\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), (uintmax_t) num); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), (uintmax_t) num); return DWARF_CB_OK; } /* else fallthrough */ @@ -5656,8 +5179,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) cbargs->addrsize, cbargs->offset_size, num); if (!cbargs->silent) printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), (uintmax_t) num); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), (uintmax_t) num); return DWARF_CB_OK; case DW_AT_ranges: @@ -5665,39 +5188,39 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) cbargs->addrsize, cbargs->offset_size, num); if (!cbargs->silent) printf (" %*s%-20s (%s) range list [%6" PRIxMAX "]\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), (uintmax_t) num); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), (uintmax_t) num); return DWARF_CB_OK; case DW_AT_language: - valuestr = dwarf_lang_string (num); + valuestr = dwarf_lang_name (num); break; case DW_AT_encoding: - valuestr = dwarf_encoding_string (num); + valuestr = dwarf_encoding_name (num); break; case DW_AT_accessibility: - valuestr = dwarf_access_string (num); + valuestr = dwarf_access_name (num); break; case DW_AT_visibility: - valuestr = dwarf_visibility_string (num); + valuestr = dwarf_visibility_name (num); break; case DW_AT_virtuality: - valuestr = dwarf_virtuality_string (num); + valuestr = dwarf_virtuality_name (num); break; case DW_AT_identifier_case: - valuestr = dwarf_identifier_case_string (num); + valuestr = dwarf_identifier_case_name (num); break; case DW_AT_calling_convention: - valuestr = dwarf_calling_convention_string (num); + valuestr = dwarf_calling_convention_name (num); break; case DW_AT_inline: - valuestr = dwarf_inline_string (num); + valuestr = dwarf_inline_name (num); break; case DW_AT_ordering: - valuestr = dwarf_ordering_string (num); + valuestr = dwarf_ordering_name (num); break; case DW_AT_discr_list: - valuestr = dwarf_discr_list_string (num); + valuestr = dwarf_discr_list_name (num); break; default: /* Nothing. */ @@ -5709,12 +5232,12 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) if (valuestr == NULL) printf (" %*s%-20s (%s) %" PRIuMAX "\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), (uintmax_t) num); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), (uintmax_t) num); else printf (" %*s%-20s (%s) %s (%" PRIuMAX ")\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), valuestr, (uintmax_t) num); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), valuestr, (uintmax_t) num); break; case DW_FORM_flag: @@ -5725,16 +5248,16 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) goto attrval_out; printf (" %*s%-20s (%s) %s\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), nl_langinfo (flag ? YESSTR : NOSTR)); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), nl_langinfo (flag ? YESSTR : NOSTR)); break; case DW_FORM_flag_present: if (cbargs->silent) break; printf (" %*s%-20s (%s) %s\n", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form), nl_langinfo (YESSTR)); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form), nl_langinfo (YESSTR)); break; case DW_FORM_exprloc: @@ -5749,8 +5272,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) goto attrval_out; printf (" %*s%-20s (%s) ", - (int) (level * 2), "", dwarf_attr_string (attr), - dwarf_form_string (form)); + (int) (level * 2), "", dwarf_attr_name (attr), + dwarf_form_name (form)); switch (attr) { @@ -5798,7 +5321,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) if (cbargs->silent) break; printf (" %*s%-20s (form: %#x) ???\n", - (int) (level * 2), "", dwarf_attr_string (attr), + (int) (level * 2), "", dwarf_attr_name (attr), (int) form); break; } @@ -5913,7 +5436,7 @@ print_debug_units (Dwfl_Module *dwflmod, if (!silent) printf (" [%6" PRIx64 "] %*s%s\n", (uint64_t) offset, (int) (level * 2), "", - dwarf_tag_string (tag)); + dwarf_tag_name (tag)); /* Print the attribute values. */ args.level = level; @@ -6746,6 +6269,412 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)), } +static void +print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), + Ebl *ebl, GElf_Ehdr *ehdr, + Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) +{ + printf (gettext ("\ +\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); + putc_unlocked ('\n', stdout); + + Elf_Data *data = elf_getdata (scn, NULL); + if (unlikely (data == NULL || data->d_buf == NULL)) + { + error (0, 0, gettext ("cannot get macro information section data: %s"), + elf_errmsg (-1)); + return; + } + + /* Get the source file information for all CUs. Uses same + datastructure as macinfo. But uses offset field to directly + match .debug_line offset. And just stored in a list. */ + Dwarf_Off offset; + Dwarf_Off ncu = 0; + size_t hsize; + struct mac_culist *culist = NULL; + size_t nculist = 0; + while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0) + { + Dwarf_Die cudie; + if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL) + continue; + + Dwarf_Attribute attr; + if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL) + continue; + + Dwarf_Word lineoff; + if (dwarf_formudata (&attr, &lineoff) != 0) + continue; + + struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp)); + newp->die = cudie; + newp->offset = lineoff; + newp->files = NULL; + newp->next = culist; + culist = newp; + ++nculist; + } + + const unsigned char *readp = (const unsigned char *) data->d_buf; + const unsigned char *readendp = readp + data->d_size; + + while (readp < readendp) + { + printf (gettext (" Offset: 0x%" PRIx64 "\n"), + (uint64_t) (readp - (const unsigned char *) data->d_buf)); + + // Header, 2 byte version, 1 byte flag, optional .debug_line offset, + // optional vendor extension macro entry table. + if (readp + 2 > readendp) + { + invalid_data: + error (0, 0, gettext ("invalid data")); + return; + } + const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp); + printf (gettext (" Version: %" PRIu16 "\n"), vers); + + // Version 4 is the GNU extension for DWARF4. DWARF5 will use version + // 5 when it gets standardized. + if (vers != 4) + { + printf (gettext (" unknown version, cannot parse section\n")); + return; + } + + if (readp + 1 > readendp) + goto invalid_data; + const unsigned char flag = *readp++; + printf (gettext (" Flag: 0x%" PRIx8 "\n"), flag); + + unsigned int offset_len = (flag & 0x01) ? 8 : 4; + printf (gettext (" Offset length: %" PRIu8 "\n"), offset_len); + Dwarf_Off line_offset = -1; + if (flag & 0x02) + { + if (offset_len == 8) + line_offset = read_8ubyte_unaligned_inc (dbg, readp); + else + line_offset = read_4ubyte_unaligned_inc (dbg, readp); + printf (gettext (" .debug_line offset: 0x%" PRIx64 "\n"), + line_offset); + } + + const unsigned char *vendor[DW_MACRO_GNU_hi_user - DW_MACRO_GNU_lo_user]; + if (flag & 0x04) + { + // 1 byte length, for each item, 1 byte opcode, uleb128 number + // of arguments, for each argument 1 byte form code. + if (readp + 1 > readendp) + goto invalid_data; + unsigned int tlen = *readp++; + printf (gettext (" extension opcode table, %" PRIu8 " items:\n"), + tlen); + for (unsigned int i = 0; i < tlen; i++) + { + if (readp + 1 > readendp) + goto invalid_data; + unsigned int opcode = *readp++; + printf (gettext (" [%" PRIx8 "]"), opcode); + if (opcode < DW_MACRO_GNU_lo_user + || opcode > DW_MACRO_GNU_hi_user) + goto invalid_data; + // Record the start of description for this vendor opcode. + // uleb128 nr args, 1 byte per arg form. + vendor[opcode - DW_MACRO_GNU_lo_user] = readp; + if (readp + 1 > readendp) + goto invalid_data; + unsigned int args = *readp++; + if (args > 0) + { + printf (gettext (" %" PRIu8 " arguments:"), args); + while (args > 0) + { + if (readp + 1 > readendp) + goto invalid_data; + unsigned int form = *readp++; + printf (" %s", dwarf_form_string (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) + goto invalid_data; + args--; + if (args > 0) + putchar_unlocked (','); + } + } + else + printf (gettext (" no arguments.")); + putchar_unlocked ('\n'); + } + } + putchar_unlocked ('\n'); + + int level = 1; + if (readp + 1 > readendp) + goto invalid_data; + unsigned int opcode = *readp++; + while (opcode != 0) + { + unsigned int u128; + unsigned int u128_2; + const unsigned char *endp; + uint64_t off; + + switch (opcode) + { + case DW_MACRO_GNU_start_file: + get_uleb128 (u128, readp); + get_uleb128 (u128_2, readp); + + /* Find the CU DIE that matches this line offset. */ + const char *fname = "???"; + if (line_offset != (Dwarf_Off) -1) + { + struct mac_culist *cu = culist; + while (cu != NULL && line_offset != cu->offset) + cu = cu->next; + if (cu != NULL) + { + if (cu->files == NULL + && dwarf_getsrcfiles (&cu->die, &cu->files, + NULL) != 0) + cu->files = (Dwarf_Files *) -1l; + + if (cu->files != (Dwarf_Files *) -1l) + fname = (dwarf_filesrc (cu->files, u128_2, + NULL, NULL) ?: "???"); + } + } + printf ("%*sstart_file %u, [%u] %s\n", + level, "", u128, u128_2, fname); + ++level; + break; + + case DW_MACRO_GNU_end_file: + --level; + printf ("%*send_file\n", level, ""); + break; + + case DW_MACRO_GNU_define: + get_uleb128 (u128, readp); + endp = memchr (readp, '\0', readendp - readp); + if (endp == NULL) + goto invalid_data; + printf ("%*s#define %s, line %u\n", + level, "", readp, u128); + readp = endp + 1; + break; + + case DW_MACRO_GNU_undef: + get_uleb128 (u128, readp); + endp = memchr (readp, '\0', readendp - readp); + if (endp == NULL) + goto invalid_data; + printf ("%*s#undef %s, line %u\n", + level, "", readp, u128); + readp = endp + 1; + break; + + case DW_MACRO_GNU_define_indirect: + get_uleb128 (u128, readp); + 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); + printf ("%*s#define %s, line %u (indirect)\n", + level, "", dwarf_getstring (dbg, off, NULL), u128); + break; + + case DW_MACRO_GNU_undef_indirect: + get_uleb128 (u128, readp); + 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); + printf ("%*s#undef %s, line %u (indirect)\n", + level, "", dwarf_getstring (dbg, off, NULL), u128); + break; + + case DW_MACRO_GNU_transparent_include: + 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); + printf ("%*s#include offset 0x%" PRIx64 "\n", + level, "", off); + break; + + default: + printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode); + if (opcode < DW_MACRO_GNU_lo_user + || opcode > DW_MACRO_GNU_lo_user + || vendor[opcode - DW_MACRO_GNU_lo_user] == NULL) + goto invalid_data; + + const unsigned char *op_desc; + op_desc = vendor[opcode - DW_MACRO_GNU_lo_user]; + + // Just skip the arguments, we cannot really interpret them, + // but print as much as we can. + unsigned int args = *op_desc++; + while (args > 0) + { + unsigned int form = *op_desc++; + Dwarf_Word val; + switch (form) + { + case DW_FORM_data1: + if (readp + 1 > readendp) + goto invalid_data; + val = *readp++; + printf (" %" PRIx8, (unsigned int) val); + break; + + case DW_FORM_data2: + if (readp + 2 > readendp) + goto invalid_data; + val = read_2ubyte_unaligned_inc (dbg, readp); + printf(" %" PRIx16, (unsigned int) val); + break; + + case DW_FORM_data4: + if (readp + 4 > readendp) + goto invalid_data; + val = read_4ubyte_unaligned_inc (dbg, readp); + printf (" %" PRIx32, (unsigned int) val); + break; + + case DW_FORM_data8: + if (readp + 8 > readendp) + goto invalid_data; + val = read_8ubyte_unaligned_inc (dbg, readp); + printf (" %" PRIx64, val); + break; + + case DW_FORM_sdata: + get_sleb128 (val, readp); + printf (" %" PRIx64, val); + break; + + case DW_FORM_udata: + get_uleb128 (val, readp); + printf (" %" PRIx64, val); + break; + + case DW_FORM_block: + get_uleb128 (val, readp); + printf (" block[%" PRIu64 "]", val); + if (readp + val > readendp) + goto invalid_data; + readp += val; + break; + + case DW_FORM_block1: + if (readp + 1 > readendp) + goto invalid_data; + val = *readp++; + printf (" block[%" PRIu64 "]", val); + if (readp + val > readendp) + goto invalid_data; + break; + + case DW_FORM_block2: + if (readp + 2 > readendp) + goto invalid_data; + val = read_2ubyte_unaligned_inc (dbg, readp); + printf (" block[%" PRIu64 "]", val); + if (readp + val > readendp) + goto invalid_data; + break; + + case DW_FORM_block4: + if (readp + 2 > readendp) + goto invalid_data; + val =read_4ubyte_unaligned_inc (dbg, readp); + printf (" block[%" PRIu64 "]", val); + if (readp + val > readendp) + goto invalid_data; + break; + + case DW_FORM_flag: + if (readp + 1 > readendp) + goto invalid_data; + val = *readp++; + printf (" %s", nl_langinfo (val != 0 ? YESSTR : NOSTR)); + break; + + case DW_FORM_string: + endp = memchr (readp, '\0', readendp - readp); + if (endp == NULL) + goto invalid_data; + printf (" %s", readp); + readp = endp + 1; + break; + + case DW_FORM_strp: + if (readp + offset_len > readendp) + goto invalid_data; + if (offset_len == 8) + val = read_8ubyte_unaligned_inc (dbg, readp); + else + val = read_4ubyte_unaligned_inc (dbg, readp); + printf (" %s", dwarf_getstring (dbg, val, NULL)); + break; + + case DW_FORM_sec_offset: + if (readp + offset_len > readendp) + goto invalid_data; + if (offset_len == 8) + val = read_8ubyte_unaligned_inc (dbg, readp); + else + val = read_4ubyte_unaligned_inc (dbg, readp); + printf (" %" PRIx64, val); + break; + + default: + error (0, 0, gettext ("vendor opcode not verified?")); + return; + } + + args--; + if (args > 0) + putchar_unlocked (','); + } + putchar_unlocked ('\n'); + } + + if (readp + 1 > readendp) + goto invalid_data; + opcode = *readp++; + if (opcode == 0) + putchar_unlocked ('\n'); + } + } +} + + /* Callback for printing global names. */ static int print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global, @@ -6781,7 +6710,8 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)), Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { - const size_t sh_size = dbg->sectiondata[IDX_debug_str]->d_size; + const size_t sh_size = (dbg->sectiondata[IDX_debug_str] ? + dbg->sectiondata[IDX_debug_str]->d_size : 0); /* Compute floor(log16(shdr->sh_size)). */ GElf_Addr tmp = sh_size; @@ -7118,8 +7048,9 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, printf (gettext (" Version: %" PRId32 "\n"), vers); // The only difference between version 4 and version 5 is the - // hash used for generating the table. - if (vers < 4 || vers > 5) + // hash used for generating the table. Version 6 contains symbols + // for inlined functions, older versions didn't. + if (vers < 4 || vers > 7) { printf (gettext (" unknown version, cannot parse section\n")); return; @@ -7163,14 +7094,14 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, readp = data->d_buf + cu_off; const unsigned char *nextp = data->d_buf + tu_off; - size_t nr = (nextp - readp) / 16; + size_t cu_nr = (nextp - readp) / 16; printf (gettext ("\n CU list at offset %#" PRIx32 " contains %zu entries:\n"), - cu_off, nr); + cu_off, cu_nr); size_t n = 0; - while (readp + 16 <= dataend && n < nr) + while (readp + 16 <= dataend && n < cu_nr) { uint64_t off = read_8ubyte_unaligned (dbg, readp); readp += 8; @@ -7185,14 +7116,14 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, readp = data->d_buf + tu_off; nextp = data->d_buf + addr_off; - nr = (nextp - readp) / 24; + size_t tu_nr = (nextp - readp) / 24; printf (gettext ("\n TU list at offset %#" PRIx32 " contains %zu entries:\n"), - tu_off, nr); + tu_off, tu_nr); n = 0; - while (readp + 24 <= dataend && n < nr) + while (readp + 24 <= dataend && n < tu_nr) { uint64_t off = read_8ubyte_unaligned (dbg, readp); readp += 8; @@ -7211,14 +7142,14 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, readp = data->d_buf + addr_off; nextp = data->d_buf + sym_off; - nr = (nextp - readp) / 20; + size_t addr_nr = (nextp - readp) / 20; printf (gettext ("\n Address list at offset %#" PRIx32 " contains %zu entries:\n"), - addr_off, nr); + addr_off, addr_nr); n = 0; - while (readp + 20 <= dataend && n < nr) + while (readp + 20 <= dataend && n < addr_nr) { uint64_t low = read_8ubyte_unaligned (dbg, readp); readp += 8; @@ -7238,14 +7169,14 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, readp = data->d_buf + sym_off; nextp = data->d_buf + const_off; - nr = (nextp - readp) / 8; + size_t sym_nr = (nextp - readp) / 8; printf (gettext ("\n Symbol table at offset %#" PRIx32 " contains %zu slots:\n"), - addr_off, nr); + addr_off, sym_nr); n = 0; - while (readp + 8 <= dataend && n < nr) + while (readp + 8 <= dataend && n < sym_nr) { uint32_t name = read_4ubyte_unaligned (dbg, readp); readp += 4; @@ -7268,10 +7199,42 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, uint32_t cus = read_4ubyte_unaligned (dbg, readcus); while (cus--) { - uint32_t cu; + uint32_t cu_kind, cu, kind; + bool is_static; readcus += 4; - cu = read_4ubyte_unaligned (dbg, readcus); - printf ("%" PRId32 "%s", cu, ((cus > 0) ? ", " : "")); + cu_kind = read_4ubyte_unaligned (dbg, readcus); + cu = cu_kind & ((1 << 24) - 1); + kind = (cu_kind >> 28) & 7; + is_static = cu_kind & (1 << 31); + if (cu > cu_nr - 1) + printf ("%" PRId32 "T", cu - (uint32_t) cu_nr); + else + printf ("%" PRId32, cu); + if (kind != 0) + { + printf (" ("); + switch (kind) + { + case 1: + printf ("type"); + break; + case 2: + printf ("var"); + break; + case 3: + printf ("func"); + break; + case 4: + printf ("other"); + break; + default: + printf ("unknown-0x%" PRIx32, kind); + break; + } + printf (":%c)", (is_static ? 'S' : 'G')); + } + if (cus > 0) + printf (", "); } printf ("\n"); } @@ -7335,6 +7298,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) NEW_SECTION (pubnames), NEW_SECTION (str), NEW_SECTION (macinfo), + NEW_SECTION (macro), NEW_SECTION (ranges), { ".eh_frame", section_frame | section_exception, print_debug_frame_section },