Удаление неиспользуемых библиотечных функций/мертвого кода из статического исполняемого файла

Я компилирую код для микроконтроллера ARM Cortex-M0 с GCC arm-none-eabi-g++ (4.8.3). Все хорошо, но я заметил, что когда я включаю и использую любую функцию из cstdlib, все функции из этого файла также включаются. Как избавиться от них?

Я вызываю только malloc() и free(), но результирующий ELF также имеет машинный код system() и isatty().

MCU имеет только 32 КБ флэш-памяти, поэтому балласт ~ 0,7 КБ имеет значение, особенно если это происходит для других заголовков.

Прямо сейчас я использую -ffunction-sections -fdata-sections для компиляции и -Wl,--gc-sections -Wl,--static при компоновке следующим образом:

arm-none-eabi-g++ -c --std=c++11 -Os -I. -Ilpc1xxx -Idrivers -Wall -mthumb \
  -ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=cortex-m0 \
  -DTARGET=LPC11xx -fno-builtin -flto -fno-exceptions -o main.o main.cpp
arm-none-eabi-gcc -c --std=c11   -Os -I. -Ilpc1xxx -Idrivers -Wall -mthumb \
  -ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=cortex-m0 \
  -DTARGET=LPC11xx -fno-builtin -flto  -o core_cm0.o lpc1xxx/nxp/core_cm0.c
arm-none-eabi-gcc -nostartfiles -mcpu=cortex-m0 -mthumb -Wl,--gc-sections -flto \
  -Os -Wl,--static -T lpc1xxx/memory.ld -o firmware.elf main.o core_cm0.o  \
  libaeabi-cortexm0/libaeabi-cortexm0.a LPC11xx_handlers.o LPC1xxx_startup.o

Редактировать: Внимание: Флаг -flto в моем примере неправильный — каким-то образом он отбрасывает подпрограммы прерывания.

В результате, когда я делаю arm-none-eabi-objdump -t firmware.elf, среди прочего я получаю:

00000fbc g     F .text  0000002c _isatty
00001798 g     F .text  00000018 fclose
00000e4c g     F .text  00000030 _kill
00000e7c g     F .text  00000018 _exit
00000fe8 g     F .text  00000050 _system

Эти функции явно избыточны (и совершенно бесполезны для mcu), но GCC сохраняет их в исполняемом файле. Обращений к ним нет, эти символы нигде не упоминаются. Это фактически мертвый код.

Как избавиться от них? Какие-то дополнительные флаги компилятора/компоновщика?


Изменить:

Минимальный код для воспроизведения моей проблемы:

#include <cstdlib>
int main(){
    [[gnu::unused]] volatile void * x = malloc(1);
    return 0;
}

Команда, используемая для компиляции:

arm-none-eabi-g++ --std=c++11 -Os -Wall -mthumb -ffunction-sections 
  -fdata-sections -fmessage-length=0 -mcpu=cortex-m0 -fno-builtin -flto
  -fno-exceptions -Wl,--static -Wl,--gc-sections -o main.elf main.cpp

И файл main.elf все еще имеет все раздувание stdlib.



person Jan K    schedule 09.07.2015    source источник
comment
Я не думаю, что это должно быть помечено avr-gcc, так как вы не используете avr-gcc.   -  person David Grayson    schedule 09.07.2015
comment
Похоже, вы предоставили правильные параметры компилятора, чтобы избавиться от неиспользуемых функций, поэтому в одной из вещей, которые вы связываете, должно быть что-то, что использует эти функции. Что такое LPC11xx_handlers.o? Вы уверены, что это не относится к этим функциям? Возможно, вы могли бы сделать меньший тестовый пример и опубликовать здесь весь код, необходимый для воспроизведения проблемы.   -  person David Grayson    schedule 09.07.2015


Ответы (1)


Здесь правильно использовать -ffunction-sections, но проблема в том, что объектный файл, предоставляющий malloc и free, создается без него (либо LPC11xx_handlers.o, LPC1xxx_startup.o, либо некоторые объектные файлы в libaeabi-cortexm0.a). В этом случае компоновщик может включить только весь объектный файл (или с -Wl,--gc-sections весь раздел), который содержит нужные вам функции.

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

Итак, чтобы решить вашу проблему, перестройте файлы стандартной библиотеки с помощью -ffunction-sections -fdata-sections.

person mstorsjo    schedule 09.07.2015
comment
объектный файл, который предоставляет malloc и free, построен без него - я должен был подумать об этом сам! - person Jan K; 12.07.2015
comment
Newlib был собран без флага -ffunction-sections. Я слишком доверяю gentoo crossdev. Пересобрал newlib, снизился с 11432B до 7384B. - person Jan K; 12.07.2015
comment
Также есть доступная опция, которую я только что видел в gcc-arm-none-eabi.../share/doc/gcc-arm-none-eabi/readme.txt об опции --specs=nano.specs, которая сообщает компилятору и компоновщику использовать оптимизированные по размеру файлы newlib-nano, libstdc++_nano.a и libsupc++_nano.a. Просто добавление этого уменьшило мой исполняемый файл на 23%. - person Craig B; 19.09.2017