Поиск по сайту: |
|
По базе: |
|
Главная страница > Статьи > Средства разработки |
|
|||||||||||||||||||||||||
Библиотеки и карта компоновкиНекоторые часто используемые подпрограммы можно хранить в объектных файлах, а не компилировать каждый раз из исходных текстов. Множество объектных файлов собирается в статические библиотеки. Компоновщик работает с объектными файлами библиотеки напрямую, без необходимости извлечения отдельных объектных файлов. В статической библиотеке вместе с объектными модулями находится список, в котором содержатся имена функций и данных принадлежащих библиотеке. Посмотреть содержимое библиотеки можно утилитой arm-none-eabi-nm из инструментария. При разрешении имён, линковщик включит подходящие символы из первого подходящего объектного файла библиотеки и прекратит дальнейшее сканирование библиотеки. Если в библиотеке имеется несколько версий функции в разных объектных файлах, важен порядок расположения файлов в библиотеке. Далее упражнение на создание и использование библиотек.
Пример программ намеренно создан простым. Библиотека libZXY.a содержит два модуля, AB.o и CD.o . В модулях sum.o и sub.o имеются ссыки на символы в модулях библиотеки. В свою очередь модуль main.o сылается на модули sum.o и sub.o. Тексты программ приведёны ниже.
Командный файл компиляции:
Каталоги /Libraries и /Utilities скопированы без изменений из демо пакета. Из подкаталога /Project/Examples/RCC , файлы примеров скопированы в каталог Src. Для удобства компиляции файлов демо проекта, я написал скрипт командного интерпретатора bash. Вот его текст:
Объектные файлы AB.o и CD.o помещаем в библиотеку:
Компонуем командой:
Файл библиотеки указан в конце списка объектных файлов подлежащих компоновке, и это не случайно. Если расположить, например библиотеку после файла st.o , то некоторые символы окажутся не разрешёнными и сборки программы не произойдёт. По умолчанию компоновщик сканирует библиотеку на предмет поиска не разрешённых ссылок, только если встретит в командной строке файл библиотеки. В модуле sub.o имеются ссылки на символы в модуле библиотеки, но если библиотека указана раньше файла sub.o , то повторного сканирования библиотеки не произойдёт. А если библиотека указана после sub.o , то символы будут успешно разрешены. Когда список объектных файлов в командной строке заканчивается, то линковщиком формируется полный список не разрешённых ссылок и после сканирования библиотеки, которая находится в конце списка, они успешно разрешаются. Но это не всё. Если библиотек несколько, то между отдельными модулями библиотек могут быть зависимости. Порядок указания библиотек тоже важен. Стандартные библиотеки компилятора, рекомендуется располагать в конце списка, в таком порядке:
Особый случай, когда зависимости между библиотеками циклические. Для решения подобных проблем, имеется универсальное средство. Список библиотек и объектных файлов можно задать в командной строке в виде:
Если файлы заданы в командной строке в таком виде, то будет происходить сканирование списка библиотек при любом разрешении ссылок и до известной степени можно не заботиться о месте и порядке расположения библиотек в командной строке компоновщика. Правда это приводит к некоторому снижению скорости линковки. Можно прописать библиотеки в скрипте линковки, для этого используют команду:
Насколько мне удалось выяснить, объединять в группы, можно не только библиотеки, но и объектные файлы. Хотя в документации говорится только о библиотечных файлах. Единственный минус от группировки файлов, увеличение времени компоновки. Благодаря флагу -Map=file.map , генерируется файл карты сборки проекта. Это текстовый файл с ценной информацией о компоновке программы. Рассмотрим структуру сгенерированного файла карты сборки. Первым идёт раздел с описанием включенных в процесс сборки библиотек. Строка из моей карты сборки:
В строке сообщается, что в конечный образ программы включались секции из модуля AB.o входящего в библиотеку libZXY.a , из-за ссылок в модуле sum.o. В скобках показывается один из символов, виновников включения секций модуля AB.o - это символ Bb. Часто компилятор включает свои библиотеки по умолчанию и в этом разделе файла карты сборки, можно определить из каких библиотек, какие модули, были включены и почему. В разделе "Memory Configuration" описана использованная конфигурация памяти. Затем описание загруженных файлов. После описания загруженных файлов, состав секций и вклад каждого объектного модуля в выходную секцию, с описанием символов видимых извне. Ниже, фрагмент файла карты:
Выходная секция .text , начинается с адреса 0x0 , размер 0xf4. С отступом ниже, входная секция из файла st.o , размером 0x6c. Ещё ниже символ start из этой входной секции и его значение. И так далее, все входные секции с указанием размеров и символов. В некоторых случаях, компоновщик генерирует секции заглушки кода, на английском языке, linker stabs. Например, для некоторых архитектур ARM, для перехода из режима ARM в THUMB, необходимы такие заглушки. Иногда такие вставки требуются для обхода некоторых различий в системе команд различных реализаций ARM. Секции, отмеченные в карте сборки, как linker stabs, относятся к этой категории, в конечный образ они не входят, так как имеют нулевой размер. При анализе файла карты сборки, можно сделать вывод, что все секции объектного файла используются как входные, даже если данные и код этих секций не используются в других объектных файлах. Секция .rodata модуля CD.o загружена, хотя ссылок на строковую константу Ff из других модулей нет. Легко обнаружить в двоичном образе программы строку "trash" - значение константы Ff. Функция ff_sub файла sub.c , не используется в других частях программы, но занесена в выходную секцию. Флаг компоновщика --gc-sections , заставляет его не использовать входные секции, код и данные которых, нигде не используются в программе. Если при линковке задать этот флаг, то в конечном образе программы не будет строки "trash". А в файле карты компоновки, появится раздел "Discarded input sections". В этом разделе перечислены входные секции всех файлов использованных в процессе сборки и рядом размер отброшенной секции. Если размер секции ноль - секция не отброшена. Такое, несколько странное представление информации. Из карты сборки видно, что 8 байт входной секции .rodata , модуля CD.o не вошли в выходной файл. В то же время, если во входной секции имеются объекты, как используемые, так и не используемые в других частях программы, то в этом случае секция используется целиком, примером служит функция ff_sub модуля sub.o. Интересно, что если не задать точку входа, к примеру, в скрипте линкера, командой ENTRY( start ), где метка start , объявлена как глобальная в стартовом модуле, то линкер отбросит все секции. Конечный образ будет нулевого размера. Для более тонкой чистки программы, на предмет не нужного кода и данных, применяют флаги компилятора, -function-sections и -fdata-sections. В этом случае компилятор помещает каждую функцию в отдельную секцию. А затем при компоновке, ненужные секции исключаются из сборки, конечно, если указан флаг линкера -gc-sections . Перекомпилируем программы с новыми флагами и посмотрим, какие образовались секции:
Компилятор поместил каждую функцию в отдельную секцию, а имя создал составное, добавив к названию секции, название функции через точку. Секции модуля с данными:
Виден результат действия флага -fdata-sections , каждый объект данных помещён в отдельную секцию. В документации к компилятору говорится, что эти флаги компиляции могут создать проблемы при отладке и усложняют структуру исполнимого файла, поэтому без особой нужды их применять не следует. Для успешной сборки, необходимо доработать скрипт линкера. В разделе SECTIONS , после описания входных секций, добавить описание секций с шаблоном "*", вот так это выглядит для секции .text:
Если использовать эти флаги для компиляции примеров библиотеки SPL, то результат будет просто разительный.
Главная - Микросхемы - DOC - ЖКИ - Источники питания - Электромеханика - Интерфейсы - Программы - Применения - Статьи |
|
Впервые? | Реклама на сайте | О проекте | Карта портала тел. редакции: +7 (995) 900 6254. e-mail:info@eust.ru ©1998-2023 Рынок Микроэлектроники |
|