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]

Re: intermittent 0-length for .note.gnu.arm.ident


On Wed, 2006-04-19 at 14:14 -0400, James Lemke wrote:
:
> I'm building a mingw x xscale-elf toolchain and some of the objects have
> normal .note.gnu.arm.ident sections (length 0x1c) and others have those
> section with length 0.  The objects with 0-length sections seem to be
> normal otherwise.  If I ignore linker warnings the DejaGNU tests run OK.

Jim Wilson suggested that it might be the amount of environment space in
use that was causing the difference.  He was correct... if I consume
about 14K of env space, gas fails everytime.  (binutils-2.15)

The problems centre on gas/subsegs.c:subseg_set_rest().  It keeps a
linked list of segment / section fragments that is sorted and searched
by the addresses of the frchainS structures.

There are two sources for the frchainS structures that are stored on
this list.  Some, like "*UND*", are globally declared.  Most, like .text
and .note.gnu.arm.ident, are dynamically allocated.

In the usual case, the statically allocated frchainS structures will
have a lower address than all of the malloc'd ones.  However, in the
MinGW environment with a lot of environment space in use, the reverse is
true placing "*UND*" at the end of the list.

".note.gnu.arm.ident" is subsequently added to this list.  In the normal
case the search hits the end of the list where it is appended.  In the
failing case the new section is inserted before "*UND*".  This works
properly except here:
#ifdef BFD_ASSEMBLER
      {
        segment_info_type *seginfo;
        seginfo = seg_info (seg);
        if (seginfo && seginfo->frchainP == frcP)
          seginfo->frchainP = newP;
      }
#endif

seginfo->frchainP is NULL for the new section.  In the normal case frcP
is also NULL because we hit the end of the list and seginfo->frchainP is
updated.  In the failing case frcP is a pointer to "*UND*".  Therefore,
seginfo->frchainP remains NULL.
Therefore the section's contents are never written out.

It looks like this potential problem also exists in the FSF HEAD
sources.

My fix was this:
--- subsegs.c-orig      2006-04-27 13:44:49.893500000 +0000
+++ subsegs.c   2006-04-27 13:47:51.909125000 +0000
@@ -297,7 +297,7 @@ subseg_set_rest (segT seg, subsegT subse
       {
        segment_info_type *seginfo;
        seginfo = seg_info (seg);
-       if (seginfo && seginfo->frchainP == frcP)
+       if (seginfo && (!seginfo->frchainP || seginfo->frchainP ==
frcP))
          seginfo->frchainP = newP;
       }
 #endif

Which I have tested with check-{binutils,gas,gcc} and works well.  So
I'm looking for comments about the approach.  Then I will make up a
patch for HEAD and test there.

Also, JimW suggested a different approach which might be better:
*** tc-arm.c.orig       2004-11-16 22:41:34.000000000 -0800
--- tc-arm.c    2006-04-27 16:22:43.664683290 -0700
*************** md_begin ()
*** 12073,12079 ****
--- 12073,12082 ----
      asection * arm_arch;
      const char * arch_string;
  
+ #if 0
      arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
+ #endif
+     arm_arch = subseg_new (ARM_NOTE_SECTION, 0);
  
  #ifdef OBJ_COFF
      bfd_set_section_flags (stdoutput, arm_arch,
*************** md_begin ()
*** 12084,12090 ****
--- 12087,12095 ----
                           SEC_READONLY | SEC_HAS_CONTENTS);
  #endif
      arm_arch->output_section = arm_arch;
+ #if 0
      subseg_set (arm_arch, 0);
+ #endif
  
      switch (mach)
        {

-- 
Jim Lemke   jwlemke@wasabisystems.com   Orillia, Ontario


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