I have a program targeting a small memory ARM R5 CPU, being compiled with gcc 11.2.0 and ld 2.37.20210721.
I have a critical symbol that I would like to know the address of, even if the binary was stripped. I would prefer to not waste memory by allocating memory to store the address in RAM or even worse, also allocating a known constant so that you can grub through the program to find where the variable is. Basically have something in a post-strip'd elf file which tells me where the variable is.
Ideally the linker script could say ADDR(symbol), but that apparently is not a thing.
Bonus points if the section starts to look like .comment without an "Addr" reported by readelf and without the W write (or of course X) flag.
I tried to use the attribute section and a linker script to make the section NOLOAD and put the memory somewhere innocuous (e.g. into address space used by some processor registers/code that I cannot use anyway). However, when I did so, the actual value was not preserved according to objdump. If I removed NOLOAD, the value was saved but then of course it was loaded into this no longer innocuous memory.
Example program:
__attribute__((unused)) unsigned int GENERAL_FAULT = 0;
volatile unsigned int critical = 5;
__attribute__((section(".criticaladdr"),unused)) const void *critical_addr = (void *)&critical;
void r5_main(void)
{
while (1)
{
if (critical != 5)
critical = 5;
}
}
In this example, the .criticaladdr section is writable and has RAM allocated to it, and objdump -s -j .criticaladdr showed the correct address.
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 010000 0000c0 00 AX 0 0 4
[ 2] .note.gnu.bu[...] NOTE 000000c0 0100c0 000024 00 A 0 0 4
[ 3] .data PROGBITS 000000e4 0100e4 000004 00 WA 0 0 4
[ 4] .criticaladdr PROGBITS 000000e8 0100e8 000004 00 WA 0 0 4
[...]
[ 9] .comment PROGBITS 00000000 01011b 000012 01 MS 0 0 1
Adding a linker script to try to prevent the load and move the allocated ram somewhere innocuous kept the memory writable, but more problematically no longer stored the actual data--objdump -s -j .criticaladdr showed 0x0 as the contents.
…
MEMORY
{
…
OCM_RAM_ATF (r) : ORIGIN = 0xFFFD0000, LENGTH = 0x20000
}
…
SECTIONS
{
…
.criticaladdr (NOLOAD) : { KEEP(*(".criticaladdr")) } > OCM_RAM_ATF
}