This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Committed: Add --relocated-dump option to readelf


Hi Guys,

  I am checking in the patch below to further enhance readelf's
  ability to display debug information found in object files created
  by the MN10300 toolchain.

  In addition this patch adds a new switch to readelf:
  --relocated-dump (or -R).  This switch acts just like the --hex-dump
  switch except that relocations are applied to the content of the
  section before it is displayed.

  Tested with all the usual suspects.

Cheers
  Nick

binutils/ChangeLog
2009-06-23  Nick Clifton  <nickc@redhat.com>

	* dwarf.c (display_debug_lines_raw): Include the name of the
	section in warning message.
	(struct debug_display): Enable reloc processing for .debug_line
	and .debug_ranges sections.

	* readelf.c: Add --relocated-dump command line option to dump the
	relocated contents of a specified section.
	(request_dump): New function.
	(parse_args): Use it.
	(dump_section_as_bytes): Add parameter to indicate whether the
	contents should be relocated.
	(target_specific_reloc_handling): Add code for a R_MN10300_16
	reloc found after a R_MN10300_SYM_DIFF reloc.
	(debug_apply_relocations): Rename to apply_relocations.
	(get_section_contents): New function.  Replaces common code found
	in dump_section_as_strings and dump_section_as_bytes.
	* doc/binutils.texi: Document new command line option.
	* NEWS: Mention the new feature.

Index: binutils/NEWS
===================================================================
RCS file: /cvs/src/src/binutils/NEWS,v
retrieving revision 1.83
diff -c -3 -p -r1.83 NEWS
*** binutils/NEWS	12 Jun 2009 15:33:30 -0000	1.83
--- binutils/NEWS	24 Jun 2009 10:36:21 -0000
***************
*** 1,4 ****
--- 1,7 ----
  -*- text -*-
+ * Readelf can now display the relocated contents of a section as a sequence
+   of bytes via the --relocated-dump=<name|number> command line option.
+ 
  * The gprof program has been given a new command line option:
    --external-symbols-table=<filename> which reads in symbols from a specified
    file.
Index: binutils/dwarf.c
===================================================================
RCS file: /cvs/src/src/binutils/dwarf.c,v
retrieving revision 1.46
diff -c -3 -p -r1.46 dwarf.c
*** binutils/dwarf.c	22 Jun 2009 08:46:13 -0000	1.46
--- binutils/dwarf.c	24 Jun 2009 10:36:22 -0000
*************** display_debug_lines_raw (struct dwarf_se
*** 2145,2151 ****
        if (info.li_length + initial_length_size > section->size)
  	{
  	  warn
! 	    (_("The line info appears to be corrupt - the section is too small\n"));
  	  return 0;
  	}
  
--- 2145,2152 ----
        if (info.li_length + initial_length_size > section->size)
  	{
  	  warn
! 	    (_("The information in section %s appears to be corrupt - the section is too small\n"),
! 	     section->name);
  	  return 0;
  	}
  
*************** struct dwarf_section_display debug_displ
*** 4872,4878 ****
    { { ".debug_info",		".zdebug_info",		NULL,	NULL,	0,	0 },
      display_debug_info,			&do_debug_info,		1,	0 },
    { { ".debug_line",		".zdebug_line",		NULL,	NULL,	0,	0 },
!     display_debug_lines,		&do_debug_lines,	0,	0 },
    { { ".debug_pubnames",	".zdebug_pubnames",	NULL,	NULL,	0,	0 },
      display_debug_pubnames,		&do_debug_pubnames,	0,	0 },
    { { ".eh_frame",		"",			NULL,	NULL,	0,	0 },
--- 4873,4879 ----
    { { ".debug_info",		".zdebug_info",		NULL,	NULL,	0,	0 },
      display_debug_info,			&do_debug_info,		1,	0 },
    { { ".debug_line",		".zdebug_line",		NULL,	NULL,	0,	0 },
!     display_debug_lines,		&do_debug_lines,	1,	0 },
    { { ".debug_pubnames",	".zdebug_pubnames",	NULL,	NULL,	0,	0 },
      display_debug_pubnames,		&do_debug_pubnames,	0,	0 },
    { { ".eh_frame",		"",			NULL,	NULL,	0,	0 },
*************** struct dwarf_section_display debug_displ
*** 4886,4892 ****
    { { ".debug_pubtypes",	".zdebug_pubtypes",	NULL,	NULL,	0,	0 },
      display_debug_pubnames,		&do_debug_pubnames,	0,	0 },
    { { ".debug_ranges",		".zdebug_ranges",	NULL,	NULL,	0,	0 },
!     display_debug_ranges,		&do_debug_ranges,	0,	0 },
    { { ".debug_static_func",	".zdebug_static_func",	NULL,	NULL,	0,	0 },
      display_debug_not_supported,	NULL,			0,	0 },
    { { ".debug_static_vars",	".zdebug_static_vars",	NULL,	NULL,	0,	0 },
--- 4887,4893 ----
    { { ".debug_pubtypes",	".zdebug_pubtypes",	NULL,	NULL,	0,	0 },
      display_debug_pubnames,		&do_debug_pubnames,	0,	0 },
    { { ".debug_ranges",		".zdebug_ranges",	NULL,	NULL,	0,	0 },
!     display_debug_ranges,		&do_debug_ranges,	1,	0 },
    { { ".debug_static_func",	".zdebug_static_func",	NULL,	NULL,	0,	0 },
      display_debug_not_supported,	NULL,			0,	0 },
    { { ".debug_static_vars",	".zdebug_static_vars",	NULL,	NULL,	0,	0 },
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.448
diff -c -3 -p -r1.448 readelf.c
*** binutils/readelf.c	22 Jun 2009 08:46:13 -0000	1.448
--- binutils/readelf.c	24 Jun 2009 10:36:25 -0000
*************** static struct group ** section_headers_g
*** 214,219 ****
--- 214,220 ----
  #define DISASS_DUMP	(1 << 1)	/* The -i command line switch.  */
  #define DEBUG_DUMP	(1 << 2)	/* The -w command line switch.  */
  #define STRING_DUMP     (1 << 3)	/* The -p command line switch.  */
+ #define RELOC_DUMP      (1 << 4)	/* The -R command line switch.  */
  
  typedef unsigned char dump_type;
  
*************** static struct option options[] =
*** 2844,2854 ****
    {"unwind",	       no_argument, 0, 'u'},
    {"archive-index",    no_argument, 0, 'c'},
    {"hex-dump",	       required_argument, 0, 'x'},
!   {"debug-dump",       optional_argument, 0, OPTION_DEBUG_DUMP},
    {"string-dump",      required_argument, 0, 'p'},
  #ifdef SUPPORT_DISASSEMBLY
    {"instruction-dump", required_argument, 0, 'i'},
  #endif
  
    {"version",	       no_argument, 0, 'v'},
    {"wide",	       no_argument, 0, 'W'},
--- 2845,2856 ----
    {"unwind",	       no_argument, 0, 'u'},
    {"archive-index",    no_argument, 0, 'c'},
    {"hex-dump",	       required_argument, 0, 'x'},
!   {"relocated-dump",   required_argument, 0, 'R'},
    {"string-dump",      required_argument, 0, 'p'},
  #ifdef SUPPORT_DISASSEMBLY
    {"instruction-dump", required_argument, 0, 'i'},
  #endif
+   {"debug-dump",       optional_argument, 0, OPTION_DEBUG_DUMP},
  
    {"version",	       no_argument, 0, 'v'},
    {"wide",	       no_argument, 0, 'W'},
*************** usage (FILE * stream)
*** 2885,2890 ****
--- 2887,2894 ----
                           Dump the contents of section <number|name> as bytes\n\
    -p --string-dump=<number|name>\n\
                           Dump the contents of section <number|name> as strings\n\
+   -R --relocated-dump=<number|name>\n\
+                          Dump the contents of section <number|name> as relocated bytes\n\
    -w[lLiaprmfFsoR] or\n\
    --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
                           Display the contents of DWARF2 debug sections\n"));
*************** request_dump_byname (const char * sectio
*** 2961,2966 ****
--- 2965,2986 ----
    dump_sects_byname = new_request;
  }
  
+ static inline void
+ request_dump (dump_type type)
+ {
+   int section;
+   char * cp;
+ 
+   do_dump++;
+   section = strtoul (optarg, & cp, 0);
+ 
+   if (! *cp && section >= 0)
+     request_dump_bynumber (section, type);
+   else
+     request_dump_byname (optarg, type);
+ }
+ 
+ 
  static void
  parse_args (int argc, char ** argv)
  {
*************** parse_args (int argc, char ** argv)
*** 2970,2980 ****
      usage (stderr);
  
    while ((c = getopt_long
! 	  (argc, argv, "ADHINSVWacdeghi:lnp:rstuvw::x:", options, NULL)) != EOF)
      {
-       char * cp;
-       int section;
- 
        switch (c)
  	{
  	case 0:
--- 2990,2997 ----
      usage (stderr);
  
    while ((c = getopt_long
! 	  (argc, argv, "ADHINR:SVWacdeghi:lnp:rstuvw::x:", options, NULL)) != EOF)
      {
        switch (c)
  	{
  	case 0:
*************** parse_args (int argc, char ** argv)
*** 3048,3067 ****
  	  do_archive_index++;
  	  break;
  	case 'x':
! 	  do_dump++;
! 	  section = strtoul (optarg, & cp, 0);
! 	  if (! *cp && section >= 0)
! 	    request_dump_bynumber (section, HEX_DUMP);
! 	  else
! 	    request_dump_byname (optarg, HEX_DUMP);
  	  break;
  	case 'p':
! 	  do_dump++;
! 	  section = strtoul (optarg, & cp, 0);
! 	  if (! *cp && section >= 0)
! 	    request_dump_bynumber (section, STRING_DUMP);
! 	  else
! 	    request_dump_byname (optarg, STRING_DUMP);
  	  break;
  	case 'w':
  	  do_dump++;
--- 3065,3077 ----
  	  do_archive_index++;
  	  break;
  	case 'x':
! 	  request_dump (HEX_DUMP);
  	  break;
  	case 'p':
! 	  request_dump (STRING_DUMP);
! 	  break;
! 	case 'R':
! 	  request_dump (RELOC_DUMP);
  	  break;
  	case 'w':
  	  do_dump++;
*************** parse_args (int argc, char ** argv)
*** 3088,3099 ****
  	  break;
  #ifdef SUPPORT_DISASSEMBLY
  	case 'i':
! 	  do_dump++;
! 	  section = strtoul (optarg, & cp, 0);
! 	  if (! *cp && section >= 0)
! 	    request_dump_bynumber (section, DISASS_DUMP);
! 	  else
! 	    request_dump_byname (optarg, DISASS_DUMP);
  #endif
  	case 'v':
  	  print_version (program_name);
--- 3098,3105 ----
  	  break;
  #ifdef SUPPORT_DISASSEMBLY
  	case 'i':
! 	  request_dump (DISASS_DUMP);
! 	  break;
  #endif
  	case 'v':
  	  print_version (program_name);
*************** process_syminfo (FILE * file ATTRIBUTE_U
*** 7759,7948 ****
    return 1;
  }
  
! #ifdef SUPPORT_DISASSEMBLY
! static int
! disassemble_section (Elf_Internal_Shdr * section, FILE * file)
! {
!   printf (_("\nAssembly dump of section %s\n"),
! 	  SECTION_NAME (section));
! 
!   /* XXX -- to be done --- XXX */
! 
!   return 1;
! }
! #endif
! 
! static int
! dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
! {
!   Elf_Internal_Shdr * relsec;
!   bfd_size_type num_bytes;
!   bfd_vma addr;
!   char * data;
!   char * end;
!   char * start;
!   char * name = SECTION_NAME (section);
!   bfd_boolean some_strings_shown;
! 
!   num_bytes = section->sh_size;
! 
!   if (num_bytes == 0 || section->sh_type == SHT_NOBITS)
!     {
!       printf (_("\nSection '%s' has no data to dump.\n"), name);
!       return 0;
!     }
! 
!   addr = section->sh_addr;
! 
!   start = get_data (NULL, file, section->sh_offset, 1, num_bytes,
! 		    _("section data"));
!   if (!start)
!     return 0;
! 
!   printf (_("\nString dump of section '%s':\n"), name);
! 
!   /* If the section being dumped has relocations against it the user might
!      be expecting these relocations to have been applied.  Check for this
!      case and issue a warning message in order to avoid confusion.
!      FIXME: Maybe we ought to have an option that dumps a section with
!      relocs applied ?  */
!   for (relsec = section_headers;
!        relsec < section_headers + elf_header.e_shnum;
!        ++relsec)
!     {
!       if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
! 	  || relsec->sh_info >= elf_header.e_shnum
! 	  || section_headers + relsec->sh_info != section
! 	  || relsec->sh_size == 0
! 	  || relsec->sh_link >= elf_header.e_shnum)
! 	continue;
! 
!       printf (_("  Note: This section has relocations against it, but these have NOT been applied to this dump.\n"));
!       break;
!     }
! 
!   data = start;
!   end  = start + num_bytes;
!   some_strings_shown = FALSE;
! 
!   while (data < end)
!     {
!       while (!ISPRINT (* data))
! 	if (++ data >= end)
! 	  break;
! 
!       if (data < end)
! 	{
! #ifndef __MSVCRT__
! 	  printf ("  [%6tx]  %s\n", data - start, data);
! #else
! 	  printf ("  [%6Ix]  %s\n", (size_t) (data - start), data);
! #endif
! 	  data += strlen (data);
! 	  some_strings_shown = TRUE;
! 	}
!     }
! 
!   if (! some_strings_shown)
!     printf (_("  No strings found in this section."));
! 
!   free (start);
! 
!   putchar ('\n');
!   return 1;
! }
! 
  
! static int
! dump_section_as_bytes (Elf_Internal_Shdr * section, FILE * file)
  {
!   Elf_Internal_Shdr * relsec;
!   bfd_size_type bytes;
!   bfd_vma addr;
!   unsigned char * data;
!   unsigned char * start;
! 
!   bytes = section->sh_size;
! 
!   if (bytes == 0 || section->sh_type == SHT_NOBITS)
!     {
!       printf (_("\nSection '%s' has no data to dump.\n"),
! 	      SECTION_NAME (section));
!       return 0;
!     }
!   else
!     printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
! 
!   addr = section->sh_addr;
! 
!   start = get_data (NULL, file, section->sh_offset, 1, bytes,
! 		    _("section data"));
!   if (!start)
!     return 0;
! 
!   /* If the section being dumped has relocations against it the user might
!      be expecting these relocations to have been applied.  Check for this
!      case and issue a warning message in order to avoid confusion.
!      FIXME: Maybe we ought to have an option that dumps a section with
!      relocs applied ?  */
!   for (relsec = section_headers;
!        relsec < section_headers + elf_header.e_shnum;
!        ++relsec)
!     {
!       if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
! 	  || relsec->sh_info >= elf_header.e_shnum
! 	  || section_headers + relsec->sh_info != section
! 	  || relsec->sh_size == 0
! 	  || relsec->sh_link >= elf_header.e_shnum)
! 	continue;
! 
!       printf (_(" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n"));
!       break;
!     }
! 
!   data = start;
  
!   while (bytes)
      {
!       int j;
!       int k;
!       int lbytes;
! 
!       lbytes = (bytes > 16 ? 16 : bytes);
! 
!       printf ("  0x%8.8lx ", (unsigned long) addr);
! 
!       for (j = 0; j < 16; j++)
! 	{
! 	  if (j < lbytes)
! 	    printf ("%2.2x", data[j]);
! 	  else
! 	    printf ("  ");
  
! 	  if ((j & 3) == 3)
! 	    printf (" ");
! 	}
  
!       for (j = 0; j < lbytes; j++)
! 	{
! 	  k = data[j];
! 	  if (k >= ' ' && k < 0x7f)
! 	    printf ("%c", k);
! 	  else
! 	    printf (".");
! 	}
  
!       putchar ('\n');
  
!       data  += lbytes;
!       addr  += lbytes;
!       bytes -= lbytes;
      }
  
!   free (start);
! 
!   putchar ('\n');
!   return 1;
  }
  
  /* Returns TRUE iff RELOC_TYPE is a 32-bit absolute RELA relocation used in
--- 7765,7821 ----
    return 1;
  }
  
! /* Check to see if the given reloc needs to be handled in a target specific
!    manner.  If so then process the reloc and return TRUE otherwise return
!    FALSE.  */
  
! static bfd_boolean
! target_specific_reloc_handling (Elf_Internal_Rela * reloc,
! 				unsigned char *     start,
! 				Elf_Internal_Sym *  symtab)
  {
!   unsigned int reloc_type = get_reloc_type (reloc->r_info);
  
!   switch (elf_header.e_machine)
      {
!     case EM_MN10300:
!     case EM_CYGNUS_MN10300:
!       {
! 	static Elf_Internal_Sym * saved_sym = NULL;
  
! 	switch (reloc_type)
! 	  {
! 	  case 34: /* R_MN10300_ALIGN */
! 	    return TRUE;
! 	  case 33: /* R_MN10300_SYM_DIFF */
! 	    saved_sym = symtab + get_reloc_symindex (reloc->r_info);
! 	    return TRUE;
! 	  case 1: /* R_MN10300_32 */
! 	  case 2: /* R_MN10300_16 */
! 	    if (saved_sym != NULL)
! 	      {
! 		bfd_vma value;
  
! 		value = reloc->r_addend
! 		  + (symtab[get_reloc_symindex (reloc->r_info)].st_value
! 		     - saved_sym->st_value);
  
! 		byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2);
  
! 		saved_sym = NULL;
! 		return TRUE;
! 	      }
! 	    break;
! 	  default:
! 	    if (saved_sym != NULL)
! 	      error (_("Unhandled MN10300 reloc type found after SYM_DIFF reloc"));
! 	    break;
! 	  }
! 	break;
!       }
      }
  
!   return FALSE;
  }
  
  /* Returns TRUE iff RELOC_TYPE is a 32-bit absolute RELA relocation used in
*************** is_32bit_pcrel_reloc (unsigned int reloc
*** 8130,8137 ****
        /* Do not abort or issue an error message here.  Not all targets use
  	 pc-relative 32-bit relocs in their DWARF debug information and we
  	 have already tested for target coverage in is_32bit_abs_reloc.  A
! 	 more helpful warning message will be generated by
! 	 debug_apply_relocations anyway, so just return.  */
        return FALSE;
      }
  }
--- 8003,8010 ----
        /* Do not abort or issue an error message here.  Not all targets use
  	 pc-relative 32-bit relocs in their DWARF debug information and we
  	 have already tested for target coverage in is_32bit_abs_reloc.  A
! 	 more helpful warning message will be generated by apply_relocations
! 	 anyway, so just return.  */
        return FALSE;
      }
  }
*************** is_none_reloc (unsigned int reloc_type)
*** 8265,8405 ****
    return FALSE;
  }
  
! /* Uncompresses a section that was compressed using zlib, in place.
!    This is a copy of bfd_uncompress_section_contents, in bfd/compress.c  */
  
! static int
! uncompress_section_contents (unsigned char ** buffer, dwarf_size_type * size)
  {
! #ifndef HAVE_ZLIB_H
!   /* These are just to quiet gcc.  */
!   buffer = 0;
!   size = 0;
!   return FALSE;
! #else
!   dwarf_size_type compressed_size = *size;
!   unsigned char * compressed_buffer = *buffer;
!   dwarf_size_type uncompressed_size;
!   unsigned char * uncompressed_buffer;
!   z_stream strm;
!   int rc;
!   dwarf_size_type header_size = 12;
! 
!   /* Read the zlib header.  In this case, it should be "ZLIB" followed
!      by the uncompressed section size, 8 bytes in big-endian order.  */
!   if (compressed_size < header_size
!       || ! streq ((char *) compressed_buffer, "ZLIB"))
!     return 0;
  
!   uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
!   uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
!   uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
!   uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
!   uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
!   uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
!   uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
!   uncompressed_size += compressed_buffer[11];
  
!   /* It is possible the section consists of several compressed
!      buffers concatenated together, so we uncompress in a loop.  */
!   strm.zalloc = NULL;
!   strm.zfree = NULL;
!   strm.opaque = NULL;
!   strm.avail_in = compressed_size - header_size;
!   strm.next_in = (Bytef *) compressed_buffer + header_size;
!   strm.avail_out = uncompressed_size;
!   uncompressed_buffer = xmalloc (uncompressed_size);
! 
!   rc = inflateInit (& strm);
!   while (strm.avail_in > 0)
!     {
!       if (rc != Z_OK)
!         goto fail;
!       strm.next_out = ((Bytef *) uncompressed_buffer
!                        + (uncompressed_size - strm.avail_out));
!       rc = inflate (&strm, Z_FINISH);
!       if (rc != Z_STREAM_END)
!         goto fail;
!       rc = inflateReset (& strm);
!     }
!   rc = inflateEnd (& strm);
!   if (rc != Z_OK
!       || strm.avail_out != 0)
!     goto fail;
! 
!   free (compressed_buffer);
!   *buffer = uncompressed_buffer;
!   *size = uncompressed_size;
!   return 1;
! 
!  fail:
!   free (uncompressed_buffer);
!   return 0;
! #endif  /* HAVE_ZLIB_H */
! }
! 
! /* Check to see if the given reloc needs to be handled in a target specific
!    manner.  If so then process the reloc and return TRUE otherwise return
!    FALSE.  */
! 
! static bfd_boolean
! target_specific_reloc_handling (Elf_Internal_Rela * reloc,
! 				unsigned char *     start,
! 				Elf_Internal_Sym *  symtab)
! {
!   unsigned int reloc_type = get_reloc_type (reloc->r_info);
! 
!   switch (elf_header.e_machine)
!     {
!     case EM_MN10300:
!     case EM_CYGNUS_MN10300:
!       {
! 	static Elf_Internal_Sym * saved_sym = NULL;
! 
! 	switch (reloc_type)
! 	  {
! 	  case 34: /* R_MN10300_ALIGN */
! 	    return TRUE;
! 	  case 33: /* R_MN10300_SYM_DIFF */
! 	    saved_sym = symtab + get_reloc_symindex (reloc->r_info);
! 	    return TRUE;
! 	  case 1: /* R_MN10300_32 */
! 	    if (saved_sym != NULL)
! 	      {
! 		bfd_vma value;
! 
! 		value = reloc->r_addend
! 		  + (symtab[get_reloc_symindex (reloc->r_info)].st_value
! 		     - saved_sym->st_value);
! 
! 		byte_put (start + reloc->r_offset, value, 4);
! 
! 		saved_sym = NULL;
! 		return TRUE;
! 	      }
! 	    break;
! 	  }
! 	break;
!       }
!     }
! 
!   return FALSE;
! }
! 
! /* Apply relocations to a debug section.  */
! 
! static void
! debug_apply_relocations (void * file,
! 			 Elf_Internal_Shdr * section,
! 			 unsigned char * start)
! {
!   Elf_Internal_Shdr * relsec;
!   unsigned char * end = start + section->sh_size;
! 
!   if (elf_header.e_type != ET_REL)
!     return;
! 
!   /* Find the reloc section associated with the debug section.  */
    for (relsec = section_headers;
         relsec < section_headers + elf_header.e_shnum;
         ++relsec)
--- 8138,8160 ----
    return FALSE;
  }
  
! /* Apply relocations to a section.
!    Note: So far support has been added only for those relocations
!    which can be found in debug sections.
!    FIXME: Add support for more relocations ?  */
  
! static void
! apply_relocations (void * file,
! 		   Elf_Internal_Shdr * section,
! 		   unsigned char * start)
  {
!   Elf_Internal_Shdr * relsec;
!   unsigned char * end = start + section->sh_size;
  
!   if (elf_header.e_type != ET_REL)
!     return;
  
!   /* Find the reloc section associated with the section.  */
    for (relsec = section_headers;
         relsec < section_headers + elf_header.e_shnum;
         ++relsec)
*************** debug_apply_relocations (void * file,
*** 8524,8529 ****
--- 8279,8552 ----
      }
  }
  
+ #ifdef SUPPORT_DISASSEMBLY
+ static int
+ disassemble_section (Elf_Internal_Shdr * section, FILE * file)
+ {
+   printf (_("\nAssembly dump of section %s\n"),
+ 	  SECTION_NAME (section));
+ 
+   /* XXX -- to be done --- XXX */
+ 
+   return 1;
+ }
+ #endif
+ 
+ /* Reads in the contents of SECTION from FILE, returning a pointer
+    to a malloc'ed buffer or NULL if something went wrong.  */
+ 
+ static char *
+ get_section_contents (Elf_Internal_Shdr * section, FILE * file)
+ {
+   bfd_size_type num_bytes;
+ 
+   num_bytes = section->sh_size;
+ 
+   if (num_bytes == 0 || section->sh_type == SHT_NOBITS)
+     {
+       printf (_("\nSection '%s' has no data to dump.\n"),
+ 	      SECTION_NAME (section));
+       return NULL;
+     }
+ 
+   return get_data (NULL, file, section->sh_offset, 1, num_bytes,
+ 		   _("section contents"));
+ }
+ 
+ 		      
+ static void
+ dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
+ {
+   Elf_Internal_Shdr * relsec;
+   bfd_size_type num_bytes;
+   bfd_vma addr;
+   char * data;
+   char * end;
+   char * start;
+   char * name = SECTION_NAME (section);
+   bfd_boolean some_strings_shown;
+ 
+   start = get_section_contents (section, file);
+   if (start == NULL)
+     return;
+ 
+   printf (_("\nString dump of section '%s':\n"), name);
+ 
+   /* If the section being dumped has relocations against it the user might
+      be expecting these relocations to have been applied.  Check for this
+      case and issue a warning message in order to avoid confusion.
+      FIXME: Maybe we ought to have an option that dumps a section with
+      relocs applied ?  */
+   for (relsec = section_headers;
+        relsec < section_headers + elf_header.e_shnum;
+        ++relsec)
+     {
+       if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
+ 	  || relsec->sh_info >= elf_header.e_shnum
+ 	  || section_headers + relsec->sh_info != section
+ 	  || relsec->sh_size == 0
+ 	  || relsec->sh_link >= elf_header.e_shnum)
+ 	continue;
+ 
+       printf (_("  Note: This section has relocations against it, but these have NOT been applied to this dump.\n"));
+       break;
+     }
+ 
+   num_bytes = section->sh_size;
+   addr = section->sh_addr;
+   data = start;
+   end  = start + num_bytes;
+   some_strings_shown = FALSE;
+ 
+   while (data < end)
+     {
+       while (!ISPRINT (* data))
+ 	if (++ data >= end)
+ 	  break;
+ 
+       if (data < end)
+ 	{
+ #ifndef __MSVCRT__
+ 	  printf ("  [%6tx]  %s\n", data - start, data);
+ #else
+ 	  printf ("  [%6Ix]  %s\n", (size_t) (data - start), data);
+ #endif
+ 	  data += strlen (data);
+ 	  some_strings_shown = TRUE;
+ 	}
+     }
+ 
+   if (! some_strings_shown)
+     printf (_("  No strings found in this section."));
+ 
+   free (start);
+ 
+   putchar ('\n');
+ }
+ 
+ static void
+ dump_section_as_bytes (Elf_Internal_Shdr * section,
+ 		       FILE * file,
+ 		       bfd_boolean relocate)
+ {
+   Elf_Internal_Shdr * relsec;
+   bfd_size_type bytes;
+   bfd_vma addr;
+   unsigned char * data;
+   unsigned char * start;
+ 
+   start = (unsigned char *) get_section_contents (section, file);
+   if (start == NULL)
+     return;
+ 
+   printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
+ 
+   if (relocate)
+     {
+       apply_relocations (file, section, start);
+     }
+   else
+     {
+       /* If the section being dumped has relocations against it the user might
+ 	 be expecting these relocations to have been applied.  Check for this
+ 	 case and issue a warning message in order to avoid confusion.
+ 	 FIXME: Maybe we ought to have an option that dumps a section with
+ 	 relocs applied ?  */
+       for (relsec = section_headers;
+ 	   relsec < section_headers + elf_header.e_shnum;
+ 	   ++relsec)
+ 	{
+ 	  if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
+ 	      || relsec->sh_info >= elf_header.e_shnum
+ 	      || section_headers + relsec->sh_info != section
+ 	      || relsec->sh_size == 0
+ 	      || relsec->sh_link >= elf_header.e_shnum)
+ 	    continue;
+ 
+ 	  printf (_(" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n"));
+ 	  break;
+ 	}
+     }
+ 
+   addr = section->sh_addr;
+   bytes = section->sh_size;
+   data = start;
+ 
+   while (bytes)
+     {
+       int j;
+       int k;
+       int lbytes;
+ 
+       lbytes = (bytes > 16 ? 16 : bytes);
+ 
+       printf ("  0x%8.8lx ", (unsigned long) addr);
+ 
+       for (j = 0; j < 16; j++)
+ 	{
+ 	  if (j < lbytes)
+ 	    printf ("%2.2x", data[j]);
+ 	  else
+ 	    printf ("  ");
+ 
+ 	  if ((j & 3) == 3)
+ 	    printf (" ");
+ 	}
+ 
+       for (j = 0; j < lbytes; j++)
+ 	{
+ 	  k = data[j];
+ 	  if (k >= ' ' && k < 0x7f)
+ 	    printf ("%c", k);
+ 	  else
+ 	    printf (".");
+ 	}
+ 
+       putchar ('\n');
+ 
+       data  += lbytes;
+       addr  += lbytes;
+       bytes -= lbytes;
+     }
+ 
+   free (start);
+ 
+   putchar ('\n');
+ }
+ 
+ /* Uncompresses a section that was compressed using zlib, in place.
+    This is a copy of bfd_uncompress_section_contents, in bfd/compress.c  */
+ 
+ static int
+ uncompress_section_contents (unsigned char ** buffer, dwarf_size_type * size)
+ {
+ #ifndef HAVE_ZLIB_H
+   /* These are just to quiet gcc.  */
+   buffer = 0;
+   size = 0;
+   return FALSE;
+ #else
+   dwarf_size_type compressed_size = *size;
+   unsigned char * compressed_buffer = *buffer;
+   dwarf_size_type uncompressed_size;
+   unsigned char * uncompressed_buffer;
+   z_stream strm;
+   int rc;
+   dwarf_size_type header_size = 12;
+ 
+   /* Read the zlib header.  In this case, it should be "ZLIB" followed
+      by the uncompressed section size, 8 bytes in big-endian order.  */
+   if (compressed_size < header_size
+       || ! streq ((char *) compressed_buffer, "ZLIB"))
+     return 0;
+ 
+   uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
+   uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
+   uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
+   uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
+   uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
+   uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
+   uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
+   uncompressed_size += compressed_buffer[11];
+ 
+   /* It is possible the section consists of several compressed
+      buffers concatenated together, so we uncompress in a loop.  */
+   strm.zalloc = NULL;
+   strm.zfree = NULL;
+   strm.opaque = NULL;
+   strm.avail_in = compressed_size - header_size;
+   strm.next_in = (Bytef *) compressed_buffer + header_size;
+   strm.avail_out = uncompressed_size;
+   uncompressed_buffer = xmalloc (uncompressed_size);
+ 
+   rc = inflateInit (& strm);
+   while (strm.avail_in > 0)
+     {
+       if (rc != Z_OK)
+         goto fail;
+       strm.next_out = ((Bytef *) uncompressed_buffer
+                        + (uncompressed_size - strm.avail_out));
+       rc = inflate (&strm, Z_FINISH);
+       if (rc != Z_STREAM_END)
+         goto fail;
+       rc = inflateReset (& strm);
+     }
+   rc = inflateEnd (& strm);
+   if (rc != Z_OK
+       || strm.avail_out != 0)
+     goto fail;
+ 
+   free (compressed_buffer);
+   *buffer = uncompressed_buffer;
+   *size = uncompressed_size;
+   return 1;
+ 
+  fail:
+   free (uncompressed_buffer);
+   return 0;
+ #endif  /* HAVE_ZLIB_H */
+ }
+ 
  static int
  load_specific_debug_section (enum dwarf_section_display_enum debug,
  			     Elf_Internal_Shdr * sec, void * file)
*************** load_specific_debug_section (enum dwarf_
*** 8551,8557 ****
        return 0;
  
    if (debug_displays [debug].relocate)
!     debug_apply_relocations (file, sec, section->start);
  
    return 1;
  }
--- 8574,8580 ----
        return 0;
  
    if (debug_displays [debug].relocate)
!     apply_relocations (file, sec, section->start);
  
    return 1;
  }
*************** process_section_contents (FILE * file)
*** 8700,8712 ****
  	disassemble_section (section, file);
  #endif
        if (dump_sects[i] & HEX_DUMP)
! 	dump_section_as_bytes (section, file);
  
!       if (dump_sects[i] & DEBUG_DUMP)
! 	display_debug_section (section, file);
  
        if (dump_sects[i] & STRING_DUMP)
  	dump_section_as_strings (section, file);
      }
  
    /* Check to see if the user requested a
--- 8723,8738 ----
  	disassemble_section (section, file);
  #endif
        if (dump_sects[i] & HEX_DUMP)
! 	dump_section_as_bytes (section, file, FALSE);
  
!       if (dump_sects[i] & RELOC_DUMP)
! 	dump_section_as_bytes (section, file, TRUE);
  
        if (dump_sects[i] & STRING_DUMP)
  	dump_section_as_strings (section, file);
+ 
+       if (dump_sects[i] & DEBUG_DUMP)
+ 	display_debug_section (section, file);
      }
  
    /* Check to see if the user requested a
Index: binutils/doc/binutils.texi
===================================================================
RCS file: /cvs/src/src/binutils/doc/binutils.texi,v
retrieving revision 1.148
diff -c -3 -p -r1.148 binutils.texi
*** binutils/doc/binutils.texi	18 Jun 2009 10:31:21 -0000	1.148
--- binutils/doc/binutils.texi	24 Jun 2009 10:36:27 -0000
*************** readelf [@option{-a}|@option{--all}]
*** 3844,3849 ****
--- 3844,3850 ----
          [@option{-D}|@option{--use-dynamic}]
          [@option{-x} <number or name>|@option{--hex-dump=}<number or name>]
          [@option{-p} <number or name>|@option{--string-dump=}<number or name>]
+         [@option{-R} <number or name>|@option{--relocated-dump=}<number or name>]
          [@option{-c}|@option{--archive-index}]
          [@option{-w[lLiaprmfFsoR]}|
           @option{--debug-dump}[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]]
*************** symbols section.
*** 3966,3975 ****
  
  @item -x <number or name>
  @itemx --hex-dump=<number or name>
! Displays the contents of the indicated section as a hexadecimal dump.
  A number identifies a particular section by index in the section table;
  any other string identifies all sections with that name in the object file.
  
  @item -p <number or name>
  @itemx --string-dump=<number or name>
  Displays the contents of the indicated section as printable strings.
--- 3967,3984 ----
  
  @item -x <number or name>
  @itemx --hex-dump=<number or name>
! Displays the contents of the indicated section as a hexadecimal bytes.
  A number identifies a particular section by index in the section table;
  any other string identifies all sections with that name in the object file.
  
+ @item -R <number or name>
+ @itemx --relocated-dump=<number or name>
+ Displays the contents of the indicated section as a hexadecimal
+ bytes.  A number identifies a particular section by index in the
+ section table; any other string identifies all sections with that name
+ in the object file.  The contents of the section will be relocated
+ before they are displayed.
+ 
  @item -p <number or name>
  @itemx --string-dump=<number or name>
  Displays the contents of the indicated section as printable strings.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]