Index: binutils/NEWS =================================================================== RCS file: /cvs/src/src/binutils/NEWS,v retrieving revision 1.44 diff -c -3 -p -r1.44 NEWS *** binutils/NEWS 8 Oct 2004 14:54:03 -0000 1.44 --- binutils/NEWS 3 Nov 2004 10:13:19 -0000 *************** *** 1,5 **** --- 1,10 ---- -*- text -*- + * readelf can now display address ranges from .debug_range sections. This + happens automatically when a DW_AT_range attribute is encountered. The + command line switch --debug-dump=Ranges (or -wR) can also be used to display + the contents of the .debug_range section. + * nm and objdump now have a switch "--special-syms" to enable the displaying of symbols which the target considers to be special. By default these symbols are no longer displayed. Currently the only special symbols are the Mapping Index: binutils/readelf.c =================================================================== RCS file: /cvs/src/src/binutils/readelf.c,v retrieving revision 1.263 diff -c -3 -p -r1.263 readelf.c *** binutils/readelf.c 3 Nov 2004 02:21:57 -0000 1.263 --- binutils/readelf.c 3 Nov 2004 10:13:21 -0000 *************** int do_debug_abbrevs; *** 159,164 **** --- 159,165 ---- int do_debug_lines; int do_debug_pubnames; int do_debug_aranges; + int do_debug_ranges; int do_debug_frames; int do_debug_frames_interp; int do_debug_macinfo; *************** size_t group_count = 0; *** 185,191 **** struct group **section_headers_groups; ! /* A dynamic array of flags indicating which sections require dumping. */ char *dump_sects = NULL; unsigned int num_dump_sects = 0; --- 186,201 ---- struct group **section_headers_groups; ! /* A dynamic array of flags indicating for which sections a hex dump ! has been requested (via the -x switch) and/or a disassembly dump ! (via the -i switch). */ ! char *cmdline_dump_sects = NULL; ! unsigned num_cmdline_dump_sects = 0; ! ! /* A dynamic array of flags indicating for which sections a dump of ! some kind has been requested. It is reset on a per-object file ! basis and then initialised from the cmdline_dump_sects array and ! the results of interpreting the -w switch. */ char *dump_sects = NULL; unsigned int num_dump_sects = 0; *************** static void (*byte_put) (unsigned char * *** 259,264 **** --- 269,278 ---- /* GET_DYNAMIC_NAME asssumes that VALID_DYNAMIC_NAME has already been called and verified that the string exists. */ #define GET_DYNAMIC_NAME(offset) (dynamic_strings + offset) + + /* This is just a bit of syntatic sugar. */ + #define streq(a,b) (strcmp ((a), (b)) == 0) + #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) static void error (const char *message, ...) *************** usage (void) *** 2576,2583 **** -A --arch-specific Display architecture specific information (if any).\n\ -D --use-dynamic Use the dynamic section info when displaying symbols\n\ -x --hex-dump= Dump the contents of section \n\ ! -w[liaprmfFso] or\n\ ! --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str,=loc]\n\ Display the contents of DWARF2 debug sections\n")); #ifdef SUPPORT_DISASSEMBLY fprintf (stdout, _("\ --- 2591,2598 ---- -A --arch-specific Display architecture specific information (if any).\n\ -D --use-dynamic Use the dynamic section info when displaying symbols\n\ -x --hex-dump= Dump the contents of section \n\ ! -w[liaprmfFsoR] or\n\ ! --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\ Display the contents of DWARF2 debug sections\n")); #ifdef SUPPORT_DISASSEMBLY fprintf (stdout, _("\ *************** usage (void) *** 2594,2599 **** --- 2609,2619 ---- exit (0); } + /* Record the fact that the user wants the contents of section number + SECTION to be displayed using the method(s) encoded as flags bits + in TYPE. Note, TYPE can be zero if we are creating the array for + the first time. */ + static void request_dump (unsigned int section, int type) { *************** parse_args (int argc, char **argv) *** 2744,2753 **** break; case 'r': - case 'R': do_debug_aranges = 1; break; case 'F': do_debug_frames_interp = 1; case 'f': --- 2764,2776 ---- break; case 'r': do_debug_aranges = 1; break; + case 'R': + do_debug_ranges = 1; + break; + case 'F': do_debug_frames_interp = 1; case 'f': *************** parse_args (int argc, char **argv) *** 2781,2790 **** do_debugging = 1; else { ! static const char *debug_dump_opt[] ! = { "line", "info", "abbrev", "pubnames", "ranges", ! "macro", "frames", "frames-interp", "str", "loc", NULL }; ! unsigned int index; const char *p; do_debugging = 0; --- 2804,2836 ---- do_debugging = 1; else { ! typedef struct ! { ! const char * option; ! int * variable; ! } ! debug_dump_long_opts; ! ! debug_dump_long_opts opts_table [] = ! { ! /* Please keep this table alpha- sorted. */ ! { "Ranges", & do_debug_ranges }, ! { "abbrev", & do_debug_abbrevs }, ! { "aranges", & do_debug_aranges }, ! { "frames", & do_debug_frames }, ! { "frames-interp", & do_debug_frames_interp }, ! { "info", & do_debug_info }, ! { "line", & do_debug_lines }, ! { "loc", & do_debug_loc }, ! { "macro", & do_debug_macinfo }, ! { "pubnames", & do_debug_pubnames }, ! /* This entry is for compatability ! with earlier versions of readelf. */ ! { "ranges", & do_debug_aranges }, ! { "str", & do_debug_str }, ! { NULL, NULL } ! }; ! const char *p; do_debugging = 0; *************** parse_args (int argc, char **argv) *** 2792,2850 **** p = optarg; while (*p) { ! for (index = 0; debug_dump_opt[index]; index++) { ! size_t len = strlen (debug_dump_opt[index]); ! if (strncmp (p, debug_dump_opt[index], len) == 0 && (p[len] == ',' || p[len] == '\0')) { ! switch (p[0]) ! { ! case 'i': ! do_debug_info = 1; ! break; ! ! case 'a': ! do_debug_abbrevs = 1; ! break; ! ! case 'l': ! if (p[1] == 'i') ! do_debug_lines = 1; ! else ! do_debug_loc = 1; ! break; ! ! case 'p': ! do_debug_pubnames = 1; ! break; ! ! case 'r': ! do_debug_aranges = 1; ! break; ! ! case 'f': ! if (len > 6) ! do_debug_frames_interp = 1; ! do_debug_frames = 1; ! break; ! ! case 'm': ! do_debug_macinfo = 1; ! break; ! ! case 's': ! do_debug_str = 1; ! break; ! } p += len; break; } } ! if (debug_dump_opt[index] == NULL) { warn (_("Unrecognized debug option '%s'\n"), p); p = strchr (p, ','); --- 2838,2865 ---- p = optarg; while (*p) { ! debug_dump_long_opts * entry; ! ! for (entry = opts_table; entry->option; entry++) { ! size_t len = strlen (entry->option); ! if (strneq (p, entry->option, len) && (p[len] == ',' || p[len] == '\0')) { ! * entry->variable = 1; ! ! /* The --debug-dump=frames-interp option also ! enables the --debug-dump=frames option. */ ! if (do_debug_frames_interp) ! do_debug_frames = 1; p += len; break; } } ! if (entry->option == NULL) { warn (_("Unrecognized debug option '%s'\n"), p); p = strchr (p, ','); *************** process_section_headers (FILE *file) *** 3740,3768 **** else if ((do_debugging || do_debug_info || do_debug_abbrevs || do_debug_lines || do_debug_pubnames || do_debug_aranges || do_debug_frames || do_debug_macinfo || do_debug_str ! || do_debug_loc) ! && strncmp (name, ".debug_", 7) == 0) { name += 7; if (do_debugging ! || (do_debug_info && (strcmp (name, "info") == 0)) ! || (do_debug_abbrevs && (strcmp (name, "abbrev") == 0)) ! || (do_debug_lines && (strcmp (name, "line") == 0)) ! || (do_debug_pubnames && (strcmp (name, "pubnames") == 0)) ! || (do_debug_aranges && (strcmp (name, "aranges") == 0)) ! || (do_debug_frames && (strcmp (name, "frame") == 0)) ! || (do_debug_macinfo && (strcmp (name, "macinfo") == 0)) ! || (do_debug_str && (strcmp (name, "str") == 0)) ! || (do_debug_loc && (strcmp (name, "loc") == 0)) ) request_dump (i, DEBUG_DUMP); } /* linkonce section to be combined with .debug_info at link time. */ else if ((do_debugging || do_debug_info) ! && strncmp (name, ".gnu.linkonce.wi.", 17) == 0) request_dump (i, DEBUG_DUMP); ! else if (do_debug_frames && strcmp (name, ".eh_frame") == 0) request_dump (i, DEBUG_DUMP); } --- 3755,3784 ---- else if ((do_debugging || do_debug_info || do_debug_abbrevs || do_debug_lines || do_debug_pubnames || do_debug_aranges || do_debug_frames || do_debug_macinfo || do_debug_str ! || do_debug_loc || do_debug_ranges) ! && strneq (name, ".debug_", 7)) { name += 7; if (do_debugging ! || (do_debug_info && streq (name, "info")) ! || (do_debug_abbrevs && streq (name, "abbrev")) ! || (do_debug_lines && streq (name, "line")) ! || (do_debug_pubnames && streq (name, "pubnames")) ! || (do_debug_aranges && streq (name, "aranges")) ! || (do_debug_ranges && streq (name, "ranges")) ! || (do_debug_frames && streq (name, "frame")) ! || (do_debug_macinfo && streq (name, "macinfo")) ! || (do_debug_str && streq (name, "str")) ! || (do_debug_loc && streq (name, "loc")) ) request_dump (i, DEBUG_DUMP); } /* linkonce section to be combined with .debug_info at link time. */ else if ((do_debugging || do_debug_info) ! && strneq (name, ".gnu.linkonce.wi.", 17)) request_dump (i, DEBUG_DUMP); ! else if (do_debug_frames && streq (name, ".eh_frame")) request_dump (i, DEBUG_DUMP); } *************** process_syminfo (FILE *file ATTRIBUTE_UN *** 6811,6817 **** } #ifdef SUPPORT_DISASSEMBLY ! static void disassemble_section (Elf_Internal_Shdr *section, FILE *file) { printf (_("\nAssembly dump of section %s\n"), --- 6824,6830 ---- } #ifdef SUPPORT_DISASSEMBLY ! static int disassemble_section (Elf_Internal_Shdr *section, FILE *file) { printf (_("\nAssembly dump of section %s\n"), *************** find_section (const char * name) *** 7051,7061 **** return NULL; } ! /* Size of pointers in the .debug_line section. This information is not ! really present in that section. It's obtained before dumping the debug ! sections by doing some pre-scan of the .debug_info section. */ ! static unsigned int * debug_line_pointer_sizes = NULL; ! static unsigned int num_debug_line_pointer_sizes = 0; /* Locate and scan the .debug_info section in the file and record the pointer sizes for the compilation units in it. Usually an executable will have --- 7065,7091 ---- return NULL; } ! /* This could just be an array of unsigned integers, but I expect ! that we will want to extend the structure to contain other ! information. */ ! typedef struct ! { ! unsigned int pointer_size; ! } ! debug_info; ! ! static debug_info * debug_information = NULL; ! static unsigned int num_debug_info_entries = 0; ! ! static unsigned int ! get_pointer_size_of_comp_unit (unsigned int comp_unit) ! { ! if (num_debug_info_entries == 0 ! || comp_unit >= num_debug_info_entries) ! return 0; ! ! return debug_information [comp_unit].pointer_size; ! } /* Locate and scan the .debug_info section in the file and record the pointer sizes for the compilation units in it. Usually an executable will have *************** static unsigned int num_debug_line_poi *** 7064,7070 **** compilation units upon success. */ static unsigned int ! get_debug_line_pointer_sizes (FILE * file) { Elf_Internal_Shdr * section; unsigned char * start; --- 7094,7100 ---- compilation units upon success. */ static unsigned int ! get_debug_info (FILE * file) { Elf_Internal_Shdr * section; unsigned char * start; *************** get_debug_line_pointer_sizes (FILE * fil *** 7074,7086 **** unsigned int num_units; unsigned int unit; section = find_section (".debug_info"); if (section == NULL) return 0; length = section->sh_size; start = get_data (NULL, file, section->sh_offset, section->sh_size, ! _("extracting pointer sizes from .debug_info section")); if (start == NULL) return 0; --- 7104,7120 ---- unsigned int num_units; unsigned int unit; + /* 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; length = section->sh_size; start = get_data (NULL, file, section->sh_offset, section->sh_size, ! _("extracting information from .debug_info section")); if (start == NULL) return 0; *************** get_debug_line_pointer_sizes (FILE * fil *** 7109,7119 **** return 0; } ! /* Then allocate an array to hold the pointer sizes. */ ! debug_line_pointer_sizes = malloc (num_units * sizeof * debug_line_pointer_sizes); ! if (debug_line_pointer_sizes == NULL) { ! error (_("Not enough memory for a pointer size array of %u entries"), num_units); free (start); return 0; --- 7143,7153 ---- 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); free (start); return 0; *************** get_debug_line_pointer_sizes (FILE * fil *** 7134,7140 **** ----------------------------- Total: 22 bytes */ ! debug_line_pointer_sizes [unit] = byte_get (begin + 22, 1); length = byte_get (begin + 4, 8); begin += length + 12; } --- 7168,7174 ---- ----------------------------- Total: 22 bytes */ ! debug_information [unit].pointer_size = byte_get (begin + 22, 1); length = byte_get (begin + 4, 8); begin += length + 12; } *************** get_debug_line_pointer_sizes (FILE * fil *** 7149,7188 **** ----------------------------- Total: 10 bytes */ ! debug_line_pointer_sizes [unit] = byte_get (begin + 10, 1); begin += length + 4; } } free (start); ! num_debug_line_pointer_sizes = num_units; ! return num_units; } static int display_debug_lines (Elf_Internal_Shdr *section, unsigned char *start, FILE *file) { - unsigned char *hdrptr; - DWARF2_Internal_LineInfo info; - unsigned char *standard_opcodes; unsigned char *data = start; unsigned char *end = start + section->sh_size; - unsigned char *end_of_sequence; - int i; - int offset_size; - int initial_length_size; unsigned int comp_unit = 0; printf (_("\nDump of debug contents of section %s:\n\n"), SECTION_NAME (section)); ! if (num_debug_line_pointer_sizes == 0) ! get_debug_line_pointer_sizes (file); while (data < end) { unsigned int pointer_size; hdrptr = data; --- 7183,7221 ---- ----------------------------- Total: 10 bytes */ ! debug_information [unit].pointer_size = byte_get (begin + 10, 1); begin += length + 4; } } free (start); ! ! return num_debug_info_entries = num_units; } 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; *************** display_debug_lines (Elf_Internal_Shdr * *** 7239,7254 **** /* Get the pointer size from the comp unit associated with this block of line number information. */ ! if (comp_unit >= num_debug_line_pointer_sizes) { error (_("Not enough comp units for .debug_line section\n")); return 0; } ! else ! { ! pointer_size = debug_line_pointer_sizes [comp_unit]; ! comp_unit ++; ! } printf (_(" Length: %ld\n"), info.li_length); printf (_(" DWARF Version: %d\n"), info.li_version); --- 7272,7284 ---- /* Get the pointer size from the comp unit associated with this block of line number information. */ ! pointer_size = get_pointer_size_of_comp_unit (comp_unit); ! if (pointer_size == 0) { error (_("Not enough comp units for .debug_line section\n")); return 0; } ! comp_unit ++; printf (_(" Length: %ld\n"), info.li_length); printf (_(" DWARF Version: %d\n"), info.li_version); *************** display_debug_loc (Elf_Internal_Shdr *se *** 8438,8445 **** return 0; } ! if (num_debug_line_pointer_sizes == 0) ! get_debug_line_pointer_sizes (file); printf (_("Contents of the .debug_loc section:\n\n")); printf (_("\n Offset Begin End Expression\n")); --- 8467,8473 ---- return 0; } ! get_debug_info (file); printf (_("Contents of the .debug_loc section:\n\n")); printf (_("\n Offset Begin End Expression\n")); *************** display_debug_loc (Elf_Internal_Shdr *se *** 8456,8471 **** /* Get the pointer size from the comp unit associated with this block of location information. */ ! if (comp_unit >= num_debug_line_pointer_sizes) { error (_("Not enough comp units for .debug_loc section\n")); return 0; } ! else ! { ! pointer_size = debug_line_pointer_sizes [comp_unit]; ! comp_unit ++; ! } while (1) { --- 8484,8496 ---- /* Get the pointer size from the comp unit associated with this block of location information. */ ! pointer_size = get_pointer_size_of_comp_unit (comp_unit); ! if (pointer_size == 0) { error (_("Not enough comp units for .debug_loc section\n")); return 0; } ! comp_unit ++; while (1) { *************** display_debug_str (Elf_Internal_Shdr *se *** 8603,8608 **** --- 8628,8783 ---- return 1; } + static const char * debug_range_contents; + static unsigned long debug_range_size; + + static void + load_debug_range (FILE *file) + { + Elf_Internal_Shdr *sec; + + /* If it is already loaded, do nothing. */ + if (debug_range_contents != NULL) + return; + + /* Locate the .debug_str section. */ + sec = find_section (".debug_ranges"); + if (sec == NULL) + return; + + debug_range_size = sec->sh_size; + + debug_range_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size, + _("debug_range section data")); + } + + static void + free_debug_range (void) + { + if (debug_range_contents == NULL) + return; + + free ((char *) debug_range_contents); + debug_range_contents = NULL; + debug_range_size = 0; + } + + + /* Decode a DW_AT_ranges attribute for 64bit DWARF3 . */ + + static void + decode_64bit_range (unsigned long offset, bfd_vma base_address) + { + const char * start = debug_range_contents + offset; + const char * end = debug_range_contents + debug_range_size; + + do + { + bfd_vma a; + bfd_vma b; + + a = byte_get ((unsigned char *) start, 8); + b = byte_get ((unsigned char *) start + 8, 8); + + if (a == 0xffffffff) + { + base_address = b; + } + else if (a == 0 && b == 0) + break; + else if (a > b) + printf (_(" [corrupt: start > end]")); + else + { + printf (" "); + print_vma (base_address + a, PREFIX_HEX); + printf (" - "); + print_vma (base_address + b, PREFIX_HEX); + printf (", "); + } + + start += 16; + } + while (start < end); + } + + /* Decode a DW_AT_ranges attribute. */ + + static void + decode_range (unsigned long offset, bfd_vma base_address) + { + const char * start; + const char * end; + + if (offset >= (debug_range_size - 8)) + { + printf (_("[corrupt: offset is outside the .debug_ranges section]")); + return; + } + + /* Since all entries in the .debug_ranges section are pairs of either + 4-byte integers (32-bit DWARF3) or 8-byte integers (64-bit DWARF3) + the offset should always be a multiple of 8 bytes. */ + if (offset % 8) + { + printf (_("[corrupt: offset is not a multiple of 8]")); + return; + } + + start = debug_range_contents + offset; + + if (offset > 0 + /* Be paranoid - check to see if the previous + two words were and end-of-range marker. */ + && (byte_get ((unsigned char *) start - 4, 4) != 0 + || byte_get ((unsigned char *) start - 8, 4) != 0)) + { + printf (_("[corrupt: offset is not at the start of a range]")); + return; + } + + end = debug_range_contents + debug_range_size; + + printf ("("); + do + { + unsigned long a; + unsigned long b; + + a = byte_get ((unsigned char *) start, 4); + b = byte_get ((unsigned char *) start + 4, 4); + + if (a == 0xffffffff) + { + if (b == 0xffffffff) + { + decode_64bit_range (offset, base_address); + return; + } + + base_address = b; + } + else if (a == 0 && b == 0) + break; + else if (a > b) + printf (_("[corrupt: start > end]")); + else + { + if (start > debug_range_contents + offset) + printf (", "); + + printf (_("0x%lx - 0x%lx"), + (unsigned long) base_address + a, + (unsigned long) base_address + b); + } + + start += 8; + } + while (start < end); + printf (")"); + } + + static unsigned char * read_and_display_attr_value (unsigned long attribute, unsigned long form, *************** read_and_display_attr_value (unsigned lo *** 8612,8617 **** --- 8787,8793 ---- unsigned long offset_size, int dwarf_version) { + static unsigned long saved_DW_AT_low_pc = 0; unsigned long uvalue = 0; unsigned char *block_start = NULL; int bytes_read; *************** read_and_display_attr_value (unsigned lo *** 8925,8935 **** printf (")"); } else if (form == DW_FORM_data4 || form == DW_FORM_data8) ! { ! printf ("("); ! printf ("location list"); ! printf (")"); ! } break; default: --- 9101,9120 ---- printf (")"); } else if (form == DW_FORM_data4 || form == DW_FORM_data8) ! printf (_("(location list)")); ! ! break; ! ! case DW_AT_low_pc: ! /* This is a hack. We keep track of the DW_AT_low_pc attributes ! and use them when decoding DW_AT_ranges attributes. The ! assumption here is that we are decoding the attributes in order ! and so the correct base address for the range is the low_pc. */ ! saved_DW_AT_low_pc = uvalue; ! break; ! ! case DW_AT_ranges: ! decode_range (uvalue, saved_DW_AT_low_pc); break; default: *************** debug_apply_rela_addends (FILE *file, *** 9007,9016 **** sym = symtab + ELF32_R_SYM (rp->r_info); if (ELF32_R_SYM (rp->r_info) != 0 ! && ELF32_ST_TYPE (sym->st_info) != STT_SECTION) { ! warn (_("Skipping unexpected symbol type %u\n"), ! ELF32_ST_TYPE (sym->st_info)); continue; } } --- 9192,9206 ---- sym = symtab + ELF32_R_SYM (rp->r_info); if (ELF32_R_SYM (rp->r_info) != 0 ! && ELF32_ST_TYPE (sym->st_info) != STT_SECTION ! /* Relocations against object symbols can happen, ! eg when referencing a global array. For an ! example of this see the _clz.o binary in libgcc.a. */ ! && ELF32_ST_TYPE (sym->st_info) != STT_OBJECT) { ! warn (_("%s: skipping unexpected symbol type %s in relocation in section .rela%s\n"), ! get_symbol_type (ELF32_ST_TYPE (sym->st_info)), ! SECTION_NAME (section)); continue; } } *************** debug_apply_rela_addends (FILE *file, *** 9019,9028 **** sym = symtab + ELF64_R_SYM (rp->r_info); if (ELF64_R_SYM (rp->r_info) != 0 ! && ELF64_ST_TYPE (sym->st_info) != STT_SECTION) { ! warn (_("Skipping unexpected symbol type %u\n"), ! ELF64_ST_TYPE (sym->st_info)); continue; } } --- 9209,9220 ---- sym = symtab + ELF64_R_SYM (rp->r_info); if (ELF64_R_SYM (rp->r_info) != 0 ! && ELF64_ST_TYPE (sym->st_info) != STT_SECTION ! && ELF64_ST_TYPE (sym->st_info) != STT_OBJECT) { ! warn (_("skipping unexpected symbol type %s in relocation in section .rela.%s\n"), ! get_symbol_type (ELF64_ST_TYPE (sym->st_info)), ! SECTION_NAME (section)); continue; } } *************** display_debug_info (Elf_Internal_Shdr *s *** 9049,9054 **** --- 9241,9247 ---- load_debug_str (file); load_debug_loc (file); + load_debug_range (file); while (start < end) { *************** display_debug_info (Elf_Internal_Shdr *s *** 9188,9193 **** --- 9381,9387 ---- } } + free_debug_range (); free_debug_str (); free_debug_loc (); *************** display_debug_aranges (Elf_Internal_Shdr *** 9292,9297 **** --- 9486,9580 ---- return 1; } + static int + display_64bit_debug_ranges (unsigned char * start, unsigned char * end) + { + bfd_vma base_address = 0; + + while (start < end) + { + bfd_vma a, b; + + a = byte_get (start, 8); + b = byte_get (start + 8, 8); + + if (a == 0xffffffffffffffffLL) + { + printf (_(" set base address to ")); + print_vma (b, PREFIX_HEX); + base_address = b; + } + else if (a == 0 && b == 0) + printf ( _("end of range")); + else if (a > b) + printf (_(" ")); + else if (base_address == 0) + { + printf ("range from base address + "); + print_vma (a, PREFIX_HEX); + printf (" to base address + "); + print_vma (b, PREFIX_HEX); + } + else + { + printf ("range from "); + print_vma (base_address + a, PREFIX_HEX); + printf (" to "); + print_vma (base_address + b, PREFIX_HEX); + } + + start += 16; + printf ("\n"); + } + + return 1; + } + + static int + display_debug_ranges (Elf_Internal_Shdr *section, + unsigned char *start, + FILE *file ATTRIBUTE_UNUSED) + { + unsigned long base_address = 0; + unsigned char *end = start + section->sh_size; + + printf (_("The section %s contains:\n\n"), SECTION_NAME (section)); + + while (start < end) + { + unsigned long a; + unsigned long b; + + a = byte_get (start, 4); + b = byte_get (start + 4, 4); + + if (a == 0xffffffff) + { + /* Attempt to handle 64-bit DWARF3 format. This assumes + that in a 32-bit DWARF3 file the base address will + never be 0xffffffff, and that the .debug_ranges section + will never contain a mixture of 32-bit and 64-bit entries. */ + if (b == 0xffffffff) + return display_64bit_debug_ranges (start, end); + + printf (_(" set base address to 0x%lx\n"), b); + base_address = b; + } + else if (a == 0 && b == 0) + printf (_(" end of range\n")); + else if (a > b) + printf (_(" \n")); + else if (base_address == 0) + printf (_(" range from base address + 0x%lx to base address + 0x%lx\n"), a, b); + else + printf (_(" range from 0x%lx to 0x%lx\n"), base_address + a, base_address + b); + + start += 8; + } + + return 1; + } + typedef struct Frame_Chunk { struct Frame_Chunk *next; *************** debug_displays[] = *** 10140,10146 **** { ".debug_str", display_debug_str }, { ".debug_loc", display_debug_loc }, { ".debug_pubtypes", display_debug_pubnames }, ! { ".debug_ranges", display_debug_not_supported }, { ".debug_static_func", display_debug_not_supported }, { ".debug_static_vars", display_debug_not_supported }, { ".debug_types", display_debug_not_supported }, --- 10423,10429 ---- { ".debug_str", display_debug_str }, { ".debug_loc", display_debug_loc }, { ".debug_pubtypes", display_debug_pubnames }, ! { ".debug_ranges", display_debug_ranges }, { ".debug_static_func", display_debug_not_supported }, { ".debug_static_vars", display_debug_not_supported }, { ".debug_types", display_debug_not_supported }, *************** display_debug_section (Elf_Internal_Shdr *** 10152,10158 **** { char *name = SECTION_NAME (section); bfd_size_type length; ! unsigned char *start; int i; length = section->sh_size; --- 10435,10441 ---- { char *name = SECTION_NAME (section); bfd_size_type length; ! int result = 1; int i; length = section->sh_size; *************** display_debug_section (Elf_Internal_Shdr *** 10162,10203 **** return 0; } ! start = get_data (NULL, file, section->sh_offset, length, ! _("debug section data")); ! if (!start) ! return 0; ! ! /* See if we know how to display the contents of this section. */ ! if (strncmp (name, ".gnu.linkonce.wi.", 17) == 0) name = ".debug_info"; for (i = NUM_ELEM (debug_displays); i--;) ! if (strcmp (debug_displays[i].name, name) == 0) { ! debug_displays[i].display (section, start, file); break; } if (i == -1) ! printf (_("Unrecognized debug section: %s\n"), name); ! ! free (start); ! ! /* If we loaded in the abbrev section at some point, ! we must release it here. */ ! free_abbrevs (); ! return 1; } ! static int process_section_contents (FILE *file) { Elf_Internal_Shdr *section; unsigned int i; if (! do_dump) ! return 1; for (i = 0, section = section_headers; i < elf_header.e_shnum && i < num_dump_sects; --- 10445,10494 ---- return 0; } ! if (strneq (name, ".gnu.linkonce.wi.", 17)) name = ".debug_info"; + /* See if we know how to display the contents of this section. */ for (i = NUM_ELEM (debug_displays); i--;) ! if (streq (debug_displays[i].name, name)) { ! unsigned char *start; ! ! start = get_data (NULL, file, section->sh_offset, length, ! _("debug section data")); ! if (start == NULL) ! { ! result = 0; ! break; ! } ! ! result &= debug_displays[i].display (section, start, file); ! free (start); ! ! /* If we loaded in the abbrev section ! at some point, we must release it here. */ ! free_abbrevs (); ! break; } if (i == -1) ! { ! printf (_("Unrecognized debug section: %s\n"), name); ! result = 0; ! } ! return result; } ! static void process_section_contents (FILE *file) { Elf_Internal_Shdr *section; unsigned int i; if (! do_dump) ! return; for (i = 0, section = section_headers; i < elf_header.e_shnum && i < num_dump_sects; *************** process_section_contents (FILE *file) *** 10214,10223 **** display_debug_section (section, file); } ! if (i < num_dump_sects) ! warn (_("Some sections were not dumped because they do not exist!\n")); ! ! return 1; } static void --- 10505,10515 ---- display_debug_section (section, file); } ! /* Check to see if the user requested a ! dump of a section that does not exist. */ ! while (i++ < num_dump_sects) ! if (dump_sects[i]) ! warn (_("Section %d was not dumped because it does not exist!\n"), i); } static void *************** process_object (char *file_name, FILE *f *** 11129,11134 **** --- 11421,11443 ---- if (show_name) printf (_("\nFile: %s\n"), file_name); + /* Initialise the dump_sects array from the cmdline_dump_sects array. + Note we do this even if cmdline_dump_sects is empty because we + must make sure that the dump_sets array is zeroed out before each + object file is processed. */ + if (num_dump_sects > num_cmdline_dump_sects) + memset (dump_sects, 0, num_dump_sects); + + if (num_cmdline_dump_sects > 0) + { + if (num_dump_sects == 0) + /* A sneaky way of allocating the dump_sects array. */ + request_dump (num_cmdline_dump_sects, 0); + + assert (num_dump_sects >= num_cmdline_dump_sects); + memcpy (dump_sects, cmdline_dump_sects, num_cmdline_dump_sects); + } + if (! process_file_header ()) return 1; *************** process_object (char *file_name, FILE *f *** 11226,11231 **** --- 11535,11547 ---- section_groups = NULL; } + if (debug_information) + { + free (debug_information); + debug_information = NULL; + num_debug_info_entries = 0; + } + return 0; } *************** int *** 11476,11483 **** main (int argc, char **argv) { int err; - char *cmdline_dump_sects = NULL; - unsigned num_cmdline_dump_sects = 0; #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) setlocale (LC_MESSAGES, ""); --- 11792,11797 ---- *************** main (int argc, char **argv) *** 11490,11502 **** parse_args (argc, argv); ! if (optind < (argc - 1)) ! show_name = 1; ! ! /* When processing more than one file remember the dump requests ! issued on command line to reset them after each file. */ ! if (optind + 1 < argc && dump_sects != NULL) { cmdline_dump_sects = malloc (num_dump_sects); if (cmdline_dump_sects == NULL) error (_("Out of memory allocating dump request table.")); --- 11804,11812 ---- parse_args (argc, argv); ! if (num_dump_sects > 0) { + /* Make a copy of the dump_sects array. */ cmdline_dump_sects = malloc (num_dump_sects); if (cmdline_dump_sects == NULL) error (_("Out of memory allocating dump request table.")); *************** main (int argc, char **argv) *** 11507,11525 **** } } err = 0; while (optind < argc) ! { ! err |= process_file (argv[optind++]); ! ! /* Reset dump requests. */ ! if (optind < argc && dump_sects != NULL) ! { ! num_dump_sects = num_cmdline_dump_sects; ! if (num_cmdline_dump_sects > 0) ! memcpy (dump_sects, cmdline_dump_sects, num_cmdline_dump_sects); ! } ! } if (dump_sects != NULL) free (dump_sects); --- 11817,11828 ---- } } + if (optind < (argc - 1)) + show_name = 1; + err = 0; while (optind < argc) ! err |= process_file (argv[optind++]); if (dump_sects != NULL) free (dump_sects); Index: binutils/doc/binutils.texi =================================================================== RCS file: /cvs/src/src/binutils/doc/binutils.texi,v retrieving revision 1.59 diff -c -3 -p -r1.59 binutils.texi *** binutils/doc/binutils.texi 26 Oct 2004 16:05:42 -0000 1.59 --- binutils/doc/binutils.texi 3 Nov 2004 10:13:22 -0000 *************** readelf [@option{-a}|@option{--all}] *** 3153,3160 **** [@option{-A}|@option{--arch-specific}] [@option{-D}|@option{--use-dynamic}] [@option{-x} |@option{--hex-dump=}] ! [@option{-w[liaprmfFso]}| ! @option{--debug-dump}[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=frames-interp,=str,=loc]] [@option{-I}|@option{-histogram}] [@option{-v}|@option{--version}] [@option{-W}|@option{--wide}] --- 3153,3160 ---- [@option{-A}|@option{--arch-specific}] [@option{-D}|@option{--use-dynamic}] [@option{-x} |@option{--hex-dump=}] ! [@option{-w[liaprmfFsoR]}| ! @option{--debug-dump}[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]] [@option{-I}|@option{-histogram}] [@option{-v}|@option{--version}] [@option{-W}|@option{--wide}] *************** symbols section. *** 3271,3278 **** @itemx --hex-dump= Displays the contents of the indicated section as a hexadecimal dump. ! @item -w[liaprmfFso] ! @itemx --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=frames-interp,=str,=loc] Displays the contents of the debug sections in the file, if any are present. If one of the optional letters or words follows the switch then only data found in those specific sections will be dumped. --- 3271,3278 ---- @itemx --hex-dump= Displays the contents of the indicated section as a hexadecimal dump. ! @item -w[liaprmfFsoR] ! @itemx --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges] Displays the contents of the debug sections in the file, if any are present. If one of the optional letters or words follows the switch then only data found in those specific sections will be dumped.