gcc / -ffunction-sections、-fdata-sections、-Wl,--gc-sections

通过GCC的-ffunction-sections和-fdata-sections编译选项,以及-Wl,--gc-sections链接选项,可以将每个函数和数据放入独立的section,并在链接时删除未使用的section,从而减小可执行程序的体积。在示例中,使用这些选项的main_sections比常规编译的main_normal文件更小。

一、背景

有时我们的程序会定义一些暂时使用不上的功能和函数,虽然我们不使用这些功能和函数,但它们往往会浪费我们的 ROM 和 RAM 的空间。这在使用静态库时,体现的更为严重。有时,我们只使用了静态库仅有的几个功能,但是系统默认会自动把整个静态库全部链接到可执行程序中,造成可执行程序的大小大大增加。

二、参数详解

为了解决前面分析的问题,我们引入了标题中的几个参数。GCC 链接操作是以 section 作为最小的处理单元,只要一个 section 中的某个符号被引用,该 section 就会被加入到可执行程序中去。

因此,GCC 在编译时可以使用 -ffunction-sections-fdata-sections 将每个函数或符号创建为一个 sections,其中每个 sections 名与 function 或 data 名保持一致。而在链接阶段, -Wl,–gc-sections 指示链接器去掉不用的section(其中-wl, 表示后面的参数 -gc-sections 传递给链接器),这样就能减少最终的可执行程序的大小了。

我们常常使用下面的配置启用这个功能:

CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS += -Wl,--gc-sections

三、栗子

#include <stdio.h>
 
int fun_0(void)
{
    printf("%s: %d\n", __FUNCTION__, __LINE__);
    return 0;
}
 
int fun_1(void)
{
    printf("%s: %d\n", __FUNCTION__, __LINE__);
    return 0;
}
 
int fun_2(void)
{
    printf("%s: %d\n", __FUNCTION__, __LINE__);
    return 0;
}
 
int fun_3(void)
{
    printf("%s: %d\n", __FUNCTION__, __LINE__);
    return 0;
}
 
void main(void)
{
    fun_0();
    fun_3();
}

Makefile 文件如下: 

main_sections:
        gcc -ffunction-sections -fdata-sections -c main.c
        gcc -Wl,--gc-sections -o $@ main.o 
 
main_normal:
        gcc -c main.c
        gcc -o $@ main.o
 
clean:
        rm -rf *.o main_sections main_normal

执行

make  main_sections

make  main_normal

 可以发现文件大小 main_sections 比 main_normal 小。

 四、分析 sections 

 1、查看 setions 信息

(1)执行 main_sections 对应 main.o

readelf -t main.o

( -t 选项是打印出 sections 信息 ) 

结果:

从 object 文件中可以发现,fun_0 ~ fun_3 每个函数都是一个独立的 section 。

(2)执行 main_normal 对应 main.o

可以发现 所有 fun_* 共享一个默认的 sections(.text)。

2、分析 elf 文件。

readelf -a main_normal | grep fun_ 

结果:

 

readelf -a main_sections | grep fun_ 

结果: 

 

可以看见,在最终的目标文件中,未使用的函数并未被链接进最终的目标文件。

转载:gcc之 -ffunction-sections_springcrazy的博客-优快云博客

 

(SAW:Game Over!) 

 

 

 

 

# 从当前用户主目录查找目录的函数 # 参数1: 要查找的目录名 define find_in_home $(shell \ found_dir=$$(find "$$HOME" -type d -name "$(1)" -print -quit 2>/dev/null); \ if [ -n "$$found_dir" ]; then \ echo "$$found_dir"; \ else \ echo "DIRECTORY_NOT_FOUND"; \ fi \ ) endef # 使用示例(查找用户主目录下的 Documents 目录) TARGET_DIR := lite-user-runtime-env ENV_DIR := $(call find_in_home,$(TARGET_DIR)) ifeq ($(ENV_DIR),DIRECTORY_NOT_FOUND) $(error Directory "$(TARGET_DIR)" not found!!) else $(info ENV_DIR = $(ENV_DIR)) endif # Kconfig 配置系统相关 KCONFIG_CONFIG ?= $(CURDIR)/.config KCONFIG_AUTOHEADER ?= $(CURDIR)/autoconf.h KCONFIG_AUTOCONF ?= $(CURDIR)/autoconf.h # 检查 Kconfig 工具是否存在 ifeq ($(shell command -v kconfig-mconf 2>/dev/null),) $(error "kconfig-frontends not found, please install it first (sudo apt install kconfig-frontends)") endif KCONFIG_TOOL := $(shell command -v kconfig-conf 2>/dev/null) ifndef KCONFIG_TOOL $(error "kconfig-conf not found! Please install kconfig-frontends (sudo apt install kconfig-frontends)") endif CROSS = $(ENV_DIR)/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin/arm-none-eabi- CREAT_TOOL = $(ENV_DIR)/bin/create-sp-img CC = gcc INC = -I . -I ./include -I ../posix/include INC += -I $(ENV_DIR)/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/include #cflag = -g ${cflags} -Wall -fPIC -fno-asynchronous-unwind-tables -fno-builtin-function -mcpu=cortex-m3 -mthumb -nostdinc #inc += -I $(SPBASEDIR)/vsoc/$(os_type)/include/ -I . #inc += -I $(SPBASEDIR)/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/include # CFLAG = -g -Wall -fPIC -fno-asynchronous-unwind-tables -mcpu=cortex-a5 -mtune=generic-armv7-a -mthumb -mfloat-abi=soft -Os # CFLAG = -g -Os -Wall -fPIC -fno-asynchronous-unwind-tables -mcpu=cortex-a5 -mtune=generic-armv7-a -mthumb -mfpu=neon-vfpv4 -mfloat-abi=hard #-ffreestanding 独立环境 CFLAG += -include $(KCONFIG_AUTOHEADER) CFLAG += -Os -fno-asynchronous-unwind-tables -mcpu=cortex-m3 -mthumb -nostdinc -nostdlib -ffreestanding -ffunction-sections -fdata-sections CFLAG += -fPIE -Wall -fno-builtin-function -Werror=implicit -flto #lflag = -g -pie -T n58.ld.lds -Os --no-warn-rwx-segments --start-group $(ENV_DIR)/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/thumb/v7-m/nofp/libgcc.a ../posix/lib/libposix.a --end-group #lflag = ../src/raw.o ../src/dns_server.o ../src/exit.o ../src/memset.o ../src/network.o ../src/strncasecmp.o ../src/timerfd.o ../src/vfs_device.o ../src/vfs.o lflag += -g -pie -T n58.ld.lds -Os -Wl,--no-warn-rwx-segments -flto -mcpu=cortex-m3 -mthumb -nostartfiles -nostdlib lflag += -Wl,--start-group,../posix/lib/libposix.a,$(ENV_DIR)/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/thumb/v7-m/nofp/libgcc.a,--end-group lflag += -Wl,-Bsymbolic,-gc-sections LD = gcc objs = main.o websocket_client.o websocket_client_posix.o uart_audio.o crc32_new.o hdlc_byte.o var_buffer_fifo.o tiny_json.o gpio.o led.o pwrkey.o adc.o rtc.o target = test image = $(target).spimg # Kconfig 配置目标:打开图形化配置界面 menuconfig: Kconfig @echo "Starting Kconfig menuconfig..." kconfig-mconf $< --output $(KCONFIG_CONFIG) @# 配置后立即生成头文件 $(MAKE) generate_header generate_header: $(KCONFIG_CONFIG) @echo "Generating autoconf.h from .config..." $(KCONFIG_TOOL) --silentoldconfig $(CURDIR)/Kconfig $(KCONFIG_CONFIG) --header=$(KCONFIG_AUTOHEADER) @test -f $(KCONFIG_AUTOHEADER) || (echo "Error: Failed to generate autoconf.h"; exit 1) @echo "Successfully generated $(KCONFIG_AUTOHEADER)" $(KCONFIG_AUTOHEADER): $(KCONFIG_CONFIG) @if [ ! -f "$(KCONFIG_CONFIG)" ]; then \ $(MAKE) menuconfig; \ else \ $(MAKE) generate_header; \ fi .c.o: $(CROSS)$(CC) -c $< $(INC) $(CFLAG) all:$(KCONFIG_AUTOHEADER) $(target) $(image) @echo "Build completed successfully" $(target):$(objs) $(CROSS)$(LD) -o $@ $^ $(lflag) $(image):$(target) $(CREAT_TOOL) $(target) host armm3 > /dev/null clean: -rm -fv $(target) -rm -fv *.o -rm -fv *.spimg spvsoc@spvsoc-vm:~/4G_8006/vsoc_posix_env$ make clean ;make make clean -C src make[1]: 进入目录“/home/spvsoc/4G_8006/vsoc_posix_env/src” ENV_DIR = /home/spvsoc/lite-user-runtime-env rm -f *.o libposix.a rm -f .depend make[1]: 离开目录“/home/spvsoc/4G_8006/vsoc_posix_env/src” make clean -C test make[1]: 进入目录“/home/spvsoc/4G_8006/vsoc_posix_env/test” ENV_DIR = /home/spvsoc/lite-user-runtime-env rm -fv test rm -fv *.o rm -fv *.spimg make[1]: 离开目录“/home/spvsoc/4G_8006/vsoc_posix_env/test” rm posix -rf make install -C src make[1]: 进入目录“/home/spvsoc/4G_8006/vsoc_posix_env/src” ENV_DIR = /home/spvsoc/lite-user-runtime-env /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -g -Wall -Os -fno-asynchronous-unwind-tables -mcpu=cortex-m3 -mthumb -nostdinc -nostdlib -ffreestanding -ffunction-sections -fdata-sections -fPIE -fno-builtin-function -Werror=implicit -flto -I ./ -I include/ -I /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/include -c dns_server.c /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -g -Wall -Os -fno-asynchronous-unwind-tables -mcpu=cortex-m3 -mthumb -nostdinc -nostdlib -ffreestanding -ffunction-sections -fdata-sections -fPIE -fno-builtin-function -Werror=implicit -flto -I ./ -I include/ -I /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/include -c exit.c /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -g -Wall -Os -fno-asynchronous-unwind-tables -mcpu=cortex-m3 -mthumb -nostdinc -nostdlib -ffreestanding -ffunction-sections -fdata-sections -fPIE -fno-builtin-function -Werror=implicit -flto -I ./ -I include/ -I /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/include -c memset.c /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -g -Wall -Os -fno-asynchronous-unwind-tables -mcpu=cortex-m3 -mthumb -nostdinc -nostdlib -ffreestanding -ffunction-sections -fdata-sections -fPIE -fno-builtin-function -Werror=implicit -flto -I ./ -I include/ -I /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/include -c network.c /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -g -Wall -Os -fno-asynchronous-unwind-tables -mcpu=cortex-m3 -mthumb -nostdinc -nostdlib -ffreestanding -ffunction-sections -fdata-sections -fPIE -fno-builtin-function -Werror=implicit -flto -I ./ -I include/ -I /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/include -c raw.c /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -g -Wall -Os -fno-asynchronous-unwind-tables -mcpu=cortex-m3 -mthumb -nostdinc -nostdlib -ffreestanding -ffunction-sections -fdata-sections -fPIE -fno-builtin-function -Werror=implicit -flto -I ./ -I include/ -I /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/include -c strncasecmp.c /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -g -Wall -Os -fno-asynchronous-unwind-tables -mcpu=cortex-m3 -mthumb -nostdinc -nostdlib -ffreestanding -ffunction-sections -fdata-sections -fPIE -fno-builtin-function -Werror=implicit -flto -I ./ -I include/ -I /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/include -c timerfd.c /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -g -Wall -Os -fno-asynchronous-unwind-tables -mcpu=cortex-m3 -mthumb -nostdinc -nostdlib -ffreestanding -ffunction-sections -fdata-sections -fPIE -fno-builtin-function -Werror=implicit -flto -I ./ -I include/ -I /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/include -c vfs.c /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc -g -Wall -Os -fno-asynchronous-unwind-tables -mcpu=cortex-m3 -mthumb -nostdinc -nostdlib -ffreestanding -ffunction-sections -fdata-sections -fPIE -fno-builtin-function -Werror=implicit -flto -I ./ -I include/ -I /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/13.2.1/include -c vfs_device.c /home/spvsoc/lite-user-runtime-env/toolschain/arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi/bin/arm-none-eabi-gcc-ar rcs libposix.a dns_server.o exit.o memset.o network.o raw.o strncasecmp.o timerfd.o vfs.o vfs_device.o rm ../posix -rf mkdir ../posix cp include ../posix -rf mkdir ../posix/lib cp libposix.a ../posix/lib make[1]: 离开目录“/home/spvsoc/4G_8006/vsoc_posix_env/src” make -C test make[1]: 进入目录“/home/spvsoc/4G_8006/vsoc_posix_env/test” ENV_DIR = /home/spvsoc/lite-user-runtime-env Starting Kconfig menuconfig... kconfig-mconf Kconfig --output /home/spvsoc/4G_8006/vsoc_posix_env/test/.config *** End of the configuration. *** Execute 'make' to start the build or try 'make help'. make generate_header make[2]: 进入目录“/home/spvsoc/4G_8006/vsoc_posix_env/test” ENV_DIR = /home/spvsoc/lite-user-runtime-env Generating autoconf.h from .config... /usr/bin/kconfig-conf --silentoldconfig /home/spvsoc/4G_8006/vsoc_posix_env/test/Kconfig /home/spvsoc/4G_8006/vsoc_posix_env/test/.config --header=/home/spvsoc/4G_8006/vsoc_posix_env/test/autoconf.h /usr/bin/kconfig-conf: 未识别的选项 "--header=/home/spvsoc/4G_8006/vsoc_posix_env/test/autoconf.h" Usage: /usr/bin/kconfig-conf [-s] [option] <kconfig-file> [option] is _one_ of the following: --listnewconfig List new options --oldaskconfig Start a new configuration using a line-oriented program --oldconfig Update a configuration using a provided .config as base --silentoldconfig Same as oldconfig, but quietly, additionally update deps --olddefconfig Same as silentoldconfig but sets new symbols to their default value --oldnoconfig An alias of olddefconfig --defconfig <file> New config with default defined in <file> --savedefconfig <file> Save the minimal current configuration to <file> --allnoconfig New config where all options are answered with no --allyesconfig New config where all options are answered with yes --allmodconfig New config where all options are answered with mod --alldefconfig New config with all symbols set to default --randconfig New config with random answer to all options make[2]: *** [Makefile:75:generate_header] 错误 1 make[2]: 离开目录“/home/spvsoc/4G_8006/vsoc_posix_env/test” make[1]: *** [Makefile:71:menuconfig] 错误 2 make[1]: 离开目录“/home/spvsoc/4G_8006/vsoc_posix_env/test” make: *** [Makefile:3:all] 错误 2
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值