GCC链接器在链接时是否可以在包含特定符号时发出错误?

huangapple go评论58阅读模式
英文:

Can the GCC linker emit an error when a specific symbol is included in the link?

问题

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?

英文:

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?

答案1

得分: 4

有趣的问题,以下是可能有所帮助的示例。示例代码来自Hello World for bare metal ARM

正如上面提到的,这种方法使用 ASSERT ( DEFINED( symbol, "message" ) )

问题

> . . . 禁止一组特定命名的符号被链接到我的可执行文件中 . . . 有没有一种方法可以在GCC链接器中实现这一点?

如果符号来自静态库文件 *.a 呢?

输出

在此输出中,符号 print_uart0 是要从对象文件 test.o 中排除的符号。还显示了当符号来自静态库文件 libtest.a 时发生的情况。

arm-none-eabi-ld -T test-no-print-uart0.ld test.o startup.o -o test.elf
arm-none-eabi-ld: 哎呀,符号 print_uart0 已定义

arm-none-eabi-ld -T test-no-print-uart0.ld libtest.a startup.o -o test.elf
arm-none-eabi-ld: 哎呀,符号 print_uart0 已定义

过程

  1. 将输入构建为可工作的ARM示例
  2. 修改链接器脚本以防止在从对象文件包含 print_uart0 时进行链接
  3. 修改链接器命令以使用从对象文件创建的静态库

# 步骤 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

# 步骤 2
arm-none-eabi-ld -T test-no-print-uart0.ld test.o startup.o -o test.elf
arm-none-eabi-ld: 哎呀,符号 print_uart0 已定义

# 步骤 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: 哎呀,符号 print_uart0 已定义

输入

startup.s

.global _Reset
_Reset:
 LDR sp, =stack_top
 BL c_entry
 B .

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 c_entry() {
 print_uart0("Hello world!\n");
}

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-no-print-uart0.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 = .;
}
ASSERT( !DEFINED(print_uart0), "哎呀,符号 print_uart0 已定义" );
英文:

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" ) )

Problem

> . . . 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 ?

Output

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

Process

  1. Build inputs into a working ARM example
  2. Modify linker script to prevent link when print_uart0 is included from object file
  3. Modify linker command to use static library created 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

Inputs

startup.s

.global _Reset
_Reset:
 LDR sp, =stack_top
 BL c_entry
 B .

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 c_entry() {
 print_uart0("Hello world!\n");
}

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-no-print-uart0.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 = .;
}
ASSERT( !DEFINED(print_uart0), "OOPS, THE SYMBOL print_uart0 IS DEFINED" );

答案2

得分: 0

请提供需要翻译的具体代码部分,我会尽力帮助您翻译。

英文:

Write an assembly source file with a line of the form <code><i>SymbolName</i>:</code> for each symbol you want to test for. Assemble this file and add its object file to the link after all libraries (and ensure the libraries are listed after other object modules that might be using these symbols).

If the program uses any of the listed symbols, the linker will report a multiply defined symbol error.

Reasoning: If any of the listed symbols is used, the library module that defines it will be linked in. Then, when the new object module is linked in, the symbol will be multiply defined.

If none of the symbols are linked in, this module will be linked in harmlessly; it should not add any space to the program.

huangapple
  • 本文由 发表于 2023年2月24日 00:10:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75547400.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定