X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Fdwarf.c;h=599c0d2ba81d03863c5f4018f65ba550312519af;hb=18464d4d31ffc294347280430c1302e576d98b47;hp=ac3753809d60212009621afab4f8e3689df69e9a;hpb=2b6f59972b0eac01b8f09e57ff8f2a8b89179784;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/dwarf.c b/binutils/dwarf.c index ac3753809d..599c0d2ba8 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -1,5 +1,5 @@ /* dwarf.c -- display DWARF contents of a BFD binary file - Copyright 2005, 2006, 2007, 2008, 2009 + Copyright 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -27,6 +27,8 @@ #include "dwarf2.h" #include "dwarf.h" +static const char *regname (unsigned int regno, int row); + static int have_frame_base; static int need_base_address; @@ -45,6 +47,7 @@ int do_debug_info; int do_debug_abbrevs; int do_debug_lines; int do_debug_pubnames; +int do_debug_pubtypes; int do_debug_aranges; int do_debug_ranges; int do_debug_frames; @@ -52,6 +55,9 @@ int do_debug_frames_interp; int do_debug_macinfo; int do_debug_str; int do_debug_loc; +int do_trace_info; +int do_trace_abbrevs; +int do_trace_aranges; int do_wide; /* Values for do_debug_lines. */ @@ -226,7 +232,7 @@ print_dwarf_vma (dwarf_vma val, unsigned byte_size) fputs (buff + (byte_size == 4 ? 8 : 0), stdout); } -static unsigned long int +unsigned long int read_leb128 (unsigned char *data, unsigned int *length_return, int sign) { unsigned long int result = 0; @@ -263,7 +269,8 @@ typedef struct State_Machine_Registers unsigned int column; int is_stmt; int basic_block; - int end_sequence; + unsigned char op_index; + unsigned char end_sequence; /* This variable hold the number of the last entry seen in the File Table. */ unsigned int last_file_entry; @@ -275,6 +282,7 @@ static void reset_state_machine (int is_stmt) { state_machine_regs.address = 0; + state_machine_regs.op_index = 0; state_machine_regs.file = 1; state_machine_regs.line = 1; state_machine_regs.column = 0; @@ -321,6 +329,7 @@ process_extended_line_op (unsigned char *data, int is_stmt) adr = byte_get (data, len - bytes_read - 1); printf (_("set Address to 0x%lx\n"), adr); state_machine_regs.address = adr; + state_machine_regs.op_index = 0; break; case DW_LNE_define_file: @@ -437,23 +446,23 @@ static abbrev_entry *last_abbrev = NULL; static void free_abbrevs (void) { - abbrev_entry *abbrev; + abbrev_entry *abbrv; - for (abbrev = first_abbrev; abbrev;) + for (abbrv = first_abbrev; abbrv;) { - abbrev_entry *next = abbrev->next; + abbrev_entry *next_abbrev = abbrv->next; abbrev_attr *attr; - for (attr = abbrev->first_attr; attr;) + for (attr = abbrv->first_attr; attr;) { - abbrev_attr *next = attr->next; + abbrev_attr *next_attr = attr->next; free (attr); - attr = next; + attr = next_attr; } - free (abbrev); - abbrev = next; + free (abbrv); + abbrv = next_abbrev; } last_abbrev = first_abbrev = NULL; @@ -929,7 +938,8 @@ decode_location_expression (unsigned char * data, case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31: - printf ("DW_OP_reg%d", op - DW_OP_reg0); + printf ("DW_OP_reg%d (%s)", op - DW_OP_reg0, + regname (op - DW_OP_reg0, 1)); break; case DW_OP_breg0: @@ -964,14 +974,16 @@ decode_location_expression (unsigned char * data, case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: - printf ("DW_OP_breg%d: %ld", op - DW_OP_breg0, + printf ("DW_OP_breg%d (%s): %ld", op - DW_OP_breg0, + regname (op - DW_OP_breg0, 1), read_leb128 (data, &bytes_read, 1)); data += bytes_read; break; case DW_OP_regx: - printf ("DW_OP_regx: %lu", read_leb128 (data, &bytes_read, 0)); + uvalue = read_leb128 (data, &bytes_read, 0); data += bytes_read; + printf ("DW_OP_regx: %lu (%s)", uvalue, regname (uvalue, 1)); break; case DW_OP_fbreg: need_frame_base = 1; @@ -981,7 +993,7 @@ decode_location_expression (unsigned char * data, case DW_OP_bregx: uvalue = read_leb128 (data, &bytes_read, 0); data += bytes_read; - printf ("DW_OP_bregx: %lu %ld", uvalue, + printf ("DW_OP_bregx: %lu (%s) %ld", uvalue, regname (uvalue, 1), read_leb128 (data, &bytes_read, 1)); data += bytes_read; break; @@ -1153,14 +1165,14 @@ read_and_display_attr_value (unsigned long attribute, uvalue = byte_get (data, pointer_size); data += pointer_size; } - else if (dwarf_version == 3) + else if (dwarf_version == 3 || dwarf_version == 4) { uvalue = byte_get (data, offset_size); data += offset_size; } else { - error (_("Internal error: DWARF version is not 2 or 3.\n")); + error (_("Internal error: DWARF version is not 2, 3 or 4.\n")); } break; @@ -1170,10 +1182,15 @@ read_and_display_attr_value (unsigned long attribute, break; case DW_FORM_strp: + case DW_FORM_sec_offset: uvalue = byte_get (data, offset_size); data += offset_size; break; + case DW_FORM_flag_present: + uvalue = 1; + break; + case DW_FORM_ref1: case DW_FORM_flag: case DW_FORM_data1: @@ -1232,10 +1249,12 @@ read_and_display_attr_value (unsigned long attribute, case DW_FORM_data4: case DW_FORM_addr: + case DW_FORM_sec_offset: if (!do_loc) printf (" 0x%lx", uvalue); break; + case DW_FORM_flag_present: case DW_FORM_flag: case DW_FORM_data1: case DW_FORM_data2: @@ -1271,6 +1290,7 @@ read_and_display_attr_value (unsigned long attribute, break; case DW_FORM_block: + case DW_FORM_exprloc: uvalue = read_leb128 (data, & bytes_read, 0); block_start = data + bytes_read; if (do_loc) @@ -1351,22 +1371,24 @@ read_and_display_attr_value (unsigned long attribute, case DW_AT_segment: case DW_AT_static_link: case DW_AT_use_location: - if (form == DW_FORM_data4 || form == DW_FORM_data8) + if (form == DW_FORM_data4 + || form == DW_FORM_data8 + || form == DW_FORM_sec_offset) { /* Process location list. */ - unsigned int max = debug_info_p->max_loc_offsets; + unsigned int lmax = debug_info_p->max_loc_offsets; unsigned int num = debug_info_p->num_loc_offsets; - if (max == 0 || num >= max) + if (lmax == 0 || num >= lmax) { - max += 1024; + lmax += 1024; debug_info_p->loc_offsets = (long unsigned int *) xcrealloc (debug_info_p->loc_offsets, - max, sizeof (*debug_info_p->loc_offsets)); + lmax, sizeof (*debug_info_p->loc_offsets)); debug_info_p->have_frame_base = (int *) xcrealloc (debug_info_p->have_frame_base, - max, sizeof (*debug_info_p->have_frame_base)); - debug_info_p->max_loc_offsets = max; + lmax, sizeof (*debug_info_p->have_frame_base)); + debug_info_p->max_loc_offsets = lmax; } debug_info_p->loc_offsets [num] = uvalue; debug_info_p->have_frame_base [num] = have_frame_base; @@ -1380,19 +1402,21 @@ read_and_display_attr_value (unsigned long attribute, break; case DW_AT_ranges: - if (form == DW_FORM_data4 || form == DW_FORM_data8) + if (form == DW_FORM_data4 + || form == DW_FORM_data8 + || form == DW_FORM_sec_offset) { /* Process range list. */ - unsigned int max = debug_info_p->max_range_lists; + unsigned int lmax = debug_info_p->max_range_lists; unsigned int num = debug_info_p->num_range_lists; - if (max == 0 || num >= max) + if (lmax == 0 || num >= lmax) { - max += 1024; + lmax += 1024; debug_info_p->range_lists = (long unsigned int *) xcrealloc (debug_info_p->range_lists, - max, sizeof (*debug_info_p->range_lists)); - debug_info_p->max_range_lists = max; + lmax, sizeof (*debug_info_p->range_lists)); + debug_info_p->max_range_lists = lmax; } debug_info_p->range_lists [num] = uvalue; debug_info_p->num_range_lists++; @@ -1590,7 +1614,9 @@ read_and_display_attr_value (unsigned long attribute, case DW_AT_segment: case DW_AT_static_link: case DW_AT_use_location: - if (form == DW_FORM_data4 || form == DW_FORM_data8) + if (form == DW_FORM_data4 + || form == DW_FORM_data8 + || form == DW_FORM_sec_offset) printf (_("(location list)")); /* Fall through. */ case DW_AT_allocated: @@ -1801,6 +1827,8 @@ get_AT_name (unsigned long attribute) case DW_AT_GNU_exclusive_locks_required: return "DW_AT_GNU_exclusive_locks_required"; case DW_AT_GNU_shared_locks_required: return "DW_AT_GNU_shared_locks_required"; case DW_AT_GNU_odr_signature: return "DW_AT_GNU_odr_signature"; + case DW_AT_use_GNAT_descriptive_type: return "DW_AT_use_GNAT_descriptive_type"; + case DW_AT_GNAT_descriptive_type: return "DW_AT_GNAT_descriptive_type"; /* UPC extension. */ case DW_AT_upc_threads_scaled: return "DW_AT_upc_threads_scaled"; @@ -1853,6 +1881,7 @@ read_and_display_attr (unsigned long attribute, static int process_debug_info (struct dwarf_section *section, void *file, + enum dwarf_section_display_enum abbrev_sec, int do_loc, int do_types) { @@ -1924,11 +1953,11 @@ process_debug_info (struct dwarf_section *section, load_debug_section (str, file); } - load_debug_section (abbrev, file); - if (debug_displays [abbrev].section.start == NULL) + load_debug_section (abbrev_sec, file); + if (debug_displays [abbrev_sec].section.start == NULL) { warn (_("Unable to locate %s section!\n"), - debug_displays [abbrev].section.name); + debug_displays [abbrev_sec].section.name); return 0; } @@ -1936,13 +1965,12 @@ process_debug_info (struct dwarf_section *section, { DWARF2_Internal_CompUnit compunit; unsigned char *hdrptr; - unsigned char *cu_abbrev_offset_ptr; unsigned char *tags; int level; unsigned long cu_offset; int offset_size; int initial_length_size; - unsigned char signature[8]; + unsigned char signature[8] = { 0 }; unsigned long type_offset = 0; hdrptr = start; @@ -1968,7 +1996,6 @@ process_debug_info (struct dwarf_section *section, cu_offset = start - section_begin; - cu_abbrev_offset_ptr = hdrptr; compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size); hdrptr += offset_size; @@ -2035,7 +2062,9 @@ process_debug_info (struct dwarf_section *section, tags = hdrptr; start += compunit.cu_length + initial_length_size; - if (compunit.cu_version != 2 && compunit.cu_version != 3) + if (compunit.cu_version != 2 + && compunit.cu_version != 3 + && compunit.cu_version != 4) { warn (_("CU at offset %lx contains corrupt or unsupported version number: %d.\n"), cu_offset, compunit.cu_version); @@ -2046,16 +2075,16 @@ process_debug_info (struct dwarf_section *section, /* Process the abbrevs used by this compilation unit. DWARF sections under Mach-O have non-zero addresses. */ - if (compunit.cu_abbrev_offset >= debug_displays [abbrev].section.size) + if (compunit.cu_abbrev_offset >= debug_displays [abbrev_sec].section.size) warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than abbrev section size (%lx)\n"), (unsigned long) compunit.cu_abbrev_offset, - (unsigned long) debug_displays [abbrev].section.size); + (unsigned long) debug_displays [abbrev_sec].section.size); else process_abbrev_section - ((unsigned char *) debug_displays [abbrev].section.start - + compunit.cu_abbrev_offset - debug_displays [abbrev].section.address, - (unsigned char *) debug_displays [abbrev].section.start - + debug_displays [abbrev].section.size); + ((unsigned char *) debug_displays [abbrev_sec].section.start + + compunit.cu_abbrev_offset, + (unsigned char *) debug_displays [abbrev_sec].section.start + + debug_displays [abbrev_sec].section.size); level = 0; while (tags < start) @@ -2206,7 +2235,7 @@ load_debug_info (void * file) return num_debug_info_entries; if (load_debug_section (info, file) - && process_debug_info (&debug_displays [info].section, file, 1, 0)) + && process_debug_info (&debug_displays [info].section, file, abbrev, 1, 0)) return num_debug_info_entries; num_debug_info_entries = DEBUG_INFO_UNAVAILABLE; @@ -2225,7 +2254,7 @@ display_debug_lines_raw (struct dwarf_section *section, while (data < end) { - DWARF2_Internal_LineInfo info; + DWARF2_Internal_LineInfo linfo; unsigned char *standard_opcodes; unsigned char *end_of_sequence; unsigned char *hdrptr; @@ -2238,13 +2267,13 @@ display_debug_lines_raw (struct dwarf_section *section, hdroff = hdrptr - start; /* Check the length of the block. */ - info.li_length = byte_get (hdrptr, 4); + linfo.li_length = byte_get (hdrptr, 4); hdrptr += 4; - if (info.li_length == 0xffffffff) + if (linfo.li_length == 0xffffffff) { /* This section is 64-bit DWARF 3. */ - info.li_length = byte_get (hdrptr, 8); + linfo.li_length = byte_get (hdrptr, 8); hdrptr += 8; offset_size = 8; initial_length_size = 12; @@ -2255,7 +2284,7 @@ display_debug_lines_raw (struct dwarf_section *section, initial_length_size = 4; } - if (info.li_length + initial_length_size > section->size) + if (linfo.li_length + initial_length_size > section->size) { warn (_("The information in section %s appears to be corrupt - the section is too small\n"), @@ -2264,55 +2293,71 @@ display_debug_lines_raw (struct dwarf_section *section, } /* Check its version number. */ - info.li_version = byte_get (hdrptr, 2); + linfo.li_version = byte_get (hdrptr, 2); hdrptr += 2; - if (info.li_version != 2 && info.li_version != 3) + if (linfo.li_version != 2 + && linfo.li_version != 3 + && linfo.li_version != 4) { - warn (_("Only DWARF version 2 and 3 line info is currently supported.\n")); + warn (_("Only DWARF version 2, 3 and 4 line info is currently supported.\n")); return 0; } - info.li_prologue_length = byte_get (hdrptr, offset_size); + linfo.li_prologue_length = byte_get (hdrptr, offset_size); hdrptr += offset_size; - info.li_min_insn_length = byte_get (hdrptr, 1); + linfo.li_min_insn_length = byte_get (hdrptr, 1); hdrptr++; - info.li_default_is_stmt = byte_get (hdrptr, 1); + if (linfo.li_version >= 4) + { + linfo.li_max_ops_per_insn = byte_get (hdrptr, 1); + hdrptr++; + if (linfo.li_max_ops_per_insn == 0) + { + warn (_("Invalid maximum operations per insn.\n")); + return 0; + } + } + else + linfo.li_max_ops_per_insn = 1; + linfo.li_default_is_stmt = byte_get (hdrptr, 1); hdrptr++; - info.li_line_base = byte_get (hdrptr, 1); + linfo.li_line_base = byte_get (hdrptr, 1); hdrptr++; - info.li_line_range = byte_get (hdrptr, 1); + linfo.li_line_range = byte_get (hdrptr, 1); hdrptr++; - info.li_opcode_base = byte_get (hdrptr, 1); + linfo.li_opcode_base = byte_get (hdrptr, 1); hdrptr++; /* Sign extend the line base field. */ - info.li_line_base <<= 24; - info.li_line_base >>= 24; + linfo.li_line_base <<= 24; + linfo.li_line_base >>= 24; printf (_(" Offset: 0x%lx\n"), hdroff); - printf (_(" Length: %ld\n"), info.li_length); - printf (_(" DWARF Version: %d\n"), info.li_version); - printf (_(" Prologue Length: %d\n"), info.li_prologue_length); - printf (_(" Minimum Instruction Length: %d\n"), info.li_min_insn_length); - printf (_(" Initial value of 'is_stmt': %d\n"), info.li_default_is_stmt); - printf (_(" Line Base: %d\n"), info.li_line_base); - printf (_(" Line Range: %d\n"), info.li_line_range); - printf (_(" Opcode Base: %d\n"), info.li_opcode_base); + printf (_(" Length: %ld\n"), linfo.li_length); + printf (_(" DWARF Version: %d\n"), linfo.li_version); + printf (_(" Prologue Length: %d\n"), linfo.li_prologue_length); + printf (_(" Minimum Instruction Length: %d\n"), linfo.li_min_insn_length); + if (linfo.li_version >= 4) + printf (_(" Maximum Ops per Instruction: %d\n"), linfo.li_max_ops_per_insn); + printf (_(" Initial value of 'is_stmt': %d\n"), linfo.li_default_is_stmt); + printf (_(" Line Base: %d\n"), linfo.li_line_base); + printf (_(" Line Range: %d\n"), linfo.li_line_range); + printf (_(" Opcode Base: %d\n"), linfo.li_opcode_base); - end_of_sequence = data + info.li_length + initial_length_size; + end_of_sequence = data + linfo.li_length + initial_length_size; - reset_state_machine (info.li_default_is_stmt); + reset_state_machine (linfo.li_default_is_stmt); /* Display the contents of the Opcodes table. */ standard_opcodes = hdrptr; printf (_("\n Opcodes:\n")); - for (i = 1; i < info.li_opcode_base; i++) + for (i = 1; i < linfo.li_opcode_base; i++) printf (_(" Opcode %d has %d args\n"), i, standard_opcodes[i - 1]); /* Display the contents of the Directory table. */ - data = standard_opcodes + info.li_opcode_base - 1; + data = standard_opcodes + linfo.li_opcode_base - 1; if (*data == 0) printf (_("\n The Directory Table is empty.\n")); @@ -2374,14 +2419,31 @@ display_debug_lines_raw (struct dwarf_section *section, op_code = *data++; - if (op_code >= info.li_opcode_base) + if (op_code >= linfo.li_opcode_base) { - op_code -= info.li_opcode_base; - uladv = (op_code / info.li_line_range) * info.li_min_insn_length; - state_machine_regs.address += uladv; - printf (_(" Special opcode %d: advance Address by %lu to 0x%lx"), - op_code, uladv, state_machine_regs.address); - adv = (op_code % info.li_line_range) + info.li_line_base; + op_code -= linfo.li_opcode_base; + uladv = (op_code / linfo.li_line_range); + if (linfo.li_max_ops_per_insn == 1) + { + uladv *= linfo.li_min_insn_length; + state_machine_regs.address += uladv; + printf (_(" Special opcode %d: advance Address by %lu to 0x%lx"), + op_code, uladv, state_machine_regs.address); + } + else + { + state_machine_regs.address + += ((state_machine_regs.op_index + uladv) + / linfo.li_max_ops_per_insn) + * linfo.li_min_insn_length; + state_machine_regs.op_index + = (state_machine_regs.op_index + uladv) + % linfo.li_max_ops_per_insn; + printf (_(" Special opcode %d: advance Address by %lu to 0x%lx[%d]"), + op_code, uladv, state_machine_regs.address, + state_machine_regs.op_index); + } + adv = (op_code % linfo.li_line_range) + linfo.li_line_base; state_machine_regs.line += adv; printf (_(" and Line by %d to %d\n"), adv, state_machine_regs.line); @@ -2389,7 +2451,7 @@ display_debug_lines_raw (struct dwarf_section *section, else switch (op_code) { case DW_LNS_extended_op: - data += process_extended_line_op (data, info.li_default_is_stmt); + data += process_extended_line_op (data, linfo.li_default_is_stmt); break; case DW_LNS_copy: @@ -2398,11 +2460,27 @@ display_debug_lines_raw (struct dwarf_section *section, case DW_LNS_advance_pc: uladv = read_leb128 (data, & bytes_read, 0); - uladv *= info.li_min_insn_length; data += bytes_read; - state_machine_regs.address += uladv; - printf (_(" Advance PC by %lu to 0x%lx\n"), uladv, - state_machine_regs.address); + if (linfo.li_max_ops_per_insn == 1) + { + uladv *= linfo.li_min_insn_length; + state_machine_regs.address += uladv; + printf (_(" Advance PC by %lu to 0x%lx\n"), uladv, + state_machine_regs.address); + } + else + { + state_machine_regs.address + += ((state_machine_regs.op_index + uladv) + / linfo.li_max_ops_per_insn) + * linfo.li_min_insn_length; + state_machine_regs.op_index + = (state_machine_regs.op_index + uladv) + % linfo.li_max_ops_per_insn; + printf (_(" Advance PC by %lu to 0x%lx[%d]\n"), uladv, + state_machine_regs.address, + state_machine_regs.op_index); + } break; case DW_LNS_advance_line: @@ -2441,17 +2519,34 @@ display_debug_lines_raw (struct dwarf_section *section, break; case DW_LNS_const_add_pc: - uladv = (((255 - info.li_opcode_base) / info.li_line_range) - * info.li_min_insn_length); - state_machine_regs.address += uladv; - printf (_(" Advance PC by constant %lu to 0x%lx\n"), uladv, - state_machine_regs.address); + uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range); + if (linfo.li_max_ops_per_insn) + { + uladv *= linfo.li_min_insn_length; + state_machine_regs.address += uladv; + printf (_(" Advance PC by constant %lu to 0x%lx\n"), uladv, + state_machine_regs.address); + } + else + { + state_machine_regs.address + += ((state_machine_regs.op_index + uladv) + / linfo.li_max_ops_per_insn) + * linfo.li_min_insn_length; + state_machine_regs.op_index + = (state_machine_regs.op_index + uladv) + % linfo.li_max_ops_per_insn; + printf (_(" Advance PC by constant %lu to 0x%lx[%d]\n"), + uladv, state_machine_regs.address, + state_machine_regs.op_index); + } break; case DW_LNS_fixed_advance_pc: uladv = byte_get (data, 2); data += 2; state_machine_regs.address += uladv; + state_machine_regs.op_index = 0; printf (_(" Advance PC by fixed size amount %lu to 0x%lx\n"), uladv, state_machine_regs.address); break; @@ -2510,7 +2605,7 @@ display_debug_lines_decoded (struct dwarf_section *section, while (data < end) { /* This loop amounts to one iteration per compilation unit. */ - DWARF2_Internal_LineInfo info; + DWARF2_Internal_LineInfo linfo; unsigned char *standard_opcodes; unsigned char *end_of_sequence; unsigned char *hdrptr; @@ -2519,7 +2614,6 @@ display_debug_lines_decoded (struct dwarf_section *section, int i; File_Entry *file_table = NULL; unsigned char **directory_table = NULL; - unsigned int prev_line = 0; hdrptr = data; @@ -2527,13 +2621,13 @@ display_debug_lines_decoded (struct dwarf_section *section, (section 6.2.4 in the Dwarf3 doc). */ /* Get the length of this CU's line number information block. */ - info.li_length = byte_get (hdrptr, 4); + linfo.li_length = byte_get (hdrptr, 4); hdrptr += 4; - if (info.li_length == 0xffffffff) + if (linfo.li_length == 0xffffffff) { /* This section is 64-bit DWARF 3. */ - info.li_length = byte_get (hdrptr, 8); + linfo.li_length = byte_get (hdrptr, 8); hdrptr += 8; offset_size = 8; initial_length_size = 12; @@ -2544,7 +2638,7 @@ display_debug_lines_decoded (struct dwarf_section *section, initial_length_size = 4; } - if (info.li_length + initial_length_size > section->size) + if (linfo.li_length + initial_length_size > section->size) { warn (_("The line info appears to be corrupt - " "the section is too small\n")); @@ -2552,47 +2646,60 @@ display_debug_lines_decoded (struct dwarf_section *section, } /* Get this CU's Line Number Block version number. */ - info.li_version = byte_get (hdrptr, 2); + linfo.li_version = byte_get (hdrptr, 2); hdrptr += 2; - if (info.li_version != 2 && info.li_version != 3) + if (linfo.li_version != 2 + && linfo.li_version != 3 + && linfo.li_version != 4) { - warn (_("Only DWARF version 2 and 3 line info is currently " + warn (_("Only DWARF version 2, 3 and 4 line info is currently " "supported.\n")); return 0; } - info.li_prologue_length = byte_get (hdrptr, offset_size); + linfo.li_prologue_length = byte_get (hdrptr, offset_size); hdrptr += offset_size; - info.li_min_insn_length = byte_get (hdrptr, 1); + linfo.li_min_insn_length = byte_get (hdrptr, 1); hdrptr++; - info.li_default_is_stmt = byte_get (hdrptr, 1); + if (linfo.li_version >= 4) + { + linfo.li_max_ops_per_insn = byte_get (hdrptr, 1); + hdrptr++; + if (linfo.li_max_ops_per_insn == 0) + { + warn (_("Invalid maximum operations per insn.\n")); + return 0; + } + } + else + linfo.li_max_ops_per_insn = 1; + linfo.li_default_is_stmt = byte_get (hdrptr, 1); hdrptr++; - info.li_line_base = byte_get (hdrptr, 1); + linfo.li_line_base = byte_get (hdrptr, 1); hdrptr++; - info.li_line_range = byte_get (hdrptr, 1); + linfo.li_line_range = byte_get (hdrptr, 1); hdrptr++; - info.li_opcode_base = byte_get (hdrptr, 1); + linfo.li_opcode_base = byte_get (hdrptr, 1); hdrptr++; /* Sign extend the line base field. */ - info.li_line_base <<= 24; - info.li_line_base >>= 24; + linfo.li_line_base <<= 24; + linfo.li_line_base >>= 24; /* Find the end of this CU's Line Number Information Block. */ - end_of_sequence = data + info.li_length + initial_length_size; + end_of_sequence = data + linfo.li_length + initial_length_size; - reset_state_machine (info.li_default_is_stmt); + reset_state_machine (linfo.li_default_is_stmt); /* Save a pointer to the contents of the Opcodes table. */ standard_opcodes = hdrptr; /* Traverse the Directory table just to count entries. */ - data = standard_opcodes + info.li_opcode_base - 1; + data = standard_opcodes + linfo.li_opcode_base - 1; if (*data != 0) { unsigned int n_directories = 0; unsigned char *ptr_directory_table = data; - int i; while (*data != 0) { @@ -2620,7 +2727,6 @@ display_debug_lines_decoded (struct dwarf_section *section, { unsigned int n_files = 0; unsigned char *ptr_file_name_table = data; - int i; while (*data != 0) { @@ -2697,15 +2803,28 @@ display_debug_lines_decoded (struct dwarf_section *section, int is_special_opcode = 0; op_code = *data++; - prev_line = state_machine_regs.line; - if (op_code >= info.li_opcode_base) + if (op_code >= linfo.li_opcode_base) { - op_code -= info.li_opcode_base; - uladv = (op_code / info.li_line_range) * info.li_min_insn_length; - state_machine_regs.address += uladv; + op_code -= linfo.li_opcode_base; + uladv = (op_code / linfo.li_line_range); + if (linfo.li_max_ops_per_insn == 1) + { + uladv *= linfo.li_min_insn_length; + state_machine_regs.address += uladv; + } + else + { + state_machine_regs.address + += ((state_machine_regs.op_index + uladv) + / linfo.li_max_ops_per_insn) + * linfo.li_min_insn_length; + state_machine_regs.op_index + = (state_machine_regs.op_index + uladv) + % linfo.li_max_ops_per_insn; + } - adv = (op_code % info.li_line_range) + info.li_line_base; + adv = (op_code % linfo.li_line_range) + linfo.li_line_base; state_machine_regs.line += adv; is_special_opcode = 1; } @@ -2714,7 +2833,6 @@ display_debug_lines_decoded (struct dwarf_section *section, case DW_LNS_extended_op: { unsigned int ext_op_code_len; - unsigned int bytes_read; unsigned char ext_op_code; unsigned char *op_code_data = data; @@ -2732,11 +2850,12 @@ display_debug_lines_decoded (struct dwarf_section *section, switch (ext_op_code) { case DW_LNE_end_sequence: - reset_state_machine (info.li_default_is_stmt); + reset_state_machine (linfo.li_default_is_stmt); break; case DW_LNE_set_address: state_machine_regs.address = byte_get (op_code_data, ext_op_code_len - bytes_read - 1); + state_machine_regs.op_index = 0; break; case DW_LNE_define_file: { @@ -2765,9 +2884,22 @@ display_debug_lines_decoded (struct dwarf_section *section, case DW_LNS_advance_pc: uladv = read_leb128 (data, & bytes_read, 0); - uladv *= info.li_min_insn_length; data += bytes_read; - state_machine_regs.address += uladv; + if (linfo.li_max_ops_per_insn == 1) + { + uladv *= linfo.li_min_insn_length; + state_machine_regs.address += uladv; + } + else + { + state_machine_regs.address + += ((state_machine_regs.op_index + uladv) + / linfo.li_max_ops_per_insn) + * linfo.li_min_insn_length; + state_machine_regs.op_index + = (state_machine_regs.op_index + uladv) + % linfo.li_max_ops_per_insn; + } break; case DW_LNS_advance_line: @@ -2812,15 +2944,29 @@ display_debug_lines_decoded (struct dwarf_section *section, break; case DW_LNS_const_add_pc: - uladv = (((255 - info.li_opcode_base) / info.li_line_range) - * info.li_min_insn_length); - state_machine_regs.address += uladv; + uladv = ((255 - linfo.li_opcode_base) / linfo.li_line_range); + if (linfo.li_max_ops_per_insn == 1) + { + uladv *= linfo.li_min_insn_length; + state_machine_regs.address += uladv; + } + else + { + state_machine_regs.address + += ((state_machine_regs.op_index + uladv) + / linfo.li_max_ops_per_insn) + * linfo.li_min_insn_length; + state_machine_regs.op_index + = (state_machine_regs.op_index + uladv) + % linfo.li_max_ops_per_insn; + } break; case DW_LNS_fixed_advance_pc: uladv = byte_get (data, 2); data += 2; state_machine_regs.address += uladv; + state_machine_regs.op_index = 0; break; case DW_LNS_set_prologue_end: @@ -2874,13 +3020,27 @@ display_debug_lines_decoded (struct dwarf_section *section, if (!do_wide || (fileNameLength <= MAX_FILENAME_LENGTH)) { - printf (_("%-35s %11d %#18lx\n"), newFileName, - state_machine_regs.line, state_machine_regs.address); + if (linfo.li_max_ops_per_insn == 1) + printf (_("%-35s %11d %#18lx\n"), newFileName, + state_machine_regs.line, + state_machine_regs.address); + else + printf (_("%-35s %11d %#18lx[%d]\n"), newFileName, + state_machine_regs.line, + state_machine_regs.address, + state_machine_regs.op_index); } else { - printf (_("%s %11d %#18lx\n"), newFileName, - state_machine_regs.line, state_machine_regs.address); + if (linfo.li_max_ops_per_insn == 1) + printf (_("%s %11d %#18lx\n"), newFileName, + state_machine_regs.line, + state_machine_regs.address); + else + printf (_("%s %11d %#18lx[%d]\n"), newFileName, + state_machine_regs.line, + state_machine_regs.address, + state_machine_regs.op_index); } if (op_code == DW_LNE_end_sequence) @@ -2900,20 +3060,13 @@ display_debug_lines_decoded (struct dwarf_section *section, } static int -display_debug_lines (struct dwarf_section *section, void *file) +display_debug_lines (struct dwarf_section *section, void *file ATTRIBUTE_UNUSED) { unsigned char *data = section->start; unsigned char *end = data + section->size; int retValRaw = 1; int retValDecoded = 1; - if (load_debug_info (file) == 0) - { - warn (_("Unable to load/parse the .debug_info section, so cannot interpret the %s section.\n"), - section->name); - return 0; - } - if (do_debug_lines == 0) do_debug_lines |= FLAG_DEBUG_LINES_RAW; @@ -2948,7 +3101,7 @@ static int display_debug_pubnames (struct dwarf_section *section, void *file ATTRIBUTE_UNUSED) { - DWARF2_Internal_PubNames pubnames; + DWARF2_Internal_PubNames names; unsigned char *start = section->start; unsigned char *end = start + section->size; @@ -2966,11 +3119,11 @@ display_debug_pubnames (struct dwarf_section *section, data = start; - pubnames.pn_length = byte_get (data, 4); + names.pn_length = byte_get (data, 4); data += 4; - if (pubnames.pn_length == 0xffffffff) + if (names.pn_length == 0xffffffff) { - pubnames.pn_length = byte_get (data, 8); + names.pn_length = byte_get (data, 8); data += 8; offset_size = 8; initial_length_size = 12; @@ -2981,24 +3134,24 @@ display_debug_pubnames (struct dwarf_section *section, initial_length_size = 4; } - pubnames.pn_version = byte_get (data, 2); + names.pn_version = byte_get (data, 2); data += 2; - pubnames.pn_offset = byte_get (data, offset_size); + names.pn_offset = byte_get (data, offset_size); data += offset_size; if (num_debug_info_entries != DEBUG_INFO_UNAVAILABLE && num_debug_info_entries > 0 - && find_debug_info_for_offset (pubnames.pn_offset) == NULL) + && find_debug_info_for_offset (names.pn_offset) == NULL) warn (_(".debug_info offset of 0x%lx in %s section does not point to a CU header.\n"), - pubnames.pn_offset, section->name); + names.pn_offset, section->name); - pubnames.pn_size = byte_get (data, offset_size); + names.pn_size = byte_get (data, offset_size); data += offset_size; - start += pubnames.pn_length + initial_length_size; + start += names.pn_length + initial_length_size; - if (pubnames.pn_version != 2 && pubnames.pn_version != 3) + if (names.pn_version != 2 && names.pn_version != 3) { static int warned = 0; @@ -3012,13 +3165,13 @@ display_debug_pubnames (struct dwarf_section *section, } printf (_(" Length: %ld\n"), - pubnames.pn_length); + names.pn_length); printf (_(" Version: %d\n"), - pubnames.pn_version); + names.pn_version); printf (_(" Offset into .debug_info section: 0x%lx\n"), - pubnames.pn_offset); + names.pn_offset); printf (_(" Size of area in .debug_info section: %ld\n"), - pubnames.pn_size); + names.pn_size); printf (_("\n Offset\tName\n")); @@ -3437,13 +3590,19 @@ display_debug_str (struct dwarf_section *section, static int display_debug_info (struct dwarf_section *section, void *file) { - return process_debug_info (section, file, 0, 0); + return process_debug_info (section, file, abbrev, 0, 0); } static int display_debug_types (struct dwarf_section *section, void *file) { - return process_debug_info (section, file, 0, 1); + return process_debug_info (section, file, abbrev, 0, 1); +} + +static int +display_trace_info (struct dwarf_section *section, void *file) +{ + return process_debug_info (section, file, trace_abbrev, 0, 0); } static int @@ -3463,7 +3622,7 @@ display_debug_aranges (struct dwarf_section *section, { unsigned char *hdrptr; DWARF2_Internal_ARange arange; - unsigned char *ranges; + unsigned char *addr_ranges; dwarf_vma length; dwarf_vma address; unsigned char address_size; @@ -3535,24 +3694,24 @@ display_debug_aranges (struct dwarf_section *section, else printf (_("\n Address Length\n")); - ranges = hdrptr; + addr_ranges = hdrptr; /* Must pad to an alignment boundary that is twice the address size. */ excess = (hdrptr - start) % (2 * address_size); if (excess) - ranges += (2 * address_size) - excess; + addr_ranges += (2 * address_size) - excess; start += arange.ar_length + initial_length_size; - while (ranges + 2 * address_size <= start) + while (addr_ranges + 2 * address_size <= start) { - address = byte_get (ranges, address_size); + address = byte_get (addr_ranges, address_size); - ranges += address_size; + addr_ranges += address_size; - length = byte_get (ranges, address_size); + length = byte_get (addr_ranges, address_size); - ranges += address_size; + addr_ranges += address_size; printf (" "); print_dwarf_vma (address, address_size); @@ -3596,14 +3755,12 @@ display_debug_ranges (struct dwarf_section *section, void *file ATTRIBUTE_UNUSED) { unsigned char *start = section->start; - unsigned char *section_end; unsigned long bytes; unsigned char *section_begin = start; unsigned int num_range_list, i; struct range_entry *range_entries, *range_entry_fill; bytes = section->size; - section_end = start + bytes; if (bytes == 0) { @@ -3751,6 +3908,8 @@ typedef struct Frame_Chunk int ra; unsigned char fde_encoding; unsigned char cfa_exp; + unsigned char ptr_size; + unsigned char segment_size; } Frame_Chunk; @@ -3807,6 +3966,13 @@ static const char *const dwarf_regnames_i386[] = "tr", "ldtr" }; +void +init_dwarf_regnames_i386 (void) +{ + dwarf_regnames = dwarf_regnames_i386; + dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_i386); +} + static const char *const dwarf_regnames_x86_64[] = { "rax", "rdx", "rcx", "rbx", @@ -3829,6 +3995,13 @@ static const char *const dwarf_regnames_x86_64[] = "mxcsr", "fcw", "fsw" }; +void +init_dwarf_regnames_x86_64 (void) +{ + dwarf_regnames = dwarf_regnames_x86_64; + dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_x86_64); +} + void init_dwarf_regnames (unsigned int e_machine) { @@ -3836,13 +4009,12 @@ init_dwarf_regnames (unsigned int e_machine) { case EM_386: case EM_486: - dwarf_regnames = dwarf_regnames_i386; - dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_i386); + init_dwarf_regnames_i386 (); break; case EM_X86_64: - dwarf_regnames = dwarf_regnames_x86_64; - dwarf_regnames_count = ARRAY_SIZE (dwarf_regnames_x86_64); + case EM_L1OM: + init_dwarf_regnames_x86_64 (); break; default: @@ -3879,11 +4051,11 @@ frame_display_row (Frame_Chunk *fc, int *need_col_headers, int *max_regs) if (*need_col_headers) { - static const char *loc = " LOC"; + static const char *sloc = " LOC"; *need_col_headers = 0; - printf ("%-*s CFA ", eh_addr_size * 2, loc); + printf ("%-*s CFA ", eh_addr_size * 2, sloc); for (r = 0; r < *max_regs; r++) if (fc->col_type[r] != DW_CFA_unreferenced) @@ -3959,6 +4131,7 @@ display_debug_frames (struct dwarf_section *section, unsigned int length_return; int max_regs = 0; const char *bad_reg = _("bad register: "); + int saved_eh_addr_size = eh_addr_size; printf (_("Contents of the %s section:\n"), section->name); @@ -3973,7 +4146,7 @@ display_debug_frames (struct dwarf_section *section, int need_col_headers = 1; unsigned char *augmentation_data = NULL; unsigned long augmentation_data_len = 0; - int encoded_ptr_size = eh_addr_size; + int encoded_ptr_size = saved_eh_addr_size; int offset_size; int initial_length_size; @@ -4029,48 +4202,36 @@ display_debug_frames (struct dwarf_section *section, fc->augmentation = (char *) start; start = (unsigned char *) strchr ((char *) start, '\0') + 1; - if (fc->augmentation[0] == 'z') + if (strcmp (fc->augmentation, "eh") == 0) + start += eh_addr_size; + + if (version >= 4) { - fc->code_factor = LEB (); - fc->data_factor = SLEB (); - if (version == 1) - { - fc->ra = GET (1); - } - else - { - fc->ra = LEB (); - } - augmentation_data_len = LEB (); - augmentation_data = start; - start += augmentation_data_len; + fc->ptr_size = GET (1); + fc->segment_size = GET (1); + eh_addr_size = fc->ptr_size; } - else if (strcmp (fc->augmentation, "eh") == 0) + else { - start += eh_addr_size; - fc->code_factor = LEB (); - fc->data_factor = SLEB (); - if (version == 1) - { - fc->ra = GET (1); - } - else - { - fc->ra = LEB (); - } + fc->ptr_size = eh_addr_size; + fc->segment_size = 0; + } + fc->code_factor = LEB (); + fc->data_factor = SLEB (); + if (version == 1) + { + fc->ra = GET (1); } else { - fc->code_factor = LEB (); - fc->data_factor = SLEB (); - if (version == 1) - { - fc->ra = GET (1); - } - else - { - fc->ra = LEB (); - } + fc->ra = LEB (); + } + + if (fc->augmentation[0] == 'z') + { + augmentation_data_len = LEB (); + augmentation_data = start; + start += augmentation_data_len; } cie = fc; @@ -4085,6 +4246,11 @@ display_debug_frames (struct dwarf_section *section, (unsigned long)(saved_start - section_start), length, cie_id); printf (" Version: %d\n", version); printf (" Augmentation: \"%s\"\n", fc->augmentation); + if (version >= 4) + { + printf (" Pointer Size: %u\n", fc->ptr_size); + printf (" Segment Size: %u\n", fc->segment_size); + } printf (" Code alignment factor: %u\n", fc->code_factor); printf (" Data alignment factor: %d\n", fc->data_factor); printf (" Return address column: %d\n", fc->ra); @@ -4114,6 +4280,8 @@ display_debug_frames (struct dwarf_section *section, q += 1 + size_of_encoded_value (*q); else if (*p == 'R') fc->fde_encoding = *q++; + else if (*p == 'S') + ; else break; p++; @@ -4129,6 +4297,7 @@ display_debug_frames (struct dwarf_section *section, { unsigned char *look_for; static Frame_Chunk fde_fc; + unsigned long segment_selector; fc = & fde_fc; memset (fc, 0, sizeof (Frame_Chunk)); @@ -4150,6 +4319,8 @@ display_debug_frames (struct dwarf_section *section, cie = fc; fc->augmentation = ""; fc->fde_encoding = 0; + fc->ptr_size = eh_addr_size; + fc->segment_size = 0; } else { @@ -4159,6 +4330,9 @@ display_debug_frames (struct dwarf_section *section, memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int)); memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int)); fc->augmentation = cie->augmentation; + fc->ptr_size = cie->ptr_size; + eh_addr_size = cie->ptr_size; + fc->segment_size = cie->segment_size; fc->code_factor = cie->code_factor; fc->data_factor = cie->data_factor; fc->cfa_reg = cie->cfa_reg; @@ -4171,6 +4345,12 @@ display_debug_frames (struct dwarf_section *section, if (fc->fde_encoding) encoded_ptr_size = size_of_encoded_value (fc->fde_encoding); + segment_selector = 0; + if (fc->segment_size) + { + segment_selector = byte_get (start, fc->segment_size); + start += fc->segment_size; + } fc->pc_begin = get_encoded_value (start, fc->fde_encoding); if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel) fc->pc_begin += section->address + (start - section_start); @@ -4185,10 +4365,12 @@ display_debug_frames (struct dwarf_section *section, start += augmentation_data_len; } - printf ("\n%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n", + printf ("\n%08lx %08lx %08lx FDE cie=%08lx pc=", (unsigned long)(saved_start - section_start), length, cie_id, - (unsigned long)(cie->chunk_start - section_start), - fc->pc_begin, fc->pc_begin + fc->pc_range); + (unsigned long)(cie->chunk_start - section_start)); + if (fc->segment_size) + printf ("%04lx:", segment_selector); + printf ("%08lx..%08lx\n", fc->pc_begin, fc->pc_begin + fc->pc_range); if (! do_debug_frames_interp && augmentation_data_len) { unsigned long i; @@ -4217,7 +4399,7 @@ display_debug_frames (struct dwarf_section *section, while (start < block_end) { unsigned op, opa; - unsigned long reg, tmp; + unsigned long reg, temp; op = *start++; opa = op & 0x3f; @@ -4288,14 +4470,14 @@ display_debug_frames (struct dwarf_section *section, LEB (); break; case DW_CFA_def_cfa_expression: - tmp = LEB (); - start += tmp; + temp = LEB (); + start += temp; break; case DW_CFA_expression: case DW_CFA_val_expression: reg = LEB (); - tmp = LEB (); - start += tmp; + temp = LEB (); + start += temp; if (frame_need_space (fc, reg) >= 0) fc->col_type[reg] = DW_CFA_undefined; break; @@ -4736,6 +4918,7 @@ display_debug_frames (struct dwarf_section *section, frame_display_row (fc, &need_col_headers, &max_regs); start = block_end; + eh_addr_size = saved_eh_addr_size; } printf ("\n"); @@ -4848,7 +5031,7 @@ dwarf_select_sections_by_names (const char *names) { const char * option; int * variable; - int val; + int val; } debug_dump_long_opts; @@ -4867,10 +5050,15 @@ dwarf_select_sections_by_names (const char *names) { "loc", & do_debug_loc, 1 }, { "macro", & do_debug_macinfo, 1 }, { "pubnames", & do_debug_pubnames, 1 }, + { "pubtypes", & do_debug_pubtypes, 1 }, /* This entry is for compatability with earlier versions of readelf. */ { "ranges", & do_debug_aranges, 1 }, { "str", & do_debug_str, 1 }, + /* These trace_* sections are used by Itanium VMS. */ + { "trace_abbrev", & do_trace_abbrevs, 1 }, + { "trace_aranges", & do_trace_aranges, 1 }, + { "trace_info", & do_trace_info, 1 }, { NULL, NULL, 0 } }; @@ -4916,10 +5104,10 @@ dwarf_select_sections_by_names (const char *names) void dwarf_select_sections_by_letters (const char *letters) { - unsigned int index = 0; + unsigned int lindex = 0; - while (letters[index]) - switch (letters[index++]) + while (letters[lindex]) + switch (letters[lindex++]) { case 'i': do_debug_info = 1; @@ -4941,6 +5129,10 @@ dwarf_select_sections_by_letters (const char *letters) do_debug_pubnames = 1; break; + case 't': + do_debug_pubtypes = 1; + break; + case 'r': do_debug_aranges = 1; break; @@ -4980,46 +5172,56 @@ dwarf_select_sections_all (void) do_debug_abbrevs = 1; do_debug_lines = FLAG_DEBUG_LINES_RAW; do_debug_pubnames = 1; + do_debug_pubtypes = 1; do_debug_aranges = 1; do_debug_ranges = 1; do_debug_frames = 1; do_debug_macinfo = 1; do_debug_str = 1; do_debug_loc = 1; + do_trace_info = 1; + do_trace_abbrevs = 1; + do_trace_aranges = 1; } struct dwarf_section_display debug_displays[] = { - { { ".debug_abbrev", ".zdebug_abbrev", NULL, NULL, 0, 0 }, + { { ".debug_abbrev", ".zdebug_abbrev", NULL, NULL, 0, 0 }, display_debug_abbrev, &do_debug_abbrevs, 0 }, - { { ".debug_aranges", ".zdebug_aranges", NULL, NULL, 0, 0 }, + { { ".debug_aranges", ".zdebug_aranges", NULL, NULL, 0, 0 }, display_debug_aranges, &do_debug_aranges, 1 }, - { { ".debug_frame", ".zdebug_frame", NULL, NULL, 0, 0 }, + { { ".debug_frame", ".zdebug_frame", NULL, NULL, 0, 0 }, display_debug_frames, &do_debug_frames, 1 }, - { { ".debug_info", ".zdebug_info", NULL, NULL, 0, 0 }, + { { ".debug_info", ".zdebug_info", NULL, NULL, 0, 0 }, display_debug_info, &do_debug_info, 1 }, - { { ".debug_line", ".zdebug_line", NULL, NULL, 0, 0 }, + { { ".debug_line", ".zdebug_line", NULL, NULL, 0, 0 }, display_debug_lines, &do_debug_lines, 1 }, - { { ".debug_pubnames", ".zdebug_pubnames", NULL, NULL, 0, 0 }, + { { ".debug_pubnames", ".zdebug_pubnames", NULL, NULL, 0, 0 }, display_debug_pubnames, &do_debug_pubnames, 0 }, - { { ".eh_frame", "", NULL, NULL, 0, 0 }, + { { ".eh_frame", "", NULL, NULL, 0, 0 }, display_debug_frames, &do_debug_frames, 1 }, - { { ".debug_macinfo", ".zdebug_macinfo", NULL, NULL, 0, 0 }, + { { ".debug_macinfo", ".zdebug_macinfo", NULL, NULL, 0, 0 }, display_debug_macinfo, &do_debug_macinfo, 0 }, - { { ".debug_str", ".zdebug_str", NULL, NULL, 0, 0 }, + { { ".debug_str", ".zdebug_str", NULL, NULL, 0, 0 }, display_debug_str, &do_debug_str, 0 }, - { { ".debug_loc", ".zdebug_loc", NULL, NULL, 0, 0 }, + { { ".debug_loc", ".zdebug_loc", NULL, NULL, 0, 0 }, display_debug_loc, &do_debug_loc, 1 }, - { { ".debug_pubtypes", ".zdebug_pubtypes", NULL, NULL, 0, 0 }, - display_debug_pubnames, &do_debug_pubnames, 0 }, - { { ".debug_ranges", ".zdebug_ranges", NULL, NULL, 0, 0 }, + { { ".debug_pubtypes", ".zdebug_pubtypes", NULL, NULL, 0, 0 }, + display_debug_pubnames, &do_debug_pubtypes, 0 }, + { { ".debug_ranges", ".zdebug_ranges", NULL, NULL, 0, 0 }, display_debug_ranges, &do_debug_ranges, 1 }, - { { ".debug_static_func", ".zdebug_static_func", NULL, NULL, 0, 0 }, + { { ".debug_static_func", ".zdebug_static_func", NULL, NULL, 0, 0 }, display_debug_not_supported, NULL, 0 }, - { { ".debug_static_vars", ".zdebug_static_vars", NULL, NULL, 0, 0 }, + { { ".debug_static_vars", ".zdebug_static_vars", NULL, NULL, 0, 0 }, display_debug_not_supported, NULL, 0 }, - { { ".debug_types", ".zdebug_types", NULL, NULL, 0, 0 }, + { { ".debug_types", ".zdebug_types", NULL, NULL, 0, 0 }, display_debug_types, &do_debug_info, 1 }, - { { ".debug_weaknames", ".zdebug_weaknames", NULL, NULL, 0, 0 }, - display_debug_not_supported, NULL, 0 } + { { ".debug_weaknames", ".zdebug_weaknames", NULL, NULL, 0, 0 }, + display_debug_not_supported, NULL, 0 }, + { { ".trace_info", "", NULL, NULL, 0, 0 }, + display_trace_info, &do_trace_info, 1 }, + { { ".trace_abbrev", "", NULL, NULL, 0, 0 }, + display_debug_abbrev, &do_trace_abbrevs, 0 }, + { { ".trace_aranges", "", NULL, NULL, 0, 0 }, + display_debug_aranges, &do_trace_aranges, 0 } };