【ARM 嵌入式 编译系列 10 -- GCC 编译缩减可执行文件 elf 文件大小】

文章目录

    • GCC 如何缩减可执行文件size
      • 测试代码

上篇文章:ARM 嵌入式 编译系列 9-- GCC 编译符号表(Symbol Table)的详细介绍
下篇文章:ARM 嵌入式 编译系列 10.1 – GCC 编译缩减可执行文件 elf 文件大小

GCC 如何缩减可执行文件size

在开发过程总,总是希望编译出来的可执行文件尽量小,因为这样可以节省更多的磁盘空间,那么有什么方法可以缩小可执行文件的大小的

A: 通常我们会首先移除了debug信息,移除了符号表信息,同时我们还希望万一出事了,比如coredump了,我们能获取更多的信息。

Linux下是怎么解决这个矛盾的呢
先看第一个问题,移除debug相关信息的影响。

测试代码

如下实现了测试代码,main 调用了 foofoo 调用了 bar,其中bar故意访问了非法地址,为了引起 core dump

#include<stdio.h>
#include<stdlib.h>static int bar(void)
{char *p = NULL;printf("I am bar,I will core dump\n");printf("%s",p);*p =0x0;return 0;
}static int foo(void)
{int i ;printf("I am foo,I will call bar\n");bar();return 0;
}int main(void)
{printf("I am main, I wll can foo\n");foo();return 0;
}

先编译出一个 debug 版本来,然后我们看到可执行程序的大小为 17464 bytes.

gcc -g test.c -o test
ls -rtl test
-rwxrwxr-x 1 codingcos codingcos 17464  814 09:43 test

再看下 section 信息:

readelf -S test
There are 37 section headers, starting at offset 0x3af8:Section Headers:[Nr] Name              Type             Address           OffsetSize              EntSize          Flags  Link  Info  Align[ 0]                   NULL             0000000000000000  000000000000000000000000  0000000000000000           0     0     0[ 1] .interp           PROGBITS         0000000000000318  00000318000000000000001c  0000000000000000   A       0     0     1[ 2] .note.gnu.pr[...] NOTE             0000000000000338  000003380000000000000030  0000000000000000   A       0     0     8[ 3] .note.gnu.bu[...] NOTE             0000000000000368  000003680000000000000024  0000000000000000   A       0     0     4[ 4] .note.ABI-tag     NOTE             000000000000038c  0000038c0000000000000020  0000000000000000   A       0     0     4[ 5] .gnu.hash         GNU_HASH         00000000000003b0  000003b00000000000000024  0000000000000000   A       6     0     8[ 6] .dynsym           DYNSYM           00000000000003d8  000003d800000000000000c0  0000000000000018   A       7     1     8[ 7] .dynstr           STRTAB           0000000000000498  000004980000000000000094  0000000000000000   A       0     0     1[ 8] .gnu.version      VERSYM           000000000000052c  0000052c0000000000000010  0000000000000002   A       6     0     2[ 9] .gnu.version_r    VERNEED          0000000000000540  000005400000000000000030  0000000000000000   A       7     1     8[10] .rela.dyn         RELA             0000000000000570  0000057000000000000000c0  0000000000000018   A       6     0     8[11] .rela.plt         RELA             0000000000000630  000006300000000000000030  0000000000000018  AI       6    24     8[12] .init             PROGBITS         0000000000001000  00001000000000000000001b  0000000000000000  AX       0     0     4[13] .plt              PROGBITS         0000000000001020  000010200000000000000030  0000000000000010  AX       0     0     16[14] .plt.got          PROGBITS         0000000000001050  000010500000000000000010  0000000000000010  AX       0     0     16[15] .plt.sec          PROGBITS         0000000000001060  000010600000000000000020  0000000000000010  AX       0     0     16[16] .text             PROGBITS         0000000000001080  000010800000000000000174  0000000000000000  AX       0     0     16[17] .fini             PROGBITS         00000000000011f4  000011f4000000000000000d  0000000000000000  AX       0     0     4[18] .rodata           PROGBITS         0000000000002000  000020000000000000000055  0000000000000000   A       0     0     4[19] .eh_frame_hdr     PROGBITS         0000000000002058  000020580000000000000044  0000000000000000   A       0     0     4[20] .eh_frame         PROGBITS         00000000000020a0  000020a000000000000000ec  0000000000000000   A       0     0     8[21] .init_array       INIT_ARRAY       0000000000003db0  00002db00000000000000008  0000000000000008  WA       0     0     8[22] .fini_array       FINI_ARRAY       0000000000003db8  00002db80000000000000008  0000000000000008  WA       0     0     8[23] .dynamic          DYNAMIC          0000000000003dc0  00002dc000000000000001f0  0000000000000010  WA       7     0     8[24] .got              PROGBITS         0000000000003fb0  00002fb00000000000000050  0000000000000008  WA       0     0     8[25] .data             PROGBITS         0000000000004000  000030000000000000000010  0000000000000000  WA       0     0     8[26] .bss              NOBITS           0000000000004010  000030100000000000000008  0000000000000000  WA       0     0     1[27] .comment          PROGBITS         0000000000000000  00003010000000000000002b  0000000000000001  MS       0     0     1[28] .debug_aranges    PROGBITS         0000000000000000  0000303b0000000000000030  0000000000000000           0     0     1[29] .debug_info       PROGBITS         0000000000000000  0000306b000000000000011a  0000000000000000           0     0     1[30] .debug_abbrev     PROGBITS         0000000000000000  0000318500000000000000cd  0000000000000000           0     0     1[31] .debug_line       PROGBITS         0000000000000000  000032520000000000000076  0000000000000000           0     0     1[32] .debug_str        PROGBITS         0000000000000000  000032c800000000000000ea  0000000000000001  MS       0     0     1[33] .debug_line_str   PROGBITS         0000000000000000  000033b2000000000000003d  0000000000000001  MS       0     0     1[34] .symtab           SYMTAB           0000000000000000  000033f000000000000003a8  0000000000000018          35    20     8[35] .strtab           STRTAB           0000000000000000  0000379800000000000001f5  0000000000000000           0     0     1[36] .shstrtab         STRTAB           0000000000000000  0000398d000000000000016a  0000000000000000           0     0     1
Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings), I (info),L (link order), O (extra OS processing required), G (group), T (TLS),C (compressed), x (unknown), o (OS specific), E (exclude),D (mbind), l (large), p (processor specific)

然后,我们用 strip 命令将 debug info 去除,指令如下:

strip --strip-debug test
ls -rtl test
-rwxrwxr-x 1 codingcos codingcos 15912   814 09:43 test

可执行文件的大小从17464减小到了15912

去除掉 debug info 的 test 和之前的 test 有什么区别呢? 我们看下去除后的 section 信息:

 readelf -S test
There are 31 section headers, starting at offset 0x3668:Section Headers:[Nr] Name              Type             Address           OffsetSize              EntSize          Flags  Link  Info  Align[ 0]                   NULL             0000000000000000  000000000000000000000000  0000000000000000           0     0     0[ 1] .interp           PROGBITS         0000000000000318  00000318000000000000001c  0000000000000000   A       0     0     1[ 2] .note.gnu.pr[...] NOTE             0000000000000338  000003380000000000000030  0000000000000000   A       0     0     8[ 3] .note.gnu.bu[...] NOTE             0000000000000368  000003680000000000000024  0000000000000000   A       0     0     4[ 4] .note.ABI-tag     NOTE             000000000000038c  0000038c0000000000000020  0000000000000000   A       0     0     4[ 5] .gnu.hash         GNU_HASH         00000000000003b0  000003b00000000000000024  0000000000000000   A       6     0     8[ 6] .dynsym           DYNSYM           00000000000003d8  000003d800000000000000c0  0000000000000018   A       7     1     8[ 7] .dynstr           STRTAB           0000000000000498  000004980000000000000094  0000000000000000   A       0     0     1[ 8] .gnu.version      VERSYM           000000000000052c  0000052c0000000000000010  0000000000000002   A       6     0     2[ 9] .gnu.version_r    VERNEED          0000000000000540  000005400000000000000030  0000000000000000   A       7     1     8[10] .rela.dyn         RELA             0000000000000570  0000057000000000000000c0  0000000000000018   A       6     0     8[11] .rela.plt         RELA             0000000000000630  000006300000000000000030  0000000000000018  AI       6    24     8[12] .init             PROGBITS         0000000000001000  00001000000000000000001b  0000000000000000  AX       0     0     4[13] .plt              PROGBITS         0000000000001020  000010200000000000000030  0000000000000010  AX       0     0     16[14] .plt.got          PROGBITS         0000000000001050  000010500000000000000010  0000000000000010  AX       0     0     16[15] .plt.sec          PROGBITS         0000000000001060  000010600000000000000020  0000000000000010  AX       0     0     16[16] .text             PROGBITS         0000000000001080  000010800000000000000174  0000000000000000  AX       0     0     16[17] .fini             PROGBITS         00000000000011f4  000011f4000000000000000d  0000000000000000  AX       0     0     4[18] .rodata           PROGBITS         0000000000002000  000020000000000000000055  0000000000000000   A       0     0     4[19] .eh_frame_hdr     PROGBITS         0000000000002058  000020580000000000000044  0000000000000000   A       0     0     4[20] .eh_frame         PROGBITS         00000000000020a0  000020a000000000000000ec  0000000000000000   A       0     0     8[21] .init_array       INIT_ARRAY       0000000000003db0  00002db00000000000000008  0000000000000008  WA       0     0     8[22] .fini_array       FINI_ARRAY       0000000000003db8  00002db80000000000000008  0000000000000008  WA       0     0     8[23] .dynamic          DYNAMIC          0000000000003dc0  00002dc000000000000001f0  0000000000000010  WA       7     0     8[24] .got              PROGBITS         0000000000003fb0  00002fb00000000000000050  0000000000000008  WA       0     0     8[25] .data             PROGBITS         0000000000004000  000030000000000000000010  0000000000000000  WA       0     0     8[26] .bss              NOBITS           0000000000004010  000030100000000000000008  0000000000000000  WA       0     0     1[27] .comment          PROGBITS         0000000000000000  00003010000000000000002b  0000000000000001  MS       0     0     1[28] .symtab           SYMTAB           0000000000000000  000030400000000000000330  0000000000000018          29    15     8[29] .strtab           STRTAB           0000000000000000  0000337000000000000001db  0000000000000000           0     0     1[30] .shstrtab         STRTAB           0000000000000000  0000354b000000000000011a  0000000000000000           0     0     1

我们可以看到.debug_aranges .debug_info .debug_abbrev .debug_line .debug_str .debug_line_str debug 相关的 section 都已经不在了,原来的 37个section减少到了31个 sections。

但是我们注意到.symtab .strtab .shstrtab 符号表信息 和 字符串信息还在。此外,可以通过nm命可以看到它们的具体信息这:

[09:53:16]shiqiang.zhu@selab-ThinkStation-P350 (*^~^*) ~/workbase/test> nm test
000000000000038c r __abi_tag
0000000000001169 t bar
0000000000004010 B __bss_start
0000000000004010 b completed.0w __cxa_finalize@GLIBC_2.2.5
0000000000004000 D __data_start
0000000000004000 W data_start
00000000000010b0 t deregister_tm_clones
0000000000001120 t __do_global_dtors_aux
0000000000003db8 d __do_global_dtors_aux_fini_array_entry
0000000000004008 D __dso_handle
0000000000003dc0 d _DYNAMIC
0000000000004010 D _edata
0000000000004018 B _end
00000000000011f4 T _fini
00000000000011ae t foo
0000000000001160 t frame_dummy
0000000000003db0 d __frame_dummy_init_array_entry
0000000000002188 r __FRAME_END__
0000000000003fb0 d _GLOBAL_OFFSET_TABLE_w __gmon_start__
0000000000002058 r __GNU_EH_FRAME_HDR
0000000000001000 T _init
0000000000002000 R _IO_stdin_usedw _ITM_deregisterTMCloneTablew _ITM_registerTMCloneTableU __libc_start_main@GLIBC_2.34
00000000000011d1 T mainU printf@GLIBC_2.2.5U puts@GLIBC_2.2.5
00000000000010e0 t register_tm_clones
0000000000001080 T _start
0000000000004010 D __TMC_END__

此时如果执行这个 test 可执行程序,会产生coredump文件,如果使用gdb调试coredump文件的时候,我们可以打印出堆栈信息,因为符号表还在

在往下进行之前我们先学习一个命令: ulimit
ulimit 是 如 Linux 中用于控制shell和其创建的进程可以使用的系统资源。

  • ulimit -c选项则用于设置核心文件(core dump)的最大大小。当一个程序奔溃时,操作系统可以将程序的内存内容和一些调试信息保存到一个核心文件中,以便开发者可以查看这些信息来调试程序。这个文件通常被称为core dump

使用ulimit -c命令可以查询或设置 core文件的最大大小。例如:

  • ulimit -c:查询当前core文件的最大大小。如果返回的是0,那么表示不会生成core文件;
  • ulimit -c unlimited:设置core文件的最大大小为无限,即允许core文件的大小不受限制。

注意: ulimit -c 设置的限制仅对当前shell及其子进程有效,不会影响到其他shell或全局设置。在一些系统中,为了安全考虑,默认可能不启用 core dump,即使你使用ulimit -c unlimited也不会生成 core文件。在这种情况下,你可能需要修改系统的核心设置或其他配置来启用core dump。

1)使用ulimit -c查看core dump是否打开。如果结果为0,则表示此功能处于关闭状态,不会生成core文件, 执行 ulimit -c 1024
2)修改/etc/sysctl.conf文件【sudo vi /etc/sysctl.conf】,添加需要保存的路径【kernel.core_pattern = /tmp/corefile/core.%e.%t】
3)输入 sudo sysctl -p /etc/sysctl.conf 命令即刻生效

由于 symtab .strtab .shstrtab 符号表信息 和 字符串信息还在,我们仍然可以使用 gdb 进行调试:

ulimit -c unlimited or ulimit -c 1024gdb -c /tmp/corefile/core.test.1691982639.1098584 test
Core was generated by `./test'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000560eb28091ab in bar () at test.c:10
10          *p =0x0;
(gdb) bt
#0  0x0000560eb28091ab in bar () at test.c:10
#1  0x0000560eb28091d1 in foo () at test.c:19
#2  0x0000560eb28091f4 in main () at test.c:27
(gdb)

虽然 debug 相关section已经去除,但是还有符号表信息,一旦出了core dump还可以进行debug。大部分的发行版的程序都会将符号表信息删除如果符号表与可执行程序完全隔离,那将是一种什么样的情况的?请见下篇文章。

上篇文章:ARM 嵌入式 编译系列 9-- GCC 编译符号表(Symbol Table)的详细介绍
下篇文章:ARM 嵌入式 编译系列 10.1 – GCC 编译缩减可执行文件 elf 文件大小

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/36940.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux下在qtcreator中创建qt程序

目录 1、新建项目 2、单工程项目创建 3、多工程项目创建 4、添加子工程&#xff08;基于多工程目录结构&#xff09; 5、 .pro文件 1、新建项目 切换到“编辑”界面&#xff0c;点击菜单栏中的“文件”-“新建文件或项目” 2、单工程项目创建 只有一个工程的项目&#…

Axure RP移动端高保真CRM办公客户管理系统原型模板及元件库

Axure RP移动端高保真CRM办公客户管理系统原型模板及元件库&#xff0c;一套典型的移动端办公工具型APP Axure RP原型模板&#xff0c;可根据实际的产品需求进行扩展&#xff0c;也可以作为移动端原型设计的参考案例。为提升本作品参考价值&#xff0c;在模板设计过程中尽量追求…

chatGPT应用于房地产行业

作为 2023 年的房地产专业人士&#xff0c;您无疑认识到技术对行业的重大影响。近年来&#xff0c;一项技术进步席卷了世界——人工智能。人工智能彻底改变了房地产业务的各个方面&#xff0c;从简化管理任务到增强客户互动。 在本文中&#xff0c;我们将探讨几种巧妙的人工智…

HTML 语言简介

1.概述 HTML 是网页使用的语言&#xff0c;定义了网页的结构和内容。浏览器访问网站&#xff0c;其实就是从服务器下载 HTML 代码&#xff0c;然后渲染出网页。 HTML 的全名是“超文本标记语言”&#xff08;HyperText Markup Language&#xff09;&#xff0c;上个世纪90年代…

zabbix自动注册服务器以及部署代理服务器

文章目录 Zabbix自动注册服务器及部署代理服务器一.zabbix自动注册1.什么是自动注册2.环境准备3.zabbix客户端配置4.在 Web 页面配置自动注册5.验证自动注册 二.部署 zabbix 代理服务器1.分布式监控的作用&#xff1a;2.环境部署3.代理服务器配置4.客户端配置5.web页面配置5.1 …

MS9940T 国产 模拟前端AFE芯片 11-15 节锂电池或磷酸盐电池管理芯片 替代BQ76940

产品简述 MS9940T 是模拟前端 (AFE) 芯片&#xff0c;支持11 到 15 组电池串联。通过 I 2 C &#xff0c;主机控制器 可以使用 MS9940T 来实现电池组管理功能&#xff0c;例如监控&#xff08;电池电压、电池组电流、电池组 温度&#xff09;、保护&#xff08;控制…

分类预测 | MATLAB实现GWO-BiLSTM-Attention多输入分类预测

分类预测 | MATLAB实现GWO-BiLSTM-Attention多输入分类预测 目录 分类预测 | MATLAB实现GWO-BiLSTM-Attention多输入分类预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.GWO-BiLSTM-Attention 数据分类预测程序 2.代码说明&#xff1a;基于灰狼优化算法&#xff08…

vuejs 设计与实现 - 组件的实现原理

1.渲染组件 如果是组件则&#xff1a;vnode .type的值是一个对象。如下&#xff1a; const vnode {type: MyComponent,}为了让渲染器能处理组件类型的虚拟节点&#xff0c;我们还需要在patch函数中对组件类型的虚拟节点进行处理&#xff0c;如下&#xff1a; function patc…

CentOS7.9 禁用22端口,使用其他端口替代

文章目录 业务场景操作步骤修改sshd配置文件修改SELinux开放给ssh使用的端口修改防火墙&#xff0c;开放新端口重启sshd生效 相关知识点介绍sshd服务SELinux服务firewall.service服务 业务场景 我们在某市实施交通信控平台项目&#xff0c;我们申请了一台服务器&#xff0c;用…

学习Vue:列表渲染(v-for)

在 Vue.js 中&#xff0c;实现动态列表的显示是非常常见的需求。为了达到这个目的&#xff0c;Vue 提供了 v-for 指令&#xff0c;它允许您迭代一个数组或对象&#xff0c;将其元素渲染为列表。然而&#xff0c;在使用 v-for 时&#xff0c;key 属性的设置也非常重要&#xff0…

微信小程序(原生)搜索功能实现

一、效果图 二、代码 wxml <van-searchvalue"{{ keyword }}"shape"round"background"#000"placeholder"请输入关键词"use-action-slotbind:change"onChange"bind:search"onSearch"bind:clear"onClear&q…

实践-CNN卷积层

实践-CNN卷积层 1 卷积层构造2 整体流程3 BatchNormalization效果4 参数对比5 测试效果 1 卷积层构造 2 整体流程 根据网络结构来写就可以了。 池化 拉平 训练一个网络需要2-3天的时间。用经典网络来&#xff0c;一些细节没有必要去扣。 损失函数&#xff1a; fit模型&…

运维监控学习笔记1

1、监控对象&#xff1a; 1、监控对象的理解&#xff1b;CPU是怎么工作的&#xff1b; 2、监控对象的指标&#xff1a;CPU使用率&#xff1b;上下文切换&#xff1b; 3、确定性能基准线&#xff1a;CPU负载多少才算高&#xff1b; 2、监控范围&#xff1a; 1、硬件监控&#x…

线性扫描寄存器分配算法介绍

线性扫描寄存器分配 文章目录 线性扫描寄存器分配1. 算法介绍2. 相关概念3. 算法的实现3.1 伪代码3.2 图示 参考文献 论文地址&#xff1a; Linear Scan Register Allocation ​ 我们描述了一种称为线性扫描的快速全局寄存器分配的新算法。该算法不基于图形着色&#xff0c;而…

echarts3d柱状图

//画立方体三个面 const CubeLeft echarts.graphic.extendShape({shape: {x: 0,y: 0,width: 9.5, //柱状图宽zWidth: 4, //阴影折角宽zHeight: 3, //阴影折角高},buildPath: function (ctx, shape) {const api shape.api;const xAxisPoint api.coord([shape.xValue, 0]);con…

陪诊小程序开发|陪诊陪护小程序让看病不再难

陪诊小程序通过与医疗机构的合作&#xff0c;整合了医疗资源&#xff0c;让用户能够更加方便地获得专业医疗服务。用户不再需要面对繁琐的挂号排队&#xff0c;只需通过小程序预约服务&#xff0c;便能够享受到合适的医疗资源。这使得用户的就医过程变得简单高效&#xff0c;并…

Redis使用规范及优化

缓存设计 缓存方案 普通缓存 查询数据时&#xff0c;先查找缓存&#xff0c;如果有延长缓存时间并返回。如果没有&#xff0c;再去查找数据库&#xff0c;将查询的数据再写到缓存&#xff0c;同时设置过期时间。如果是静态热点数据&#xff0c;可以不设置缓存失效时间。 冷…

IntelliJ最佳插件

基于 IntelliJ 平台的 JetBrains IDE 可能是当今最常见的 IDE 之一。它们的受欢迎程度在 JVM 语言社区中尤其明显&#xff0c;IntelliJ IDEA 仍然是大多数开发人员的首选 IDE。所有这一切都是在一些新竞争对手的出现和老竞争对手克服以前的缺点并重新加入竞争者的情况下实现的。…

【EI/SCOPUS检索】第三届计算机视觉、应用与算法国际学术会议(CVAA 2023)

第三届计算机视觉、应用与算法国际学术会议&#xff08;CVAA 2023) The 3rd International Conference on Computer Vision, Application and Algorithm 2023年第三届计算机视觉、应用与算法国际学术会议&#xff08;CVAA 2023&#xff09;主要围绕计算机视觉、计算机应用、计…

PPT颜色又丑又乱怎么办?

一、设计一套PPT时&#xff0c;可以从这5个方面进行设计 二、PPT颜色 &#xff08;一&#xff09;、PPT常用颜色分类 一个ppt需要主色、辅助色、字体色、背景色即可。 &#xff08;二&#xff09;、搭建PPT色彩系统 设计ppt时&#xff0c;根据如下几个步骤&#xff0c;依次选…