public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* ppc apuinfo processing
@ 2010-02-05 11:45 Nathan Sidwell
  2010-02-06 23:17 ` Alan Modra
  0 siblings, 1 reply; 2+ messages in thread
From: Nathan Sidwell @ 2010-02-05 11:45 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 945 bytes --]

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


[-- Attachment #2: apuinfo.patch --]
[-- Type: text/x-patch, Size: 8988 bytes --]

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}

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: ppc apuinfo processing
  2010-02-05 11:45 ppc apuinfo processing Nathan Sidwell
@ 2010-02-06 23:17 ` Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2010-02-06 23:17 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: binutils

On Fri, Feb 05, 2010 at 11:45:13AM +0000, Nathan Sidwell wrote:
> 	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.

OK, thanks!

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2010-02-06 23:17 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-05 11:45 ppc apuinfo processing Nathan Sidwell
2010-02-06 23:17 ` Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).