Fix the merging of .PPC.EMB.apuinfo sections. Add a test to make sure that
the fix continues to work.
This commit is contained in:
parent
a823923bf6
commit
e1a9cb8e15
10 changed files with 364 additions and 2 deletions
|
@ -1,3 +1,23 @@
|
|||
2002-12-03 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* elf32-ppc.c (apuinfo_list_init): New function.
|
||||
(apuinfo_list_add): New function: Add a value to the list.
|
||||
(apuinfo_list_length): New function: Return the number of
|
||||
values on the list.
|
||||
(apuinfo_list_element): New function: Return a value on the
|
||||
list.
|
||||
(apuinfo_list_finish): New function: Free the resources used
|
||||
by the list.
|
||||
(ppc_elf_begin_write_processing): New function. Scan the
|
||||
input bfds for apuinfo sections.
|
||||
(ppc_elf_write_section): New function: Delay the creation of
|
||||
the contents of an apuinfo section in an output bfd.
|
||||
(ppc_elf_final_write_processing): New function. Create the
|
||||
contents of an apuinfo section in an output bfd.
|
||||
(elf_backend_begin_write_processing): Define.
|
||||
(elf_backend_final_write_processing): Define.
|
||||
(elf_backend_write_section): Define.
|
||||
|
||||
2002-12-03 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* cpu-ia64-opc.c (elf64_ia64_operands): Add ldxmov entry.
|
||||
|
|
300
bfd/elf32-ppc.c
300
bfd/elf32-ppc.c
|
@ -3783,6 +3783,303 @@ ppc_elf_grok_psinfo (abfd, note)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Very simple linked list structure for recording apuinfo values. */
|
||||
typedef struct apuinfo_list
|
||||
{
|
||||
struct apuinfo_list * next;
|
||||
unsigned long value;
|
||||
}
|
||||
apuinfo_list;
|
||||
|
||||
static apuinfo_list * head;
|
||||
|
||||
static void apuinfo_list_init PARAMS ((void));
|
||||
static void apuinfo_list_add PARAMS ((unsigned long));
|
||||
static unsigned apuinfo_list_length PARAMS ((void));
|
||||
static unsigned long apuinfo_list_element PARAMS ((unsigned long));
|
||||
static void apuinfo_list_finish PARAMS ((void));
|
||||
|
||||
extern void ppc_elf_begin_write_processing
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
extern void ppc_elf_final_write_processing
|
||||
PARAMS ((bfd *, bfd_boolean));
|
||||
extern bfd_boolean ppc_elf_write_section
|
||||
PARAMS ((bfd *, asection *, bfd_byte *));
|
||||
|
||||
|
||||
|
||||
static void
|
||||
apuinfo_list_init PARAMS ((void))
|
||||
{
|
||||
head = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
apuinfo_list_add (value)
|
||||
unsigned long value;
|
||||
{
|
||||
apuinfo_list * entry = head;
|
||||
|
||||
while (entry != NULL)
|
||||
{
|
||||
if (entry->value == value)
|
||||
return;
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
entry = bfd_malloc (sizeof (* entry));
|
||||
if (entry == NULL)
|
||||
return;
|
||||
|
||||
entry->value = value;
|
||||
entry->next = head;
|
||||
head = entry;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
apuinfo_list_length PARAMS ((void))
|
||||
{
|
||||
apuinfo_list * entry;
|
||||
unsigned long count;
|
||||
|
||||
for (entry = head, count = 0;
|
||||
entry;
|
||||
entry = entry->next)
|
||||
++ count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
apuinfo_list_element (number)
|
||||
unsigned long number;
|
||||
{
|
||||
apuinfo_list * entry;
|
||||
|
||||
for (entry = head;
|
||||
entry && number --;
|
||||
entry = entry->next)
|
||||
;
|
||||
|
||||
return entry ? entry->value : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
apuinfo_list_finish PARAMS ((void))
|
||||
{
|
||||
apuinfo_list * entry;
|
||||
|
||||
for (entry = head; entry;)
|
||||
{
|
||||
apuinfo_list * next = entry->next;
|
||||
free (entry);
|
||||
entry = next;
|
||||
}
|
||||
|
||||
head = NULL;
|
||||
}
|
||||
|
||||
#define APUINFO_SECTION_NAME ".PPC.EMB.apuinfo"
|
||||
#define APUINFO_LABEL "APUinfo"
|
||||
|
||||
/* Scan the input BFDs and create a linked list of
|
||||
the APUinfo values that will need to be emitted. */
|
||||
|
||||
void
|
||||
ppc_elf_begin_write_processing (abfd, link_info)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *link_info;
|
||||
{
|
||||
bfd * ibfd;
|
||||
asection * asec;
|
||||
char * buffer;
|
||||
unsigned num_input_sections;
|
||||
bfd_size_type output_section_size;
|
||||
unsigned i;
|
||||
unsigned num_entries;
|
||||
unsigned long offset;
|
||||
unsigned long length;
|
||||
const char * error_message = NULL;
|
||||
|
||||
/* Scan the input bfds, looking for apuinfo sections. */
|
||||
num_input_sections = 0;
|
||||
output_section_size = 0;
|
||||
|
||||
for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next)
|
||||
{
|
||||
asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME);
|
||||
if (asec)
|
||||
{
|
||||
++ num_input_sections;
|
||||
output_section_size += asec->_raw_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* We need at least one input sections
|
||||
in order to make merging worthwhile. */
|
||||
if (num_input_sections < 1)
|
||||
return;
|
||||
|
||||
/* Just make sure that the output section exists as well. */
|
||||
asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
|
||||
if (asec == NULL)
|
||||
return;
|
||||
|
||||
/* Allocate a buffer for the contents of the input sections. */
|
||||
buffer = bfd_malloc (output_section_size);
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
|
||||
offset = 0;
|
||||
apuinfo_list_init ();
|
||||
|
||||
/* Read in the input sections contents. */
|
||||
for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next)
|
||||
{
|
||||
unsigned long datum;
|
||||
char * ptr;
|
||||
|
||||
|
||||
asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME);
|
||||
if (asec == NULL)
|
||||
continue;
|
||||
|
||||
length = asec->_raw_size;
|
||||
if (length < 24)
|
||||
{
|
||||
error_message = _("corrupt or empty %s section in %s");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (bfd_seek (ibfd, asec->filepos, SEEK_SET) != 0
|
||||
|| (bfd_bread (buffer + offset, length, ibfd) != length))
|
||||
{
|
||||
error_message = _("unable to read in %s section from %s");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Process the contents of the section. */
|
||||
ptr = buffer + offset;
|
||||
error_message = _("corrupt %s section in %s");
|
||||
|
||||
/* Verify the contents of the header. Note - we have to
|
||||
extract the values this way in order to allow for a
|
||||
host whose endian-ness is different from the target. */
|
||||
datum = bfd_get_32 (ibfd, ptr);
|
||||
if (datum != sizeof APUINFO_LABEL)
|
||||
goto fail;
|
||||
|
||||
datum = bfd_get_32 (ibfd, ptr + 8);
|
||||
if (datum != 0x2)
|
||||
goto fail;
|
||||
|
||||
if (strcmp (ptr + 12, APUINFO_LABEL) != 0)
|
||||
goto fail;
|
||||
|
||||
/* Get the number of apuinfo entries. */
|
||||
datum = bfd_get_32 (ibfd, ptr + 4);
|
||||
if ((datum * 4 + 20) != length)
|
||||
goto fail;
|
||||
|
||||
/* Make sure that we do not run off the end of the section. */
|
||||
if (offset + length > output_section_size)
|
||||
goto fail;
|
||||
|
||||
/* Scan the apuinfo section, building a list of apuinfo numbers. */
|
||||
for (i = 0; i < datum; i++)
|
||||
apuinfo_list_add (bfd_get_32 (ibfd, ptr + 20 + (i * 4)));
|
||||
|
||||
/* Update the offset. */
|
||||
offset += length;
|
||||
}
|
||||
|
||||
error_message = NULL;
|
||||
|
||||
/* Compute the size of the output section. */
|
||||
num_entries = apuinfo_list_length ();
|
||||
output_section_size = 20 + num_entries * 4;
|
||||
|
||||
asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
|
||||
|
||||
if (! bfd_set_section_size (abfd, asec, output_section_size))
|
||||
ibfd = abfd,
|
||||
error_message = _("warning: unable to set size of %s section in %s");
|
||||
|
||||
fail:
|
||||
free (buffer);
|
||||
|
||||
if (error_message)
|
||||
_bfd_error_handler (error_message, APUINFO_SECTION_NAME,
|
||||
bfd_archive_filename (ibfd));
|
||||
}
|
||||
|
||||
|
||||
/* Prevent the output section from accumulating the input sections'
|
||||
contents. We have already stored this in our linked list structure. */
|
||||
|
||||
bfd_boolean
|
||||
ppc_elf_write_section (abfd, asec, contents)
|
||||
bfd * abfd ATTRIBUTE_UNUSED;
|
||||
asection * asec;
|
||||
bfd_byte * contents ATTRIBUTE_UNUSED;
|
||||
{
|
||||
return strcmp (asec->name, APUINFO_SECTION_NAME) == 0;
|
||||
}
|
||||
|
||||
|
||||
/* Finally we can generate the output section. */
|
||||
|
||||
void
|
||||
ppc_elf_final_write_processing (abfd, linker)
|
||||
bfd * abfd;
|
||||
bfd_boolean linker ATTRIBUTE_UNUSED;
|
||||
{
|
||||
bfd_byte * buffer;
|
||||
asection * asec;
|
||||
unsigned i;
|
||||
unsigned num_entries;
|
||||
bfd_size_type length;
|
||||
|
||||
asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
|
||||
if (asec == NULL)
|
||||
return;
|
||||
|
||||
length = asec->_raw_size;
|
||||
if (length < 20)
|
||||
return;
|
||||
|
||||
buffer = bfd_malloc (length);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
_bfd_error_handler (_("failed to allocate space for new APUinfo section."));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create the apuinfo header. */
|
||||
num_entries = apuinfo_list_length ();
|
||||
bfd_put_32 (abfd, sizeof APUINFO_LABEL, buffer);
|
||||
bfd_put_32 (abfd, num_entries, buffer + 4);
|
||||
bfd_put_32 (abfd, 0x2, buffer + 8);
|
||||
strcpy (buffer + 12, APUINFO_LABEL);
|
||||
|
||||
length = 20;
|
||||
for (i = 0; i < num_entries; i++)
|
||||
{
|
||||
bfd_put_32 (abfd, apuinfo_list_element (i), buffer + length);
|
||||
length += 4;
|
||||
}
|
||||
|
||||
if (length != asec->_raw_size)
|
||||
_bfd_error_handler (_("failed to compute new APUinfo section."));
|
||||
|
||||
if (! bfd_set_section_contents (abfd, asec, buffer, (file_ptr) 0, length))
|
||||
_bfd_error_handler (_("failed to install new APUinfo section."));
|
||||
|
||||
free (buffer);
|
||||
|
||||
apuinfo_list_finish ();
|
||||
}
|
||||
|
||||
#define TARGET_LITTLE_SYM bfd_elf32_powerpcle_vec
|
||||
#define TARGET_LITTLE_NAME "elf32-powerpcle"
|
||||
#define TARGET_BIG_SYM bfd_elf32_powerpc_vec
|
||||
|
@ -3832,5 +4129,8 @@ ppc_elf_grok_psinfo (abfd, note)
|
|||
#define elf_backend_grok_prstatus ppc_elf_grok_prstatus
|
||||
#define elf_backend_grok_psinfo ppc_elf_grok_psinfo
|
||||
#define elf_backend_reloc_type_class ppc_elf_reloc_type_class
|
||||
#define elf_backend_begin_write_processing ppc_elf_begin_write_processing
|
||||
#define elf_backend_final_write_processing ppc_elf_final_write_processing
|
||||
#define elf_backend_write_section ppc_elf_write_section
|
||||
|
||||
#include "elf32-target.h"
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2002-12-03 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* config/tc-ppc.c (ppc_cleanup): Do not set SEC_MERGE flag on
|
||||
.PPC.EMB>apuinfo sections.
|
||||
|
||||
2002-12-03 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* config/tc-ia64.c (operand_match): Add IA64_OPND_LDXMOV case.
|
||||
|
|
|
@ -1330,7 +1330,7 @@ ppc_cleanup ()
|
|||
apuinfo_secp = subseg_new (".PPC.EMB.apuinfo", 0);
|
||||
bfd_set_section_flags (stdoutput,
|
||||
apuinfo_secp,
|
||||
SEC_HAS_CONTENTS | SEC_READONLY | SEC_MERGE);
|
||||
SEC_HAS_CONTENTS | SEC_READONLY);
|
||||
|
||||
p = frag_more (4);
|
||||
md_number_to_chars (p, (valueT) 8, 4);
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2002-12-03 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* ld-powerpc/powerpc.exp (ppcelftests): Add apuinfo merging
|
||||
test.
|
||||
* ld-powerpc/apuinfo1.s: New assembler source file.
|
||||
* ld-powerpc/apuinfo2.s: New assembler source file.
|
||||
* ld-powerpc/apuinfo.rd: New expected output file.
|
||||
|
||||
2002-12-01 Stephane Carrez <stcarrez@nerim.fr>
|
||||
|
||||
Fix PR savannah/1417:
|
||||
|
|
10
ld/testsuite/ld-powerpc/apuinfo.rd
Normal file
10
ld/testsuite/ld-powerpc/apuinfo.rd
Normal file
|
@ -0,0 +1,10 @@
|
|||
#source: apuinfo1.s
|
||||
#source: apuinfo2.s
|
||||
#as: -me500
|
||||
#readelf: -x5
|
||||
#target: powerpc-eabi*
|
||||
|
||||
Hex dump of section '.PPC.EMB.apuinfo':
|
||||
0x00000000 00000008 00000007 00000002 41505569 ............APUi
|
||||
0x00000010 6e666f00 00420001 00430001 00410001 nfo..B...C...A..
|
||||
0x00000020 01020001 01010001 00400001 01000001 .........@......
|
9
ld/testsuite/ld-powerpc/apuinfo1.s
Normal file
9
ld/testsuite/ld-powerpc/apuinfo1.s
Normal file
|
@ -0,0 +1,9 @@
|
|||
.text
|
||||
.global apuinfo1
|
||||
apuinfo1:
|
||||
evstdd 29,8(1)
|
||||
isellt 29, 28, 27
|
||||
efsabs 29, 28
|
||||
.global _start
|
||||
_start:
|
||||
nop
|
8
ld/testsuite/ld-powerpc/apuinfo2.s
Normal file
8
ld/testsuite/ld-powerpc/apuinfo2.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
.text
|
||||
.global apuinfo2
|
||||
apuinfo2:
|
||||
evstdd 29,8(1)
|
||||
mfbbear 29
|
||||
mfpmr 29, 27
|
||||
dcbtstls 1, 29, 28
|
||||
rfmci
|
|
@ -41,6 +41,8 @@ if { [istarget "*-*-macos*"] || [istarget "*-*-netware*"]
|
|||
set ppcelftests {
|
||||
{"Reloc section order" "-shared -z nocombreloc" "" {reloc.s}
|
||||
{{objdump -hw reloc.d}} "reloc.so"}
|
||||
{"APUinfo section processing" "" "-me500" {apuinfo1.s apuinfo2.s}
|
||||
{{readelf -x5 apuinfo.rd}} "apuinfo"}
|
||||
}
|
||||
|
||||
run_ld_link_tests $ppcelftests
|
||||
|
|
|
@ -370,7 +370,7 @@ setup_xfail "thumb-*-elf*"
|
|||
setup_xfail "arm*-*-linux*"
|
||||
|
||||
# The S-record linker doesn't build special EABI sections.
|
||||
setup_xfail "powerpc*-*-eabi*"
|
||||
# setup_xfail "powerpc*-*-eabi*"
|
||||
|
||||
# The S-record linker doesn't include the .{zda} sections.
|
||||
setup_xfail "v850*-*-elf"
|
||||
|
|
Loading…
Reference in a new issue