使用GCC链接时优化器出现undefined references问题求助
GCC LTO链接时无法解析newlib_syscalls.c中的符号(Clang可正常编译)
我在为AArch64裸机项目启用GCC的链接时优化(LTO)功能,遇到链接错误——链接器无法解析newlib_syscalls.c中定义的_close、_write等系统调用符号,但相同源码、库和编译选项下,Clang可以正常完成编译。
Clang编译成功输出
❯ CC=clang make clang -mlittle-endian -mcpu=cortex-a55 -mtune=cortex-a55 -target aarch64-none-elf --sysroot=/Applications/ArmGNUToolchain/13.2.Rel1/aarch64-none-elf/bin/../aarch64-none-elf -flto -c startup.c -o startup.o clang -mlittle-endian -mcpu=cortex-a55 -mtune=cortex-a55 -target aarch64-none-elf --sysroot=/Applications/ArmGNUToolchain/13.2.Rel1/aarch64-none-elf/bin/../aarch64-none-elf -flto -ffat-lto-objects -c newlib_syscalls.c -o newlib_syscalls.o clang -static -nostdlib -T link.ld -target aarch64-none-elf --sysroot=/Applications/ArmGNUToolchain/13.2.Rel1/aarch64-none-elf/bin/../aarch64-none-elf -flto -o test.elf startup.o newlib_syscalls.o -lc /Applications/ArmGNUToolchain/13.2.Rel1/aarch64-none-elf/bin/../lib/gcc/aarch64-none-elf/13.2.1/libgcc.a
GCC编译错误输出
❯ CC=aarch64-none-elf-gcc make aarch64-none-elf-gcc -mlittle-endian -mcpu=cortex-a55 -mtune=cortex-a55 -flto -c startup.c -o startup.o aarch64-none-elf-gcc -mlittle-endian -mcpu=cortex-a55 -mtune=cortex-a55 -flto -ffat-lto-objects -c newlib_syscalls.c -o newlib_syscalls.o aarch64-none-elf-gcc -static -nostdlib -T link.ld -flto -o test.elf startup.o newlib_syscalls.o -lc /Applications/ArmGNUToolchain/13.2.Rel1/aarch64-none-elf/bin/../lib/gcc/aarch64-none-elf/13.2.1/libgcc.a /Applications/ArmGNUToolchain/13.2.Rel1/aarch64-none-elf/bin/../lib/gcc/aarch64-none-elf/13.2.1/../../../../aarch64-none-elf/bin/ld: /Applications/ArmGNUToolchain/13.2.Rel1/aarch64-none-elf/bin/../lib/gcc/aarch64-none-elf/13.2.1/../../../../aarch64-none-elf/lib/libc.a(libc_a-closer.o): in function `_close_r': /Volumes/data/jenkins/workspace/GNU-toolchain/arm-13/src/newlib-cygwin/newlib/libc/reent/closer.c:47:(.text._close_r+0x1c): undefined reference to `_close' ...
已确认的信息
- 用
aarch64-none-elf-nm检查newlib_syscalls.o,确认目标文件中包含缺失的符号:
❯ aarch64-none-elf-nm newlib_syscalls.o 000000000000006c T _close 00000000000000d4 T _exit 0000000000000080 T _fstat 00000000000000f8 T _getpid 00000000000000a4 T _isatty 00000000000000e0 T _kill 00000000000000b8 T _lseek 000000000000011c T _read 0000000000000000 T _sbrk 0000000000000100 T _write U end 0000000000000000 b heap.0
- 由于GNU工具链自带的
libc.a未用-flto编译,没有GIMPLE字节码,已经为newlib_syscalls.c添加-ffat-lto-objects参数确保生成目标代码,但问题依旧。Clang无论是否添加该参数都能正常编译。
项目代码
startup.c
#include <stdio.h> void entrypoint() { printf("Hello, World!\n"); }
newlib_syscalls.c
#include <stdint.h> #include <stdbool.h> #include <stddef.h> #include <errno.h> #include <sys/stat.h> extern int end; void *_sbrk(int incr) { static unsigned char *heap = NULL; unsigned char *prev_heap; if (heap == NULL) { heap = (unsigned char *)&end; } prev_heap = heap; heap += incr; return prev_heap; } int _close(int file) {return -1;} int _fstat(int file, struct stat *st) { st->st_mode = S_IFCHR; return 0; } int _isatty(int file) { return 1; } int _lseek(int file, int ptr, int dir) { return 0; } void _exit(int status) {while(1) asm volatile("");} void _kill(int pid, int sig) {return;} int _getpid(void) {return -1;} int _write (int file, char * ptr, int len) {return len;} int _read (int file, char * ptr, int len) {return len;}
link.ld
OUTPUT_FORMAT("elf64-littleaarch64") OUTPUT_ARCH(aarch64) ENTRY(entrypoint) MEMORY { ROM (rx): ORIGIN = 0x00000000, LENGTH = 256K SRAM (rwx): ORIGIN = 0x00100000, LENGTH = 512K DRAM (rwx): ORIGIN = 0x40000000, LENGTH = 0xC0000000 } SECTIONS { .ro : { _ro_start = .; *entrypoint*(.text*) *(SORT_BY_ALIGNMENT(.text*)) *(SORT_BY_ALIGNMENT(.rodata*)) *(.vectors) _ro_end = .; } >ROM .data : ALIGN(32) { _data_start = .; *(SORT_BY_ALIGNMENT(.data*)) . = ALIGN(32); _data_end = .; } >SRAM AT>ROM _data_start_lma = LOADADDR(.data); _data_size = SIZEOF(.data); .bss (NOLOAD) : ALIGN(32) { _bss_start = .; *(SORT_BY_ALIGNMENT(.bss*)) *(COMMON) . = ALIGN(32); _bss_end = .; } >SRAM .heap (NOLOAD) : { end = .; _heap_start = .; . += 0x4000; _heap_end = .; } >SRAM .stack (NOLOAD) : { _stack_start = .; . += 0x4000; _stack_end = .; _stack_top = .; } >SRAM _all_end = .; /DISCARD/ : { *(.eh_frame*) } }
Makefile
CC ?= aarch64-none-elf-gcc CFLAGS = -mlittle-endian -mcpu=cortex-a55 -mtune=cortex-a55 LTO = -flto LDFLAGS = -static -nostdlib -T link.ld EXTRA_LDFLAGS = -lc $(shell aarch64-none-elf-gcc -print-libgcc-file-name) ifeq ($(CC),clang) CFLAGS += -target aarch64-none-elf --sysroot=$(shell aarch64-none-elf-gcc -print-sysroot) LDFLAGS += -target aarch64-none-elf --sysroot=$(shell aarch64-none-elf-gcc -print-sysroot) endif newlib_syscalls.o : $(CC) $(CFLAGS) $(LTO) -ffat-lto-objects -c newlib_syscalls.c -o $@ startup.o : $(CC) $(CFLAGS) $(LTO) -c startup.c -o $@ test.elf : startup.o newlib_syscalls.o $(CC) $(LDFLAGS) $(LTO) -o $@ $? $(EXTRA_LDFLAGS) .PHONY : clean clean : rm -f *.o *.elf .DEFAULT_GOAL := test.elf # ❯ aarch64-none-elf-gcc --version # aarch64-none-elf-gcc (Arm GNU Toolchain 13.2.rel1 (Build arm-13.7)) 13.2.1 20231009 # Copyright (C) 2023 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # ❯ clang --version # Homebrew clang version 18.1.7 # Target: arm64-apple-darwin23.5.0 # Thread model: posix # InstalledDir: /opt/homebrew/opt/llvm/bin
内容的提问来源于stack exchange,提问作者sskk
相关产品推荐
相关产品推荐

