【Linux】GCC程序开发工具(中)
发布日期:2021-06-29 20:47:45 浏览次数:2 分类:技术文章

本文共 14543 字,大约阅读时间需要 48 分钟。

00. 目录

文章目录

01. GCC的二进制工具

在GCC的开发环境中,除了基本程序生成的编译、链接工具,还有其它一系列二进制的工具可以使用。

ar 归档工具

readelf 读取ELF格式文件信息

strings 查看字符串

nm 显示符号信息

strip 删除符号

02. ar命令

ar工具用于建立、修改、提取归档文件(archive)。一个归档文件是包含多个目标文件的单个文件,它也被称为静态库。归档文件的结构保证了可以从中检索并得到原始的被包含的文件,也就是这个归档文件的成员。被包含的原始文件的内容、模式(权限)、时间戳、所有者和组等属性都保存在归档文件中,在提取后,可以恢复原始文件的相关属性。

2.1 ar用法命令

Usage: ar [emulation options] [-]{
dmpqrstx}[abcDfilMNoOPsSTuvV] [--plugin
] [member-name] [count] archive-file file... ar -M [
- 从
读取选项 --target=BFDNAME - 指定目标对象格式为 BFDNAME --output=DIRNAME - specify the output directory for extraction operations 可选项: --plugin

- 加载指定的插件程序

2.2 用法示例

在GCC工具系列中,ar工具常用于生成静态库(static lib)文件。

生成静态库

deng@itcast:~/share/3rd/1static_lib$ ar -rv libtest.a add.o sub.o mul.o div.o ar: 正在创建 libtest.aa - add.oa - sub.oa - mul.oa - div.odeng@itcast:~/share/3rd/1static_lib$

2.3 查看已经生成的静态库的内容

deng@itcast:~/share/3rd/1static_lib$ ar -t libtest.a add.osub.omul.odiv.odeng@itcast:~/share/3rd/1static_lib$

2.4 对于一个已经生成的静态库,再次调用ar可以替换静态库中的内容

deng@itcast:~/share/3rd/1static_lib$ ar -rv libtest.a  add.o sub.or - add.or - sub.odeng@itcast:~/share/3rd/1static_lib$

2.5 使用ar工具加-d选项,可以删除库中的成员

deng@itcast:~/share/3rd/1static_lib$ ar -d libtest.a add.odeng@itcast:~/share/3rd/1static_lib$ ar -t libtest.a sub.omul.odiv.odeng@itcast:~/share/3rd/1static_lib$

2.6 追加文件到归档文件中

deng@itcast:~/share/3rd/1static_lib$ ar -rv libtest.a add.oa - add.odeng@itcast:~/share/3rd/1static_lib$

2.7 提取其中的各个目标文件

deng@itcast:~/share/3rd/1static_lib$ ar -x libtest.a deng@itcast:~/share/3rd/1static_lib$ ls -l *.o-rw-r--r-- 1 deng deng 1368 6月  15 22:38 add.o-rw-r--r-- 1 deng deng 1368 6月  15 22:38 div.o-rw-r--r-- 1 deng deng 1368 6月  15 22:38 mul.o-rw-r--r-- 1 deng deng 1368 6月  15 22:38 sub.o

03. readelf命令

readelf用来显示ELF格式文件的信息,可通过参数选项来控制显示那些特定信息。readelf工具的使用方式如下所示:

deng@itcast:~$ readelf --help用法:readelf 
<选项>
elf-文件 显示关于 ELF 格式文件内容的信息 Options are: -a --all 显示所有,等价于-h -l -S -s -r -d -V -A -I -h --file-header 显示ELF文件头信息 -l --program-headers 显示ELF程序头 --segments --program-headers的别名 -S --section-headers Display the sections' header 显示节头 --sections --section-headers的别名 -g --section-groups Display the section groups -t --section-details Display the section details -e --headers Equivalent to: -h -l -S -s --syms 显示符号表 --symbols An alias for --syms --dyn-syms Display the dynamic symbol table -n --notes 显示核心注释 -r --relocs 显示重定向信息 -u --unwind 显示unwind信息 -d --dynamic 显示动态段 -V --version-info 显示版本节 -A --arch-specific 显示体系架构特定信息 -c --archive-index Display the symbol/file index in an archive -D --use-dynamic 显示信息使用动态节 -x --hex-dump=
Dump the contents of section
as bytes -p --string-dump=
Dump the contents of section
as strings -R --relocated-dump=
Dump the contents of section
as relocated bytes -z --decompress Decompress section before dumping it -w[lLiaprmfFsoRtUuTgAckK] or --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames, =frames-interp,=str,=loc,=Ranges,=pubtypes, =gdb_index,=trace_info,=trace_abbrev,=trace_aranges, =addr,=cu_index,=links,=follow-links] Display the contents of DWARF debug sections --dwarf-depth=N Do not display DIEs at depth N or greater --dwarf-start=N Display DIEs starting with N, at the same depth or deeper --ctf=
Display CTF info from section
--ctf-parent=
Use section
as the CTF parent --ctf-symbols=
Use section
as the CTF external symtab --ctf-strings=
Use section
as the CTF external strtab -I --histogram 显示柱状图 -W --wide 对超过80列的输出设备指定一些行的格式 @
Read options from
-H --help 显示帮助信息 -v --version Display the version number of readelf将 bug 报告到

3.1 显示目标文件ELF文件头信息

deng@itcast:~/share/3rd/1static_lib$ readelf -h add.oELF 头:  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00   类别:                              ELF64  数据:                              2 补码,小端序 (little endian)  Version:                           1 (current)  OS/ABI:                            UNIX - System V  ABI 版本:                          0  类型:                              REL (可重定位文件)  系统架构:                          Advanced Micro Devices X86-64  版本:                              0x1  入口点地址:               0x0  程序头起点:          0 (bytes into file)  Start of section headers:          600 (bytes into file)  标志:             0x0  Size of this header:               64 (bytes)  Size of program headers:           0 (bytes)  Number of program headers:         0  Size of section headers:           64 (bytes)  Number of section headers:         12  Section header string table index: 11deng@itcast:~/share/3rd/1static_lib$

3.2 显示共享库头信息

deng@itcast:~/share/3rd/3share_lib$ readelf -h libtest.so ELF 头:  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00   类别:                              ELF64  数据:                              2 补码,小端序 (little endian)  Version:                           1 (current)  OS/ABI:                            UNIX - System V  ABI 版本:                          0  类型:                              DYN (共享目标文件)  系统架构:                          Advanced Micro Devices X86-64  版本:                              0x1  入口点地址:               0x1040  程序头起点:          64 (bytes into file)  Start of section headers:          14208 (bytes into file)  标志:             0x0  Size of this header:               64 (bytes)  Size of program headers:           56 (bytes)  Number of program headers:         11  Size of section headers:           64 (bytes)  Number of section headers:         25  Section header string table index: 24deng@itcast:~/share/3rd/3share_lib$

3.3 显示可执行文件头信息如下

deng@itcast:~/share/3rd/4share_test$ readelf -h mainELF 头:  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00   类别:                              ELF64  数据:                              2 补码,小端序 (little endian)  Version:                           1 (current)  OS/ABI:                            UNIX - System V  ABI 版本:                          0  类型:                              DYN (共享目标文件)  系统架构:                          Advanced Micro Devices X86-64  版本:                              0x1  入口点地址:               0x10e0  程序头起点:          64 (bytes into file)  Start of section headers:          14816 (bytes into file)  标志:             0x0  Size of this header:               64 (bytes)  Size of program headers:           56 (bytes)  Number of program headers:         13  Size of section headers:           64 (bytes)  Number of section headers:         31  Section header string table index: 30deng@itcast:~/share/3rd/4share_test$

04. strings命令

strings是一个简单的工具,用于查看文件中的字符串。

deng@itcast:~/share/3rd/4share_test$ strings --help用法:strings [选项] [文件] 打印 [文件] (默认为标准输入) 中可打印的字符串 选项为:  -a - --all                扫描整个文件,而不是数据段  -d --data                 扫描数据段  -f --print-file-name      在字符串前面打印文件的名字  -n --bytes=[number]       定位和打印任何以NUL结束的序列,至少number个字节,默认为4个字节  -
least [number] characters (default 4). -t --radix={
o,d,x} 基于八、十、十六进制打印字符串 -w --include-all-whitespace Include all whitespace as valid string characters -o An alias for --radix=o -T --target=
指定二进制文件的格式 -e --encoding={
s,S,b,l,B,L} 选择字符大小 s = 7-bit, S = 8-bit, {
b,l} = 16-bit, {
B,L} = 32-bit -s --output-separator=
String used to separate strings in output. @
Read options from
-h --help 显示strings的所有选项然后退出 -v -V --version 显示strings的版本号然后退出deng@itcast:~/share/3rd/4share_test$

4.1 查看目标文件中的字符串

deng@itcast:~/share/3rd/1static_lib$ strings  add.o GCC: (Ubuntu 9.3.0-10ubuntu2) 9.3.0add.c.symtab.strtab.shstrtab.text.data.bss.comment.note.GNU-stack.note.gnu.property.rela.eh_framedeng@itcast:~/share/3rd/1static_lib$

05. nm命令

nm工具用于显示文件中的符号,可以用于各种ELF格式的文件。使用nm查看前面的目标文件(可重定向文件),将显示符号及其相关内容。

deng@itcast:~/share/3rd/1static_lib$ nm --help用法:nm [选项] [文件] 列举 [文件] 中的符号 (默认为 a.out)。 The options are:  -a, --debug-syms       只显示调试符号  -A, --print-file-name  在每个符号前打印输入文件的名称  -B                     Same as --format=bsd  -C, --demangle[=STYLE] 将底层的符号解码位用户层的符号。						 The STYLE, if specified, can be `auto' (the default),						 `gnu', `lucid', `arm', `hp', `edg', `gnu-v3', `java'						  or `gnat'      --no-demangle      不解析底层符号      --recurse-limit    Enable a demangling recursion limit.  This is the default.      --no-recurse-limit Disable a demangling recursion limit.  -D, --dynamic          显示动态符号而不是普通符号。对动态目标文件有意义。      --defined-only     只显示定义的符号  -e                     (ignored)  -f, --format=FORMAT    使用输出的格式  FORMAT can be `bsd',                           `sysv' or `posix'.  The default is `bsd'  -g, --extern-only      只显示外部符号  -l, --line-numbers     对每个符号,使用调试信息去视图找到文件名符号。对于已定义的符号,查找符号地址的行号。  						 对于未定义的符号,查找指定符号重定位入口的行号。如果可以找到行号信息,  						 在其它符号信息之后显示该信息。  -n, --numeric-sort     按符号对应地址的顺序排序,而不是按符号名的字符顺序  -o                     Same as -A  -p, --no-sort          不以任何顺序对符号进行排序  -P, --portability      Same as --format=posix  -r, --reverse-sort     反转排序的顺序(按照数字或者字母顺序)显示      --plugin NAME      Load the specified plugin  -S, --print-size       Print size of defined symbols  -s, --print-armap      列出归档文件中成员的符号时包含索引,即名字和包含该名字定义的模块的映射      --size-sort        按照大小排列符号顺序,改大小是按照一个符号的值与它下一个符号的值进行计算      --special-syms     包括输出特殊符号      --synthetic        显示综合符号  -t, --radix=RADIX      Use RADIX for printing symbol values      --target=BFDNAME   Specify the target object format as BFDNAME  -u, --undefined-only   仅显示没有定义的符号(那些目标文件中的外部符号)      --with-symbol-versions  Display version strings after symbol names  -X 32_64               (ignored)  @FILE                  Read options from FILE  -h, --help             Display this information  -V, --version          Display this program's version number

nm符号类型

符号类型 含义
A Absolute 符号的值是绝对值,并且不会被将来的连接所改变
B BSS 符号位于未初始化数据段
C Common 符号是公共。公共符号是未初始化的数据。在连接时,多个公共符号可能以相同的名字出现。如果符号在其它地方被定义,该符号会被当做未定义的引用来处理。
D Data,符号位于已经初始化数据部分
N 调试符号
R ReadOnly Data 符号位于只读数据段
T Text 符号位于代码段
U Undefined 未被定义的符号
W Weak 弱定义符号,也称为弱符号。当一个弱定义符号和一个已定义的普通符号连接时,使用该以定义的普通符号不会引起错误。当一个未定义的弱符号被连接且该符号位被定义时,该Weak符号变为零,并且不会产生错误。

在nm显示的符号中,小写字母表示这个符号是局部符号,大写字母表示这个符号是全局符号。

5.1 查看目标文件中的符号

deng@itcast:~/share/3rd/1static_lib$ nm add.o 0000000000000000 T adddeng@itcast:~/share/3rd/1static_lib$

5.2 查看共享库中的符号

deng@itcast:~/share/3rd/3share_lib$ nm libtest.so 00000000000010f9 T add0000000000004020 b completed.8059                 w __cxa_finalize0000000000001040 t deregister_tm_clones00000000000010b0 t __do_global_dtors_aux0000000000003e88 d __do_global_dtors_aux_fini_array_entry0000000000004018 d __dso_handle0000000000003e90 d _DYNAMIC0000000000001158 t _fini00000000000010f0 t frame_dummy0000000000003e80 d __frame_dummy_init_array_entry0000000000002118 r __FRAME_END__0000000000004000 d _GLOBAL_OFFSET_TABLE_                 w __gmon_start__0000000000002000 r __GNU_EH_FRAME_HDR0000000000001000 t _init                 w _ITM_deregisterTMCloneTable                 w _ITM_registerTMCloneTable0000000000001127 T mul000000000000113e T mydiv0000000000001070 t register_tm_clones0000000000001111 T sub0000000000004020 d __TMC_END__deng@itcast:~/share/3rd/3share_lib$

5.3 查看可执行文件中的符号

deng@itcast:~/share/3rd/2static_test$ nm main 00000000000011f2 T add0000000000004010 B __bss_start0000000000004010 b completed.8059                 w __cxa_finalize@@GLIBC_2.2.50000000000004000 D __data_start0000000000004000 W data_start0000000000001090 t deregister_tm_clones0000000000001100 t __do_global_dtors_aux0000000000003dc0 d __do_global_dtors_aux_fini_array_entry0000000000004008 D __dso_handle0000000000003dc8 d _DYNAMIC0000000000004010 D _edata0000000000004018 B _end00000000000012c8 T _fini

06. strip命令

strip工具用于删除文件中的符号。使用strip既可以删除目标文件中的某个符号,也可以删除整个节。使用strip至少要有一个输入文件,也可以输入一个文件列表。

strip命令用法如下

deng@itcast:~/share/3rd/3share_lib$ strip --help用法:strip 
<选项>
输入文件 从文件中删除符号和节 选项为: -I --input-target=
默认所有输入文件为
格式 -O --output-target=
建立
格式的输出文件 -F --target=
Set both input and output format to
-p --preserve-dates 保留时间戳信息 -D --enable-deterministic-archives Produce deterministic output when stripping archives (default) -U --disable-deterministic-archives Disable -D behavior -R --remove-section=
删除名称为
的节 --remove-relocations
Remove relocations from section
-s --strip-all 删除所有的节 -g -S -d --strip-debug 删除所有符号和重定向信息 --strip-dwo Remove all DWO sections --strip-unneeded 删除所有重定向不需要的节 --only-keep-debug Strip everything but the debug information -M --merge-notes Remove redundant entries in note sections (default) --no-merge-notes Do not attempt to remove redundant notes -N --strip-symbol=
删除名称为name的符号 --keep-section=
Do not strip section
-K --keep-symbol=
保留名称为name的符号 --keep-file-symbols Do not strip file symbol(s) -w --wildcard Permit wildcard in symbol comparison -x --discard-all 删除所有非全局符号 -X --discard-locals 删除所有编译产生的符号 -v --verbose 显示所有修改的文件 -V --version Display this program's version number -h --help Display this output --info List object formats & architectures supported -o
输出文件为file

6.1 使用strip删除main文件中的符号,输出为main_stripped文件。

# main_stripped是被删除了符号的可执行程序。deng@itcast:~/projects/Project1$ strip main -o main_strippeddeng@itcast:~/projects/Project1$ ls -lh main main_stripped -rwxrwxr-x 1 deng deng 17K 6月  18 20:11 main-rwxrwxr-x 1 deng deng 15K 6月  18 20:11 main_strippeddeng@itcast:~/projects/Project1$ # main_stripped中已经不包含任何符号deng@itcast:~/projects/Project1$ nm main_stripped nm: main_stripped:无符号deng@itcast:~/projects/Project1$

6.2 使用file命令对比main和main_stripped两个文件

deng@itcast:~/projects/Project1$ file mainmain: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=655998d8473f3943b09638ea12e6bb148838c2e1, for GNU/Linux 3.2.0, not strippeddeng@itcast:~/projects/Project1$ file main_stripped main_stripped: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=655998d8473f3943b09638ea12e6bb148838c2e1, for GNU/Linux 3.2.0, strippeddeng@itcast:~/projects/Project1$

友情提示:

strip工具在嵌入式这种存储空间非常有限的系统中很有用,它可以极大程度的减少程序的体积,去掉复杂的符号表,因为符号表主要用于调试,所以可以再PC上调试完成后,烧写到目标板之前就直接利用strip命令。

07. 附录

7.1

7.2
7.3

转载地址:https://dengjin.blog.csdn.net/article/details/106849502 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【Linux】GCC程序开发工具(下)
下一篇:【ARM】乘法指令

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月27日 14时42分36秒