Why do I get the fixup error, and how can I correct it?

There are a number of fixup-related errors, and all roughly mean the same thing. They are all produced by the linker application and have the form:

(476) fixup overflow referencing %s %s (location 0x%lX (0x%lX+%d), size %d, value 0x%lX)
(477) fixup overflow in expression (location 0x%lX (0x%lX+%d), size %d, value 0x%lX)
(1267) fixup overflow referencing %s %s (0x%lX) into %d byte%s at address 0x%lX (%s%s%s %d/0x%X)
(1268) fixup overflow storing 0x%lX in %d byte%s at address 0x%lX (%s%s%s %d/0x%X)
(1356) fixup overflow referencing %s %s (0x%lX) into %d byte%s at 0x%lX/0x%X -> 0x%lX (%s%s%s %d/0x%X)
(1357) fixup overflow storing 0x%lX in %d byte%s at 0x%lX/0x%X -> 0x%lX (%s%s%s %d/0x%X)

where the printf-style placeholders will be replaced with names and values, and the numbers in brackets are the error numbers that uniquely identify the message. The latter two messages are actually replacements for the others. They contain additional information to help you understand what is happening. You will see the other messages on earlier versions of the compiler.

Most of the confusion arising as a result of this error message relates to the fact that most people do not know what the process of fixup is. That makes it difficult to understand the error. So what is fixup?

When you reference a symbol in either C or assembly code, the generated opcodes ultimately produced by the assembler cannot be completed because at that time the addresses of the symbols are not known. The binary opcodes are output with zeros in the opcode value where the symbol address would normally be located. Other information is output to tell the linker how to adjust the opcodes once the addresses of the symbols are determined. The process of adjusting the opcodes with the actual numeric addresses is called fixup.

Now consider the case when the symbol address should take up, say, eight bits in the opcode, but the linker determines the address to be substituted is a value like 0x110, which is larger than eight bits in size. In this case, the fixup process has overflowed and this is exactly what the error indicates.

So what causes this? In rough order of likelihood, this error is generated by:

  • Hand-written assembly code that did not include the required address masking
  • Incorrect bank qualifiers
  • Functions or statements (e.g. switch statements) that are too big
  • Incorrect linker options defined by the programmer

If you determine that none of the above-mentioned reasons are cause for the fixup error, please send a message to Microchip Support for further analysis.

In order to determine the cause, you need to find out the assembly instruction that triggered the error. If you received error messages 1356 or 1357, then the job is easy. Depending on the exact cause, the file and line number information produced in the error may be valid and you can find the offending C code. However, even if this is the case, remember the error relates to an assembly instruction and to look at that in detail, you will probably want to look at the assembly listing file.

Example 1:

If an assembler instruction has an 8-bit field to hold an address and the linker determines that the symbol that has been used to represent this address is greater than eight bits (say, 0x110), then this value cannot be used with the instruction. This will cause a fixup error.

Example 2:

main.c: 11: (1356) fixup overflow referencing psect nvBANK2 (0x110) into 1 byte...
...at 0xFDA/0x2 -> 0x7ED (main.obj 30/0x8)

Open the list file main.lst generated after the main.c is built, and look for address 0x7ED. If you are not sure where the addresses are located, read the assembler section in the manual to understand the list file. Once you can see the assembly at fault, you can determine if this was something handwritten or generated by the compiler.

If it is the handwriting assembly code, check the device datasheet to determine the exact size of the instruction operands. Operands for some instructions are less than eight bits wide (operand size is seven for movwf on some 8-bit devices). When using symbols as operands, ensure that the address has been masked, if required. Often, upper bits of an address relate to a bank or page number and the instruction operand is an offset into these banks or pages.

For a PIC18 device hand written assembly as this may cause fixup error:

because _output is eight bits wide (max value 0xFF), but the operand that the movwf can take is only seven bits wide (max operand 0x7F).

To prevent fixup, select the bank in which the _output resides. Mask the upper bit of the _output to truncate it to the max size of 0x7F, and then move the 7-bit data.

Check the compiler manual for more details about the fixup process.

© 2024 Microchip Technology, Inc.
Notice: ARM and Cortex are the registered trademarks of ARM Limited in the EU and other countries.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.