See the good advice about avoiding link time manipulations of owned code, if you don't need it then consider removing it at compilation.
CAUTION
This approach can lead to removal of some needed sections. Read how this author used --print-gc-sections
to review and discover removed sections.
REVIEW
This presentation on link time dead code and data elimination using GNU toolchain
SIMILAR here is how to separate the functions and data and use gc-sections
to remove symbols.
Maybe that can help, here is how I experiemented with that answer...
Problem
How to discard unused symbols in the resulting elf file
Output
Shows the unused function foo
was included in the before elf and removed in the after elf file.
# BEFORE SHOWS THAT SYMBOL FOO EXIST
arm-none-eabi-readelf -a test-before.elf
. . .
25: 00010068 24 FUNC GLOBAL DEFAULT 2 foo
# AFTER SHOWS THAT SYMBOL FOO ABSENT
arm-none-eabi-readelf -a test-after.elf
. . .
25: 00010068 28 FUNC GLOBAL DEFAULT 3 c_entry
26: 00010000 0 NOTYPE GLOBAL DEFAULT 1 _Reset
Process
- Create arm elf w/ symbols that aren't used (before)
- Modify arm elf to remove symbols that aren't used (after)
Input
Here are the commands, the code is based on Hello World for bare metal ARM
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-before.o
arm-none-eabi-gcc -fdata-sections -ffunction-sections -c -mcpu=arm926ej-s -g test.c -o test-after.o
arm-none-eabi-ld --gc-sections -T test.ld test-before.o startup.o -o test-before.elf
arm-none-eabi-ld --gc-sections -T test.ld test-after.o startup.o -o test-after.elf
arm-none-eabi-readelf -a test-before.elf
arm-none-eabi-readelf -a test-after.elf
# SEE OUTPUT FOR RESULTS OF READELF SHOWING UNUSED SYMBOL foo WAS REMOVED
startup.s
.global _Reset
_Reset:
LDR sp, =stack_top
BL c_entry
B .
test.ld
ENTRY(_Reset)
SECTIONS
{
. = 0x10000;
.startup . : { startup.o(.text) }
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss COMMON) }
. = ALIGN(8);
. = . + 0x1000; /* 4kB of stack memory */
stack_top = .;
}
test.c
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 foo()
{
}
void c_entry() {
print_uart0("Hello world!\n");
}
Linking .a
Instead of .o
The comment about using a library looked interesting so I wrote this experiment. Based on the specific linker and commands below, foo
was included in the resulting elf. Still maybe a solution for different linker or better commands. Cool idea though.
arm-none-eabi-ar rcs libtest-before.a test-before.o
arm-none-eabi-ld --static -T test.ld libtest-before.a startup.o -o test-before-lib.elf
arm-none-eabi-readelf -a test-before-lib.elf
. . .
25: 00010068 24 FUNC GLOBAL DEFAULT 2 foo
26: 00010000 0 NOTYPE GLOBAL DEFAULT 1 _Reset