我正在开发一个嵌入式系统,它有自己的库(例如libc_alt)从标准 libc (fopen、fclose、fread、fseek、ftell)实现一些功能,但不是全部(我需要memset、memcpy、longjmp、setjmp等)标准的libc)。当我尝试将两个库都提供给编译器时
提供libc_alt
# makefile.mk
(SRC_C += \
$(COMP_PATH_libc_alt)/stdio.c \
)
提供标准库
STD_LIBS += -lc -lgcc
在链接器步骤中,编译器 (arm-eabi-gcc) 正确地抱怨 fclose() 的多个定义。我的问题是,是否可以指示编译器排除标准 libc 定义 fclose() 并使用我在 $(COMP_PATH_libc_alt)/stdio.c 中编写的定义?
或者,我如何指示编译器先使用我的stdio.c,然后使用标准 libc 的 stdio.c而忽略重复的函数定义?
例如,在$(COMP_PATH_libc_alt)/stdio.c中找到 fopen() 定义之后;它将忽略标准 libc 中的 fopen()。这样我就可以同时使用 libc_alt fopen()和标准的 libc memcpy(), memset()
更新:谢谢大家的回答。@artless_noise 我之前确实放置了我的 stdio.c -lc
。关于使用--wrap symbol
,如果我理解正确,引用fclose()
将更改为__wrap_fclose()
,我需要将我fclose()
在stdio.c中的名称更改为__wrap__fclose()
; 不幸的是,修改“我的” stdio.c是不可能的。实际上,最奇怪的是,由于我将stdio.c 放在-lc 之前,LinaroGCC arm-eabi-gcc能够为fopen(), fseek(), ftell(), fread()
(nice) 选择我的定义。但它给出了multiple definition
错误fclose()
根据https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Link-Options.html;上ld -l
; 链接器应该忽略-lc
在 my 之后出现的重复符号libc_alt.a
。它确实做到了,除了一个例外fclose()
,我不知道为什么?
在命令中编写此选项的位置有所不同;链接器按照指定的顺序搜索和处理库和目标文件。因此,在文件 foo.o 之后但在 bar.o 之前
foo.o -lz bar.o
搜索库。如果 bar.o 引用 中的函数,则可能不会加载这些函数。链接器在标准目录列表中搜索该库,该库实际上是一个名为 liblibrary.a 的文件。然后,链接器使用这个文件,就好像它已经按名称精确指定了一样。z
z
搜索的目录包括几个标准系统目录以及您使用 -L 指定的任何目录。通常以这种方式找到的文件是库文件——其成员是目标文件的归档文件。链接器通过扫描归档文件来处理归档文件,其中的成员定义了迄今为止已被引用但尚未定义的符号。但是如果找到的文件是一个普通的目标文件,它会以通常的方式链接。使用 -l 选项和指定文件名之间的唯一区别是 -l 用 and 包围库lib
并.a
搜索多个目录。
我如何调用链接器(libc_alt.a
包含“我的”stdio.o)
gcc-linaro-7.1.1-2017.08-x86_64_arm-eabi/bin/arm-eabi-gcc
-Xlinker --wrap=fclose -nostdlib -Xlinker --gc-sections
-Xlinker --fatal-warnings -Xlinker --no-wchar-size-warning
-Xlinker --no-enum-size-warning -Xlinker --build-id=none -T
/home/alice/Tools/Out/trusted_application.ld -Xlinker -pie -o
/home/alice/Out/Bin/taMbedTLS.axf /home/alice/Locals/Code/aes.o
/home/alice/Locals/Code/sha1.o /home/alice/libraries/libc_alt.a -lc -lgcc
使用nm
我的内容libc_alt.a
stdio.o:
U __aeabi_uidiv
000000d0 t $d
0000004c t $d
00000030 t $d
00000010 N $d
00000001 T fclose
00000001 T fopen
00000001 T fread
00000001 T fseek
00000001 T ftell
U memset
U __stack_chk_fail
U __stack_chk_guard
U strchr
U strcmp
U strlen
stdlib.o:
使用nm
Linaro LinaroGCC arm-eabi-gcc 的内容 libc.a
lib_a-fclose.o:
00000000 t $a
00000110 t $d
00000010 N $d
00000100 T fclose
00000000 T _fclose_r
U _free_r
U _impure_ptr
U __sflush_r
U __sfp_lock_acquire
U __sfp_lock_release
U __sinit
lib_a-fopen.o:
00000000 t $a
000000fc t $a
000000e8 t $d
00000110 t $d
00000010 N $d
000000fc T fopen
00000000 T _fopen_r
U _fseek_r
U _impure_ptr
U _open_r
U __sclose
U __sflags
U __sfp
U __sfp_lock_acquire
U __sfp_lock_release
U __sread
U __sseek
U __swrite