Subject: bug#9927: 24.0.90; unexec/unexmacosx fails with GCC 4.6.1

From: Samuel Bronson <[email-masked]>
Date: Fri, 29 Jun 2012 13:03:49 -0400

found 9927 24.1.50
retitle 9927 24.1.90; unexec/unexmacosx doesn't grok new sections  
emitted by GCC 4.6+
thanks

Peter Dyballa <[email-masked]> wrote:

 > Am 18.05.2012 um 00:54 schrieb Andreas Schwab:
 >
 > > temacs, not emacs (which didn't build).
 >
 > src/temacs:     file format mach-o-i386
 > src/temacs
 > architecture: i386, flags 0x00000012:
 > EXEC_P, HAS_SYMS
 > start address 0x00002650
 > Mach-O header:
 >  magic     : feedface
 >  cputype   : 00000007 (i386)
 >  cpusubtype: 00000003
 >  filetype  : 00000002 (execute)
 >  ncmds     : 00000019 (25)
 >  sizeofcmds: 00000a04
 >  flags     : 01000085 (noundefs+dyldlink+twolevel+0x1000000)
 >  reserved  : 00000002

[Irrelevant segments scrubbed]

 > Load command segment: name: __DATA
 >     vmaddr: 00000000001b1000   vmsize: 00000000001dc000
 >    fileoff: 00000000001b0000 filesize: 0000000000198000 endoff:
 >    0000000000348000
 >    nsects: 10   flags: 0
 >  Section: __program_vars   __DATA           (bfdname:  
__DATA.__program_vars)
 >   addr: 00000000001b1000 size: 0000000000000014 offset:  
00000000001b0000
 >   align: 2  nreloc: 0  reloff: 0000000000000000
 >   flags: 00000000 (type: regular attr: -)
 >   reserved1: 0x0  reserved2: 0x0  reserved3: 0x0
 >  Section: __nl_symbol_ptr  __DATA            
(bfdname: .non_lazy_symbol_ptr)
 >   addr: 00000000001b1014 size: 0000000000000b14 offset:  
00000000001b0014
 >   align: 2  nreloc: 0  reloff: 0000000000000000
 >   flags: 00000006 (type: non_lazy_symbol_pointers attr: -)
 >   first indirect sym: 536 (709 entries)  reserved2: 0x0  reserved3:  
0x0
 >  Section: __la_symbol_ptr  __DATA            
(bfdname: .lazy_symbol_ptr)
 >   addr: 00000000001b1b28 size: 0000000000000860 offset:  
00000000001b0b28
 >   align: 2  nreloc: 0  reloff: 0000000000000000
 >   flags: 00000007 (type: lazy_symbol_pointers attr: -)
 >   first indirect sym: 1245 (536 entries)  reserved2: 0x0   
reserved3: 0x0
 >  Section: __data           __DATA           (bfdname: .data)
 >   addr: 00000000001b2390 size: 00000000001956dc offset:  
00000000001b1390
 >   align: 4  nreloc: 0  reloff: 0000000000000000
 >   flags: 00000000 (type: regular attr: -)
 >   reserved1: 0x0  reserved2: 0x0  reserved3: 0x0
 >  Section: __const          __DATA           (bfdname: .const_data)
 >   addr: 0000000000347a70 size: 0000000000001008 offset:  
0000000000346a70
 >   align: 4  nreloc: 0  reloff: 0000000000000000
 >   flags: 00000000 (type: regular attr: -)
 >   reserved1: 0x0  reserved2: 0x0  reserved3: 0x0

We obviously know how to deal with all of the preceding sections...

 >  Section: __static_data    __DATA           (bfdname:  
__DATA.__static_data)
 >   addr: 0000000000348a80 size: 0000000000000031 offset:  
0000000000347a80
 >   align: 4  nreloc: 0  reloff: 0000000000000000
 >   flags: 00000000 (type: regular attr: -)
 >   reserved1: 0x0  reserved2: 0x0  reserved3: 0x0

While unexmacosx.c doesn't yet know how to deal with  
__DATA.__static_data, it would be easy enough to add it: just dump  
from memory, like __DATA.__data.  (Apple's own assembler even has a  
".static_data" shorthand for switching this section, they just never  
got around to making the compiler actually use it.)  The real trouble  
is with these sections:

 >  Section: __bss4           __DATA           (bfdname: __DATA.__bss4)
 >   addr: 0000000000348ac0 size: 0000000000006554 offset:  
0000000000000000
 >   align: 4  nreloc: 0  reloff: 0000000000000000
 >   flags: 00000001 (type: zerofill attr: -)
 >   reserved1: 0x0  reserved2: 0x0  reserved3: 0x0
 >  Section: __bss2           __DATA           (bfdname: __DATA.__bss2)
 >   addr: 000000000034f014 size: 000000000002fb68 offset:  
0000000000000000
 >   align: 2  nreloc: 0  reloff: 0000000000000000
 >   flags: 00000001 (type: zerofill attr: -)
 >   reserved1: 0x0  reserved2: 0x0  reserved3: 0x0
 >  Section: __pu_bss2        __DATA           (bfdname:  
__DATA.__pu_bss2)
 >   addr: 000000000037eb7c size: 0000000000005414 offset:  
0000000000000000
 >   align: 2  nreloc: 0  reloff: 0000000000000000
 >   flags: 00000001 (type: zerofill attr: -)
 >   reserved1: 0x0  reserved2: 0x0  reserved3: 0x0
 >  Section: __pu_bss4        __DATA           (bfdname:  
__DATA.__pu_bss4)
 >   addr: 0000000000383f90 size: 00000000000085e4 offset:  
0000000000000000
 >   align: 4  nreloc: 0  reloff: 0000000000000000
 >   flags: 00000001 (type: zerofill attr: -)
 >   reserved1: 0x0  reserved2: 0x0  reserved3: 0x0

You see, recent versions of GCC generate more-or-less arbitrarily many  
BSS sections on Darwin (see the darwin_output_aligned_bss () function  
in gcc/config/darwin.c).  This is a problem for us because of what we  
try to do with BSS sections:

       else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0)
         {
           extern char *my_endbss_static;
           unsigned long my_size;

           sectp->flags = S_REGULAR;

           /* Clear uninitialized local variables in statically linked
              libraries.  In particular, function pointers stored by
              libSystemStub.a, which is introduced in Mac OS X 10.4 for
              binary compatibility with respect to long double, are
              cleared so that they will be reinitialized when the
              dumped binary is executed on other versions of OS.  */
           my_size = (unsigned long)my_endbss_static - sectp->addr;
           if (!(sectp->addr <= (unsigned long)my_endbss_static
                 && my_size <= sectp->size))
             unexec_error ("my_endbss_static is not in section %.16s",
                           sectp->sectname);
           if (!unexec_write (sectp->offset, (void *) sectp->addr,  
my_size))
             unexec_error ("cannot write section %.16s", sectp- 
 >sectname);
           if (!unexec_write_zero (sectp->offset + my_size,
                                   sectp->size - my_size))
             unexec_error ("cannot write section %.16s", sectp- 
 >sectname);
           if (!unexec_write (header_offset, sectp, sizeof (struct  
section)))
             unexec_error ("cannot write section %.16s's header",  
sectp->sectname);
         }

To do this for these new BSS sections, we'd need to insert dummy  
markers into each of these sections.  This would be manageable enough  
if it were only these four, but it isn't necessarily: there are two  
categories we care about (__bss, used for statics, and __pu_bss, used  
for globals; the other two are for zero-length objects), and these  
each get one section per object alignment.

For example, take a gander at this:

iMac:ppc user$ otool -arch ppc -l /sw/src/fink.build/gcc47-4.7.1-1000/ 
darwin_objdir/gcc/cc1plus | grep bss
   sectname __bss2
   sectname __pu_bss2
   sectname __bss3
   sectname __pu_bss0
   sectname __pu_bss3
   sectname __bss1
   sectname __bss12
   sectname __bss0

Now, we could *still* add a bunch of dummy variables to deal with all  
alignments within some range, but this might end up wasting a lot of  
space for the higher alignments (in theory, I think it could be kept  
down to 4x the highest alignment), and would be quite ugly in any  
case.  (Also, the numbers appear to be log2(alignment) in GCC 4.7 but  
just aligment in GCC 4.6.)  Unfortunately, it seems that Apple's tools  
don't like zero-length sections/objects, so we can't use those for the  
markers (and for which reason they get their own sections).  How zero- 
length objects (which on other platforms are allowed to share  
addresses with other objects) could be of any use in their own  
sections is beyond me...

I suppose, though, that if we could be sure that we aren't linking in  
any static libraries with these *new* BSS sections which will have  
trouble because of Emacs' dumping them, we could just skip that part;  
then all we'd need to do is make sure that my_endbss_static refers to  
an address in __DATA.__bss, not __DATA.__bss1 or __DATA.bss2 like it  
would naturally end up at on GCC 4.6 or 4.7 (respectively).  (And make  
unexmacosx.c dump these new BSS sections, of course.)