PRODUCT : Borland C++ NUMBER : 1150 VERSION : 3.1 OS : All DATE : October 19, 1993 PAGE : 1/7 TITLE : Coping with 'Fixup Overflow' messages. Are you getting fixup overflow messages? Here's a plan of attack to get rid of them. Note that this is not the same as the 'NO STUB FOR FIXUP' message, for which you would usually want to recompile all modules with overlay support. This document presumes that you have TASM.EXE, which ships with the Borland C++ package. The most common reason why you might get a fixup overflow error message is if you've switched from one memory model to another. If some of your object files (.OBJs) or libraries (.LIBs) are in one memory model, and others are in another model, the linker may not properly fixup (or match) addresses for the symbols that it gets from the compiler. The best way to find out if this is the case is to do a Build All (under the Compile menu in the Integrated Development Environment, aka IDE) or force recompilation of all object files (with the command-line compiler, aka BCC). If this doesn't solve your problem, roll up your sleeves and keep reading. If a Build All doesn't solve the problem, then the error almost always occurs because you've used a near symbol (variable or function) when it should have been far or you've used a far one when it should have been near. [NOTE: the 'near' and 'far' keywords are not restricted to pointers and in this context refer to the accessibility of the symbol: accessible from an assumed segment, and not accessible from the assumed segment respectively]. Solving a fixup overflow error involves careful inspection of your code to make sure that all symbols that are expected to be near really are near and that all variables that are expected to be far really are far. The following paragraphs describe an example that creates a fixup overflow error message and shows you the step-by-step solution to what went wrong. To create our fixup overflow error message, we use two files: ASSEM.ASM and MAIN.CPP. /* --------- *\ | ASSEM.ASM | \* --------- */ PRODUCT : Borland C++ NUMBER : 1150 VERSION : 3.1 OS : All DATE : October 19, 1993 PAGE : 2/7 TITLE : Coping with 'Fixup Overflow' messages. title GLOBALVAR page 85 .sall public _cfunction myseg segment word public 'code' _cfunction label word dw 0,0 myseg ends end /* --------- *\ | MAIN.CPP | \* --------- */ #include extern "C" void pascal cTest( void ); extern void pascal far ( *cfunction )( void ); void main( void ) { cfunction = cTest; } void pascal cTest( void ) { printf( "ctest\n" ); } Now execute these commands: BCC -ml -c main.cpp TASM /Zi /Ml assem.asm TLINK c0l main assem, fixup, fixup, emu mathl cl If you are using Turbo C++ instead of Borland C++, use TCC instead of BCC. If the BCC and TASM both successfully created .OBJ files, the TLINK command should give you: PRODUCT : Borland C++ NUMBER : 1150 VERSION : 3.1 OS : All DATE : October 19, 1993 PAGE : 3/7 TITLE : Coping with 'Fixup Overflow' messages. Turbo Link Version 5.1 Copyright (c) 1992 Borland International Error: Fixup overflow at MAIN_TEXT:000B, target=_CFUNCTION in module MAIN.CPP Error: Fixup overflow at MAIN_TEXT:0005, target=_CFUNCTION in module MAIN.CPP In these error messages, MAIN_TEXT is the name of the segment in which the error occurred. This name is usually the name of the module (perhaps truncated) followed by _TEXT. The _TEXT indicates that it is a code segment. The 000B and 0005 indicate the offsets at which the error occurred. The target is the name of the symbol that the linker cannot fix up. This can either be the name of a function or the name of a variable. Offsets, targets, and module names do not always show up in a fixup overflow error message. The next step is to generate a detailed map file. To do so, use the /s option for TLINK: TLINK /s c0l main assem, fixup, fixup, emu mathl cl You should see the same fixup overflow errors as before, but you should now have a file called FIXUP.MAP in your directory. If you search for _CFUNCTION in FIXUP.MAP, you should find a line like this: 01A5:000A _CFUNCTION This doesn't show us the real value of the segment, so we need to shift the segment digits left by one to get 1A50. If we look at the top of the map file, Start Stop Length Name Class 00000H 01A3DH 01A3EH _TEXT CODE 01A3EH 01A58H 0001BH MAIN_TEXT CODE 01A5AH 01A5DH 00004H MYSEG CODE 01A60H 01A60H 00000H _FARDATA FAR_DATA 01A60H 01A60H 00000H _FARBSS FAR_BSS PRODUCT : Borland C++ NUMBER : 1150 VERSION : 3.1 OS : All DATE : October 19, 1993 PAGE : 4/7 TITLE : Coping with 'Fixup Overflow' messages. we see that 1A50 is an address in the MAIN_TEXT segment. This tells us that the error is occuring in MAIN_TEXT, which is the segment created by MAIN.CPP. We now know what segment (and consequently what module) the errors are in, and we know the offsets that they occur at--0005 and 000B. We can now look at the assembly output to see exactly what is happening. Follow these steps to generate the assembly output: BCC -ml -S main.cpp TASM /l main You should now have a file called MAIN.LST. This is called a listing file and is also known as a list file, for short. A portion of our list file is shown below. The first column indicates the line number in the list file. It is generally used just for relative referencing. The next column specifies the offset of the machine code that you are looking at. Everything after the offset is the machine code that is generated by the assembler. Also note that the C++ source code is embedded in the listing with comments. 27 0000 MAIN_TEXT segment byte public 'CODE' 28 ; 29 ; void main( void ) 30 ; 31 assume cs:MAIN_TEXT 32 0000 _main proc far 33 0000 55 push bp 34 0001 8B EC mov bp,sp 35 ; 36 ; { 37 ; cfunction = cTest; 38 ; 39 0003 C7 06 0002e 0000s mov word ptr DGROUP:_cfunction+2,seg CTEST 40 0009 C7 06 0000e 0011r mov word ptr DGROUP:_cfunction,offset CTEST 41 ; 42 ; } 43 ; 44 000F 5D pop bp 45 0010 CB ret PRODUCT : Borland C++ NUMBER : 1150 VERSION : 3.1 OS : All DATE : October 19, 1993 PAGE : 5/7 TITLE : Coping with 'Fixup Overflow' messages. We see that offset 0005 occurs on line 39 and offset 000B occurs on line 40. (If you don't see this, perhaps it may help to know that line 39 actually contains offsets 0003 through 0008 and that line 40 actually contains offsets 0009 through 000E.) Now let's take a closer look at lines 39 and 40. On line 39: C7 is byte 0003 06 is byte 0004 0002 are bytes 0005 & 0006 39 0003 C7 06 0002e 0000s mov word ptr DGROUP:_cfunction+2,seg CTEST On line 40: C7 is byte 0009 06 is byte 000A 0000 are bytes 000B & 000C 40 0009 C7 06 0000e 0011r mov word ptr DGROUP:_cfunction,offset CTEST We immediately see that these lines have _cfunction on them, so we can be fairly certain that we have arrived at the right place. Another way to verify that you have found the source of the problem is if you see XXXXe XXXXs or XXXXe XXXXr in the machine code generated for that line (where XXXX is a 4-digit number). We also see that offsets 0005 and 000B occur on addresses that depend on _cfunction. All of these things are indications that we have found the core of the problem. Now we need to understand exactly why the problem exists. For some of these XXXX values, the linker is required to fix up (or patch in) the correct value because the value was not known at the time that the source code was assembled. It will help us to know the meanings of the lowercase letters following the XXXX values. These letters are interpreted according to this chart: Notation Meaning PRODUCT : Borland C++ NUMBER : 1150 VERSION : 3.1 OS : All DATE : October 19, 1993 PAGE : 6/7 TITLE : Coping with 'Fixup Overflow' messages. -------- ------- r Indicates an offset fixup type for symbols within the module s Indicates a segment fixup type for symbols (either within the module or external) sr Indicates both segment and offset fixup type for symbols within the module e Indicates an offset fixup on an external symbol se Indicates a pointer fixup on an external symbol so Indicates a segment-only fixup + Indicates that the object code has been truncated or wrapped to the next line So, bytes 0005 and 000B both end in e. This means that _cfunction is a symbol external to the module MAIN.CPP. We know this is true because our ASSEM.ASM file declares the _cfunction variable and our MAIN.CPP declares _cfunction as extern. For some reason, the linker sees this fixup as a problem because something that really should be near is not near or something that really should be far is not far. On lines 39 and 40 above, we know that the compiler thinks that _cfunction is in DGROUP. However, if we look at our ASSEM.ASM, we know that _cfunction is in segment MYSEG, not DGROUP. To rectify the problem, we must either put _cfunction in DGROUP or make the compiler think that _cfunction is not in DGROUP so that the code above on lines 39 and 40 is generated correctly. Choosing the latter solution, we make this change to MAIN.CPP: OLD: extern void ( pascal far *cfunction )( void ); NEW: extern void ( pascal far * far cfunction )( void ); Compiling and linking again with BCC -ml -c main.cpp TASM /zi assem.asm TLINK c0l main assem, fixup, fixup, emu mathl cl PRODUCT : Borland C++ NUMBER : 1150 VERSION : 3.1 OS : All DATE : October 19, 1993 PAGE : 7/7 TITLE : Coping with 'Fixup Overflow' messages. should give us no errors. The far keyword that we added acts as a signal to the compiler to not assume that our pointer called cfunction is near. This prevents the compiler from assuming that cfunction is in DGROUP and consequently causes the linker to figure out on its own which segment it is in. Various variations of the above scenario will also cause fixup overflow messages. Watch for OBJs or LIBs with non- standard segment naming conventions, explicit usage of the 'huge', 'far' and 'near' keywords, out-of-date versions of libraries and compiler options which may affect segment configurations. DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.