Subject: Re: nbgroff chokes on -current sparc64
To: matthew green <mrg@eterna.com.au>
From: James Chacon <jchacon@genuity.net>
List: tech-toolchain
Date: 12/01/2001 05:13:50
>   On Thu, Nov 22, 2001 at 12:07:04AM +0000, David Brownlee wrote:
>   > 	Looks like the sparc64 c++ issues now prevent a native build for
>   > 	sparc64 current?
>   > 
>   > [ tail of build log ]
>   > building llib-lc.ln
>   > Lint pass2:
>   > /var/obj/tooldir/bin/nbgroff -Tascii -mtty-char -mandoc 
>   >    /home/netbsd/current/lib/libc/db/man/btree.3  > btree.cat3
>   > /usr/lib/libstdc++.so.4: Undefined symbol "" (reloc type = 54, symnum = 18)
>   >[...]
>   
>   just to make sure it isn't the sparc64 instance of misc/13927 (although 
>   this libstdc++.so problem seems to be older):
>   
>   Can you please run 
>    objdump -R /usr/lib/libstdc++.so.4 
>   and look for occurrences of R_SPARC_UAdd, where dd are two digits 
>   (presumably 64)?
>
>
>FWIW, i tried the similar patch for elf64_sparc.c but it didn't
>seem to make any difference for the sparc64 lossage.... that's
>why i didn't commit it.

I did some more testing and here's what I was able to determine.

Apply Michael's patch and the reloc errors will go away (as expected since
the UA64 reloc's don't appear in the final output anymore). What you need
to do is 

1. Build a new compiler with the patch
2. Rebuild libstdc++ with the patch and reinstall it
3. Then try to run nbgroff again

Now you'll die in an alighment error which is a bit more promising to
see what's going on. (The address in question is 4 byte aligned, but not 8
byte).

Tracking this down in the exception code I found the eh code header that
gets put at the beginning of the eh_frame section only does 4 byte alignment
of the reference to __EXCEPTION_TABLE__ which will be a problem then if
that's actually eventually used as a 64bit address ref later on.

The attached patches will address this by forcing this to 8
byte aligned (just make the identifier string longer and have the routines
searching for it look for either the old or the new tag).

This fixes enough things so groff will now function (it was formatting man
pages just fine for me).

I went ahead and checked gcc 3.0.2 to see how's it been done moving forward
and this whole section got rewritten to allow for targets which force
alignment and then it forces alignment based on target bit size for long long.
So unless that code is pulled back any fix along the lines I have below is
probably local only.

These patches need serious testing before actually applying/committing unless
they get wrapped in some way to only apply on sparc64 for now (I'm not
going to chance blowing up exception handling for all other ports...)

I also beleive the other patch posted is also needed and should be committed.
It catches any UA64's which fall through and by that point they're misaligned
if they got that far (as far as 64 bit alignment goes) so the resulting
binary should core on an alignment fault (which is better in my mind than
a reloc error).

If you're going to use these patches and your installed libstdc++ is bad
you'll need to do as I described above (build a new toolchain, build and
install a replacement libstdc++) before attempting a build. The toolchain 
build does presume a working local compiler which isn't the case if you
have the libstdc++ output from before this change.

Thoughts?

James

Index: gnu/dist/toolchain/gcc/dwarf2out.c
===================================================================
RCS file: /cvsroot/gnusrc/gnu/dist/toolchain/gcc/dwarf2out.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 dwarf2out.c
--- gnu/dist/toolchain/gcc/dwarf2out.c  2001/04/23 11:58:11     1.1.1.2
+++ gnu/dist/toolchain/gcc/dwarf2out.c  2001/12/01 10:11:18
@@ -1787,17 +1787,18 @@
   if (eh_ptr)
     {
       /* The CIE contains a pointer to the exception region info for the
-         frame.  Make the augmentation string three bytes (including the
-         trailing null) so the pointer is 4-byte aligned.  The Solaris ld
-         can't handle unaligned relocs.  */
+         frame.  Make the augmentation string seven bytes (including the
+         trailing null) so the pointer is 8-byte aligned.  The Solaris ld
+         can't handle unaligned relocs and this needs to handle 32 and 64 bit
+        compilers. */
       if (flag_debug_asm)
        {
-         ASM_OUTPUT_DWARF_STRING (asm_out_file, "eh");
+         ASM_OUTPUT_DWARF_STRING (asm_out_file, "ehfrme");
          fprintf (asm_out_file, "\t%s CIE Augmentation", ASM_COMMENT_START);
        }
       else
        {
-         ASM_OUTPUT_ASCII (asm_out_file, "eh", 3);
+         ASM_OUTPUT_ASCII (asm_out_file, "ehfrme", 7);
        }
       fputc ('\n', asm_out_file);
 
Index: gnu/dist/toolchain/gcc/frame.c
===================================================================
RCS file: /cvsroot/gnusrc/gnu/dist/toolchain/gcc/frame.c,v
retrieving revision 1.2
diff -u -r1.2 frame.c
--- gnu/dist/toolchain/gcc/frame.c      2001/10/05 07:35:04     1.2
+++ gnu/dist/toolchain/gcc/frame.c      2001/12/01 10:11:18
@@ -564,14 +564,18 @@
 
   c->augmentation = get_cie (f)->augmentation;
 
+  /* "eh" is the old form and "ehfrme" is the current string. Check for either
+     to retain compatibility with objects. */
   if (strcmp (c->augmentation, "") != 0
       && strcmp (c->augmentation, "eh") != 0
+      && strcmp (c->augmentation, "ehfrme") != 0
       && c->augmentation[0] != 'z')
     return 0;
 
   p = c->augmentation + strlen (c->augmentation) + 1;
 
-  if (strcmp (c->augmentation, "eh") == 0)
+  if ((strcmp (c->augmentation, "eh") == 0) ||
+      (strcmp (c->augmentation, "ehfrme") == 0))
     {
       c->eh_ptr = read_pointer (p);
       p += sizeof (void *);