背景

有时我们的程序会定义一些暂时使用不上的功能和函数,虽然我们不使用这些功能和函数,但它们往往会浪费我们的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

例子

main.c 文件如下:

#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.cgcc -Wl,--gc-sections -o $@ main.o main_normal:gcc -c main.cgcc -o $@ main.oclean:rm -rf *.o main_sections main_normal

验证

运行

$ make main_sections
gcc -ffunction-sections -fdata-sections -c main.c
gcc -Wl,--gc-sections -o main_sections main.o
$ make main_normal
gcc -c main.c
gcc -o main_normal main.o

比较大小

$ ll main_*
-rwxrwxr-x 1 8896 2月  16 00:42 main_normal*
-rwxrwxr-x 1 8504 2月  16 00:42 main_sections*

可以看见使用该功能的二进制文件要小于不使用该功能的二进制文件

分析sections

$ make clean
rm -rf *.o main_sections main_normal
$ make main_sections
gcc -ffunction-sections -fdata-sections -c main.c
gcc -Wl,--gc-sections -o main_sections main.o
$ readelf -t main.o
...[ 5] .text.fun_0PROGBITS               PROGBITS         0000000000000000  0000000000000048  00000000000000024 0000000000000000  0                 1[0000000000000006]: ALLOC, EXEC[ 6] .rela.text.fun_0RELA                   RELA             0000000000000000  0000000000000508  240000000000000048 0000000000000018  5                 8[0000000000000040]: INFO LINK[ 7] .text.fun_1PROGBITS               PROGBITS         0000000000000000  000000000000006c  00000000000000024 0000000000000000  0                 1[0000000000000006]: ALLOC, EXEC[ 8] .rela.text.fun_1RELA                   RELA             0000000000000000  0000000000000550  240000000000000048 0000000000000018  7                 8[0000000000000040]: INFO LINK[ 9] .text.fun_2PROGBITS               PROGBITS         0000000000000000  0000000000000090  00000000000000024 0000000000000000  0                 1[0000000000000006]: ALLOC, EXEC[10] .rela.text.fun_2RELA                   RELA             0000000000000000  0000000000000598  240000000000000048 0000000000000018  9                 8[0000000000000040]: INFO LINK[11] .text.fun_3PROGBITS               PROGBITS         0000000000000000  00000000000000b4  00000000000000024 0000000000000000  0                 1[0000000000000006]: ALLOC, EXEC[12] .rela.text.fun_3RELA                   RELA             0000000000000000  00000000000005e0  240000000000000048 0000000000000018  11                8[0000000000000040]: INFO LINK

从object文件中可以发现,fun_0 ~ fun_3 每个函数都是一个独立的section.
而如果使用 make main_normal 生成的object文件,则共享一个默认的sections(.text)。

分析elf文件

$ readelf -a main_normal | grep fun_52: 0000000000400526    36 FUNC    GLOBAL DEFAULT   14 fun_055: 000000000040056e    36 FUNC    GLOBAL DEFAULT   14 fun_265: 0000000000400592    36 FUNC    GLOBAL DEFAULT   14 fun_366: 000000000040054a    36 FUNC    GLOBAL DEFAULT   14 fun_1
$ readelf -a main_sections | grep fun_49: 0000000000400526    36 FUNC    GLOBAL DEFAULT   14 fun_057: 000000000040054a    36 FUNC    GLOBAL DEFAULT   14 fun_3

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

gcc -ffunction-sections -fdata-sections -Wl,–gc-sections 参数详解相关推荐

  1. [转]gcc -ffunction-sections -fdata-sections -Wl,–gc-sections 参数详解

    背景 有时我们的程序会定义一些暂时使用不上的功能和函数,虽然我们不使用这些功能和函数,但它们往往会浪费我们的ROM和RAM的空间.这在使用静态库时,体现的更为严重.有时,我们只使用了静态库仅有的几个功 ...

  2. Linux平台Makefile文件的编写基础篇和GCC参数详解

    问:gcc中的-I.是什么意思....看到了有的是gcc -I. -I/usr/xxxxx..那个-I.是什么意思呢 最佳答案 答:-Ixxx 的意思是除了默认的头文件搜索路径(比如/usr/incl ...

  3. Linux 之 编译器 gcc/g++参数详解

    2016年12月9日16:48:53 ----------------------------- 内容目录: [介绍]  gcc and g++分别是gnu的c & c++编译器 gcc/g+ ...

  4. 实用的GCC Makefile语法及参数详解

    二话不说,先上一个Makefile的源码. 基于下述的Makefile,可以直接执行命令: 编译: make   or   make -f Makefile all 清除: make clean  o ...

  5. JAVA之JVM垃圾回收(GC)机制详解

    一.为什么需要垃圾回收 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收.除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此.所以,垃圾回收是必须的. 二. ...

  6. Java垃圾回收(GC)机制详解

    Java垃圾回收(GC)机制详解 转自:https://www.cnblogs.com/xiaoxi/p/6486852.html 一.为什么需要垃圾回收 如果不进行垃圾回收,内存迟早都会被消耗空,因 ...

  7. 关于GCC/LLVM编译器中的sanitize选项用处用法详解

    关于GCC/LLVM编译器中的sanitize选项用处用法详解 ​ 编译器中sanitize选项原本来自google的开源C/C+ +工具集sanitizers项目, 包括了AddressSaniti ...

  8. java gc信息_JVM之GC回收信息详解

    新一代垃圾回收器ZGC设计与实现 70.31元 (需用券) 去购买 > 一.-XX:+PrintGCDetails 打印GC日志 参数配置:-Xms10M -Xmx10M -XX:+PrintG ...

  9. jvm中GC日志格式详解(十)

    一.日志相关参数 1.-XX:+PrintGCDetails 2.-XX:+PrintGCTimeStamps 打印时间戳 3.-XX:+PrintGCDateStamps 4.-Xloggc:/tm ...

最新文章

  1. Linux安装Nginx、Redis、django
  2. mysql+在服务中无法启动_MySQL服务初始化后无法启动
  3. 有关自动目视解译系统的假设
  4. SimplifiedHibernate:简化了的Hibernate
  5. 互链网-未来世界的连接方式 (1)央行数字货币CBDC模型
  6. http协议 和 https
  7. html5 网络断开,html5 – websocket不断断开连接
  8. 微软power bi_Microsoft Power Platform快速概述
  9. Spring3中的mvc:interceptors标签配置拦截器
  10. Windows Phone开发之 WebClient 讲解
  11. mac安装虚拟机win10,Mac安装VirtualBox
  12. CNN卷积神经网络结构遐思
  13. 百度地图经纬度和像素坐标互转
  14. 错过这次,再等一年!视频云CDN全线折扣Hi购启动...
  15. python文件夹操作指令
  16. openNI驱动控制kinect马达
  17. Python中私有变量和私有方法芳
  18. sql数据库表格id重置
  19. 测试数据科学家机器学习技能的40个问题
  20. java JFrame 桌宠 下部

热门文章

  1. ATF:Gicv源码文件系列-gicv2.h
  2. tkmybatis 子查询_【10/21】南池袋送餐桌和椅子 收纳盒子 洗衣机 | 下落合站送洗衣机...
  3. 秋草独寻人去后——986山野穿越点滴(七)
  4. Pytorch里addmm()和addmm_()的用法详解
  5. RTKLIB中PPP程序结构及重要函数
  6. oracle lsnrctl命令,oracle lsnrctl
  7. SSH登录及失败解决
  8. 如何将 Excel 单元格内容按换行符拆分为多列
  9. 建站用阿里云还是腾讯云好?
  10. Android视频编辑器(二)预览、录制视频加上水印和美白磨皮效果