Я работаю над встроенной системой, которая имеет свою собственную библиотеку (например, 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 , игнорируя повторяющиеся определения функций?
например. после того, как он нашел определение fopen () в $ (COMP_PATH_libc_alt) /stdio.c; он будет игнорировать fopen () внутри стандартного libc. Таким образом я могу использовать как libc_alt fopen () , так и стандартную libc memcpy (), memset ()
ОБНОВЛЕНИЕ: Спасибо всем за ответы. @artless_noise Я разместил свой stdio.c до -lc
. Что касается использования --wrap symbol
, если я правильно понимаю, ссылка на fclose()
изменится на __wrap_fclose()
, и мне нужно изменить имя моего fclose()
в моем stdio.c на __wrap__fclose()
; к сожалению, изменение "my" stdio.c не подлежит обсуждению.
На самом деле, самое странное, что, поскольку я помещаю свой stdio.c перед -lc, LinaroGCC arm-eabi-gcc смог выбрать мое определение для fopen(), fseek(), ftell(), fread()
(отлично). Но это дает multiple definition
ошибка для fclose()
Согласно https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Link-Options.html; на ld -l
; компоновщик должен был игнорировать повторяющийся символ в -lc
, который идет после моего libc_alt.a
. И это, за одним исключением fclose()
, и я не знаю почему?
Имеет значение, где в команде вы пишете эту опцию; компоновщик ищет и обрабатывает библиотеки и объектные файлы в указанном порядке. Таким образом, foo.o -lz bar.o
ищет библиотеку z
после файла foo.o, но до bar.o. Если bar.o ссылается на функции в z
, эти функции могут не загружаться.
Компоновщик ищет в стандартном списке каталогов библиотеку, которая на самом деле является файлом с именем liblibrary.a. Затем компоновщик использует этот файл, как если бы он был указан точно по имени.
В число найденных каталогов входят несколько стандартных системных каталогов плюс любые, которые вы указываете с помощью -L.
Обычно файлы, найденные таким образом, являются библиотечными файлами - архивными файлами, членами которых являются объектные файлы. Компоновщик обрабатывает архивный файл, просматривая его на предмет элементов, которые определяют символы, на которые до сих пор ссылались, но не определяли . Но если найденный файл является обычным объектным файлом, он связывается обычным способом. Единственное различие между использованием параметра -l и указанием имени файла заключается в том, что -l окружает библиотеку 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