Subject: Large C++ program problem
To: None <port-alpha@NetBSD.ORG>
From: Cliff Romash <romash@BBN.COM>
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
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:
.ident "GCC: (GNU) 126.96.36.199"
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