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:
Nick Clifton 2002-12-03 18:24:33 +00:00
parent a823923bf6
commit e1a9cb8e15
10 changed files with 364 additions and 2 deletions

View file

@ -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.

View file

@ -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"

View file

@ -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.

View file

@ -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);

View file

@ -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:

View 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 .........@......

View file

@ -0,0 +1,9 @@
.text
.global apuinfo1
apuinfo1:
evstdd 29,8(1)
isellt 29, 28, 27
efsabs 29, 28
.global _start
_start:
nop

View file

@ -0,0 +1,8 @@
.text
.global apuinfo2
apuinfo2:
evstdd 29,8(1)
mfbbear 29
mfpmr 29, 27
dcbtstls 1, 29, 28
rfmci

View file

@ -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

View file

@ -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"