GNU LD: How to override a symbol value (an address) defined by the linker script specified using -T

Go To StackoverFlow.com

9

My usecase is as follows:

  • I am using a typical SDK that comes with Makefile based projects
  • I belive the linker is patched gcc. gcc --version gives me 4.3.4
  • SDK defines the linker script (lets call it Linker.ld)
  • Linker.ld includes LinkerMemMap.cfg, which defines the absolute addresses for various sections in the linked ELF image
  • SDK provides application templates based on Makefiles (GNU Make 3.81) and make itself
  • In the SDK provided Makefile template, when gcc is invoked the Linker.ld is provided with -T command line option, as follows:

gcc $(OBJS) -l$(Lib1) -l$(Lib2) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections -o$(OUTPUT).elf

My requirement is as follows:

  • I would like to use the sections as defined in Linker.ld and use the memory map as per LinkerMemMap.cfg however tweak a particular symbol(lets call it SYMBOL_RAM_START) defined in LinkerMemMap.cfg

What works:

  • I have tried in the makefile, prior to linking the final ELF image, copy the LinkerMemMap.cfg (which is included by Linker.ld) to the build directory and patch it to redefine SYMBOL_RAM_START. This does work as the linker searches for the linker scripts and the files included by the linker scripts in the current folder first.

What doesn't:

  • Unfortunately our stakeholders think the above method is too risky and complex to understand. I would like to override the symbol value on the linker command line with something like below:

    1. gcc $(OBJS) -l$(Lib1) -l$(Lib2) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections,--defsym=SYMBOL_RAM_START=$(VALUE_TO_OVERRIDE) -o$(OUTPUT).elf

    2. gcc $(OBJS) -l$(Lib1) -l$(Lib2) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections --defsym=SYMBOL_RAM_START=$(VALUE_TO_OVERRIDE) -o$(OUTPUT).elf

    3. gcc $(OBJS) -l$(Lib1) -l$(Lib2) --defsym=SYMBOL_RAM_START=$(VALUE_TO_OVERRIDE) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections -o$(OUTPUT).elf

None of these seem to have any effect on the linked image created by the linker.

  • Can --defsym override the symbols defined by linkerscript specified using -T?
  • Could any of you please see what am I doing wrong here?
2012-04-05 16:43
by Aravind


13

While waiting for someone to respond, I did resolve the issue. There are few issues with the problem here and I thought of explaining my findings for someone who might do the same mistake.

First of all Any options to be passed to the linker must be specified with -Xlinker or with -Wl. Hence both 2 and 3 won't work in the above case. The corrected 2 and 3 would be as follows:

  1. Is correct already

  2. gcc $(OBJS) -l$(Lib1) -l$(Lib2) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections -Xlinker --defsym=SYMBOL_RAM_START=$(VALUE_TO_OVERRIDE) -o$(OUTPUT).elf

  3. gcc $(OBJS) -l$(Lib1) -l$(Lib2) -Xlinker --defsym=SYMBOL_RAM_START=$(VALUE_TO_OVERRIDE) -nostdlib -lgcc -L$(library_path) -g -msmall-mode -mconst-switch-tables -mas-mode -mno-initc -Wl,--start-group,--end-group,-T,$(PATH_TO_Linker.ld),--gc-sections -o$(OUTPUT).elf

Now for the case of options 1 & 2 above, --defsym comes after linker script and SYMBOL_RAM_START was already defined by the linker script. It does override it. But the overriden value will not be used, because the sections have already been defined as the linker script has already been used.

For the case of option 3 above, the SYMBOL_RAM_START was defined before the linker script was read by the linker. Hence when linker script is parsed, the value specified in the script overrides it.

Solution:

In order for this to work, the linker script will need to conditionally initialize the symbol SYMBOL_RAM_START, something like below:

SYMBOL_RAM_START = DEFINED( SYMBOL_RAM_START ) ? SYMBOL_RAM_START : DEFAULT_VALUE ;

Given the above in the linker script, when the SYMBOL_RAM_START was defined before the linker script is included (as shows in option 3 above) it did work. But in the end I had to patch the linker script.

This solution doesn't really override the symbol, but provides a way in which a symbol can be defined so that it can be overridden.

2012-04-11 17:02
by Aravind
Just an idea, I'm not sure if it works: Could it also have worked to declare SYMBOL_RAM_START as a weak symbol in the base linker script? That way, the value provided through command line parameter might be able to override the label from the linker script - Multisync 2015-01-16 16:48
@Aravind, if I could give you a hug, I would! :) This answer turned out to be invaluable for me tonight, since I was debugging a complex multi-process operating system kernel, where gdb was basically useless because the processes hade the same (virtual) addresses. Being able to move the memory locations apart was incredibly helpful for me when debugging a complex problem. Thanks! For reference: https://github.com/chaos4ever/chaos/commit/177957dac462b6134c5134e6567019f73a401b8 - Per Lundberg 2017-10-11 21:23
@Multisync interesting thought, but I don't know if weak symbols work the same way when it comes to linker symbols. The section allocation is a link time thing, and as I stated options 1, 2 & 3 didn't work precisely because the linker need to know where to put the section as it is allocating them while going through the linker script. At least that's what I thought it did based on my findings explained above - Aravind 2017-10-13 13:21
@Per Lundberg - I am glad it was useful for you. In the end it seems like such a simple thing to do, but it took a while to get there - Aravind 2017-10-13 13:22
Ads