Improve .rsrc section merging again. This time with an algorithm that
should work for all types of input .rsrc section. * 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. * scripttempl/pe.sc (R_RSRC): Fix default-manifest exclusion. (.rsrc): Add SUBALIGN(4). Remove SORT. * scripttempl/pep.sc: Likewise.
This commit is contained in:
parent
288c6b306e
commit
6caf711179
@ -1,8 +1,8 @@
|
||||
2014-03-19 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* peXXigen.c (rsrc_align): New function. Attempts to cope with
|
||||
alignment variances when .rsrc sections are merged.
|
||||
(rsrc_process_section): Use rsrc_align.
|
||||
* 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.
|
||||
|
||||
2014-03-17 Tristan Gingold <gingold@adacore.com>
|
||||
|
||||
|
124
bfd/peXXigen.c
124
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
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Makefile.in: Regenerate.
|
||||
* emultempl/default-manifest.rc: Fix typo.
|
||||
* scripttempl/pe.sc (R_RSRC): Fix default-manifest exclusion.
|
||||
(.rsrc): Add SUBALIGN(4).
|
||||
(.rsrc): Add SUBALIGN(4). Remove SORT.
|
||||
* scripttempl/pep.sc: Likewise.
|
||||
|
||||
2014-03-17 Christopher Faylor <me.cygwin2014@cgf.cx>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user