atom feed2 messages in com.omnigroup.macosx-devRe: relocation overflow
FromSent OnAttachments
Jeff TerryOct 26, 2000 4:17 pm 
Guy EnglishOct 26, 2000 6:36 pm 
Subject:Re: relocation overflow
From:Guy English (guy.@sympatico.ca)
Date:Oct 26, 2000 6:36:49 pm
List:com.omnigroup.macosx-dev

Hi,

On Thursday, October 26, 2000, at 07:18 PM, Jeff Terry wrote:

I am having trouble compiling a program. I get the following error:

/usr/bin/ld: /usr/lib/crt1.o relocation overflow for relocation entry 24 in
section (__TEXT,__text) (displacement too large) /usr/bin/ld: /usr/lib/crt1.o relocation overflow for relocation entry 29 in
section (__TEXT,__text) (displacement too large)

This program was a very large fortran program that I used f2c on to convert to
c. The program compiles but will not link. I get the above link errors. Does anyone have any
idea what to do in this case.

I had the same problem on DP3. The error is basically caused by having a huge
statically allocated array. I asked about it here and got no reply so I asked on
Darwin-Development and Chris Kane of Apple was kind enough to help me out.
Attached is a big series of email where we discuss the problem and come to a
solution. Sorry for burdening the list like this but I've had three or four
people mail me directly after finding my question in the list archives and this
way people will find a complete explanation to go along with the question...

Guy

------------------------------------------------- I posted the same mail on Darwin-Development and got some great help from the
Apple engineers there. I suggest you check it out for any of this Darwinish kind
of stuff.

My problem turned out to be that I has a *huge* array. It was a temp hack to
something we were working on and was the last thing on my mind, of course. It
all got much better when I started allocating it at run time. You may have a
slightly different problem so you'll find attached all the correspondence I had
with Chris Kane of Apple were he goes through the process with me. Some of his
email was off-list and is now on my old machine which isn't hooked up right now.
I patched this together from the Darwin-Developer list archives at:
darwin.anu.edu.au

Its long but I found it very helpful:

------------------------------------------------------------------ From: Guy English Date: Sat, 13 May 2000 13:26:38 -0500

Hi,

Sorry for the long code-ridden post...

I've been trying for days now to get my project to compile on DP3. The code base compiles clean on Linux and Windows but craps out during the linking stage on Darwin/DP3. Here is the error message:

/usr/bin/ld: /lib/crt1.o relocation overflow for relocation entry 20 in section (__TEXT,__text) (displacement too large)

This is the most simple example of this problem I can find. This code compiles and runs on FreeBSD 4.0 but runs into the linking problem on Darwin:

#include

static char test[1024 * 35000]; // <- this is the problem

int main( void ) { printf( "Hello, world!\n" );

return 0; }

Darwin 1.0 cc -v: Apple Computer, Inc. version cc-792, based on gcc driver version 2.7.2.1 executing gcc version 2.8.1-egcs

FreeBSD 4.0 cc -v: Using builtin specs. gcc version 2.95.2 19991024 (release)

After looking at the source for Darwins ld I find this is where the error is being detected:

cctools-318-3_0/cctools-3/ld/ppc_reloc.c line 815:

if((value & 0xfffe0000) != 0xfffe0000 && (value & 0xfffe0000) != 0x00000000) error_with_cur_obj("relocation overflow " "for relocation entry %lu in section " "(%.16s,%.16s) (displacement too large)" , i, section_map->s->segname, section_map->s->sectname);

I tried simply commenting out the check. :) But I couldn't get the cctools project to compile. It was missing some headers files.

Here are my questions:

a) Is there a maximum size to the text segment under mach-o, what is it, and is there a known work around.

b) Is there a known bug with ld that prevents large text segments and if so what are the alternatives.

c) Am I just missing something obvious?

I should note that the actual project doesn't just have one large string in it. I've changed most of the statically allocated arrays into calls to malloc(), Taken all the wide characters strings out of the project ( L"Hello World" ), and compiled with all the nastiest warnings. The strings that remain are basic operation of the program.

If anyone has any ideas, please, please put me out of my misery.

Thanks, Guy

------------------------------------------------------------------ From: Chris Kane Date: Sat, 13 May 2000 19:38:19 -0700

Guy English wails:

Here is the error message: /usr/bin/ld: /lib/crt1.o relocation overflow for relocation entry 20 in section (__TEXT,__text) (displacement too large) [...]

#include static char test[1024 * 35000]; // <- this is the problem int main( void ) { printf( "Hello, world!\n" ); return 0; }

My (long, it's complicated) analysis, take with salt. Delve in only if you are 1) fascinated by linkers and linkage, or 2) Guy.

What is happening is that the compiler compiles up code into assembly language instructions, some of which use immediate values (constants put into the instruction), and some don't. The compiler leaves the actual values "blank", and spits out information for the linker to fix all these up when linkage is done. During linkage, the linker has found (because it is getting several compilation units, and has a somewhat bigger picture than the compiler) that it has to put a value in an instruction which is too large for the instruction (on ppc, many instructions which take immediates have only 16 bits for immediate values). The linker can't rewrite the particular instructions the compiler has emitted (to a sequence of instructions which would allow for a larger displacment, like load into the ctr register, and branch through that). Thus the error.

To dump the relocation entries, do `otool -v -r crt1.o` (since the linker is complaining about that .o), find the section with starting with (__TEXT,__text) in the label, and count down 20 (I get two errors, one at 20, one at 25, on my system). I think the indexing starts at 0. If I disassemble crt1.o with `otool -tV`, I get two "bl" instructions at the addresses indicated by the relocation entries.

At this point, you take down your PPC Programming Environments manual and discover that the branch-and-link instruction can have a 26-bit offset. The branches in crt1.o which are having trouble are branches to addresses stored in the __DATA __common se pushed too far away from the code by that big data symbol (which, since you didn't initialize it, ends up in the __bss section). That is, these function pointers being branched to are specially declared so that they don't have to be defined (they'll be 0 if they're not defined, and then not called).

% size -m a.out Segment __PAGEZERO: 4096 Segment __TEXT: 4096 Section __text: 648 Section __cstring: 148 Section __picsymbol_stub: 72 total 868 Segment __DATA: 33554432 Section __data: 16 Section __la_symbol_ptr: 8 Section __nl_symbol_ptr: 20 Section __dyld: 20 Section __bss: 33553408 Section __common: 64 total 33553536 Segment __LINKEDIT: 4096

(I reduced the size to 32MB - 1K to produce a working binary.)

Why does the limit seem to relate to 32MB (2^25) rather than 2^26? The 26-bit displacement is a signed displacement.

When the common symbols are defined, the branches get the filled in with good values which are to the picsymbol stub for that function which the linker inserts into the binary. But when the functions aren't defined, the branches remain, trying to branch a long distance to the common symbol (which is 0, and not a valid instruction, but the branch won't be attempted if the value is zero, so that's harmless at execution time). When the linker tries to fix those branches up, albeit to bogus and uninteresting values, the distance is too large. [This is all voodoo having to do with the linkage semantics of C and this light haquery with these "external" symbols in crt1.o.]

A similar problem would result, but in a somewhat different way, if the functions were defined, and a lot of constant strings pushed the __text and __picsymbol_stub sections too far apart. That might be worked-arond by -fwritable-strings, which might put them in the __DATA segment instead, though I haven't tried that. It'd also be solved for the lots-of-strings case by the linker ordering the sections with executable code in them together (__text and __picsymbol_stub here). [Possibly a linker bug could be filed f this -- it's probably a simple change too.] (Even if the functions aren't defined, lots of __cstring is going to push __text and __common apart.)

A huge __text section alone would still push parts of it too far away from the __picsymbol_stub section and there would be trouble in some scenarios. That could be solved by not using lots of big .a files or whatever, but putting some code in a dynamic library(s) instead, to shrink the __text size.

The answer for this little test program would be that it's better to malloc -- lazily when first needed -- the data rather than declaring a huge array to be put in the binary. (If you cause the array to be initialized with "= {0};" on the end of the definition, then the variable goes in the __DATA __data section, and the binary is 32MB+ in size!)

Chris Kane Application Frameworks, Apple, Inc.

------------------------------------------------------------------ From: Guy English Date: Sun, 14 May 2000 22:46:57 -0500

Hello again.

Run `size -m` on the .o file. Look for large numbers. Those are likely your trouble spots.

Try `ld -r -o new.o /lib/crt1.o your.o`. Look at new.o's numbers.

The biggest sections are:

Section (__DATA, __bss): 73968068 Section (__TEXT, __text): 404440 Section (__DATA, __data): 33449 Section (__TEXT, __const): 5800

ls -l: ... 768324 pit.o ...

I can't, without changing the way my program works, shrink the __text section down much further. What I'm confused about is that the "bl" instruction has a signed 26 bit argument and the whole file should fit inside that range...

I'm adding AppKit, Foundation and NSGL using -framework. Am I doing something wrong there? From examining ProjectBuilders output it does the same thing.

Would it be possible to compile my whole game into a dynamic library and write a little loader we the c run time in it? All the loader would do is load up the game dynlib, and call its entry point. Would that skirt the problem?

Guy

------------------------------------------------------------------ In a lost email: ...Chris basically tells me that no it wouldn't work because the dynamic library
would have the same problems...

------------------------------------------------------------------ From: Guy English Date: Sun, 14 May 2000 23:51:18 -0500

Chris,

I finally nailed down the problem. While grasping at straws I was doing a 'size -m' listing on all the .o files.

menu.o caught my eye...

Segment : 74009136 ... Section (__DATA, __bss): 73957168 <- !!!! ... total 74009136

Turns out another team member had slipped this in while I wasn't looking:

static MENU_INPUT_EVENT menuEvents[1000]; static MENU_INPUT_EVENT menuPlaybackEvents[5000];

MENU_INPUT_EVENT is a pretty big structure too, so it bulked up a *huge* amount.

Thanks a lot for you suggestions, they proved invaluable.

I'm still surprised that the Apple linker couldn't handle this while Windows and Linux had no problem. Is the limitation because of the 'bl' instructions range? Does Intel use a full 32bit ( signed ) offset?

Thanks again, Guy

------------------------------------------------------------------ In another lost email: Yes the limitation is because of the bl instruction. It could possibly be
considered a bug that the compiler emits them when it could determine that they
would break. Best solution is, "Don't do that". Dynamically allocate large
arrays.

Project Leader/Lead Programmer StrategyFirst, Inc.