Subject: Large C++ program problem
To: None <port-alpha@NetBSD.ORG>
From: Cliff Romash <romash@BBN.COM>
List: port-alpha
Date: 01/27/1998 21:34:29
I'm not sure if this is the correct forum for this, but I am looking for
guidance on a NetBSD related problem that has recently cropped up here at
GTE Internetworking.

One of our programmers is developing a large C++ application, whose text
segment has recently grown to just larger than 4 megabytes. This week, he
started receiving a link error, as follows:

/usr/lib/crtbegin.o: In function `__dtors':
crtbegin.c(.fini+0x10): relocation truncated to fit: BRADDR text

My reading of this is that a branch address at .fini+0x10 had to be
truncated to fit the available instruction space. 

After some poking, I pulled out the source to lib/csu/alpha/crtbegin.c, and
discovered that .fini+0x10 was a bsr instruction in __fini that was
branching to a static function __dtors in the same file. But __fini was
being explicitly put into section .fini by the C code in crtbegin.c. This
was resulting in __fini being AFTER the .text section, while __dtors was
BEFORE the text section. Since the user's text section had recently grown
bigger than 4 megabytes, the displacement on the bsr in __fini could not
reach __dtors (if my understanding is correct, a bsr instruction on an
Alpha has a 21 bit displacement word field, for a 4MB limit).

I have temporarily resolved the problem by removing the 
--attribute__((section(".fini"))) from the prototype declaration for __fini
in crtbegin.c. This was originally just a wild stab on my part, although my
investigation leads me to believe this is at least reasonable. Probably a
better fix might be to put __dtors into the same section as __fini. Or
possibly to compile ctrbegin.c with an option that forces bsr's to become
jsr's, if there is such.

I looked at the -current version of crtbegin.c, but saw no differences, so
I assume this problem is still lurking. I'd be happy to send a pr, but I'm
unsure of what I'm doing here and thought I'd try the mailing list first.

Here's the assembly code for __fini from the original version of crtbegin:

.section        .fini,"ax",@progbits
        .align 3
        .globl __fini
        .ent __fini
        ldgp $29,0($27)
        lda $30,-16($30)
        .frame $30,16,$26,0
        stq $26,0($30)
        .mask 0x4000000,-16
        .prologue 1
        bsr $26,
        ldq $26,0($30)
        addq $30,16,$30
        ret $31,($26),1
        .end __fini
        .ident  "GCC: (GNU)"

and here is the diff from my change:

< extern void __fini(void) __attribute__((section(".fini")));
> extern void __fini(void);

Any guidance on this is greatly appreciated.

Cliff Romash, GTE Internetworking