This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

ppc apuinfo processing


Hi,
I met a toolchain that emitted empty apuinfo sections (all header, no data), and these are currently rejected by bfd. I couldn't see anything in the apuinfo ABI documentation indicating this is an error, so it seems best to allow it.


While working on that, I noticed the apuinfo processing being done is rather baroque. We scan the input apusections and then allocate one big buffer to concatenate them into. We then read them one at a time, appending to this buffer and processing each as we go. Then we throw the buffer away. That seems less than optimal :)

So this patch scans the input sections only once, reusing a temporary buffer for each input section -- in addition to allowing empty apuinfo sections.

I added a dummy apuinfo case to the testsuite, to make sure it is correctly ignored.

built and tested for powerpc-eabi, ok?

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::         CodeSourcery

2010-02-05  Nathan Sidwell  <nathan@codesourcery.com>

	bfd/
	* elf32-ppc.c (ppc_elf_begin_write_processing): Allow empty
	apuinfo sections, only scan input sections once and reuse the
	buffer.

	ld/testsuite/
	* ld-powerpc/apuinfo-nul.s: New.
	* ld-powerpc/apuinfo.rd: Add it.
	* ld-powerpc/powerpc.exp: Likewise.

Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.275
diff -c -3 -p -r1.275 elf32-ppc.c
*** bfd/elf32-ppc.c	4 Feb 2010 09:16:39 -0000	1.275
--- bfd/elf32-ppc.c	5 Feb 2010 11:38:20 -0000
*************** ppc_elf_begin_write_processing (bfd *abf
*** 2159,2281 ****
  {
    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;
  
    if (link_info == NULL)
      return;
  
-   /* 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->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->size;
!       if (length < 24)
  	{
! 	  error_message = _("corrupt or empty %s section in %B");
! 	  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 %B");
  	  goto fail;
  	}
  
-       /* Process the contents of the section.  */
-       ptr = buffer + offset;
-       error_message = _("corrupt %s section in %B");
- 
        /* 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 bytes used for apuinfo entries.  */
!       datum = bfd_get_32 (ibfd, ptr + 4);
        if (datum + 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 += 4)
! 	apuinfo_list_add (bfd_get_32 (ibfd, ptr + 20 + i));
! 
!       /* 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 %B");
  
   fail:
!   free (buffer);
  
    if (error_message)
      (*_bfd_error_handler) (error_message, ibfd, APUINFO_SECTION_NAME);
--- 2159,2250 ----
  {
    bfd *ibfd;
    asection *asec;
!   char *buffer = NULL;
!   bfd_size_type largest_input_size = 0;
    unsigned i;
    unsigned num_entries;
    unsigned long length;
    const char *error_message = NULL;
  
    if (link_info == NULL)
      return;
  
    apuinfo_list_init ();
  
    /* Read in the input sections contents.  */
    for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next)
      {
        unsigned long datum;
  
        asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME);
        if (asec == NULL)
  	continue;
  
+       error_message = _("corrupt %s section in %B");
        length = asec->size;
!       if (length < 20)
! 	goto fail;
! 
!       if (largest_input_size < asec->size)
  	{
! 	  if (buffer)
! 	    free (buffer);
! 	  largest_input_size = asec->size;
! 	  buffer = bfd_malloc (largest_input_size);
! 	  if (!buffer)
! 	    return;
  	}
!       
        if (bfd_seek (ibfd, asec->filepos, SEEK_SET) != 0
! 	  || (bfd_bread (buffer, length, ibfd) != length))
  	{
  	  error_message = _("unable to read in %s section from %B");
  	  goto fail;
  	}
  
        /* 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, buffer);
        if (datum != sizeof APUINFO_LABEL)
  	goto fail;
  
!       datum = bfd_get_32 (ibfd, buffer + 8);
        if (datum != 0x2)
  	goto fail;
  
!       if (strcmp (buffer + 12, APUINFO_LABEL) != 0)
  	goto fail;
  
        /* Get the number of bytes used for apuinfo entries.  */
!       datum = bfd_get_32 (ibfd, buffer + 4);
        if (datum + 20 != length)
  	goto fail;
  
        /* Scan the apuinfo section, building a list of apuinfo numbers.  */
        for (i = 0; i < datum; i += 4)
! 	apuinfo_list_add (bfd_get_32 (ibfd, buffer + 20 + i));
      }
  
    error_message = NULL;
  
    /* Compute the size of the output section.  */
    num_entries = apuinfo_list_length ();
  
!   if (num_entries)
!     {
!       /* Set the output section size, if it exists.  */
!       asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME);
!       if (asec && ! bfd_set_section_size (abfd, asec, 20 + num_entries * 4))
! 	{
! 	  ibfd = abfd;
! 	  error_message = _("warning: unable to set size of %s section in %B");
! 	}
!     }
  
   fail:
!   if (buffer)
!     free (buffer);
  
    if (error_message)
      (*_bfd_error_handler) (error_message, ibfd, APUINFO_SECTION_NAME);
Index: ld/testsuite/ld-powerpc/apuinfo-nul.s
===================================================================
RCS file: ld/testsuite/ld-powerpc/apuinfo-nul.s
diff -N ld/testsuite/ld-powerpc/apuinfo-nul.s
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- ld/testsuite/ld-powerpc/apuinfo-nul.s	5 Feb 2010 11:38:20 -0000
***************
*** 0 ****
--- 1,10 ----
+ 	.text
+ 	nop
+ 
+ 	# dummy empty apuinfo
+ 	# some other tools emit these
+ 	.section ".PPC.EMB.apuinfo"
+ 	.long 8
+ 	.long 0
+ 	.long 2
+ 	.asciz "APUinfo"
Index: ld/testsuite/ld-powerpc/apuinfo.rd
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/apuinfo.rd,v
retrieving revision 1.3
diff -c -3 -p -r1.3 apuinfo.rd
*** ld/testsuite/ld-powerpc/apuinfo.rd	16 Mar 2005 21:52:47 -0000	1.3
--- ld/testsuite/ld-powerpc/apuinfo.rd	5 Feb 2010 11:38:20 -0000
***************
*** 1,5 ****
--- 1,6 ----
  #source: apuinfo1.s
  #source: apuinfo2.s
+ #source: apuinfo-nul.s
  #as: -me500
  #readelf: -x2
  #target: powerpc-eabi*
Index: ld/testsuite/ld-powerpc/powerpc.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/powerpc.exp,v
retrieving revision 1.29
diff -c -3 -p -r1.29 powerpc.exp
*** ld/testsuite/ld-powerpc/powerpc.exp	21 Sep 2009 11:51:02 -0000	1.29
--- ld/testsuite/ld-powerpc/powerpc.exp	5 Feb 2010 11:38:20 -0000
*************** set ppcelftests {
*** 101,107 ****
      {"Reloc section order" "-melf32ppc -shared -z nocombreloc" "-a32" {reloc.s}
       {{objdump -hw reloc.d}} "reloc.so"}
      {"APUinfo section processing" "-melf32ppc"
!      "-a32 -me500" {apuinfo1.s apuinfo2.s}
      {{readelf -x2 apuinfo.rd}} "apuinfo"}
      {"TLS32 static exec" "-melf32ppc" "-a32"  {tls32.s tlslib32.s}
       {{objdump -dr tls32.d} {objdump -sj.got tls32.g}
--- 101,107 ----
      {"Reloc section order" "-melf32ppc -shared -z nocombreloc" "-a32" {reloc.s}
       {{objdump -hw reloc.d}} "reloc.so"}
      {"APUinfo section processing" "-melf32ppc"
!      "-a32 -me500" {apuinfo1.s apuinfo-nul.s apuinfo2.s}
      {{readelf -x2 apuinfo.rd}} "apuinfo"}
      {"TLS32 static exec" "-melf32ppc" "-a32"  {tls32.s tlslib32.s}
       {{objdump -dr tls32.d} {objdump -sj.got tls32.g}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]