aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog20
-rw-r--r--bfd/elf32-ppc.c300
-rw-r--r--gas/ChangeLog5
-rw-r--r--gas/config/tc-ppc.c2
-rw-r--r--ld/testsuite/ChangeLog8
-rw-r--r--ld/testsuite/ld-powerpc/apuinfo.rd10
-rw-r--r--ld/testsuite/ld-powerpc/apuinfo1.s9
-rw-r--r--ld/testsuite/ld-powerpc/apuinfo2.s8
-rw-r--r--ld/testsuite/ld-powerpc/powerpc.exp2
-rw-r--r--ld/testsuite/ld-srec/srec.exp2
10 files changed, 364 insertions, 2 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 57d7ee9..c16c741 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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.
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 0c33a90..c117f54 100644
--- a/bfd/elf32-ppc.c
+++ b/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"
diff --git a/gas/ChangeLog b/gas/ChangeLog
index d891166..5c59ad5 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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.
diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c
index 04fae38..ba058f6 100644
--- a/gas/config/tc-ppc.c
+++ b/gas/config/tc-ppc.c
@@ -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);
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 2f8179b..4226307 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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:
diff --git a/ld/testsuite/ld-powerpc/apuinfo.rd b/ld/testsuite/ld-powerpc/apuinfo.rd
new file mode 100644
index 0000000..421ae7d
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/apuinfo.rd
@@ -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 .........@......
diff --git a/ld/testsuite/ld-powerpc/apuinfo1.s b/ld/testsuite/ld-powerpc/apuinfo1.s
new file mode 100644
index 0000000..fd42eac
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/apuinfo1.s
@@ -0,0 +1,9 @@
+ .text
+ .global apuinfo1
+apuinfo1:
+ evstdd 29,8(1)
+ isellt 29, 28, 27
+ efsabs 29, 28
+ .global _start
+_start:
+ nop
diff --git a/ld/testsuite/ld-powerpc/apuinfo2.s b/ld/testsuite/ld-powerpc/apuinfo2.s
new file mode 100644
index 0000000..7f4e7bb
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/apuinfo2.s
@@ -0,0 +1,8 @@
+ .text
+ .global apuinfo2
+apuinfo2:
+ evstdd 29,8(1)
+ mfbbear 29
+ mfpmr 29, 27
+ dcbtstls 1, 29, 28
+ rfmci
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index f52278d..a853df9 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -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
diff --git a/ld/testsuite/ld-srec/srec.exp b/ld/testsuite/ld-srec/srec.exp
index d3fa764..af1ceed 100644
--- a/ld/testsuite/ld-srec/srec.exp
+++ b/ld/testsuite/ld-srec/srec.exp
@@ -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"