Issue with new linker release BLD-1705: Order or expression evaluation

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

Issue with new linker release BLD-1705: Order or expression evaluation

562 Views
peter_vranken
Contributor IV

Dear NXP Team,

I run into an issue with the latest PowerPC GCC,
gcc-4.9.4-Ee200-eabivle-i686-mingw32-g2724867_signed, which is labelled
BLD-1705. Downloaded a few days ago from your site.

The existing linker script (perfectly fine till BLD-1607) fails.
A comparison of the map files shows that the problem results from the way,
the memory regions are defined. They are not set via literals but by
linker run-time expressions, and the two compilers seem to differ in the
way, when these expressions are expanded.

Below you find the relevant excerpt from the linker script. Besides
some likely irrelated stack and heap size assignments (all using literals),
it is the beginning of the linker script.

The concept is using a flag, ld_linkInRAM, to have different memory
partitioning. This way, the SW can be loaded either in RAM or in ROM. The
flag is set from the linker command line using --defsym.

Unfortunately, using this technique, the linker BLD-1705 ends up with
totally wrong memory regions (see below). My presumption is that this has
to do with the order of evaluation of the conditional expressions.

I think so because of the observation, that the new linker re-produces
the behavior of BLD-1607 if I replace all conditional expressions with
their results (see commented blocks below). Now, the map file shows the
old, correct figures for memory region origins and lengths - in either
case, RAM and ROM.

Moreover, the wrong values for origin and length, which I see when using
the conditional expressions with BLD-1705, can be explained by a value of
zero for the intermediate variables. It looks much as if origin and length
of the memory regions were evaluated before the conditional expressions
are evaluated.

As said, BLD-1607 works as expected, which is expression evaluation in
strictly sequential order from top to bottom of the linker script, i.e.,
line after line.

Here is the wrong memory region table, found in the map file with BLD-1705
and ld_linkInRAM==0:

Name Origin Length Attributes
memBoot 0x00000000 0x00000008 xr
memFlash 0x00000008 0xfffffff8 xr
memData 0x00000000 0xffff0000 xrw
memDataUncached 0xffff0000 0x00010000 xrw
*default* 0x00000000 0xffffffff

Here is the same memory region table, found in the map file with BLD-1607
(ld_linkInRAM==0) and also found with BLD-1705, if the conditional
expressions are replaced by the code block using unconditional
assignments:

Name Origin Length Attributes
memBoot 0x00800000 0x00000008 xr
memFlash 0x00800008 0x003ffff8 xr
memData 0x40000000 0x00070000 xrw
memDataUncached 0x40070000 0x00010000 xrw
*default* 0x00000000 0xffffffff

Would you please double check the linker's way of expression evaluation?

Would you please try to re-produce the problem?

As a workaround, I can let my makefile take the decision and load
either/or a ROM/RAM script.

Best regards,
Peter

 

Down here is the excerpt from the linker script:

/* We use the simple conditional operator the linker script syntax offers for switching
from normal build of a flashable binary to an equivalent binary that can be loaded into
RAM by the debugger. Using RAM can have these advantages:
- We save flash ROM programming cycles, which are limited
- It reduces the turnaround time between code changes. Loading RAM is faster than
erasing and re-flashing
- The risk of bricking the CPU is lower if we work on code, which is critical in this
respect; e.g. self-tests, security, reset logic, reset escalation
The major drawback is the software size; code and data need to fit into RAM. We use a
hardcoded distribution of both, 75% for code, 25% for data.
Note, the switch ld_linkInRAM is set by the makefile using the linker command line
option --defsym. */
ld_textSegStartAddr = ld_linkInRAM==1? 0x40000000 : 0x00800000;
ld_textSegSize = ld_linkInRAM==1? 3*128k : 0x400000;
ld_dataSegStartAddr = ld_linkInRAM==1? ld_textSegStartAddr + ld_textSegSize : 0x40000000;
ld_dataSegSize = ld_linkInRAM==1? 4*128k - ld_textSegSize : 4*128k;

/* ROM */
/*
ld_textSegStartAddr = 0x00800000 ;
ld_textSegSize = 0x400000 ;
ld_dataSegStartAddr = 0x40000000 ;
ld_dataSegSize = 4*128k ;
*/
/* RAM */
/*
ld_textSegStartAddr = 0x40000000 ;
ld_textSegSize = 3*128k ;
ld_dataSegStartAddr = ld_textSegStartAddr + ld_textSegSize ;
ld_dataSegSize = 4*128k - ld_textSegSize ;
*/

/* On the MPC5775B/E only the MMU can realize uncached memory. This restricts the size and
adress to powers of two. Our startup code configures the last 64k of RAM as uncached.
The next settings are not changeable. */
ASSERT(ld_dataSegSizeTmp >= 128k, "linkerControlFile.ld: Data segment is too little")
ld_dataSegSize -= 64k;
ld_dataUncachedSegStartAddr = ld_dataSegStartAddr + ld_dataSegSize ;
ld_dataUncachedSegSize = 64k ;

/* Definition of memory regions using absolute addresses of physical memories. */
MEMORY
{
memBoot(rx): org = ld_textSegStartAddr, len = 0x8
memFlash(rx): org = ld_textSegStartAddr + LENGTH(memBoot), len = ld_textSegSize - LENGTH(memBoot)
memData(rwx): org = ld_dataSegStartAddr, len = ld_dataSegSize
memDataUncached(rwx): org = ld_dataUncachedSegStartAddr, len = ld_dataUncachedSegSize
}

/* Export the location of the (physical) RAM storage space as far as required by the startup
code.
Note: For operation of code in RAM, it is essential to not refer to the entire physical
RAM - otherwise our startup code would erase all the code segments, which had just
before been loaded by the debugger. */
ld_memRamStart = ORIGIN(memData);
ld_memRamSize = LENGTH(memData) + LENGTH(memDataUncached);
ld_memRamEnd = ld_memRamStart + ld_memRamSize;
ASSERT(ld_memRamSize == (ld_linkInRAM==1? 128k: 512k), "linkerControlFile.ld: Bad partitioning of RAM");

0 Kudos
0 Replies