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
rather
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
__fini:
ldgp $29,0($27)
__fini..ng:
lda $30,-16($30)
.frame $30,16,$26,0
stq $26,0($30)
.mask 0x4000000,-16
.prologue 1
bsr $26,__dtors..ng
ldq $26,0($30)
addq $30,16,$30
ret $31,($26),1
.end __fini
.ident "GCC: (GNU) 2.7.2.2"
and here is the diff from my change:
108c108
< extern void __fini(void) __attribute__((section(".fini")));
---
> extern void __fini(void);
Any guidance on this is greatly appreciated.
Cliff Romash, GTE Internetworking