From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8430 invoked by alias); 19 Mar 2014 15:20:44 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Received: (qmail 8417 invoked by uid 89); 19 Mar 2014 15:20:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.9 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,SPF_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 19 Mar 2014 15:20:42 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s2JFKdOK006984 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 19 Mar 2014 11:20:41 -0400 Received: from littlehelper.redhat.com (vpn1-5-55.ams2.redhat.com [10.36.5.55]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s2JEnFMR028306 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO) for ; Wed, 19 Mar 2014 10:49:18 -0400 From: Nick Clifton To: binutils@sourceware.org Subject: Commit: Improve .rsrc section merging. Date: Wed, 19 Mar 2014 15:20:00 -0000 Message-ID: <87siqetf9x.fsf@redhat.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-IsSubscribed: yes X-SW-Source: 2014-03/txt/msg00207.txt.bz2 --=-=-= Content-Type: text/plain Content-length: 673 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 * 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 * scripttempl/pe.sc (R_RSRC): Fix default-manifest exclusion. (.rsrc): Add SUBALIGN(4). Remove SORT. * scripttempl/pep.sc: Likewise. --=-=-= Content-Type: text/x-patch Content-Disposition: inline; filename=rsrc_merge.patch Content-length: 8186 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 --=-=-=--