I'd like to forbid a set of specifically-named symbols from being linked into my executable, to ensure that my executable isn't carrying around functionality and dependencies that I don't want.
In my specific case, these symbols come from libc_nano.a
on an ARM Cortex-M MCU, but I've wanted this functionality for application-level code as well on "bigger" computers as well, so my question is general-purpose.
I don't see a linker flag that would trigger an error if a named symbol is included in the final link, but I think that would do what I want.
Is there a way to achieve this with the GCC linker?
Interesting question, below is an example that might help. The example code comes from Hello World for bare metal ARM
As mentioned above this approach uses ASSERT ( DEFINED( symbol, "message" ) )
. . . forbid a set of specifically-named symbols from being linked into my executable . . . Is there a way to achieve this with the GCC linker?
What if the symbols are coming from a static library file *.a
?
In this output the symbol print_uart0
is the symbol being excluded from an object file test.o
. Also shown is what happens when the symbols are coming from a static library file libtest.a
.
arm-none-eabi-ld -T test-no-print-uart0.ld test.o startup.o -o test.elf
arm-none-eabi-ld: OOPS, THE SYMBOL print_uart0 IS DEFINED
arm-none-eabi-ld -T test-no-print-uart0.ld libtest.a startup.o -o test.elf
arm-none-eabi-ld: OOPS, THE SYMBOL print_uart0 IS DEFINED
print_uart0
is included from object file
# step 1
arm-none-eabi-as -mcpu=arm926ej-s -g startup.s -o startup.o
arm-none-eabi-gcc -c -mcpu=arm926ej-s -g test.c -o test.o
arm-none-eabi-ld -T test.ld test.o startup.o -o test.elf
arm-none-eabi-objcopy -O binary test.elf test.bin
qemu-system-arm -M versatilepb -m 128M -nographic -kernel test.bin
Hello World!
# ctrl-a x
# Step 2
arm-none-eabi-ld -T test-no-print-uart0.ld test.o startup.o -o test.elf
arm-none-eabi-ld: OOPS, THE SYMBOL print_uart0 IS DEFINED
# Step 3
arm-none-eabi-ar rcs libtest.a test.o
arm-none-eabi-ld -T test.ld libtest.a startup.o -o test.elf
arm-none-eabi-ld: OOPS, THE SYMBOL print_uart0 IS DEFINED
.global _Reset
_Reset:
LDR sp, =stack_top
BL c_entry
B .
volatile unsigned int * const UART0DR = (unsigned int *)0x101f1000;
void print_uart0(const char *s) {
while(*s != '\0') { /* Loop until end of string */
*UART0DR = (unsigned int)(*s); /* Transmit char */
s++; /* Next char */
}
}
void c_entry() {
print_uart0("Hello world!\n");
}
ENTRY(_Reset)
SECTIONS
{
. = 0x10000;
.startup . : { startup.o(.text) }
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss COMMON) }
. = ALIGN(8);
. = . + 0x1000; /* 4kB of stack memory */
stack_top = .;
}
ENTRY(_Reset)
SECTIONS
{
. = 0x10000;
.startup . : { startup.o(.text) }
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss COMMON) }
. = ALIGN(8);
. = . + 0x1000; /* 4kB of stack memory */
stack_top = .;
}
ASSERT( !DEFINED(print_uart0), "OOPS, THE SYMBOL print_uart0 IS DEFINED" );