public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Commit: Improve .rsrc section merging.
@ 2014-03-19 15:20 Nick Clifton
  0 siblings, 0 replies; only message in thread
From: Nick Clifton @ 2014-03-19 15:20 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 673 bytes --]

Hi Guys,

  Following on from my previous update to the .rsrc section merging
  code, I am committing a second patch that improves the algorithm
  further.  This time it should be able to cope with all sizes of input
  .rsrc section.

Cheers
  Nick

bfd/ChangeLog
2014-03-19  Nick Clifton  <nickc@redhat.com>

	* peXXigen.c (rsrc_process_section): Add code to scan input
	sections and record their lengths.  Use these lengths to find the
	start of each merged .rsrc section.

ld/ChangeLog
2014-03-19  Nick Clifton  <nickc@redhat.com>

	* scripttempl/pe.sc (R_RSRC): Fix default-manifest exclusion.
	(.rsrc): Add SUBALIGN(4).  Remove SORT.
	* scripttempl/pep.sc: Likewise.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: rsrc_merge.patch --]
[-- Type: text/x-patch, Size: 8186 bytes --]

diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index e53d6c7..6d95827 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -3477,63 +3477,6 @@ rsrc_merge (struct rsrc_entry * a, struct rsrc_entry * b)
   rsrc_sort_entries (& adir->ids, FALSE, adir);
 }
 
-static bfd_byte *
-rsrc_align (bfd * abfd, bfd_byte * data, bfd_byte * dataend)
-{
-  ptrdiff_t d;
-
-  /* Align the data pointer - we no longer have access to the original sections
-     so we do not know the alignment value they used.  We default to 1^2 alignment
-     but check to see if 1^3 is better.  */
-  d = (ptrdiff_t) data;
-  d = (d + 3) & ~3;
-
-  if ((bfd_byte *) d == (dataend - 4))
-    return dataend;
-      
-  if ((d & 0x4) == 0)
-    return (bfd_byte *) d;
-
-  /* Aligning to 1^3 would change the value of the pointer.  See if the
-     next 16 bytes (without aligning to 1^3) would form a valid Resource
-     Directory Table.  If not then increase the alignment.  */
-  data = (bfd_byte *) d;
-
-  if (data + 16 >= dataend)
-    /* Not enough room left for a resource table anyway.  Just stop.  */
-    return dataend;
-
-  if (bfd_get_32 (abfd, data) != 0)
-    /* A non-zero characteristics field.  This should not happen.
-       Possibly the padding between merged .rsrc sections was not zero.
-       Choose to advance the pointer.  */
-    return (bfd_byte *) (d + 4);
-
-  if (bfd_get_32 (abfd, data + 4) != 0)
-    /* A non-zero time field.  It cannot be the characteristics field
-       of a 1^3 aligned .rsrc section because the characteristics are
-       always zero.   Hence we should not increase the alignment.  */
-    return (bfd_byte *) d;
-
-  /* Looking at bytes 8..11 does not help.  These are either the time stamp
-     or the version fields.  They can both have arbitary values, and zero
-     is quite commmon, so we have no way to distinguish them.  */
-
-  /* Bytes 12..15 are either the version values or the number of entries
-     to follow.  If the value is zero then this must be the version fields,
-     since we must always have at least one entry.  A non-zero value on the
-     other hand is ambiguous.  */
-  if (bfd_get_32 (abfd, data + 12) == 0)
-    return (bfd_byte *) (d + 4);
-
-  /* Ho Hum, we have no easy way to resolve this problem, so punt for now.
-     FIXME: try parsing the entire remaining .rsrc section.  If it fails,
-     try re-aligning data and reparsing.  If that works go with the new
-     alignment.  Note - this has the potential to be dangerously recursive.  */
-
-  return (bfd_byte *) d;
-}
-
 /* Check the .rsrc section.  If it contains multiple concatenated
    resources then we must merge them properly.  Otherwise Windows
    will ignore all but the first set.  */
@@ -3555,6 +3498,10 @@ rsrc_process_section (bfd * abfd,
   rsrc_directory *  type_tables;
   rsrc_write_data   write_data;
   unsigned int      indx;
+  bfd *             input;
+  unsigned int      num_input_rsrc = 0;
+  unsigned int      max_num_input_rsrc = 4;
+  ptrdiff_t *       rsrc_sizes = NULL;
 
   new_table.names.num_entries = 0;
   new_table.ids.num_entries = 0;
@@ -3577,6 +3524,44 @@ rsrc_process_section (bfd * abfd,
   if (! bfd_get_section_contents (abfd, sec, data, 0, size))
     goto end;
 
+  /* Step zero: Scan the input bfds looking for .rsrc sections and record
+     their lengths.  Note - we rely upon the fact that the linker script
+     does *not* sort the input .rsrc sections, so that the order in the
+     linkinfo list matches the order in the output .rsrc section.
+
+     We need to know the lengths because each input .rsrc section has padding
+     at the end of a variable amount.  (It does not appear to be based upon
+     the section alignment or the file alignment).  We need to skip any
+     padding bytes when parsing the input .rsrc sections.  */
+  rsrc_sizes = bfd_malloc (max_num_input_rsrc * sizeof * rsrc_sizes);
+  if (rsrc_sizes == NULL)
+    goto end;
+
+  for (input = pfinfo->info->input_bfds;
+       input != NULL;
+       input = input->link_next)
+    {
+      asection * rsrc_sec = bfd_get_section_by_name (input, ".rsrc");
+
+      if (rsrc_sec != NULL)
+	{
+	  if (num_input_rsrc == max_num_input_rsrc)
+	    {
+	      max_num_input_rsrc += 10;
+	      rsrc_sizes = bfd_realloc (rsrc_sizes, max_num_input_rsrc
+					* sizeof * rsrc_sizes);
+	      if (rsrc_sizes == NULL)
+		goto end;
+	    }
+
+	  BFD_ASSERT (rsrc_sec->size > 0);
+	  rsrc_sizes [num_input_rsrc ++] = rsrc_sec->size;
+	}
+    }
+
+  if (num_input_rsrc < 2)
+    goto end;
+  
   /* Step one: Walk the section, computing the size of the tables,
      leaves and data and decide if we need to do anything.  */
   dataend = data + size;
@@ -3598,14 +3583,21 @@ rsrc_process_section (bfd * abfd,
 	  goto end;
 	}
 
-      data = rsrc_align (abfd, data, dataend);
+      if ((data - p) > rsrc_sizes [num_resource_sets])
+	{
+	  _bfd_error_handler (_("%s: .rsrc merge failure: unexpected .rsrc size"),
+			      bfd_get_filename (abfd));
+	  bfd_set_error (bfd_error_file_truncated);
+	  goto end;
+	}
+      /* FIXME: Should we add a check for "data - p" being much smaller
+	 than rsrc_sizes[num_resource_sets] ?  */
+
+      data = p + rsrc_sizes[num_resource_sets];
       rva_bias += data - p;
       ++ num_resource_sets;
     }
-
-  if (num_resource_sets < 2)
-    /* No merging necessary.  */
-    goto end;
+  BFD_ASSERT (num_resource_sets == num_input_rsrc);
 
   /* Step two: Walk the data again, building trees of the resources.  */
   data = datastart;
@@ -3620,11 +3612,11 @@ rsrc_process_section (bfd * abfd,
     {
       bfd_byte * p = data;
 
-      data = rsrc_parse_directory (abfd, type_tables + indx, data, data,
+      (void) rsrc_parse_directory (abfd, type_tables + indx, data, data,
 				   dataend, rva_bias, NULL);
-      data = rsrc_align (abfd, data, dataend);
+      data = p + rsrc_sizes[indx];
       rva_bias += data - p;
-      indx ++;
+      ++ indx;
     }
   BFD_ASSERT (indx == num_resource_sets);
 
@@ -3681,8 +3673,10 @@ rsrc_process_section (bfd * abfd,
   sec->size = sec->rawsize = size;
 
  end:
+  /* Step size: Free all the memory that we have used.  */
   /* FIXME: Free the resource tree, if we have one.  */
   free (datastart);
+  free (rsrc_sizes);
 }
 
 /* Handle the .idata section and other things that need symbol table
diff --git a/ld/scripttempl/pe.sc b/ld/scripttempl/pe.sc
index 4a1951c..e9e5f64 100644
--- a/ld/scripttempl/pe.sc
+++ b/ld/scripttempl/pe.sc
@@ -47,15 +47,18 @@ if test "${RELOCATING}"; then
   if test -z "$DEFAULT_MANIFEST"; then
     R_RSRC='
       *(.rsrc)
-      *(SORT(.rsrc$*))'
+      *(.rsrc$*)'
   else
     R_RSRC="
       /* The default manifest contains information necessary for
          binaries to run under Windows 8 (or later).  It is included as
          the last resource file so that if the application has provided
-         its own manifest then that one will take precedence.  */
+         its own manifest then that one will take precedence.
+
+	 Note - the .rsrc section merging code relies upon the fact
+	 that the input .rsrc sections are *not* sorted.  */
       *(EXCLUDE_FILE (*$DEFAULT_MANIFEST) .rsrc)
-      *(SORT(.rsrc*))
+      *(.rsrc*)
       KEEP ($DEFAULT_MANIFEST(.rsrc))"
   fi
 else
diff --git a/ld/scripttempl/pep.sc b/ld/scripttempl/pep.sc
index 592489a..5f97d31 100644
--- a/ld/scripttempl/pep.sc
+++ b/ld/scripttempl/pep.sc
@@ -47,15 +47,18 @@ if test "${RELOCATING}"; then
   if test -z "$DEFAULT_MANIFEST"; then
     R_RSRC='
       *(.rsrc)
-      *(SORT(.rsrc$*))'
+      *(.rsrc$*)'
   else
     R_RSRC="
       /* The default manifest contains information necessary for
          binaries to run under Windows 8 (or later).  It is included as
          the last resource file so that if the application has provided
-         its own manifest then that one will take precedence.  */
+         its own manifest then that one will take precedence.
+
+	 Note - the .rsrc section merging code relies upon the fact
+	 that the input .rsrc sections are *not* sorted.  */
       *(EXCLUDE_FILE (*$DEFAULT_MANIFEST) .rsrc)
-      *(SORT(.rsrc*))
+      *(.rsrc*)
       KEEP ($DEFAULT_MANIFEST(.rsrc))"
   fi
 else

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2014-03-19 15:20 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-19 15:20 Commit: Improve .rsrc section merging Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).