Предотвращение связывания объектов, если они не нужны? - PullRequest
2 голосов
/ 23 марта 2010

У меня есть проект ARM, который я создаю с помощью make. Я создаю список объектных файлов для ссылки на основе имен всех файлов .c и .cpp в моем исходном каталоге. Тем не менее, я хотел бы исключить объекты из связанных, если они никогда не используются. Будет ли компоновщик исключать эти объекты из файла .elf автоматически, даже если я включу их в список объектов для ссылки? Если нет, есть ли способ создать список только тех объектов, которые необходимо связать?

Ответы [ 7 ]

2 голосов
/ 25 марта 2010

Вы должны скомпилировать свой код по-другому, чтобы удалить функцию и данные, которые не используются. Обычно все объекты компилируются в один и тот же символ, поэтому их нельзя по отдельности опустить, если они не используются.

Добавьте два следующих параметра в строку вашего компилятора: -ffunction-section -fdata-секции Когда вы компилируете, компилятор теперь помещает отдельные функции и данные в свои собственные секции, а не объединяет их все в одну секцию модуля.

Затем в своем компоновщике укажите следующее: --gc сечения Это указывает компоновщику удалить неиспользуемые разделы («gc» для сборки мусора). Он будет собирать части файлов и целые файлы. Например, если вы компилируете объект, но используете в нем только 1 функцию из 100, он выбросит остальные 99, которые вы не используете.

Если вы столкнулись с проблемами с функциями, которые не были найдены (это происходит по разным причинам, например, externs между библиотеками), вы можете использовать директивы .keep в файле компоновщика (* .ld), чтобы предотвратить сборку мусора для этих отдельных функций .

Наслаждайтесь своим значительно меньшим приложением.

1 голос
/ 24 марта 2010

Как говорили многие люди, ответ «зависит». По моему опыту, RVCT очень хорошо разбирает мертвый код. Неиспользуемый код и данные почти всегда будут удалены на последнем этапе ссылки. С другой стороны, GCC (по крайней мере, без серверной части LLVM) плохо справляется со статическим анализом всего изображения и не очень хорошо справляется с удалением неиспользуемого кода (и вам будет хорошо, если ваш код находится в разных разделах требует прыжков в длину). Вы можете предпринять некоторые шаги, чтобы смягчить его, например, с помощью функциональных разделов, которые создают отдельный раздел для каждой функции и обеспечивают лучшее удаление мертвого кода.

Пусть ваш компоновщик сгенерирует файл карты вашего бинарного файла, чтобы вы могли увидеть, что там было, а что удалено.

1 голос
/ 23 марта 2010

Если вы используете RealView, кажется, что это возможно. Этот раздел обсуждает это:

3.3.3 Удаление неиспользуемой секции

Удаление неиспользуемого раздела удаляет код, который никогда не выполняется, или данные, которые не выполняются ссылка на код, из окончательного изображения. Эта оптимизация может контролироваться Параметры компоновщика --remove, --no_remove, --first, --last и --keep. Используйте --info не используется опция компоновщика для указания компоновщику создать список неиспользуемых разделов, которые были устранена.

0 голосов
/ 24 марта 2010

Традиционно компоновщики связывают во всех объектных файлах, которые явно указаны в командной строке, даже если они могут быть опущены, и программа не будет иметь неразрешенных символов. Это означает, что вы можете сознательно изменить поведение программы, включив объектный файл, который выполняет что-то, вызванное статической инициализацией, но не вызывается прямо или косвенно из main.

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

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

0 голосов
/ 24 марта 2010

По моему опыту, многие компиляторы не будут включать неиспользуемый код на основе объектных файлов. Некоторые могут не иметь этого разрешения и включать целые библиотеки («потому что это ускоряет процесс сборки»).

Например, дан файл junk.c и он имеет три функции: Func1, Func2 и Func3. В процессе сборки создается объектный файл junk.o, в котором есть все три функции. Если функция Func2 не используется, она все равно будет включена, потому что компоновщик не может исключить одну функцию из объектного файла.

С другой стороны, данные файлы: Func1.c, Func2.c и Func3.c, с указанными выше функциями, по одному на файл. Если Func2 в Func2.c не используется, компоновщик не будет его включать.

Некоторые компоновщики достаточно умны, чтобы исключать файлы из библиотек. Однако каждый компоновщик отличается по степени детализации включения файла (и, следовательно, исключения файла). Прочитайте руководство вашего компоновщика или обратитесь в его службу поддержки для получения точной информации.

Я предлагаю переместить подозрительные функции в отдельный файл (по одной функции на файл) и перестроить. Измерьте размер кода до и после. Кроме того, может быть разница между связью отладки и выпуска. Связывание отладки может быть ленивым и просто добавлять все, а связывание релиза прилагает больше усилий для удаления неиспользуемого кода.

Только мои мысли и опыт, Ваш пробег может меняться (YMMV).

0 голосов
/ 23 марта 2010

Какой компилятор / компоновщик вы используете? Некоторые компоновщики делают это автоматически, а некоторые предоставляют эту функцию в качестве параметра командной строки.

0 голосов
/ 23 марта 2010

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

...