2017-02-17 31 views
1

Я работаю над встроенным проектом, и я дублирую примерный проект. Не учитывая порядок связывания объектных файлов, я просто помещаю файлы c в произвольном порядке в свой Makefile.найти дублированные объявленные функции в библиотеке c (отдельные файлы)

Компиляция и связывание дает executable.elf из 1.9Mb. Ошибок не было, но исполняемый файл не работал.

После долгих поисков, без решения я, наконец, дублирует проект именно, в том числе порядка c файлов (120 из них), и вот я получил executable.elf из 2.2Mb и без каких-либо ошибок. И исполняемый файл работал.

Ничего не изменилось в параметрах компиляции и/или ссылках. Просто изменил порядок, в котором файлы c перечислены в make-файле и, следовательно, порядок объектных файлов во время ссылки.

Я подозреваю, что существует несколько реализаций дубликатов функций с разными телами/размерами. Моя гипотеза заключается в том, что время ссылки компоновщика, без памяти предыдущих действий ссылки, просто выбирает первый, с которым он сталкивается, не поднимая ошибку.

Однако я хотел бы получить эту предоставленную библиотеку (все файлы c, файл lib *.a) и найти дубликаты функций. Поэтому я знаю, в каком порядке я должен предоставить файлы c и, что более важно, почему.

Два вопроса:

  1. ли приведенное выше описание, на самом деле потенциальной причиной вопросов?
  2. Есть ли другие возможности?
  3. Как найти дубликаты функций?

К сожалению, скомпилированный код является патентованным, и детали не могут быть предоставлены в настоящее время.

Компилятор:

arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496] 

Цель является:

cortex-m3 

Ваша помощь ценится.

--- EDIT ---

Есть два файла:

  1. является список со всеми исходным кодом (source.mk):

    C_FILES_SRC = $(SDK_DIR)/file001.c 
    C_FILES_SRC += $(SDK_DIR)/file002.c 
    C_FILES_SRC += $(SDK_DIR)/ ..... 
        | 
    C_FILES_SRC += $(APPL_DIR)/file121.c 
    C_FILES_SRC += $(APPL_DIR)/file122.c 
    
  2. является Makefile (краткая версия):

    include source.mk 
    CFLAGS = xxxxx 
    # create objects 
    %.o: %.c 
        $(GCC) $(CFLAGS) -MMD -MP -MF($(@:%.o=%.d) -o [email protected] -c $< 
    
    # link it all together 
    executable.elf 
        $(GCC) $(MAIN_CFLAGS) $(LINK_SCRIPTS) -Xlinker --gc-sections $(LIBS_DIR) $(EXTRA_LINK_FLAGS) $(SPECS) -o [email protected] $(OBJS) $(LIBS) 
        $(SIZE) --format=berkeley [email protected] 
    

В Makefile ничего не меняю. Изменен только порядок файлов в источнике.mk

+0

Я знаю, что вы сказали, что не можете публиковать сам код, но можете ли вы опубликовать обфусканный эквивалент вашего 'Makefile'? Благодаря! Как мы знаем, мы даже не знаем, что такое структура вашего 'Makefile' или какая buildsystem вы используете для его создания (если есть). Это, скорее всего, затруднит вам окончательный ответ. –

+1

Вы говорите: «Моя гипотеза заключается в том, что ... компоновщик ... просто выбирает первый, с которым он сталкивается, не создавая ошибки». Это было бы крайне необычно и неправильно. Если есть два объектных файла, определяющих одну и ту же внешнюю видимую функцию, соединение должно завершиться ошибкой с повторяющейся функцией. Самый простой способ имитации заключается в том, чтобы добавить один объектный файл в список дважды; ссылка не сработает, когда вы это сделаете. Вы проверили размеры объектных файлов? Вы сравнили вывод 'size' для двух бинарных файлов? Были ли варианты компиляции одинаковыми? Версия компилятора? –

+0

Я просто добавил произвольный файл библиотеки 'c' в мое приложение и скомпилировал/связал его. Таким образом, существует два идентичных объектных файла с разными местоположениями. Ошибок от компоновщика нет. – Robert

ответ

1

Только статические библиотеки (.a или .lib) демонстрируют «разрешение первого совпадения», так что порядок ссылок имеет решающее значение. Начиная с все объектные файлы явно связаны, вы получите ошибку ссылки, если бы были дубликаты символов. Таким образом, такой эффект может иметь только порядок, в котором файлы .a/.lib представлены компоновщику.

Возможно, у вас есть две разные версии библиотеки и связаны между собой в другом порядке?

В корзину binutils GNU toolchain входит инструмент nm для проверки символов в объектных и архивных (библиотечных) файлах.

Альтернативная возможность заключается в том, что исполняемая точка входа чувствительна к порядку привязки на вашей платформе; в этом случае это может быть просто порядок ссылок crt0 (или другой код запуска во время запуска).

+0

После тестирования я думаю, что ваша ** альтернативная возможность ** является одной. Помещение файла «startup_AMRCM0.S» в начало списка идет хорошо, поместив «startup_AMRCM0.S» в качестве последнего файла в списке, ссылка идет не так. Я проверил другие проекты, которые я сделал с той же самой компиляцией компилятора 'GCC', и все они имеют код запуска в начале списка файлов/объектов, случайно :-), поэтому я никогда не сталкивался с этой проблемой раньше. – Robert

+0

Было бы неплохо найти подтверждение об этом в документации [GNU ARM Embedded Toolchain] (https://launchpad.net/gcc-arm-embedded). Если я найду что-нибудь, я расскажу об этом здесь. – Robert

+0

@Robert: Проблема с набором инструментов из нескольких проектов, чья ответственность заключается в том, чтобы документировать эти вещи? Это не может быть неотъемлемой проблемой с инструментальной цепочкой GNU. Cortex-M3 загружает указатель стека и начальный адрес из вектора сброса - существует множество способов убедиться, что они совпадают с символом '_reset' (или что-то еще) во время запуска кода запуска; может быть возможно принудительно установить местоположение в сценарии компоновщика, а затем полагаться на порядок ссылок по умолчанию. Я вспомнил об этой проблеме давным-давно с GNU, поэтому я и упомянул об этом. – Clifford