community.borland.com

Article #15961: Coping with 'Fixup Overflow' messages.

 Technical Information Database

TI961C.txt   Coping with 'Fixup Overflow' messages.            
Category   :General
Platform    :All
Product    :Borland C++  3.1    

Description:
       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  |
  \* --------- */
       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:
  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
  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
       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
       --------  -------
       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
  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.


Reference:


7/2/98 10:39:27 AM
 

Last Modified: 01-SEP-99