Watch, Follow, &
Connect with Us

Please visit our new home
community.embarcadero.com.

Public Report
Report From: Kylix/Linker/ILINK32    [ Add a report in this area ]  
Report #:  2813   Status: Open
Large libs and apps cannot be linked
Project:  Kylix Build #:  4.186
Version:    3.0 Submitted By:   Felix Edgar Klee
Report Type:  Crash / Data loss / Total failure Date Reported:  11/4/2002 12:34:43 AM
Severity:    Infrequently encountered problem Last Updated: 3/20/2012 2:24:39 AM
Platform:    Kylix C++ IDE Internal Tracking #:   155951
Resolution: None  Resolved in Build: : None
Duplicate of:  None
Voting and Rating
Overall Rating: (7 Total Ratings)
5.00 out of 5
Total Votes: 15
Description
When trying to link a very large application, shared object, or static library the linker emits the error message
    Assertion failed: specialSymIndex < specialSymIndexLimit at         "../exemaker.c", line 157
While this will not be a problem for most people, it happened to me when trying to link QT 3.0.5. I also know of someone who tried to statically link a large geospatial application and got the same error message.
Steps to Reproduce:
To reproduce the error message I wrote a little program than can create sources of arbitrary size.

Making the source creation program:
1. Download the attached files.
2. Setup the Kylix command line environment:
   source <your-kylix-install-path>/bin/kylixpath
3. Run make. This will create an executable called "create".

To create a large source:
1. Run "create" as follows:
     ./create nFiles nClasses nFuncs nParams \
              fileBaseName classBaseName \
              funcBaseName paramBaseName
   In case you don't want to specify all values, the defaults are
     nFiles = 0, nClasses = 0, nFuncs = 0, nParams = 0,
     fileBaseName = "foo", classBaseName = "Foo",
     funcBaseName = "f", paramBaseName = "x"
   For example
     ./create 100 100 10 5
   will create 100 files, each with 100 classes that contain 10 functions with 5
   parameters. This code base is large enough to trigger the error message.

To see the error message:
1. Open the Kylix C++ IDE
2. Create a new shared object project (I always uncheck "Use CLX" and
   "Multithreaded"). Alternatively, you can also create a new
   library project or a new console application project.
3. Add the sources created with "create" to the project.
4. Hit Ctrl-F9 to make the project. If your system behaves like mine, after a
   while you'll get the following error message repeated several times:
     [Linker Error] Fatal: Assertion failed: specialSymIndex <
     specialSymIndexLimit at "../exemaker.c", line 157
   Note that for an extremely large code base I get other errors instead. I
   didn't get them in real life projects, though.
Workarounds
Splitting the code base into several smaller shared objects should work. However, this workaround is hardly an option when trying to link existing code bases that cannot easily be split up, eg. the QT library. Also, adding dll exporting of classes to existing code bases might be tedious.
Attachment
2813.zip
Comments

Garrett Potts at 11/4/2002 5:09:53 AM -
We are evaluating Borland as a potential development tool for our projects here at work.  Because of this error we are unable to compile our libraries using your compiler.  This bug is critical in our decision to use Borland as a development tool for the Linux environment.

Stefan Hoffmeister at 11/4/2002 5:50:17 PM -
You might want to call Borland then and contact a Borland Support Engineer.

This engineer might be able to provide you with a special hot fix, depending, of course, on a number of factors.

Matthias Thoma at 2/22/2003 2:19:30 PM -
Yep, I can reproduce that. Doesn't happen with gcc :-)

Eric Sanford at 12/26/2007 4:37:50 PM -
In ilink, MakeFullExe calls Initialize, which reserves memory for 100000 symbols.

A1 24 B8 0C 08     mov     eax, ds:gsxCnt
8B 15 A4 29 0C 08  mov     edx, ds:specialSymIndex
81 C2 60 79 FE FF  add     edx, FFFE7960h ; edx = edx - 100000
89 C1              mov     ecx, eax
29 D1              sub     ecx, edx
89 0D A8 29 0C 08  mov     ds:specialSymIndexLimit, ecx
....
A1 24 B8 0C 08     mov     eax, ds:gsxCnt
05 A0 86 01 00     add     eax, 186A0h     ; eax = eax + 100000
89 C2              mov     edx, eax
89 D0              mov     eax, edx
C1 E0 04           shl     eax, 4
50                 push    eax
E8 C5 38 FE FF     call    mem_malloc
....
A1 24 B8 0C 08     mov     eax, ds:gsxCnt
05 A0 86 01 00     add     eax, 186A0h     ; eax = eax + 100000

As a workaround, patch 3 lines in Initalize to reserve more memory for symbols.

A1 24 B8 0C 08     mov     eax, ds:gsxCnt
8B 15 A4 29 0C 08  mov     edx, ds:specialSymIndex
81 C2 E0 5E F8 FF  add     edx, FFF85EE0h  ; edx = edx - 500000
89 C1              mov     ecx, eax
29 D1              sub     ecx, edx
89 0D A8 29 0C 08  mov     ds:specialSymIndexLimit, ecx
....
A1 24 B8 0C 08     mov     eax, ds:gsxCnt
05 20 A1 07 00     add     eax, 7A120h     ; eax = eax + 500000
89 C2              mov     edx, eax
89 D0              mov     eax, edx
C1 E0 04           shl     eax, 4
50                 push    eax
E8 C5 38 FE FF     call    mem_malloc
....
A1 24 B8 0C 08     mov     eax, ds:gsxCnt
05 20 A1 07 00     add     eax, 7A120h     ; eax = eax + 500000

In the ilink and ilink.so binaries distributed with Kylix 3 Open Edition, the byte sequences representing decimal +- 100000 (A0 86 01 00 and 60 79 FE FF) only appear in the Initalize function and only to hard-code specialSymIndexLimit.  Accordingly, replacing all instances of these byte sequences with +- 500000 (20 A1 07 00 and E0 5E F8 FF) may resolve the problem. For example, a perl script could be used to increase specialSymIndexLimit in ilink and ilink.so, example below:

perl -pe 's/\xA0\x86\x01\x00/\x2

Eric Sanford at 12/26/2007 4:46:50 PM -
Re-sending perl script (cut-off in previous comment)
perl -pe 's/\xA0\x86\x01\x00/\x20\xA1\x07\x00/g' ilink > ilink.tmp
perl -pe 's/\x60\x79\xFE\xFF/\xE0\x5E\xF8\xFF/g' ilink.tmp > ilink.1

Server Response from: ETNACODE01