Getting address of special symbols in stripped ELF
13:02 02 Nov 2025

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
}
gcc ld strip