去除可执行文件中没用到的符号

关于STM32 使用ARM GCC编译链接C++生成固件的压缩、减少和优化大小的几个编译链接参数 随之进来的物联网的兴起,要像安卓那样建立生态,需要跟多的开发者投入其中,那么就要降低门槛。物联网系统中arm 自家的mbed 系统就采用了c++, 用对象的形式封装了外设驱动,比如GPIO口封装成AnalogIn,AnalogOut,BusIn,BusInOut,BusOut,DigitalInOut,DigitalIn,DigitalOut等类。使开发者 可以不用非常熟悉cortex-m 内 阅读详情

1. 编译阶段使用:
-ffunction-sections
-fdata-sections

2. 链接阶段使用:
-Wl,--gc-sections

在GCC,LD官方文档中如下讲解:
在GCC,LD官方文档中如下讲解:
-ffunction-sections
-fdata-sections
Place each function or data item into its own section in the output file if the target supports arbitrary sections. The name of the function or the name of the data item determines the section's name in the output file. Use these options on systems where the linker can perform optimizations to improve locality of reference in the instruction space. Most systems using the ELF object format and SPARC processors running Solaris 2 have linkers with such optimizations. AIX may have these optimizations in the future.
Only use these options when there are significant benefits from doing so. When you specify these options, the assembler and linker will create larger object and executable files and will also be slower. You will not be able to use gprof on all systems if you specify this option and you may have problems with debugging if you specify both this option and -g.

--gc-sections
--no-gc-sections
Enable garbage collection of unused input sections. It is ignored on targets that do not support this option. The default behaviour (of not performing this garbage collection) can be restored by specifying `--no-gc-sections' on the command line.
`--gc-sections' decides which input sections are used by examining symbols and relocations. The section containing the entry symbol and all sections containing symbols undefined on the command-line will be kept, as will sections containing symbols referenced by dynamic objects. Note that when building shared libraries, the linker must assume that any visible symbol is referenced. Once this initial set of sections has been determined, the linker recursively marks as used any section referenced by their relocations. See `--entry' and `--undefined'.
This option can be set when doing a partial link (enabled with option `-r'). In this case the root of symbols kept must be explicitly specified either by an `--entry' or `--undefined' option or by a ENTRY command in the linker script.
 

 

因为GCC链接操作以section作为最小的处理单元,只要一个section中有某个符号被引用,该section就会被加入。
如果我们的某个.c程序中所有function都加入同一个section.则如果用到这个.c生成的.o的其中任何一个function.则必须将所有

function(符号)加入其中。如此,则使用-ffunction-sections 和 -fdata-sections将每个符号创建为一个sections. sections名

与function,data名保持一致。
则在link阶段,-Wl,--gc-sections 申明去掉不用的section。就可以去掉没用的function(符号)了。

 

 

验证如下:

#cat main.c
#include <stdio.h>
int data_main[20];
extern int ff(void);

int fun(void)
{
 return 0;
}
int main(void)
{
 ff();
 return 0;
}

#cat ff.c
#include <stdio.h>
int data_ff[30];
int ff(void)
{
 printf("ff\n");
 return 0;
}
int jj(void)
{
 printf("jj\n");
 return 0;
}
int hh(void)
{
 printf("hh\n");
 return 0;
}
int gg(void)
{
 printf("gg\n");
 return 0;
}

 

1 不去除无用符号

# gcc -c ff.c -o ff.o
# readelf -S ff.o
There are 11 section headers, starting at offset 0x11c:
Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000034 000064 00  AX  0   0  4
  [ 2] .rel.text         REL             00000000 0003d4 000040 08      9   1  4
  [ 3] .data             PROGBITS        00000000 000098 000000 00  WA  0   0  4
  [ 4] .bss              NOBITS          00000000 000098 000000 00  WA  0   0  4
  [ 5] .rodata           PROGBITS        00000000 000098 00000c 00   A  0   0  1
  [ 6] .comment          PROGBITS        00000000 0000a4 000024 01  MS  0   0  1
  [ 7] .note.GNU-stack   PROGBITS        00000000 0000c8 000000 00      0   0  1
  [ 8] .shstrtab         STRTAB          00000000 0000c8 000051 00      0   0  1
  [ 9] .symtab           SYMTAB          00000000 0002d4 0000e0 10     10   8  4
  [10] .strtab           STRTAB          00000000 0003b4 00001f 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

# ls -l ff.o
-rw-r--r-- 1 root root 1044 2011-12-06 23:20 ff.o
# gcc ff.o main.c -o main.elf
# nm -S main.elf
08049f20 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
0804852c 00000004 R _IO_stdin_used
         w _Jv_RegisterClasses
08049f10 d __CTOR_END__
08049f0c d __CTOR_LIST__
08049f18 D __DTOR_END__
08049f14 d __DTOR_LIST__
0804853c r __FRAME_END__
08049f1c d __JCR_END__
08049f1c d __JCR_LIST__
0804a018 A __bss_start
0804a00c D __data_start
080484e0 t __do_global_ctors_aux
08048360 t __do_global_dtors_aux
0804a010 D __dso_handle
         w __gmon_start__
080484da T __i686.get_pc_thunk.bx
08049f0c d __init_array_end
08049f0c d __init_array_start
08048470 00000005 T __libc_csu_fini
08048480 0000005a T __libc_csu_init
         U
0804a018 A _edata
0804a0b8 A _end
0804850c T _fini
08048528 00000004 R _fp_hw
080482b8 T _init
08048330 T _start
0804a020 00000001 b completed.7021
0804a014 00000004 D data_a
0804a040 00000078 Bdata_ff
0804a00c W data_start
0804a024 00000004 b dtor_idx.7023
080483e4 00000019 T ff
080483c0 t frame_dummy
08048448 0000000a T fun
0804842f 00000019 T gg
08048416 00000019 T hh
080483fd 00000019 T jj
08048452 00000014 T main
         U

 

 2 去除无用符号

# gcc -ffunction-sections -fdata-sections -c ff.c -o ff.o
# readelf -S ff.o
There are 18 section headers, starting at offset 0x14c:
Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000034 000000 00  AX  0   0  4
  [ 2] .data             PROGBITS        00000000 000034 000000 00  WA  0   0  4
  [ 3] .bss              NOBITS          00000000 000034 000000 00  WA  0   0  4
  [ 4] .rodata           PROGBITS        00000000 000034 00000c 00   A  0   0  1
  [ 5] .text.ff          PROGBITS        00000000 000040 000019 00  AX  0   0  1
  [ 6] .rel.text.ff      REL             00000000 00055c 000010 08     16   5  4
  [ 7] .text.jj          PROGBITS        00000000 000059 000019 00  AX  0   0  1
  [ 8] .rel.text.jj      REL             00000000 00056c 000010 08     16   7  4
  [ 9] .text.hh          PROGBITS        00000000 000072 000019 00  AX  0   0  1
  [10] .rel.text.hh      REL             00000000 00057c 000010 08     16   9  4
  [11] .text.gg          PROGBITS        00000000 00008b 000019 00  AX  0   0  1
  [12] .rel.text.gg      REL             00000000 00058c 000010 08     16  11  4
  [13] .comment          PROGBITS        00000000 0000a4 000024 01  MS  0   0  1
  [14] .note.GNU-stack   PROGBITS        00000000 0000c8 000000 00      0   0  1
  [15] .shstrtab         STRTAB          00000000 0000c8 000081 00      0   0  1
  [16] .symtab           SYMTAB          00000000 00041c 000120 10     17  12  4
  [17] .strtab           STRTAB          00000000 00053c 00001f 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

# ls -l ff.o
-rw-r--r-- 1 root root 1436 2011-12-06 23:15 ff.o
# gcc -Wl,--gc-sections ff.o main.c -o main.elf
# nm -S main.elf
08049f20 d _DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
080484b8 00000004 R _IO_stdin_used
         w _Jv_RegisterClasses
08049f10 d __CTOR_END__
08049f0c d __CTOR_LIST__
08049f18 D __DTOR_END__
08049f14 d __DTOR_LIST__
080484c8 r __FRAME_END__
08049f1c d __JCR_END__
08049f1c d __JCR_LIST__
0804a00c A __bss_start
08048470 t __do_global_ctors_aux
08048340 t __do_global_dtors_aux
         w __gmon_start__
0804846a T __i686.get_pc_thunk.bx
08049f0c d __init_array_end
08049f0c d __init_array_start
08048400 00000005 T __libc_csu_fini
08048410 0000005a T __libc_csu_init
         U
0804a00c A _edata
0804a014 A _end
0804849c T _fini
08048298 T _init
08048310 T _start
0804a00c 00000001 b completed.7021
0804a010 00000004 b dtor_idx.7023
080483c3 00000019 T ff
080483a0 t frame_dummy
080483dc 0000000a T fun
080483e6 00000014 T main
         U


 绿色部分为两者的区别,仔细分析即可发现该编译选项的作用。


====

http://hi.baidu.com/vv1133/item/11432a104932ccfa9c778adc

STM32CubeMX GCC工程Makefile内容详解 关于STM32CubeMX生成的Makefile文件,其中的运行原理、参数以及作为修改方法的记录介绍。 阅读详情

相关推荐

GCC - 无效代码删除优化

前言   无效代码删除(DCE)是一种广泛使用的编译优化技术,它的目的是删除程序中不会影响程序运行的代码和变量,减少代码体积,更好地促使其它相关优化的进行,以提高程序效率,特别是在一些对资源受限的嵌入式设备上,使用无效代码删除操作来减少代码体积是非常重要的。数据流分析技术的发展,许多传统优化问题有了成熟的解决方案,无效代码删除优化也越发高效稳定。 对于以下示例: #include<stdio.h> void func(); void a() { int i = 0; for

zhugl的博客 3314

gcc之 -ffunction-sections

背景 有时我们的程序会定义一些暂时使用不上的功能和函数,虽然我们不使用这些功能和函数,但它们往往会浪费我们的ROM和RAM的空间。这在使用静态库时,体现的更为严重。有时,我们只使用了静态库仅有的几个功能,但是系统默认会自动把整个静态库全部链接到可执行程序中,造成可执行程序的大小大大增加。 参数详解 为了解决前面分析的问题,我们引入了标题中的几个参数。GCC链接操作是以section作为最小的处理单元,只要一个section中的某个符号被引用,该section就会被加入到可执行程序中去。因此,GCC在编

liyucheng987的博客 5248

动态库、可执行文件符号表分析

1. 动态库编译 基本思路为: 先编写两个C文件,其中各自实现几个函数,变量,然后将其分别编译为动态库; 再编写一个实现main函数的C文件,分别调用上述第一步动态库中的函数; 分析最后的可执行文件和动态库文件的符号表; 1.1 第一个C文件:basic.c 这个C文件只定义并实现了四个不同形参的函数、五个静态变量、一个全局变量。由于只关心符号表或者其他二进制内容,因此不具体实现特定功能...

遇见你是我最美丽的意外 8354

gcc -ffunction-sections -fdata-sections -Wl,–gc-sections 参数详解

有时我们的程序会定义一些暂时使用不上的功能和函数,虽然我们不使用这些功能和函数,但它们往往会浪费我们的ROM和RAM的空间。这在使用静态库时,体现的更为严重。有时,我们只使用了静态库仅有的几个功能,但是系统默认会自动把整个静态库全部链接到可执行程序中,造成可执行程序的大小大大增加。指示链接器去掉不用的section(其中-wl, 表示后面的参数 -gc-sections 传递给链接器),这样就能减少最终的可执行程序的大小了。可以看见,在最终的目标文件中,未使用的函数并未被链接进最终的目标文件。

木牛的博客 2286

二进制文件分析之Linux下符号表裁剪对可执行文件影响(三)

变量‌:存储变量的数据类型、作用域等信息。‌函数‌:存储函数的参数类型、返回值等信息。‌其他符号‌:如常量、类型定义等。该信息在.o文件中被划分到主要两个section内,静态符号表、动态符号表。

牧羊人的博客 1273

【python3.7】解决报错 error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++

解决pip安装py7zr遇到的报错问题。

水w的博客 3942

Python去除文本所有标点符号

去除标点符号方式多种多样,这里介绍两种自己常用的。 1、python自带punctuation包,可以消除所有中文标点符号。 import re,string from zhon.hanzi import punctuation text = " Hello, world! 这,是:我;第!一个程序\?()()<>《》 " print(re.sub(r"[%s]+" %punct...

haiziccc的专栏 3万+

BRep实战指南:从理论到文件格式的全面解析

本文全面解析BRep(边界表示法)从基础概念到文件格式的实战应用。详细介绍了BRep的数学定义、工业应用场景,以及STEP、IGES等主流文件格式的对比与使用技巧,帮助读者掌握三维建模核心技术并优化性能。

weixin_29235923的博客 407

python ——使用正则化去除标点符号

python ——使用正则化去除标点符号 在进行文本预处理时,可以使用正则化去掉文本中的标点符号。 re.sub(pattern, repl, string, count=0, flags=0) 去除掉一般符号代码如下: r = "[A-Za-z0-9_.!+-=——,$%^,。?、~@#¥%……&*《》<>「」{}【】()/]" sentence = re.sub(r, ' ', sentence) 但如果要去除 []’"\ 这些符号,则需要使用转义符号 r = "[\\\[\

sinat_28375239的博客 2万+

支付宝支付(三):周期扣款实现注意细节

一、周期扣款实现说明 1、官方文档入口:https://opendocs.alipay.com/open/20190319114403226822/intro 2、根据官方文档说明,周期扣款有两种方式:先签约后代扣场景和支付后签约场景 3、周期扣款接入问题文档: a>https://opendocs.alipay.com/support/01rg24 b>https://opensupport.alipay.com/support/knowledge/50249/20160248753

新鲜雾霾的博客 5702

《C语言小游戏之贪吃蛇程序代码》

//为广大编程游戏爱好者提供一个参考的游戏源代码#include&lt;stdio.h&gt;#include&lt;conio.h&gt;#include&lt;windows.h&gt;#include&lt;time.h&gt;#define framex 5#define framey 5#define wide 20#define high 20int i,j,a[2];//将光标移动到...

qq_42052821的博客 2万+

关于linux中strip去除相关符号表的问题

例如,当一个程序引用静态库中的一个全局变量时,符号信息帮助确定该变量在最终目标文件中的存储位置,清除符号会使重定位出错。例如,对于一个独立的Linux可执行文件,在开发和测试过程中需要保留符号以方便调试,但在发布给用户时,这些符号就不是必需的了。当程序加载到内存中时,较小的文件通常意味着占用更少的内存页面,从而在一定程度上优化了内存的使用。例如,在调试一个出现段错误的程序时,调试器依靠符号来追踪出错的函数调用和变量访问,如果符号不存在,就很难定位问题的根源。函数,如果静态库的符号被清除,链接器就不知道。

最后一个bug的博客 1499

一文掌握SourceTree使用(超级详细)

SourceTree是一款开源的代码仓库客户端工具,界面美观,操作简单,具有代码克隆、本地创建、提交代码、撤销修改,拉取(pull)代码、上传(push)代码、合并分支等操作。对于软件开发人员是一款必备的应用软件。

GM_115的博客 3万+

python如何去除文本标点符号_python中如何去除标点符号

python中如何去除标点符号,写法,方法,字符,字母,都是python中如何去除标点符号易采站长站,站长之家为您整理了python中如何去除标点符号的相关内容。Python去掉标点符号的方法如下:方法一:str.isalnum:S.isalnum() -> bool返回值:如果string至少有一个字符并且所有字符都是字母或数字则返回True,否则返回False。实例:>>&g...

weixin_39943370的博客 4629

2006NOIP普及组真题 4. 数列

从上述推理中,我们发现要输出的幂次和中的第 N 项(也就是幂次和中的序号N),对应的二进制位数和幂次和对应的二进制位数相同。当 k=3 时,k的幂次为1, 3, 9, 27, 81…,即第0位,第2位均为1,转成 k 进制(k=3)时。,即第2位,第3位均为1,转成 k 进制(k=3)时。转成 k 进制(k=3)时的幂次和为。,即第0位,第1位,第2位均为1,(即第0位,第1位,第2位均为1)N=12时,12的二进制是。(即第0位,第2位均为1)(即第2位,第3位均为1)结论:这道题就变成了。

weixin_40252159的博客 1514

【信息系统项目管理师】第1章:信息化发展 考点梳理

本文主要详细梳理高项:信息化、新型基础设施建设、两化融合、数字中国、数字化转型与元宇宙等内容。

数据知道的博客 8584

python 去除所有的中文 英文标点符号

去除英文标点符号 python的string模块下的 punctuation 包含所有的英文标点符号,所以用replace()一下就可以去除。 代码示例: import string stri = 'today is friday, so happy..!!!' punctuation_string = string.punctuation print("所有的英文标点符号:", punctua...

菜鸡小白的成长记录 3万+

10、智慧变电站 - 加载vue大屏元素(整体效果)

这一篇文章非常简单,但是也非常出效果阅读前面几篇文章,都可以看到有顶部、左侧、右侧的面板,主要我不会录gif图片,大屏元素面板还有一些动态加载的效果。 vue的transition标签 Vue 提供了 transition 的封装组件,可以给任何元素和组件添加进入/离开过渡;在进入/离开的过渡中,会有 6 个 class 切换:v-enter 、v-enter-active 、v-enter-to 、v-leave 、v-leave-active 、v-leave-to。我们正好使用这个特性来达到面板进入

github_39988036的博客 1041

NLP-中文文本去除标点符号

简单记录一下中文文本如何去除标点和特殊符号的问题。。。 目录 目录 一、回顾一下英文如何去除符号等预处理问题 ①去除特殊符号 ②去除数字 ③词形归一 ④停止词 ⑤将上述内容综合 二、中文文本去除标点符号 1.背景知识 2.示例说明1:使用Zhon库中的符号集 ①命令行中安装Zhon库 ②代码 ③结果 ④问题说明 3.示例说明2:自定义特殊符号集进行去除 ...

spring_willow的博客 1万+

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

java 去除空格、标点符号

public class TempTest { public static void main(String[] args) { //string去除空格 String str=" hello world "; System.out.println(str); String str1=str.trim();//去除首尾

iCoding91 2万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

目标文件或可执行文件中的符号信息和调试信息是怎么回事儿?

符号信息:包括程序中的函数、变量的名称和地址。调试信息:包括源代码行号、变量类型、函数调用信息等,用于调试时映射源代码和机器代码。执行strip命令会去除这些信息,减少文件大小,但也使得调试变得更加困难,因为我们无法再查看源代码中的变量、函数名等符号。

昊虹AI笔记 1100

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

python如何去除中文标点符号_python中如何去除标点符号

Python去掉标点符号的方法如下:方法一:str.isalnum:S.isalnum() -> bool返回值:如果string至少有一个字符并且所有字符都是字母或数字则返回True,否则返回False。实例:>>> string = "Special $#! characters spaces 888323">>> ''.join(e for e ...

weixin_39943202的博客 4760

【编译】strip去除符号表

所以动态库去掉debug信息,对于gdb大部分功能没有影响(打断点、查调用栈、call函数、查内存地址)去掉,这个时候可以查看静态编译产生的二进制没有任何符号表。这个时候可以说gdb无法打断点,无法查看调用栈,可以说根本没办法使用。gdb功能基本上都围绕这符号表展开的,dbg信息主要给gdb使用,缺失dbg信息,对于静态库和动态库的影响程度不一样。动态库的重定位发生在加载过程中,这个时候虽然去掉了符号表里面的.debug这个节,但是符号表还在。静态库因为在装载的过程中没有重定位符号表的需求。

XYshaonianhaofang的博客 3293

Python使用jieba库分词并去除标点符号

Python使用jieba库分词并去除标点符号

Alexabc3000的专栏 1万+

linux调试符号表,strip去除目标文件中符号表、调试符号表信息

strip经常用来去除目标文件中的一些符号表、调试符号表信息,以减小程序的大小,在rpmbuild包的最后就用到。其支持的选项如下:>strip -h用法:strip 输入文件从文件中删除符号和节选项为:-I --input-target= Assume input file is in format -O --output-target= Create an outpu...

weixin_36257615的博客 3314

Linux下,使用nm命令输出可执行文件的符号表

可执行文件的符号表(symbol table)记录了某个可执行文件中的函数名、全局变量、宏定义等符号信息,这些信息对于我们调试十分重要。目前,我正在DragonOS上开发内核栈traceback程序,因此需要导出内核文件的符号表.这个时候就需要用到Linux的nm命令。nm命令属于GNU binutils的功能,能够输出可执行文件的符号表。它的用法是这样的: 看了上面的帮助信息,人都晕了。这里需要用到-n选项,就以DragonOS的内核文件为例,我们输出来看看: 为了便于查看,上面的命令把nm的输出

龙进的博客 2545
上一篇: 如何查看arm-linux-gcc某个版本支持的-mcpu,-march可选值
下一篇: 一步一步教你怎么编译GNU ARM GCC 交叉编译器 arm-none-eabi-gcc
Alan0521
博客等级 码龄19年 77粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值