GCC编译器原理(一)------GCC 工具:addr2line、ar、as、c++filt和elfedit

1.3 GCC 工具

1.3.1 binutils 工具集

工具

描述

addr2line

给出一个可执行文件的内部地址,addr2line 使用文件中的调试信息将地址翻译成源代码文件名和行号。

ar

这是一个程序,可通过从文档中增加、删除和析取文件来维护库文件。通常使用该工具是为了创建和管理连接程序使用的目标库文档。

as

GNU 汇编器。实际上它是一族汇编器,因为它可以被编译或能够在各种不同平台上工作。

c++filt

程序接受被 C++编译程序转换过的名字(不是被重载的) ,而且将该名字翻译成初始形式。

elfedit

更新 ELF 文件的 ELF 头。

gprof

该程序会监督编译程序的执行过程,并报告程序中各个函数的运行时间,可以根据所提供的配置文件来优化程序。

ld

GNU 连接程序。该程序将目标文件的集合组合成可执行程序。

ld.bfd

到 ld 的硬链接。

libbfd

二进制文件描述器库。该程序是 binutils 包的一部分

libiberty

包含多个 GNU 程序会使用的途径,包括 getoptobstackstrerrorstrtol 和 strtoul。

libopcodes

一个库,用于处理 opcodes——处理器指令的 "可读文本" 版本;用于编制 objdump 这样的工具。

nlmconv

将可重定位的目标文件转换成 NetWare 可加载模块(NetWare Loadable ModuleNLM) 。

nm

列出目标文件中定义的符号。

objcopy

将目标文件从一种二进制格式复制和翻译到另外一种。

objdump

显示一个或多个目标文件中保存的多种不同信息。

ranlib

创建和添加到 ar 文档的索引。该索引被 ld 使用来定位库中的模块。

readelf

ELF 格式的目标文件显示信息

size

列出目标文件中每个部分的名字和尺寸。

strings

浏览所有类型的文件,析取出用于显示的字符串。

strip

从目标文件或文档库中去掉符号表,以及其他调试所需的信息。

windres

Window 资源文件编译程序。

 

1.3.2 addr2line:地址翻译工具

addr2line用于得到程序指令地址所对应的函数,以及函数所在的源文件名和行号。

参照对应工具的man和info信息,可以查找到详细信息。或者运行相应的工具并指定--help参数,可以获得该工具的简单帮助信息。

用法:addr2line [选项] [地址]

将地址转换成文件名/行号对。

如果没有在命令行中给出地址,就从标准输入中读取它们

选项是:@<file> 读取选项从 <file>

选项

描述

-a

--addresses 显示地址

-b

--target=<bfdname> 设置二进位文件格式

-e

--exe=<executable><name> 设置输入文件名称(默认为 a.out)

-i

--inlines 解开内联函数

-j

--section=<name> 读取相对于段的偏移而非地址

-p

--pretty-print 让输出对人类更可读

-s

--basenames 去除目录名

-f

--functions 显示函数名

-C

--demangle[=style] 解码函数名

-h

--help 显示本帮助

 

测试代码:main.c

1

2

3

4

5

6

7

8

9

10

11

12

13

#include <stdio.h>

#include <stdlib.h>

 

void func(void)

{

printf("func() address is %p\n", func);

}

 

int main(int argc, char *argv[])

{

func();

return 0;

}

编译:gcc -g main.c -o main -Wall

执行:./main

根据地址找到对应的代码位置

1.3.3 ar:创建和管理连接程序使用的目标库文档

ar 命令的语法如下:ar [options] [positionname] [count] archive objectfile [objectfile ...]

  • options:选项标签,选项的字母表示之间没有空格,选项可通过(也可不通过)连字符来表达。
  • 可选的命令行项目 positionname count 只有当用到了某些需要它们的选项时才会出现。
  • ar 命令的选项分为两类:命令行选项告诉 ar 应该采取什么样的操作(有效命令行选项中的一个) ,以及修改子(modifier) 选项指出如何执行该命令操作

指明操作的ar 选项:

选项

描述

d

从文档中删除模块 objectfiles。利用 v 修改子,列出的所有模块都要被删除

m

将模块移入文档内部。默认情况下,列举的所有 objectfiles 成员都会移到文档尾部。利用修改子 ab i 可将指定模块移到其他位置

p

将指定的目标文件 objectfiles 的二进制内容打印到标准输出上。如果没有指定目标文件objectfiles,就打印所有目标文件。修改子 v 会打印所有列在其内容之前的名字

q

将指定目标文件 objectfiles 快速附加到文档末尾,而不检查是否可以取代而不是一味添加。不会更新索引,因此 ranlib 必须在连接库之前使用

r

将指定目标文件 objectfiles 插入文档。如果指定的所有目标文件都已经在文档中了,就用新的替换老的。如果指定文档不存在,就会创建此文档。默认条件下,新的模块会添加到文件的末尾,但是修改子 ab i 可用来指定新模块的位置

t

显示一列文档文件的内容。修改子 v 会为该列表加上时间戳、所有者、组、以及每个模块的大小。如果没有指定目标文件 objectfiles,就会列出整个文档

x

将指定目标文件展开成正常的磁盘文件。如果没有指定目标文件,就会展开所有文件

 

修改子选项:

选项

描述

a

将新文件添加到命令行指定文件位置之后,该文件是作为位置文件的

b

将新文件添加到命令行指定文件位置之前,该文件是作为位置文件的。这和选项 i 一样

c

如果必要就创建文档。只要需要总会创建新的文档,但使用该选项会禁止警告消息

f

截断文档内的文件名。通常 ar 允许任意长度的文件名,可是这样会导致文档的创建过程在某些系统中不能相互兼容

i

立即将所有新文件添加到命令行指定的文件位置之前。这和选项 b 一样

N

当文档中存在多个指定的目标文件时,count 参数可用来当作指定目标文件的选择子(selector

o

当文件是从文档中展开时,原始日期可以得到保留

s

即使没有改动文档,也会创建新的文档索引。在 ar 中会单独使用修改子,这和使用 ranlib 的结果一样

u

当文件加入文档时,该选项说明只有比文档中现有文件更新的文件才会被添加。该修改子只有和选项 r 在一起才有效

v

按照详细模式运行,在运行处理过程中显示附加信息

V

显示版本信息,然后退出

1.3.4 as:GNU汇编器

它是 GNU 汇编器,主要用来编译 GNU C 编译器 gcc 输出的汇编文件,它将汇编代码转换成二进制代码,并存放到一个 object 文件中,该目标文件将由连接器 ld 连接

  • as的内部预处理主要包括三个方面的工作
    • 调整和去除额外的间隔符,保留每行的关键字前的一个空格或者TAB,其他任意的间隔符都转换为一个空格。
    • 去除所有注释,代之以一个空格,或者新行的合适的数字。
    • 把字符常量转换成相应的数字值。
  • 它不能做宏处理和文件包含处理,如果需要用,可以交给 C 预处理器来处理

语法:as(选项)(参数)

常用选项如下:

选项

描述

-ac

忽略失败条件;

-ad

忽略调试指令;

-ah

包括高级源;

-al

包括装配;

-am

包括宏扩展;

-an

忽略形式处理;

-as

包括符号;

=file

设置列出文件的名字;

--alternate

以交互宏模式开始;

-f

跳过空白和注释预处理;

-g

产生调试信息;

-J

对于有符号溢出不显示警告信息;

-L

在符号表中保留本地符号;

-o

指定要生成的目标文件;

--statistics

打印汇编所用的最大空间和总时间。

例子:as -o main.o main.s –32,编译32位的汇编代码

1.3.5 c++filt:修复 C++ 和 Java 符号

主要是为了防止 C++ 和 Java 中的多个函数名重复产生的重载问题。由于每个重载函数都使用与原函数相同的名称,因此,支持函数重载的语言必须拥有一种机制,以区分同一个函数的许多重载版本。

c++filt 将每个输入的名称看成是改编后的名称,并设法确定用于生成该名称的编译器。

如果这个名称是一个合法的改编名称,那么,c++filt 就输出改编之前的名称; 如果c++filt无法识别一个改编名称,那它就按原样输出该名称。

不关注除 C 语言之外的语言,命令选项查看 man 手册

1.3.6 elfedit:检查或编辑 ELF 文件

elfedit 是一个用于检查或修改现有 ELF 目标文件内容的工具。可以访问目标文件中包含的大多数 ELF 数据,这些数据包括 ELF 头、节头表、程序头表、动态节、硬件和软件功能、字符串表和符号表。

elfedit 可以处理来自命令行(–e 选项)或标准输入的命令。如果标准输入是一个终端,elfedit 可提供终端编辑功能以及涵盖大量命令的命令补齐功能。ELF 对特殊整数值和位掩码使用许多标准符号名称。elfedit 可识别此类名称的最有可能的完整形式。在输入 elfedit 命令时,可以随时按 TAB 键,令 elfedit 显示用法消息以及当前光标处文本的任意已知完整形式。

elfedit 功能以模块形式组织。每个模块提供一组命令,这些命令针对相关功能。通过使用冒号 (:) 分隔符将模块和命令名称组合到一起(中间无空格)来指定命令。例如,dyn:runpath 指的是由 dyn 模块提供的 runpath 命令。模块名称必须是唯一的。给定模块中的命令名称在该模块中必须唯一,但可在多个模块中使用相同的命令名称。

某些模块将模块内的某个命令指定为该模块的缺省命令。用户只需指定模块名称,就可运行此命令。大多数 elfedit 模块均提供一个名为 dump 的命令,它针对模块涵盖的 ELF 文件部分生成的信息与 elfdump 实用程序所显示的信息相同。通常,模块会将 dump 指定为其缺省命令。

用于执行 elfedit 命令的语法在设计上采用类似 UNIX 命令行实用程序的语法,这样任何会使用 UNIX 命令行实用程序的人都可以方便地使用 elfedit 命令。该语法由空格分隔的标记组成:第一个标记是命令名称。选项(即以连字符 (-) 开头的参数)跟在命令后面。纯参数(操作数)跟在选项后面。一个给定的命令可以有 0 个或多个选项和操作数,但是如果它们同时存在,选项始终位于纯参数前面。可使用特殊选项 --(两个连字符)来限定选项的结尾。如果遇到此选项,其余所有参数均被视为纯参数,即使它们以 - 开头。

elfedit 标记中的字符的解释取决于所用的引用格式:

引用格式

描述

非引用

单引号 (') 或双引号 (") 外面的反斜杠 (\) 充当转义符。elfedit 发现反斜杠字符时会将其忽略,并按字面意思处理反斜杠后面的字符(即使它后面的字符为反斜杠)。此功能可用于在命令的字符串参数中插入一个空白字符,从而无需将一个字符串分为两个单独的标记。同样,它可用于插入一个引号或反斜杠作为文本字符。

单引号

在单引号 (') 中,空白字符不用于分隔标记,且会被解释为标记内部的文本字符。双引号 (") 和反斜杠 (\) 字符会被解释为文本字符,无特殊意义。

双引号

在双引号 (") 中,空白字符不用于分隔标记。单引号字符会被解释为文本,不具有引用功能。反斜杠 (\) 是一个转义字符,在字符串文本中,其作用与 C 编程语言中反斜杠的作用类似:

\a        警报(响铃)

\b        退格键

\f        换页符

\n        换行符

\r        回车

\t        水平制表符

\v        垂直制表符

\\        反斜杠

\'        单引号

\"        双引号

\ooo    八进制常量,其中 ooo 是 1 到 3 个八进制位 (0...7)

在反斜杠后面跟有任何其他字符,均会出错。

 

核心命令均属于一个名为 sys 的内部模块。所有其他模块均打包为可动态装入的可共享目标文件。当执行需要某个模块的命令时或者当执行 sys:load 命令时,elfedit 会按需装入模块。由于 sys 模块特殊的内置状态,而且其命令使用频繁,所以 elfedit 命令允许在不加 sys: 前缀的情况下指定 sys 模块中的命令,例如,使用 load 而非 sys:load。要访问任何其他模块中的命令,必须采用 module:cmd 完整格式指定。

elfedit 随以下标准模块一起提供:

模块

描述

cap

功能节

dyn

动态节

ehdr

ELF 头

reloc

重定位节

phdr

程序头数组

shdr

节头数组

str

字符串表节

sym

符号表节

syminfo

Syminfo 节

sys

内置的核心 elfedit 命令

 

命令用法:elfedit [-adr] [-e cmd] [-L path] [-o default | simple | num] [infile] [outfile]

选项

描述

–a

启用 autoprint 模式。启用 autoprint 后,elfedit 将输出修改 ELF 文件后所生成的修改值。此输出以当前输出样式显示,可使用 –o 选项更改此样式。缺省输出样式是 elfdump(1) 实用程序使用的样式。以交互方式使用 elfedit 时,autoprint 模式为缺省模式(当 stdin 和 stdout 为终端时)。因此,仅当在非交互式上下文中使用 elfedit 时,–a 选项才有意义。要在交互式会话中禁用 autoprint,请使用 elfedit 命令:> set a off

–d

如果已设置,此选项可使 elfedit 发布信息性消息,说明其内部操作和要处理的 ELF 目标文件的详细信息。这在需要深入了解所执行的操作时非常有用。

–e cmd

指定一个编辑命令。可以指定多个 –e 选项。如果在命令行上指定了多个编辑命令,elfedit 将在批处理模式下运行。打开文件后,elfedit 按给定的顺序执行每个命令,然后保存修改的文件,最后 elfedit 退出。从 shell 脚本和 makefile 执行简单操作时,批处理模式非常有用。

–L path

设置用于定位 elfedit 模块的缺省路径。本手册页的"模块搜索路径"部分介绍了各个模块。

–o default | simple | num

用于显示 ELF 数据的样式。此选项用于确立会话的当前样式。可在 elfedit 会话中更改此样式,方法是使用 set (sys:set) 命令或向会话中执行的各个命令提供 –o 选项。

default

缺省样式是以适合用户查看的格式显示输出。此样式与 elfdump 实用程序使用的样式类似。

num

整数值始终以整数格式显示。字符串显示为在内含的字符串表中定位所用的整数偏移量。

simple

显示 ELF 文件中的字符串时,仅显示字符串。如果可能,整数值显示为符号常量,否则以整数格式显示。不显示任何标题、头或其他补充输出。

–r

只读模式。输入文件以只读访问模式打开,编辑会话的结果不会保存。指定了 –r 时,elfedit 不允许使用 outfile 参数。如果不打算修改文件,强烈建议使用只读模式。除了提供额外保护以防止意外修改外,该选项还允许检查用户没有写入权限的文件。

 

操作数支持:

操作数

描述

infile

包含要处理的 ELF 目标文件的输入文件。

此文件可以为可执行文件 (ET_EXEC)、共享目标文件 (ET_DYN) 或可重定位目标文件 (ET_REL)。不直接支持归档文件。要编辑归档中的目标文件,必须提取目标文件,编辑副本,然后将其重新插入到该归档文件。

如果未提供 infile,elfedit 将在限定模式下运行,此模式仅允许执行 sys: 模块中的命令。此模式主要用于访问 help (sys:help) 命令提供的命令文档。

如果提供了 infile,但未给定任何 outfile,elfedit 将就地编辑文件并将结果写入同一文件,这会导致原始文件内容被覆盖。通常,不建议以此模式使用 elfedit,建议指定输出文件。生成的文件经过测试和验证后,可将其移动到原始文件所在的位置。

–r 选项可用于以只读访问模式打开 infile。在检查不希望修改的现有文件时,此选项非常有用。

outfile

输出文件。如果同时提供了 infile 和 outfile,infile 将以只读访问模式打开,修改的目标文件内容会写入到 outfile 中。

posted @ 2018-07-31 10:40  游戏进行中  阅读(9963)  评论(0编辑  收藏  举报