RT1064: How to solve gcc linker error (.ARM.exidx+0x0): relocation truncated to fit: R_ARM_PREL31

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

RT1064: How to solve gcc linker error (.ARM.exidx+0x0): relocation truncated to fit: R_ARM_PREL31

6,452 Views
udoeb
Contributor II

Hi,

According to my understanding this linker error occurs because of the following requirements from the ARM ABI standard:

- There is a separate .ARM.exidx section created by the compiler which contains entries that refer to addresses in the code.

- Each entry in .ARM.exidx contains a 31 bit signed integer to express the offset where the code resides. One bit is used for other purposes (to indicate the type of the entry). So the maximum offset that can be stored in an entry is 0x3FFF_FFFF.

- There is exactly one .ARM.exidx section in an image.

- The .ARM.exidx section is used for C++ exception handling but also for C code. Using compiler option -fno-exceptions does not solve the problem. In my specific case the entries in .ARM.exidx are created by assembler code in irq_cm4f.o (CMSIS RTOS) and C code in libgcc.a(_udivmoddi4.o).

If parts of the code are placed in ITCM (which is the whole purpose of ITCM) then the following problem occurs:

ITCM address: 0x0000_0000

FLASH address: 0x7000_0000  Offset: 0x7000_0000

The linker produces the above error message.

For RT1052 I was able to work around this by placing .ARM.exidx in OCRAM:

ITCM address: 0x0000_0000

OCRAM address: 0x2020_0000  Offset: 0x2020_0000

FLASH address: 0x6000_0000  Offset: 0x3FE_00000

For RT1064 this approach does not work because the internal FLASH resides at 0x7000_0000:

ITCM address: 0x0000_0000

OCRAM address: 0x2020_0000  Offset: 0x2020_0000

FLASH address: 0x7000_0000  Offset: 0x4FE_00000

The linker produces the above error message.

My questions:

1. Is there a solution to this problem at the linker level? For example, is it safe to simply discard the .ARM.exidx section?

2. Is it possible to map the FLASH to a lower address? It occurs to me that choosing such high addresses for the FLASH is a bit unfortunate.

Thanks

Udo

Labels (2)
0 Kudos
10 Replies

6,162 Views
john_c_kennedy
Contributor I

I'm using the EVKMIMXRT1060. I followed the example for modifying the linker script in the MCUXpresso Users Guide section 17.15.1 for keeping the startup code in flash but moving the bulk of the application code to RAM, specifically in my case SRAM_ITC.  This gives the same link errors because the generated managed linker script puts the .ARM.extab and .ARM.exidx sections in BOARD_FLASH so any offsets to code in SRAM_ITC are greater than 0x3FFF_FFFF.  So I also added a modified exdata.ldt file to my linkscripts folder which links the .ARM.extab and .ARM.exidx sections to SRAM_ITC also.  This compiled and linked without errors.  However, when I try to debug this code I get a hard fault in the startup code when it calls data_init to move the code from BOARD_FLASH to SRAM_ITC?  Also I tried using SRAM_OC instead of SRAM_ITC, this time the debugger actually made it to main in SRAM_OC but at that point it's stuck on the first instruction, never executes beyond that?

NXP should provide additional documentation about this as it seems to be a common problem when linking code in both BOARD_FLASH and SRAM_ITC and there doesn't seem to be any examples of how to do this.  I suggest updating the MCUXpresso Users Guide section 17.15.1 to provide explicit information about this for the MIMXRT1060 family and other NXP MCUs that it may be relevant to.

Note also that adding -fno-exceptions to the complier flags does NOT solve this problem.

0 Kudos

6,162 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi,

Please refer MCUXpresso SDK for RT1064 release note, which was tested with below version ARM GCC toolchain:

Makefiles support with GNU Tools for Arm Embedded Processors 8-2018q4-major

1> Please try with mentioned GCC ARM Embedded tool chain:

Download and run the installer from launchpad.net/gcc-arm-embedded. This is the actual toolset (in other words, compiler,linker, etc.). The GCC toolchain should correspond to the latest supported version, as described in the MCUXpresso SDK
Release Notes Supporting EVK-MIMXRT1064 (document MCUXSDKMIMXRT1064RN).

2> The onchip Flash address is fixed. 

Please let us know if you still have link issue with  release note suggested GCC ARM tool chain.

Wish it helps.


Have a great day,
Mike

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

6,162 Views
udoeb
Contributor II

Hi,

I verified that the issue occurs with the latest MCUXpresso v11.0.1 release as well. So it's not related to tool chain version.

Meanwhile I found the root cause. The problem occurs if the following conditions are met:

1. The project contains a .s (assembler language) file which implements functions called from C/C++ code.

2. The functions implemented in assembler use the .fnstart/.fnend directives which create an unwind table entry for the given function. This creates an .ARM.exidx section in the .o file produced from the .s file.

3. The .o file produced from assembler code is placed in ITCM via linker script.

The linker creates a .ARM.exidx output section which is placed in FLASH. But entries in that table cannot refer to the assembler functions in ITCM because the distance exceeds 0x3FFF_FFFF. The linker produces the error

"relocation truncated to fit: R_ARM_PREL31 ...".

I experienced this issue while using CMSIS RTOSv2 which comes with irq_cm4f.s which fulfills conditions 1 and 2 above. Then I tried to place the RTOS kernel in ITCM which adds condition 3.

Possible solutions:

- Remove the .fnstart/.fnend statements from assembler code.

- If the C++ project uses -fno-exceptions then it should be safe to discard .ARM.exidx input sections using a /DISCARD/  output section in the linker script. In this case __exidx_start/__exidx_end markers should still be placed in FLASH somewhere but may refer to an empty range.

Udo

0 Kudos

1,043 Views
bp1979
Senior Contributor I

Dear @udoeb 

 

Sorry to bother you on quite an old issue, but I have the exact same error.

I thought to try if it's possible to use exception handling on an imx rt 1024,so I added -fexceptions, but after compiling (linking) received a bunch of linker errors, like:

CMakeFiles/app.dir/home/dev/app/source/hal/rtc/rtc.cpp.obj:(.ARM.exidx.RamFunction+0x0): relocation truncated to fit: R_ARM_PREL31 against `.RamFunction'

 

After googling I found you answer, which explains what goes wrong. I think I understand most of it, but I can't say it's all crisp and clear for me. In my case, I do not use any assembler files, but there of course is inline assembly in different files (both nxp provided library, but also my own code has a few lines of assembly). I guess that results in the exact same problem, where my c++ code calls into assembly and causes the problem you clearly explained?

Is there a way for to enable exceptions, AND still have ITC code linked in my program?

0 Kudos

1,017 Views
udoeb
Contributor II

Hi,

I don't have experience with enabling exceptions (-fexceptions) as I generally don't do that in embedded projects. But if you want to use C++ exceptions, you need to keep the .ARM.exidx output sections created by the linker and you cannot simply discard them via linker script (which was my solution to the original problem).

Due to the aforementioned limitations of the entries in those tables, you need to make sure that the distance between the table and the code that uses exceptions does not exceed 0x3FFF_FFFF. Unfortunately, in some RT models (not sure about RT1024) the offset between ITCM and flash is greater than 0x3FFF_FFFF. So you cannot have the .ARM.exidx sections in flash and code in ITCM. 

I agree that the problem is not only related to assembly. This was just the case where I stumbled accross it.

Udo

0 Kudos

1,008 Views
bp1979
Senior Contributor I

Hi @udoeb ,

Thanks for the insights again.

You explain that the distance between .ARM.exidx table and ITCM can't be larger than 0x3FFF_FFFF.

On IMX RT 1024 flash starts at 0x6000 0000, ITCM sits at 0x0. So that seems to explain why the linker complains.

I think the distance is created as follows:

Eenabling exceptions tells the compiler to produces "unwind" information which are stored in .ARM.exidx. In my linker script I keep this section and put them in flash.

When I compile everything to flash, all works fine. I can compile, link, debug. I can also use try catch in code, and it works as expected.

When I compile "flash read/write" code to ITCM (because I use a region of flash as sort of EEPROM, and IMX RT1024 does not have RWW flash), all source files, including the one intented for ITCM, are now compiled with the compiler flag -fexceptions. Because of that the .ARM.exidx is filled with "unwind" information for stuff compiled in ITCM. This will trip that limit that you explained earlier. These indices in the table will exceed the 0x3FFF_FFFF distance, and the linker will produce errors.

Am i getting this right so far?

Because if this is the case, I will try if I can manage to compile everything which must run in ITCM with -fnoexceptions, and compile all other source files with -fexceptions. Then when the linker starts to populate the .ARM.exidx table, it should only find indices that refer to flash, and none that refer to ITCM.

With my (limited) understanding, this would solve my linker errors.

0 Kudos

1,001 Views
udoeb
Contributor II

This is a correct summary of my findings. In theory, compiling the sources for ITCM with -fnoexceptions should eliminate the linker errors. But I don't have tried this in practice.

Udo

820 Views
bp1979
Senior Contributor I

Just for the sake of it I found some time to try and get it to work. TLDR: It doesn't

What already worked before, is try/catch exceptions thrown deeper in the callstack without having any code running in ITC memory.

In order to use try/catch with code running in ITC, first I needed to tackle the distance problem. I managed to extract the code that runs in ITC into a separate library and compile that library with the flag -fno-exceptions.

Then I linked library to the rest of my application, while the rest of the app is compiled without -fno-exceptions (and thus uses the default: -fexceptions).

After straightening out some details, I can compile and link my program. It indeed is "flash costly" because my application size (debug build) went from 558392 B to 610756 B (about 50KB of flashed burned, meh ;-)).

But when giving any try/catch block a try where the try would throw, the app hard faulted. I also have a timer running in itc (to get ms precision timers together with the 1sec rtc clock in the cpu). And that also has to run in ITC memory to have them continue while freertos task switches or goes into critical sections e.g.. So something goes wrong, not sure what. Maybe task switches while unwinding the stack results in a hard fault, or more specifically a jump to ITC code is causing the problem, because thats the part which is not compiled with -fexceptions enabled.

This is the stack trace anyway.

bp1979_0-1701886833341.png

I don't know, I guess using exception handling is a bad idea for at least the reasons a) it burns quite a bit of flash, and b) it's rather CPU heavy to unwind the stack, which might even get in the way of the watchdog e.g. The latter was what I was most curious about, just wanted to actually measure how long stack unwinding really took.

But I guess this is a dead end for this application anyway.

If you could be bothered to shared your thoughts, would be appreciated. If you have better things to do too, feel completely free to ignore me :D.

Thx for the insights anyway! It helped a lot.

0 Kudos

724 Views
udoeb
Contributor II

I cannot comment much on this as I don't have significant experience with exception handling. I think you should not mix exception-enabled code with code that's not exception aware, or at least this requires special measures. Generally, it's not advisable to use exceptions in embedded projects due to code bloat (as you confirmed) and non-deterministic runtime behavior.

6,162 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Udo,

Many thanks for the sharing.

best regards,

Mike

0 Kudos