+ case DW_AT_calling_convention:
+ switch (uvalue)
+ {
+ case DW_CC_normal: printf ("(normal)"); break;
+ case DW_CC_program: printf ("(program)"); break;
+ case DW_CC_nocall: printf ("(nocall)"); break;
+ default:
+ if (uvalue >= DW_CC_lo_user
+ && uvalue <= DW_CC_hi_user)
+ printf ("(user defined)");
+ else
+ printf ("(unknown convention)");
+ }
+ break;
+
+ case DW_AT_ordering:
+ switch (uvalue)
+ {
+ case -1: printf ("(undefined)"); break;
+ case 0: printf ("(row major)"); break;
+ case 1: printf ("(column major)"); break;
+ }
+ break;
+
+ case DW_AT_frame_base:
+ have_frame_base = 1;
+ case DW_AT_location:
+ case DW_AT_data_member_location:
+ case DW_AT_vtable_elem_location:
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_data_location:
+ case DW_AT_stride:
+ case DW_AT_upper_bound:
+ case DW_AT_lower_bound:
+ if (block_start)
+ {
+ int need_frame_base;
+
+ printf ("(");
+ need_frame_base = decode_location_expression (block_start,
+ pointer_size,
+ uvalue,
+ cu_offset);
+ printf (")");
+ if (need_frame_base && !have_frame_base)
+ printf (_(" [without DW_AT_frame_base]"));
+ }
+ else if (form == DW_FORM_data4 || form == DW_FORM_data8)
+ printf (_("(location list)"));
+
+ break;
+
+ default:
+ break;
+ }
+
+ return data;
+}
+
+static char *
+get_AT_name (unsigned long attribute)
+{
+ switch (attribute)
+ {
+ case DW_AT_sibling: return "DW_AT_sibling";
+ case DW_AT_location: return "DW_AT_location";
+ case DW_AT_name: return "DW_AT_name";
+ case DW_AT_ordering: return "DW_AT_ordering";
+ case DW_AT_subscr_data: return "DW_AT_subscr_data";
+ case DW_AT_byte_size: return "DW_AT_byte_size";
+ case DW_AT_bit_offset: return "DW_AT_bit_offset";
+ case DW_AT_bit_size: return "DW_AT_bit_size";
+ case DW_AT_element_list: return "DW_AT_element_list";
+ case DW_AT_stmt_list: return "DW_AT_stmt_list";
+ case DW_AT_low_pc: return "DW_AT_low_pc";
+ case DW_AT_high_pc: return "DW_AT_high_pc";
+ case DW_AT_language: return "DW_AT_language";
+ case DW_AT_member: return "DW_AT_member";
+ case DW_AT_discr: return "DW_AT_discr";
+ case DW_AT_discr_value: return "DW_AT_discr_value";
+ case DW_AT_visibility: return "DW_AT_visibility";
+ case DW_AT_import: return "DW_AT_import";
+ case DW_AT_string_length: return "DW_AT_string_length";
+ case DW_AT_common_reference: return "DW_AT_common_reference";
+ case DW_AT_comp_dir: return "DW_AT_comp_dir";
+ case DW_AT_const_value: return "DW_AT_const_value";
+ case DW_AT_containing_type: return "DW_AT_containing_type";
+ case DW_AT_default_value: return "DW_AT_default_value";
+ case DW_AT_inline: return "DW_AT_inline";
+ case DW_AT_is_optional: return "DW_AT_is_optional";
+ case DW_AT_lower_bound: return "DW_AT_lower_bound";
+ case DW_AT_producer: return "DW_AT_producer";
+ case DW_AT_prototyped: return "DW_AT_prototyped";
+ case DW_AT_return_addr: return "DW_AT_return_addr";
+ case DW_AT_start_scope: return "DW_AT_start_scope";
+ case DW_AT_stride_size: return "DW_AT_stride_size";
+ case DW_AT_upper_bound: return "DW_AT_upper_bound";
+ case DW_AT_abstract_origin: return "DW_AT_abstract_origin";
+ case DW_AT_accessibility: return "DW_AT_accessibility";
+ case DW_AT_address_class: return "DW_AT_address_class";
+ case DW_AT_artificial: return "DW_AT_artificial";
+ case DW_AT_base_types: return "DW_AT_base_types";
+ case DW_AT_calling_convention: return "DW_AT_calling_convention";
+ case DW_AT_count: return "DW_AT_count";
+ case DW_AT_data_member_location: return "DW_AT_data_member_location";
+ case DW_AT_decl_column: return "DW_AT_decl_column";
+ case DW_AT_decl_file: return "DW_AT_decl_file";
+ case DW_AT_decl_line: return "DW_AT_decl_line";
+ case DW_AT_declaration: return "DW_AT_declaration";
+ case DW_AT_discr_list: return "DW_AT_discr_list";
+ case DW_AT_encoding: return "DW_AT_encoding";
+ case DW_AT_external: return "DW_AT_external";
+ case DW_AT_frame_base: return "DW_AT_frame_base";
+ case DW_AT_friend: return "DW_AT_friend";
+ case DW_AT_identifier_case: return "DW_AT_identifier_case";
+ case DW_AT_macro_info: return "DW_AT_macro_info";
+ case DW_AT_namelist_items: return "DW_AT_namelist_items";
+ case DW_AT_priority: return "DW_AT_priority";
+ case DW_AT_segment: return "DW_AT_segment";
+ case DW_AT_specification: return "DW_AT_specification";
+ case DW_AT_static_link: return "DW_AT_static_link";
+ case DW_AT_type: return "DW_AT_type";
+ case DW_AT_use_location: return "DW_AT_use_location";
+ case DW_AT_variable_parameter: return "DW_AT_variable_parameter";
+ case DW_AT_virtuality: return "DW_AT_virtuality";
+ case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location";
+ /* DWARF 2.1 values. */
+ case DW_AT_allocated: return "DW_AT_allocated";
+ case DW_AT_associated: return "DW_AT_associated";
+ case DW_AT_data_location: return "DW_AT_data_location";
+ case DW_AT_stride: return "DW_AT_stride";
+ case DW_AT_entry_pc: return "DW_AT_entry_pc";
+ case DW_AT_use_UTF8: return "DW_AT_use_UTF8";
+ case DW_AT_extension: return "DW_AT_extension";
+ case DW_AT_ranges: return "DW_AT_ranges";
+ case DW_AT_trampoline: return "DW_AT_trampoline";
+ case DW_AT_call_column: return "DW_AT_call_column";
+ case DW_AT_call_file: return "DW_AT_call_file";
+ case DW_AT_call_line: return "DW_AT_call_line";
+ /* SGI/MIPS extensions. */
+ case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde";
+ case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin";
+ case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin";
+ case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin";
+ case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor";
+ case DW_AT_MIPS_software_pipeline_depth:
+ return "DW_AT_MIPS_software_pipeline_depth";
+ case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name";
+ case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride";
+ case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name";
+ case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin";
+ case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines";
+ /* GNU extensions. */
+ case DW_AT_sf_names: return "DW_AT_sf_names";
+ case DW_AT_src_info: return "DW_AT_src_info";
+ case DW_AT_mac_info: return "DW_AT_mac_info";
+ case DW_AT_src_coords: return "DW_AT_src_coords";
+ case DW_AT_body_begin: return "DW_AT_body_begin";
+ case DW_AT_body_end: return "DW_AT_body_end";
+ case DW_AT_GNU_vector: return "DW_AT_GNU_vector";
+ /* UPC extension. */
+ case DW_AT_upc_threads_scaled: return "DW_AT_upc_threads_scaled";
+ default:
+ {
+ static char buffer[100];
+
+ sprintf (buffer, _("Unknown AT value: %lx"), attribute);
+ return buffer;
+ }
+ }
+}
+
+static unsigned char *
+read_and_display_attr (unsigned long attribute,
+ unsigned long form,
+ unsigned char *data,
+ unsigned long cu_offset,
+ unsigned long pointer_size,
+ unsigned long offset_size,
+ int dwarf_version,
+ debug_info *debug_info_p,
+ int do_loc)
+{
+ if (!do_loc)
+ printf (" %-18s:", get_AT_name (attribute));
+ data = read_and_display_attr_value (attribute, form, data, cu_offset,
+ pointer_size, offset_size,
+ dwarf_version, debug_info_p,
+ do_loc);
+ if (!do_loc)
+ printf ("\n");
+ return data;
+}
+
+
+/* Process the contents of a .debug_info section. If do_loc is non-zero
+ then we are scanning for location lists and we do not want to display
+ anything to the user. */
+
+static int
+process_debug_info (Elf_Internal_Shdr *section, unsigned char *start,
+ FILE *file, int do_loc)
+{
+ unsigned char *end = start + section->sh_size;
+ unsigned char *section_begin;
+ unsigned int unit;
+ unsigned int num_units = 0;
+
+ if ((do_loc || do_debug_loc || do_debug_ranges)
+ && num_debug_info_entries == 0)
+ {
+ unsigned long length;
+
+ /* First scan the section to get the number of comp units. */
+ for (section_begin = start, num_units = 0; section_begin < end;
+ num_units ++)
+ {
+ /* Read the first 4 bytes. For a 32-bit DWARF section, this
+ will be the length. For a 64-bit DWARF section, it'll be
+ the escape code 0xffffffff followed by an 8 byte length. */
+ length = byte_get (section_begin, 4);
+
+ if (length == 0xffffffff)
+ {
+ length = byte_get (section_begin + 4, 8);
+ section_begin += length + 12;
+ }
+ else
+ section_begin += length + 4;
+ }
+
+ if (num_units == 0)
+ {
+ error (_("No comp units in .debug_info section ?"));
+ return 0;
+ }
+
+ /* Then allocate an array to hold the information. */
+ debug_information = malloc (num_units *
+ sizeof (* debug_information));
+ if (debug_information == NULL)
+ {
+ error (_("Not enough memory for a debug info array of %u entries"),
+ num_units);
+ return 0;
+ }
+ }
+
+ if (!do_loc)
+ {
+ printf (_("The section %s contains:\n\n"),
+ SECTION_NAME (section));
+
+ load_debug_str (file);
+ load_debug_loc (file);
+ load_debug_range (file);
+ }
+
+ for (section_begin = start, unit = 0; start < end; unit++)
+ {
+ 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;
+
+ hdrptr = start;
+
+ compunit.cu_length = byte_get (hdrptr, 4);
+ hdrptr += 4;
+
+ if (compunit.cu_length == 0xffffffff)
+ {
+ compunit.cu_length = byte_get (hdrptr, 8);
+ hdrptr += 8;
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
+ }
+
+ compunit.cu_version = byte_get (hdrptr, 2);
+ hdrptr += 2;
+
+ cu_offset = start - section_begin;
+ start += compunit.cu_length + initial_length_size;
+
+ if (elf_header.e_type == ET_REL
+ && !debug_apply_rela_addends (file, section, offset_size,
+ section_begin, hdrptr, start))
+ return 0;
+
+ cu_abbrev_offset_ptr = hdrptr;
+ compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
+ hdrptr += offset_size;
+
+ compunit.cu_pointer_size = byte_get (hdrptr, 1);
+ hdrptr += 1;
+ if ((do_loc || do_debug_loc || do_debug_ranges)
+ && num_debug_info_entries == 0)
+ {
+ debug_information [unit].cu_offset = cu_offset;
+ debug_information [unit].pointer_size
+ = compunit.cu_pointer_size;
+ debug_information [unit].base_address = 0;
+ debug_information [unit].loc_offsets = NULL;
+ debug_information [unit].have_frame_base = NULL;
+ debug_information [unit].max_loc_offsets = 0;
+ debug_information [unit].num_loc_offsets = 0;
+ debug_information [unit].range_lists = NULL;
+ debug_information [unit].max_range_lists= 0;
+ debug_information [unit].num_range_lists = 0;
+ }
+
+ tags = hdrptr;
+
+ if (!do_loc)
+ {
+ printf (_(" Compilation Unit @ %lx:\n"), cu_offset);
+ printf (_(" Length: %ld\n"), compunit.cu_length);
+ printf (_(" Version: %d\n"), compunit.cu_version);
+ printf (_(" Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
+ printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size);
+ }
+
+ if (compunit.cu_version != 2 && compunit.cu_version != 3)
+ {
+ warn (_("Only version 2 and 3 DWARF debug information is currently supported.\n"));
+ continue;
+ }
+
+ free_abbrevs ();
+
+ /* Read in the abbrevs used by this compilation unit. */
+ {
+ Elf_Internal_Shdr *sec;
+ unsigned char *begin;
+
+ /* Locate the .debug_abbrev section and process it. */
+ sec = find_section (".debug_abbrev");
+ if (sec == NULL)
+ {
+ warn (_("Unable to locate .debug_abbrev section!\n"));
+ return 0;
+ }
+
+ begin = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+ _("debug_abbrev section data"));
+ if (!begin)
+ return 0;
+
+ process_abbrev_section (begin + compunit.cu_abbrev_offset,
+ begin + sec->sh_size);
+
+ free (begin);
+ }
+
+ level = 0;
+ while (tags < start)
+ {
+ int bytes_read;
+ unsigned long abbrev_number;
+ abbrev_entry *entry;
+ abbrev_attr *attr;
+
+ abbrev_number = read_leb128 (tags, & bytes_read, 0);
+ tags += bytes_read;
+
+ /* A null DIE marks the end of a list of children. */
+ if (abbrev_number == 0)
+ {
+ --level;
+ continue;
+ }
+
+ /* Scan through the abbreviation list until we reach the
+ correct entry. */
+ for (entry = first_abbrev;
+ entry && entry->entry != abbrev_number;
+ entry = entry->next)
+ continue;
+
+ if (entry == NULL)
+ {
+ warn (_("Unable to locate entry %lu in the abbreviation table\n"),
+ abbrev_number);
+ return 0;
+ }
+
+ if (!do_loc)
+ printf (_(" <%d><%lx>: Abbrev Number: %lu (%s)\n"),
+ level,
+ (unsigned long) (tags - section_begin
+ - bytes_read),
+ abbrev_number,
+ get_TAG_name (entry->tag));
+
+ switch (entry->tag)
+ {
+ default:
+ need_base_address = 0;
+ break;
+ case DW_TAG_compile_unit:
+ need_base_address = 1;
+ break;
+ case DW_TAG_entry_point:
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_subprogram:
+ need_base_address = 0;
+ /* Assuming that there is no DW_AT_frame_base. */
+ have_frame_base = 0;
+ break;
+ }
+
+ for (attr = entry->first_attr; attr; attr = attr->next)
+ tags = read_and_display_attr (attr->attribute,
+ attr->form,
+ tags, cu_offset,
+ compunit.cu_pointer_size,
+ offset_size,
+ compunit.cu_version,
+ &debug_information [unit],
+ do_loc);
+
+ if (entry->children)
+ ++level;
+ }
+ }
+
+ /* Set num_debug_info_entries here so that it can be used to check if
+ we need to proecess .debug_loc and .debug_ranges sections. */
+ if ((do_loc || do_debug_loc || do_debug_ranges)
+ && num_debug_info_entries == 0)
+ num_debug_info_entries = num_units;
+
+ if (!do_loc)
+ {
+ free_debug_range ();
+ free_debug_str ();
+ free_debug_loc ();
+
+ printf ("\n");
+ }
+
+ return 1;
+}
+
+/* Retrieve the pointer size associated with the given compilation unit.
+ Optionally the offset of this unit into the .debug_info section is
+ also retutned. If there is no .debug_info section then an error
+ message is issued and 0 is returned. If the requested comp unit has
+ not been defined in the .debug_info section then a warning message
+ is issued and the last know pointer size is returned. This message
+ is only issued once per section dumped per file dumped. */
+
+static unsigned int
+get_pointer_size_and_offset_of_comp_unit (unsigned int comp_unit,
+ const char * section_name,
+ unsigned long * offset_return)
+{
+ unsigned long offset = 0;
+
+ if (num_debug_info_entries == 0)
+ error (_("%s section needs a populated .debug_info section\n"),
+ section_name);
+
+ else if (comp_unit >= num_debug_info_entries)
+ {
+ if (!warned_about_missing_comp_units)
+ {
+ warn (_("%s section has more comp units than .debug_info section\n"),
+ section_name);
+ warn (_("assuming that the pointer size is %d, from the last comp unit in .debug_info\n\n"),
+ last_pointer_size);
+ warned_about_missing_comp_units = TRUE;
+ }
+ }
+ else
+ {
+ last_pointer_size = debug_information [comp_unit].pointer_size;
+ offset = debug_information [comp_unit].cu_offset;
+ }
+
+ if (offset_return != NULL)
+ * offset_return = offset;
+
+ return last_pointer_size;
+}
+
+/* Locate and scan the .debug_info section in the file and record the pointer
+ sizes and offsets for the compilation units in it. Usually an executable
+ will have just one pointer size, but this is not guaranteed, and so we try
+ not to make any assumptions. Returns zero upon failure, or the number of
+ compilation units upon success. */
+
+static unsigned int
+get_debug_info (FILE * file)
+{
+ Elf_Internal_Shdr * section;
+ unsigned char * start;
+ int ret;
+
+ /* Reset the last pointer size so that we can issue correct error
+ messages if we are displaying the contents of more than one section. */
+ last_pointer_size = 0;
+ warned_about_missing_comp_units = FALSE;
+
+ /* If we already have the information there is nothing else to do. */
+ if (num_debug_info_entries > 0)
+ return num_debug_info_entries;
+
+ section = find_section (".debug_info");
+ if (section == NULL)
+ return 0;
+
+ start = get_data (NULL, file, section->sh_offset, section->sh_size,
+ _("extracting information from .debug_info section"));
+ if (start == NULL)
+ return 0;
+
+ ret = process_debug_info (section, start, file, 1);
+ free (start);
+
+ return ret ? num_debug_info_entries : 0;
+}
+
+static int
+display_debug_lines (Elf_Internal_Shdr *section,
+ unsigned char *start, FILE *file)
+{
+ unsigned char *data = start;
+ unsigned char *end = start + section->sh_size;
+ unsigned int comp_unit = 0;
+
+ printf (_("\nDump of debug contents of section %s:\n\n"),
+ SECTION_NAME (section));
+
+ get_debug_info (file);
+
+ while (data < end)
+ {
+ DWARF2_Internal_LineInfo info;
+ unsigned char *standard_opcodes;
+ unsigned char *end_of_sequence;
+ unsigned char *hdrptr;
+ unsigned int pointer_size;
+ int initial_length_size;
+ int offset_size;
+ int i;
+
+ hdrptr = data;
+
+ /* Check the length of the block. */
+ info.li_length = byte_get (hdrptr, 4);
+ hdrptr += 4;
+
+ if (info.li_length == 0xffffffff)
+ {
+ /* This section is 64-bit DWARF 3. */
+ info.li_length = byte_get (hdrptr, 8);
+ hdrptr += 8;
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
+ }
+
+ if (info.li_length + initial_length_size > section->sh_size)
+ {
+ warn
+ (_("The line info appears to be corrupt - the section is too small\n"));
+ return 0;
+ }
+
+ /* Check its version number. */
+ info.li_version = byte_get (hdrptr, 2);
+ hdrptr += 2;
+ if (info.li_version != 2 && info.li_version != 3)
+ {
+ warn (_("Only DWARF version 2 and 3 line info is currently supported.\n"));
+ return 0;
+ }
+
+ info.li_prologue_length = byte_get (hdrptr, offset_size);
+ hdrptr += offset_size;
+ info.li_min_insn_length = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_default_is_stmt = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_line_base = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_line_range = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_opcode_base = byte_get (hdrptr, 1);
+ hdrptr++;
+
+ /* Sign extend the line base field. */
+ info.li_line_base <<= 24;
+ info.li_line_base >>= 24;
+
+ /* Get the pointer size from the comp unit associated
+ with this block of line number information. */
+ pointer_size = get_pointer_size_and_offset_of_comp_unit
+ (comp_unit, ".debug_lines", NULL);
+ comp_unit ++;
+
+ 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 (_(" (Pointer size: %u)\n"), pointer_size);
+
+ end_of_sequence = data + info.li_length + initial_length_size;
+
+ reset_state_machine (info.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++)
+ 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;
+
+ if (*data == 0)
+ printf (_("\n The Directory Table is empty.\n"));
+ else
+ {
+ printf (_("\n The Directory Table:\n"));
+
+ while (*data != 0)
+ {
+ printf (_(" %s\n"), data);
+
+ data += strlen ((char *) data) + 1;
+ }
+ }
+
+ /* Skip the NUL at the end of the table. */
+ data++;
+
+ /* Display the contents of the File Name table. */
+ if (*data == 0)
+ printf (_("\n The File Name Table is empty.\n"));
+ else
+ {
+ printf (_("\n The File Name Table:\n"));
+ printf (_(" Entry\tDir\tTime\tSize\tName\n"));
+
+ while (*data != 0)
+ {
+ unsigned char *name;
+ int bytes_read;
+
+ printf (_(" %d\t"), ++state_machine_regs.last_file_entry);
+ name = data;
+
+ data += strlen ((char *) data) + 1;
+
+ printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
+ data += bytes_read;
+ printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
+ data += bytes_read;
+ printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0));
+ data += bytes_read;
+ printf (_("%s\n"), name);
+ }
+ }
+
+ /* Skip the NUL at the end of the table. */
+ data++;
+
+ /* Now display the statements. */
+ printf (_("\n Line Number Statements:\n"));
+
+ while (data < end_of_sequence)
+ {
+ unsigned char op_code;
+ int adv;
+ int bytes_read;
+
+ op_code = *data++;
+
+ if (op_code >= info.li_opcode_base)
+ {
+ op_code -= info.li_opcode_base;
+ adv = (op_code / info.li_line_range) * info.li_min_insn_length;
+ state_machine_regs.address += adv;
+ printf (_(" Special opcode %d: advance Address by %d to 0x%lx"),
+ op_code, adv, state_machine_regs.address);
+ adv = (op_code % info.li_line_range) + info.li_line_base;
+ state_machine_regs.line += adv;
+ printf (_(" and Line by %d to %d\n"),
+ adv, state_machine_regs.line);
+ }
+ else switch (op_code)
+ {
+ case DW_LNS_extended_op:
+ data += process_extended_line_op (data, info.li_default_is_stmt,
+ pointer_size);
+ break;
+
+ case DW_LNS_copy:
+ printf (_(" Copy\n"));
+ break;
+
+ case DW_LNS_advance_pc:
+ adv = info.li_min_insn_length * read_leb128 (data, & bytes_read, 0);
+ data += bytes_read;
+ state_machine_regs.address += adv;
+ printf (_(" Advance PC by %d to %lx\n"), adv,
+ state_machine_regs.address);
+ break;
+
+ case DW_LNS_advance_line:
+ adv = read_leb128 (data, & bytes_read, 1);
+ data += bytes_read;
+ state_machine_regs.line += adv;
+ printf (_(" Advance Line by %d to %d\n"), adv,
+ state_machine_regs.line);
+ break;
+
+ case DW_LNS_set_file:
+ adv = read_leb128 (data, & bytes_read, 0);
+ data += bytes_read;
+ printf (_(" Set File Name to entry %d in the File Name Table\n"),
+ adv);
+ state_machine_regs.file = adv;
+ break;
+
+ case DW_LNS_set_column:
+ adv = read_leb128 (data, & bytes_read, 0);
+ data += bytes_read;
+ printf (_(" Set column to %d\n"), adv);
+ state_machine_regs.column = adv;
+ break;
+
+ case DW_LNS_negate_stmt:
+ adv = state_machine_regs.is_stmt;
+ adv = ! adv;
+ printf (_(" Set is_stmt to %d\n"), adv);
+ state_machine_regs.is_stmt = adv;
+ break;
+
+ case DW_LNS_set_basic_block:
+ printf (_(" Set basic block\n"));
+ state_machine_regs.basic_block = 1;
+ break;
+
+ case DW_LNS_const_add_pc:
+ adv = (((255 - info.li_opcode_base) / info.li_line_range)
+ * info.li_min_insn_length);
+ state_machine_regs.address += adv;
+ printf (_(" Advance PC by constant %d to 0x%lx\n"), adv,
+ state_machine_regs.address);
+ break;
+
+ case DW_LNS_fixed_advance_pc:
+ adv = byte_get (data, 2);
+ data += 2;
+ state_machine_regs.address += adv;
+ printf (_(" Advance PC by fixed size amount %d to 0x%lx\n"),
+ adv, state_machine_regs.address);
+ break;
+
+ case DW_LNS_set_prologue_end:
+ printf (_(" Set prologue_end to true\n"));
+ break;
+
+ case DW_LNS_set_epilogue_begin:
+ printf (_(" Set epilogue_begin to true\n"));
+ break;
+
+ case DW_LNS_set_isa:
+ adv = read_leb128 (data, & bytes_read, 0);
+ data += bytes_read;
+ printf (_(" Set ISA to %d\n"), adv);
+ break;
+
+ default:
+ printf (_(" Unknown opcode %d with operands: "), op_code);
+
+ for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
+ {
+ printf ("0x%lx%s", read_leb128 (data, &bytes_read, 0),
+ i == 1 ? "" : ", ");
+ data += bytes_read;
+ }
+ putchar ('\n');
+ break;
+ }
+ }
+ putchar ('\n');
+ }
+
+ return 1;
+}
+
+static int
+display_debug_pubnames (Elf_Internal_Shdr *section,
+ unsigned char *start,
+ FILE *file ATTRIBUTE_UNUSED)
+{
+ DWARF2_Internal_PubNames pubnames;
+ unsigned char *end;
+
+ end = start + section->sh_size;
+
+ printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
+
+ while (start < end)
+ {
+ unsigned char *data;
+ unsigned long offset;
+ int offset_size, initial_length_size;
+
+ data = start;
+
+ pubnames.pn_length = byte_get (data, 4);
+ data += 4;
+ if (pubnames.pn_length == 0xffffffff)
+ {
+ pubnames.pn_length = byte_get (data, 8);
+ data += 8;
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
+ }
+
+ pubnames.pn_version = byte_get (data, 2);
+ data += 2;
+ pubnames.pn_offset = byte_get (data, offset_size);
+ data += offset_size;
+ pubnames.pn_size = byte_get (data, offset_size);
+ data += offset_size;
+
+ start += pubnames.pn_length + initial_length_size;
+
+ if (pubnames.pn_version != 2 && pubnames.pn_version != 3)
+ {
+ static int warned = 0;
+
+ if (! warned)
+ {
+ warn (_("Only DWARF 2 and 3 pubnames are currently supported\n"));
+ warned = 1;
+ }
+
+ continue;
+ }
+
+ printf (_(" Length: %ld\n"),
+ pubnames.pn_length);
+ printf (_(" Version: %d\n"),
+ pubnames.pn_version);
+ printf (_(" Offset into .debug_info section: %ld\n"),
+ pubnames.pn_offset);
+ printf (_(" Size of area in .debug_info section: %ld\n"),
+ pubnames.pn_size);
+
+ printf (_("\n Offset\tName\n"));
+
+ do
+ {
+ offset = byte_get (data, offset_size);
+
+ if (offset != 0)
+ {
+ data += offset_size;
+ printf (" %-6ld\t\t%s\n", offset, data);
+ data += strlen ((char *) data) + 1;
+ }
+ }
+ while (offset != 0);
+ }
+
+ printf ("\n");
+ return 1;
+}
+
+static int
+display_debug_macinfo (Elf_Internal_Shdr *section,
+ unsigned char *start,
+ FILE *file ATTRIBUTE_UNUSED)
+{
+ unsigned char *end = start + section->sh_size;
+ unsigned char *curr = start;
+ unsigned int bytes_read;
+ enum dwarf_macinfo_record_type op;
+
+ printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
+
+ while (curr < end)
+ {
+ unsigned int lineno;
+ const char *string;
+
+ op = *curr;
+ curr++;
+
+ switch (op)
+ {
+ case DW_MACINFO_start_file:
+ {
+ unsigned int filenum;
+
+ lineno = read_leb128 (curr, & bytes_read, 0);
+ curr += bytes_read;
+ filenum = read_leb128 (curr, & bytes_read, 0);
+ curr += bytes_read;
+
+ printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"),
+ lineno, filenum);
+ }
+ break;
+
+ case DW_MACINFO_end_file:
+ printf (_(" DW_MACINFO_end_file\n"));
+ break;
+
+ case DW_MACINFO_define:
+ lineno = read_leb128 (curr, & bytes_read, 0);
+ curr += bytes_read;
+ string = curr;
+ curr += strlen (string) + 1;
+ printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"),
+ lineno, string);
+ break;
+
+ case DW_MACINFO_undef:
+ lineno = read_leb128 (curr, & bytes_read, 0);
+ curr += bytes_read;
+ string = curr;
+ curr += strlen (string) + 1;
+ printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"),
+ lineno, string);
+ break;
+
+ case DW_MACINFO_vendor_ext:
+ {
+ unsigned int constant;
+
+ constant = read_leb128 (curr, & bytes_read, 0);
+ curr += bytes_read;
+ string = curr;
+ curr += strlen (string) + 1;
+ printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"),
+ constant, string);
+ }
+ break;
+ }
+ }
+
+ return 1;
+}
+
+
+static int
+display_debug_abbrev (Elf_Internal_Shdr *section,
+ unsigned char *start,
+ FILE *file ATTRIBUTE_UNUSED)
+{
+ abbrev_entry *entry;
+ unsigned char *end = start + section->sh_size;
+
+ printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
+
+ do
+ {
+ start = process_abbrev_section (start, end);
+
+ if (first_abbrev == NULL)
+ continue;
+
+ printf (_(" Number TAG\n"));
+
+ for (entry = first_abbrev; entry; entry = entry->next)