当前位置: 首页 > ds >正文

GCC编译/连接/优化等选项

1. GCC编译/连接/优化等选项

  • 1. GCC编译/连接/优化等选项
    • 1.1. 简介
    • 1.2. 常用选项
      • 1.2.1. -c -E -S -o
      • 1.2.2. -L<path> -l<library>
      • 1.2.3. -D<macro>
      • 1.2.4. -I<path>
    • 1.3. 代码生成和优化
      • 1.3.1. -std=<standard>
      • 1.3.2. -shared
      • 1.3.3. -fPIC
      • 1.3.4. -static
      • 1.3.5. -O0 -O1 -O2 -O3 -Os
      • 1.3.6. -ffunction-sections-fdata-sections
    • 1.4. 调试与警告选项
      • 1.4.1. -g -ggdb
      • 1.4.2. -Wall -Werror -Wextra
      • 1.4.3. -Wno-pointer-sign
      • 1.4.4. -fno-strict-aliasing -fstrict-aliasing
    • 1.5. 安全与连接选项
      • 1.5.1. -z noexecstack -z relro -z now
      • 1.5.2. -Wl,option
      • 1.5.3. -Wl,--strip-all,--gc-sections,--as-needed
      • 1.5.4. -Wl,--verbose,-soname,<name>
      • 1.5.5. -Wl,-T,<script>,-Ttext,<address>,-Tdata,<address>
    • 1.6. 高级选项
      • 1.6.1. -pedantic
      • 1.6.2. -fsanitize=<type>
      • 1.6.3. -rpath <path>

1.1. 简介

GCC 编译流程分为四个阶段:预处理、编译、汇编、链接,这里讲解gcc用到的一些参数

  • GCC 原生选项:直接由 GCC 处理,如:

    • -o(输出文件名)
    • -lm(链接数学库 libm)
    • -Wall(启用警告)
    • -O2(优化级别)
  • 链接器专属选项:需通过 -Wl, 传递给链接器(如 ld),如:

    • –gc-sections(移除未使用的节)
    • -soname(设置共享库运行时名称)
    • -T(使用自定义链接脚本)

1.2. 常用选项

1.2.1. -c -E -S -o

-E 仅进行预处理,输出预处理后的代码。
gcc -E source.c -o source.i

-c 只进行编译,不进行链接,生成目标文件(.o)
gcc -c source.c # 生成 source.o

-S 生成汇编代码(.s)。
gcc -S source.c # 生成 source.s

-o 指定输出文件的名称
gcc source.c -o program

1.2.2. -L<path> -l<library>

-l 链接指定的库(如-lm链接数学库)。
-L 指定库文件的搜索路径。
gcc source.c -L/path/to/lib -lmylib

1.2.3. -D<macro>

定义宏(等价于在代码中使用#define)。

1.2.4. -I<path>

指定头文件的搜索路径。

1.3. 代码生成和优化

1.3.1. -std=<standard>

指定 C/C++ 标准(如-std=c99、-std=c++17)。

1.3.2. -shared

生成共享库(.so)

1.3.3. -fPIC

生成位置无关代码(用于共享库)。

1.3.4. -static

静态链接所有库(生成独立可执行文件)。
gcc -static source.c

1.3.5. -O0 -O1 -O2 -O3 -Os

选项优化目标编译时间代码体积运行性能典型场景
-O0无优化(调试)最快最大最慢开发调试
-O1平衡性能与时间较快较小一般日常开发的 release 版本
-O2优化性能较长中等生产环境默认
-O3最高性能最长最大最快高性能计算
-Os最小代码体积较长最小接近- O2 嵌入式系统、固件

1.3.6. -ffunction-sections-fdata-sections

-ffunction-sections:将每个函数放在独立的 ELF 节(section)中。
-fdata-sections:将每个全局变量放在独立的节中。
目的:配合链接器选项 -Wl,--gc-sections(垃圾回收),在最终二进制文件中移除未使用的函数和变量,减小文件体积。

1.4. 调试与警告选项

1.4.1. -g -ggdb

-g 生成调试信息,用于 GDB 调试。
-ggdb 生成更详细的 GDB 调试信息。

一般配合 -O0 使用, 优化选项(如 -O2)可能会改变代码结构,导致调试信息与实际执行不匹配。

选项调试信息格式适用调试器文件大小调试体验
-g标准 DWARF通用较小基本调试
-ggdbGDB 扩展GDB 专用较大高级调试

1.4.2. -Wall -Werror -Wextra

-Wall 启用常见的编译警告(如未使用的变量、隐式转换等)。
-Werror 将所有警告视为错误,强制修复警告。
-Wextra 启用额外的警告(如未初始化的变量、冗余代码等)。一般用的比较少

1.4.3. -Wno-pointer-sign

-Wno-pointer-sign 是 GCC 编译器的一个警告选项,用于禁用关于指针符号不匹配的警告
禁用警告:通过 -Wno-pointer-sign 可以关闭这类警告,避免编译时产生干扰信息。
相反选项:对应的启用警告选项是 -Wpointer-sign,但通常通过 -Wall 或 -Wextra 自动启用。

1.4.4. -fno-strict-aliasing -fstrict-aliasing

-fstrict-aliasing(默认启用):严格遵循别名规则,进行激进优化。
-fno-strict-aliasing:禁用规则,允许不同类型指针别名,可能导致显著的性能损失。

  • 禁用 GCC 的严格别名规则优化,允许不同类型指针指向同一块内存。
  • 禁用优化会降低性能,建议优先修改代码以符合严格别名规则(如使用 union)。
  • 适用于遗留代码或依赖类型双关(type punning)的场景(如底层硬件访问)。
int a = 1;
float* f = (float*)&a;  // 违反规则
*f = 3.14f;
printf("%d\n", a);  // 可能输出 1(而非预期的修改后的值)

解决方案:

  • 使用 union 实现类型双关,确保类型兼容。
  • 使用字符指针转换
  • 使用 memcpy

1.5. 安全与连接选项

1.5.1. -z noexecstack -z relro -z now

  • -z noexecstack
    • 现代操作系统(如 Linux)支持内存区域的 NX 位(No-eXecute),通过该选项将栈标记为不可执行。
    • 若攻击者尝试在栈上执行恶意代码,会触发内存访问异常。
    • 某些动态链接库(如使用 setjmp/longjmp 的库)可能需要可执行栈,此时需谨慎使用。
    • 现代 Linux 发行版默认启用 NX 保护,但通过 -z execstack 可禁用(不推荐)。
  • -z relro (Relocation Read-Only)
    • 功能:启用只读重定位(Relocation Read-Only)。
    • 防御机制:将全局偏移表(GOT,Global Offset Table)和动态符号表标记为只读,防止攻击者修改这些表中的函数地址。
  • -z now
    • 功能:强制链接器立即绑定所有符号(而非延迟绑定)。
    • 防御机制:减少动态加载时的符号表修改机会,增强 RELRO 的安全性。

1.5.2. -Wl,option

-Wl,option 是 GCC 编译器用于将参数传递给链接器(如 ld)的语法。通过 , 分隔多个选项,例如 -Wl,–gc-sections,-Map=output.map

gcc source.c -Wl,-o,program.out       # -o 选项,指定输出文件名,等价于 gcc source.c -o program.out
gcc source.c -Wl,-e,my_entry_point    # -e 选项,指定入口点,代替 main 函数,等价于 gcc source.c -emy_entry_point
gcc source.c -Wl,-L,/path/to/lib      # -L 选项,指定库搜索路径,等价与 gcc source.c -L/path/to/lib
gcc source.c -Wl,-l,m                 # -l 选项,等价与 gcc source.c -lm,建议直接使用 -lm,语法更简洁。
  • 选项类别 必须使用 -Wl, 的典型选项
    • 代码优化 --gc-sections, --as-needed
    • 内存布局 -T, -Ttext, -Tdata
    • 共享库 -soname, --version-script
    • 安全增强 -z noexecstack, -z relro, -z now
    • 调试 --verbose, --cref

1.5.3. -Wl,--strip-all,--gc-sections,--as-needed

gcc source.c -Wl,--strip-all,--gc-sections,--as-needed
gcc source.c -Wl,--wrap,malloc  # 使用 __wrap_malloc 替代 malloc
  • --gc-sections 移除未使用的代码和数据段(需配合 -ffunction-sections 和 -fdata-sections)。
    • 用于移除可执行文件中未使用的代码和数据段(sections),从而减小二进制文件体积。
    • 若某个节被标记为 USED(如通过 attribute((used))),则不会被回收。
    • 启用 GC 会增加链接时间(需分析所有符号),但通常对运行时性能无影响。
    • 若二进制体积不是关键因素,可关闭此选项以加快编译。
    • -O2 会自动启用一些内联优化,但无法替代 --gc-sections 的全局代码删除能力。
    • 验证:使用 size 命令对比文件大小
  • --strip-all 或 --strip-debug 移除符号表和调试信息。
  • --as-needed 仅链接真正使用的共享库(减少依赖)。
  • --wrap <symbol> 允许替换标准库函数(用于测试或钩子)。

1.5.4. -Wl,--verbose,-soname,<name>

gcc source.c -Wl,--verbose,-soname,libmylib.so.1

--verbose 输出链接过程的详细信息。
-soname <name> 设置共享库的运行时名称(用于版本控制)。

1.5.5. -Wl,-T,<script>,-Ttext,<address>,-Tdata,<address>

gcc source.c -Wl,-T,memory_layout.ld
gcc source.c -Wl,-Ttext,0x10000
gcc source.c -Wl,-Tdata,0x20000

-T <script> 使用自定义链接脚本(用于嵌入式系统或特殊内存布局)。
-Ttext <address> 指定代码段(.text)的加载地址。
-Tdata <address> 指定数据段(.data)的加载地址。

1.6. 高级选项

1.6.1. -pedantic

严格遵循语言标准,拒绝非标准特性。

1.6.2. -fsanitize=<type>

启用运行时检查(如内存泄漏、未定义行为)。

1.6.3. -rpath <path>

设置运行时库搜索路径(替代 LD_LIBRARY_PATH)。

gcc source.c -Wl,-rpath,/path/to/lib

http://www.xdnf.cn/news/14009.html

相关文章:

  • Solon框架模板漏洞深度剖析与修复实战
  • python格式化字符串的几种方式
  • mysql表备份数据,改表名
  • Ubuntu下使用PyTurboJPEG加速图像编解码
  • 【阿里巴巴 x 浙江大学】信息与交互设计 - 交互设计流程与要素
  • PDB Bank怎么下载小分子sdf(选择哪个)和复合物
  • Spring依赖注入的四种方式(面)
  • DC3靶机渗透
  • python计算生态库:18个常用标准库+第三方库
  • 杭州电商代运营公司排名前十
  • SPRING AI 入门
  • 前端八股文 - JavaScript 篇
  • UE接口通信常见问题
  • Ubuntu下搭建Black Magic Probe (BMP) 编译环境
  • AbMole| 2-Deoxy-D-glucose(M5140;2-脱氧-D-葡萄糖)
  • 第七章接入技术
  • opencv opencv_contrib vs2020 源码安装
  • 简述Python里面search和match的区别
  • ZooKeeper详解以及应用部署(AI)
  • Spring Cache 详细介绍——补充
  • 深度解析 JuiceFS 权限管理:Linux 多种安全机制全兼容
  • JavaScript 原型(Prototype)详解
  • 金属切削机床制造企业如何破局?探索项目管理数字化转型
  • 学习STC51单片机35(芯片为STC89C52RCRC)智能小车3(PWM调速小车)
  • C++学习之虚析构函数
  • 【QT】QVariant 转换为自定义的枚举类型
  • 当机械工程师的餐桌变身实验室:立创电赛的真实创新启示录
  • 《深度优先搜索》题集
  • 结构型模式 (7种)
  • 鸿蒙期末总结