Hello all,
I recently run into an issue where the compiler obviously creates an invalid executable.
We are using a DM6435 with CCS 5.2.0, SYS/BIOS 6.34.2.18, XDC 3.24.3.33 and NDK 2.21.0.32. Both usign C6000 CGTools 7.3.4 and 7.4.14 we see the following problem:
Our output file is quite large (approx. 9 MB) and the .text section is sometimes automatically splitted into 2 (sometimes even more) sections. The resulting .text.1 section is quite large, the subsequent .text.2 section usually contains only a few functions, probably only some trampoline functions.
The resulting MAP files usually look like that (some lib and func names replaced since I don't want to see these names in public):
MEMORY CONFIGURATION
name origin length used unused attr fill
---------------------- -------- --------- -------- -------- ---- --------
...
DDR2 80000000 01000000 00926c7a 006d9386 RWIX
DDR2_UNINITIALIZED 81000000 00400000 0030649b 000f9b65 RWIX
DDR2_HEAP 81400000 0ac00000 0ac00000 00000000 RWIX
DDR2_STATIC 8c000000 04000000 00000000 04000000 RWIX
...
.text.1 0 80000040 0082e2a0
80000040 000163e0 lib_a.lib : obj_1.obj (.text)
80016420 000152e0 lib_b.lib : obj_2.obj (.text)
...
8082e2a0 00000020 lib_c.lib : obj_3.o ($Tramp$S$$_Func1)
8082e2c0 00000020 lib_d.lib : obj_4.o ($Tramp$S$$_Func2)
.text.2 0 8082e2c0 00000200
8082e2c0 00000020 lib_d.lib : obj_4.o ($Tramp$S$$_Func2)
8082e2e0 00000020 lib_c.lib : obj_5.o ($Tramp$S$$_Func3)
8082e300 00000020 : obj_6.o ($Tramp$S$$_Func4)
...
In the resulting binary file the trampoline function listed both at the end of .text.1 and at the beginning of .text.2 contains only NOPs (0x00):
If the .text section is splitted into more than two parts the same thing happens to the (trampoline) functions placed at the beginning of the next .text.<n> sections too.
This problem will finally cause our application to crash since instead of calling Func2() (using the trampoline) a different Func3() will be called (because execution falls through into the next trampoline function for Func3() with invalid args since these were prepared for Func2()) and if it doesn't crash itself (because of the silly args) the result is not the expected result of Func2() which may finally cause the calling code to crash because of "unexpected behaviour of Func2()".
All program code and vars (.pinit, .text, .const, .cinit, .switch, .neardata, .rodata, .bss), all together approx. 9,4 MB are put into the 16 MB large "DDR2" area. So I think there should be no need to split the .text section.
The problem seems to occure "randomly", at least we don't understand the situations triggering that behaviour. When we change some code somewhere the problem occures and disappears.
Despite I've been chasing the problem for quite a time I just recently understood what happens. Since I didn't store the MAP files of previous builds I only can talk about a few tries. But in these few tries it was always a linker generated trampoline function that has been "NOPed out", but it were trampolines for different functions. The address of the boundary between .text.1 and .text.2 is also not constant.
Why is the .text section splitted at all?
Why is the effected func listed both at the end of .text.1 section and the beginning of .text.2 section?
Why is the code of the first func in .text.2 replaced by NOPs?
And most important: What can we do to overcome this problem???
Any help will be greatly appreciated.
Thanks,
Lars