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]

Commit: Enhance 'objdump -p' to display the contents of .rsrc sections


Hi Guys,

  I am applying the attached patch to enhance objdump's -p output to
  include the contents of .rsrc sections found in COFF/PE binaries.
  This is part of a larger patch (still in development) which will
  handle the merging of .rsrc sections.

Cheers
  Nick

bfd/ChangeLog
2013-12-03  Nick Clifton  <nickc@redhat.com>

	* peXXigen.c (pe_print_resource_entries): New function: Displays
	an entry in a .rsrc section.
	(pe_print_resource_directory): New function: Displays a directory
	in a .rsrc section.
	(pe_print_rsrc): New function: Displays the contents of .rsrc
	section.
	(_bfd_XX_print_private_bfd_data_common): Call pe_print_rsrc.

binutils/testsuite/ChangeLog
2013-12-03  Nick Clifton  <nickc@redhat.com>

	* binutils-all/windres/windres.exp: Run for x86_64-pc-cygwin.
	Add test of "objump -p" output.

diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 287e4a2..b720668 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -1991,6 +1991,214 @@ pe_print_reloc (bfd * abfd, void * vfile)
   return TRUE;
 }
 
+static bfd_byte *
+pe_print_resource_directory (FILE * , bfd *, unsigned int,
+			     bfd_byte *, bfd_byte *, bfd_byte *, bfd_vma);
+
+static bfd_byte *
+pe_print_resource_entries (FILE *        file,
+			   bfd *         abfd,
+			   unsigned int  indent,
+			   bfd_boolean   is_name,
+			   bfd_byte *    data,
+			   bfd_byte *    datastart,
+			   bfd_byte *    dataend,
+			   bfd_vma       rva_bias)
+{
+  unsigned long entry, addr, size;
+
+  if (data + 8 >= dataend)
+    return dataend + 1;
+
+  fprintf (file, _("%*.s Entry: "), indent, " ");
+
+  entry = (long) bfd_get_32 (abfd, data);
+  if (is_name)
+    {
+      if (datastart + entry < dataend)
+	{
+	  unsigned int len;
+	  len = bfd_get_16 (abfd, datastart + entry);
+      
+	  fprintf (file, _("name: %08lx [%d:]"), entry, len);
+	  if (datastart + entry - rva_bias + 2 + len < dataend)
+	    fprintf (file, "%.*s", len, (char *) (datastart + entry - rva_bias + 2));
+	  else
+	    fprintf (file, _("<corrupt>"));
+	}
+      else
+	fprintf (file, _("<corrupt>"));
+    }
+  else
+    fprintf (file, _("ID: %#08lx"), entry);
+	     
+  entry = (long) bfd_get_32 (abfd, data + 4);
+  fprintf (file, _(", Value: %#08lx"), entry);
+
+  if (entry & 0x80000000)
+    {
+      fprintf (file, _(" sub-table:\n"));
+      return pe_print_resource_directory (file, abfd, indent + 1,
+					  datastart + (entry & 0x7fffffff),
+					  datastart, dataend, rva_bias);
+    }
+
+  if (datastart + entry + 16 >= dataend)
+    {
+      fprintf (file, "\n");      
+      return dataend + 1;
+    }
+
+  fprintf (file, _(" leaf: Addr: %#08lx, Size: %#08lx, Codepage: %d\n"),
+	   addr = (long) bfd_get_32 (abfd, datastart + entry),
+	   size = (long) bfd_get_32 (abfd, datastart + entry + 4),
+	   (int) bfd_get_32 (abfd, datastart + entry + 8));
+
+  /* Check that the reserved entry is 0.  */
+  if (bfd_get_32 (abfd, datastart + entry + 12) != 0
+      /* And that the data address/size is valid too.  */
+      || (datastart + addr - rva_bias + size > dataend))
+    return dataend + 1;
+
+  return datastart + addr - rva_bias + size;
+}
+
+static bfd_byte *
+pe_print_resource_directory (FILE *        file,
+			     bfd *         abfd,
+			     unsigned int  indent,
+			     bfd_byte *    data,
+			     bfd_byte *    datastart,
+			     bfd_byte *    dataend,
+			     bfd_vma       rva_bias)
+{
+  unsigned int num_names, num_ids;
+  bfd_byte * enddata = data;
+
+  if (data + 16 >= dataend)
+    return dataend + 1;
+
+  fprintf (file, "%*.s ", indent, " ");
+  switch (indent)
+    {
+    case 0: fprintf (file, "Type"); break;
+    case 2: fprintf (file, "Name"); break;
+    case 4: fprintf (file, "Language"); break;
+    default: fprintf (file, "<unknown>"); break;
+    }
+
+  fprintf (file, _(" Table: Char: %d, Time: %08lx, Ver: %d/%d, Num Names: %d, IDs: %d\n"),
+	   (int) bfd_get_32 (abfd, data),
+	   (long) bfd_get_32 (abfd, data + 4),
+	   (int)  bfd_get_16 (abfd, data + 8),
+	   (int)  bfd_get_16 (abfd, data + 10),
+	   num_names = (int) bfd_get_16 (abfd, data + 12),
+	   num_ids =   (int) bfd_get_16 (abfd, data + 14));
+  data += 16;
+
+  if (num_names)
+    {
+      while (num_names --)
+	{
+	  bfd_byte * ndata;
+	  ndata = pe_print_resource_entries (file, abfd, indent + 1, TRUE,
+					     data, datastart, dataend, rva_bias);
+	  data += 8;
+	  if (ndata > enddata)
+	    enddata = ndata;
+	  if (ndata >= dataend)
+	    break;
+	}
+    }
+
+  if (num_ids)
+    {
+      while (num_ids --)
+	{
+	  bfd_byte * ndata;
+	  ndata = pe_print_resource_entries (file, abfd, indent + 1, FALSE,
+					     data, datastart, dataend, rva_bias);
+	  data += 8;
+	  if (ndata > enddata)
+	    enddata = ndata;
+	  if (ndata >= dataend)
+	    break;
+	}
+    }
+
+  return enddata > data ? enddata : data;
+}
+
+/* Display the contents of a .rsrc section.  We do not try to
+   reproduce the resources, windres does that.  Instead we dump
+   the tables in a human readable format.  */
+
+static bfd_boolean
+pe_print_rsrc (bfd * abfd, void * vfile)
+{
+  bfd_vma rva_bias;
+  pe_data_type * pe;
+  FILE * file = (FILE *) vfile;
+  bfd_size_type datasize;
+  asection * section;
+  bfd_byte * data;
+  bfd_byte * dataend;
+  bfd_byte * datastart;
+
+
+  pe = pe_data (abfd);
+ if (pe == NULL)
+    return TRUE;
+
+ section = bfd_get_section_by_name (abfd, ".rsrc");
+ if (section == NULL)
+    return TRUE;
+
+  rva_bias = section->vma - pe->pe_opthdr.ImageBase;
+ 
+  datasize = section->size;
+  if (datasize == 0)
+    return TRUE;
+
+  if (! bfd_malloc_and_get_section (abfd, section, &data))
+    {
+      if (data != NULL)
+	free (data);
+      return FALSE;
+    }
+  datastart = data;
+  dataend = data + datasize;
+
+  fflush (file);
+  fprintf (file, "\nThe .rsrc Resource Directory section:\n");
+
+  while (data < dataend)
+    {
+      data = pe_print_resource_directory (file, abfd, 0, data, data, dataend, rva_bias);
+
+      if (data == dataend + 1)
+	fprintf (file, _("Corrupt .rsrc section detected!\n"));
+      else
+	{
+	  /* Align data before continuing.  */
+	  int align = (1 << section->alignment_power) - 1;
+	  data = (bfd_byte *) (((long) (data + align)) & ~ align);
+	  rva_bias += data - datastart;
+
+	  /* For reasons that are unclear .rsrc sections are sometimes created
+	     aligned to a 1^3 boundary even when their alignment is set at
+	     1^2.  Catch that case here before we issue a spurious warning
+	     message.  */
+	  if (data == (dataend - 4))
+	    data = dataend;
+	  else if (data < dataend)
+	    fprintf (file, _("\nWARNING: Extra data in .rsrc section - it will be ignored by Windows:\n"));
+	}
+    }
+
+  return TRUE;
+}
+
 /* Print out the program headers.  */
 
 bfd_boolean
@@ -2165,6 +2373,8 @@ _bfd_XX_print_private_bfd_data_common (bfd * abfd, void * vfile)
     pe_print_pdata (abfd, vfile);
   pe_print_reloc (abfd, vfile);
 
+  pe_print_rsrc (abfd, vfile);
+  
   return TRUE;
 }
 
diff --git a/binutils/testsuite/binutils-all/windres/windres.exp b/binutils/testsuite/binutils-all/windres/windres.exp
index 2ef73ff..9f8dd25 100644
--- a/binutils/testsuite/binutils-all/windres/windres.exp
+++ b/binutils/testsuite/binutils-all/windres/windres.exp
@@ -19,15 +19,18 @@
 
 # Written by DJ Delorie <dj@redhat.com>
 
-if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw*"] } {
+if {![istarget "i*86-*-*"] && ![istarget "x86_64-*-mingw*"] && ![istarget "x86_64-*-cygwin"] } {
+    verbose "Not a Cygwin/Mingw target" 1
     return
 }
 
 if {![info exists WINDRES]} then {
+    verbose "WINDRES not defined" 1
     return
 }
 
 if {[which $WINDRES] == 0} then {
+    verbose "$WINDRES not found" 1
     return
 }
 
@@ -139,3 +142,37 @@ foreach res $res_list {
 	file delete "tmpdir/$broot.dump"
     }
 }
+
+# Test objdump -p
+
+if {[which $OBJDUMP] == 0} then {
+    unsupported "objdump -p"
+    return
+}
+
+verbose    "$wr $cpp_opts -J rc $srcdir/$subdir/version.rc tmpdir/version.o" 1
+catch "exec $wr $cpp_opts -J rc $srcdir/$subdir/version.rc tmpdir/version.o" err
+
+if ![string match "" $err] then {
+    send_log "$err\n"
+    verbose "$err" 1
+    if [string match "*windows.h: No such file*" $err] then {
+	unsupported "objdump -p (no header files found)"
+    } else {
+	fail "objdump -p (build)"
+    }
+    continue
+}
+
+set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -p tmpdir/version.o"]
+
+# FIXME: We should extend this regexp to check for more information.
+set want ".*The .rsrc Resource Directory section.*Type Table:.*Entry: ID:.*Name Table:.*Entry: ID:.*Language Table:.*Entry: ID:.*"
+
+if ![regexp $want $got] then {
+    fail "objdump -p"
+} else {
+    pass "objdump -p"
+}
+
+# file delete "tmpdir/version.o"

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