GNU binutils文档格式.docx

上传人:b****5 文档编号:21771626 上传时间:2023-02-01 格式:DOCX 页数:8 大小:19.26KB
下载 相关 举报
GNU binutils文档格式.docx_第1页
第1页 / 共8页
GNU binutils文档格式.docx_第2页
第2页 / 共8页
GNU binutils文档格式.docx_第3页
第3页 / 共8页
GNU binutils文档格式.docx_第4页
第4页 / 共8页
GNU binutils文档格式.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

GNU binutils文档格式.docx

《GNU binutils文档格式.docx》由会员分享,可在线阅读,更多相关《GNU binutils文档格式.docx(8页珍藏版)》请在冰豆网上搜索。

GNU binutils文档格式.docx

v:

显示ar操作的附加信息

创建动态库(利用gcc,未用ar)

(1)生成目标文件

$gcc-Wall-c-fpicfile1.cfile2.cfile3.c

-fpic:

指定生成的.o目标文件可被重定址.pic是positionidependentcode的缩写:

位置无关代码.

(2)生成动态库文件

$gcc-shared-olibNAME.sofile1.ofile2.ofile3.o

一般地,连接器使用main()函数作为程序入口.但在动态共享库中没有这样的入口.所以就要指定-shared选项来避免编译器显示出错信息.

实际上,上述的两条命令可以合并为下面这条:

$gcc-Wall-shared-fpic-olibNAME.sofile1.cfile2.cfile3.c

此后,将main函数所在的程序与libNAME.so连接

至此,与动态库连接的函数编译成了一个可执行文件。

貌似成功了,但还差最后一步。

如果直接运行该程序,会给出这样的错误信息:

errorwhileloadingsharedlibraries:

libhello.so:

cannotopensharedobjectfile:

Nosuchfileordirectory

这是因为与动态库连接的程序在运行时,首先将该动态库加载到内存中,而gcc默认加载动态库文件所在目录为/usr/local/lib,/usr/lib。

刚才的程序虽然能编译成功,但如果我们自己建立的动态库没有位于默认目录中,则执行时会应为无法找到它而失败。

解决办法:

改变加载路径对应的环境变量,然后再执行。

exportLD_LIBRARY_PATH=动态库所在目录:

$LD_LIBRARY_PATH

查看archive内容

$artvarchiveNAME

t:

显示archive中member的内容,若不指定member,则列出所有。

v:

与t结合使用时,显示member的详细信息。

要想进了解ar的详细选项,参考ar的on-linemanual

nm

nm用来列出目标文件中的符号,可以帮助程序员定位和分析执行程序和目标文件中的符号信息和它的属性。

如果没有目标文件作为参数传递给nm,nm假定目标文件为a.out.

这里用一个简单的示例程序来介绍nm的用法:

main.c:

intmain(intargc,char*argv[])

{

hello();

bye();

return0;

}

hello.c:

voidhello(void)

printf("

hello!

\n"

);

bye.c:

voidbye(void)

goodbye!

运行下列命令:

$gcc-Wall-cmain.chello.cbye.c

gcc生成main.o,hello.o,bye.o三个目标文件(这里没有声明函数原型,加了-Wall,gcc会给出警告)

$nmmain.ohello.obye.o

结果显示如下:

main.o:

 

Ubye

Uhello

00000000Tmain

hello.o:

00000000Thello

Uputs

bye.o:

00000000Tbye

结合这些输出结果,以及程序代码,可以知道:

对于main.o,bye和hello未被定义,main被定义了

对于hello.o,hello被定义了,puts未被定义

对于bye.o,bye被定义了,puts未被定义

几个值得注意的问题:

(1)"

目标文件"

指.o文件,库文件,最终的可执行文件

.o:

编译后的目标文件,即含有最终编译出的机器码,但它里面所引用的其他文件中函数的内存位置尚未定义.

(2)如果用nm查看可执行文件,输出会比较多,仔细研究输出,可以对nm用法有更清醒的认识.

(3)在上述hello.c,bye.c中,调用的是printf(),而nm输出中显示调用的是puts(),说明最终程序实际调用的puts(),如果令hello.c或bye.c中的printf()使用格式化输出,则nm显示调用printf().(如:

printf("

%d"

1);

关于nm的参数选项,参考on-linemanual

objcopy

objcopy可以将一种格式的目标文件转化为另外一种格式的目标文件.它使用GNUBFD库进行读/写目标文件.使用BFD,objcopy就能将原格式的目标文件转化为不同格式的目标文件.

以我们在nm中使用的hello.o目标文件和hello可执行为例:

$filehello.ohello

file命令用来判别文件类型,输出如下:

ELF32-bitLSBrelocatable,Intel80386,version1(SYSV),notstripped

hello:

ELF32-bitLSBexecutable,Intel80386,version1(SYSV),forGNU/Linux2.2.0,dynamicallylinked(usessharedlibs),notstripped

现在运行objcopy来改变hello的文件类型:

原先它是ELF格式的可执行程序,现将它转换为srec格式.srec格式文件是MotoloraS-Record格式的文件,主要用来在主机和目标机之间传输数据.

$objcopy-Osrechellohello_srec

file命令结果:

hello_srec:

MotorolaS-Record;

binarydataintextformat

注意objcopy的格式,"

-O"

指定输出文件类型;

输入文件名和输出文件名位于命令末尾.关于objcopy命令的详细选项,参考on-linemanual

objdump

objdump用来显示目标文件的信息.可以通过选项控制显示那些特定信息.objdump一个最大的用处恐怕就是将C代码反汇编了.在嵌入式软件开发过程中,也可以用它查看执行文件或库文件的信息.

下面我们用上文提到的hello可执行文件和hello_srec可执行文件为例,介绍objdump的简单用法:

$objdump-fhellohello_srec

输出如下:

fileformatelf32-i386

architecture:

i386,flags0x00000112:

EXEC_P,HAS_SYMS,D_PAGED

startaddress0x080482c0

hello_srec:

fileformatsrec

UNKNOWN!

flags0x00000000:

startaddress0x00000000080482c0

-f:

显示目标文件的头文件概要信息.

生成反汇编代码:

$objdump-dhello.o

显示如下:

Disassemblyofsection.text:

00000000<

hello>

:

0:

55 

push 

%ebp

1:

89e5 

mov 

%esp,%ebp

3:

83ec08 

sub 

$0x8,%esp

6:

83ec0c 

$0xc,%esp

9:

6800000000 

$0x0

e:

e8fcffffff 

call 

f<

hello+0xf>

13:

83c410 

add 

$0x10,%esp

16:

c9 

leave

17:

c3 

ret

-d:

显示目标文件中机器指令使用的汇编语言.只反汇编那些应该含有指令机器码的节(显示.text段);

如果用-D,则反汇编所有节的内容.

关于objcopy命令的详细选项,参考on-linemanual

readelf

readelf用来显示ELF格式目标文件的信息.可通过参数选项来控制显示哪些特定信息.(注意:

readelf不支持显示archive文档,也不支持64位的ELF文件).

下面利用先前的hello可执行文件演示readelf的简单用法:

$readelf-hhello

ELFHeader:

Magic:

7f454c46010101000000000000000000

Class:

ELF32

Data:

2'

scomplement,littleendian

Version:

1(current)

OS/ABI:

UNIX-SystemV

ABIVersion:

0

Type:

EXEC(Executablefile)

Machine:

Intel80386

0x1

Entrypointaddress:

0x80482c0

Startofprogramheaders:

52(bytesintofile)

Startofsectionheaders:

3848(bytesintofile)

Flags:

0x0

Sizeofthisheader:

52(bytes)

Sizeofprogramheaders:

32(bytes)

Numberofprogramheaders:

7

Sizeofsectionheaders:

40(bytes)

Numberofsectionheaders:

34

Sectionheaderstringtableindex:

31

注意:

readelf只能用于ELF格式目标文件,且选项中至少要指定一个(除V,H外)的选项!

gprof

gprof被用来测量程序的性能.它记录每个函数被调用的次数以及相应的执行时间.这样就能锁定程序执行时花费时间最多的部分,对程序的优化就可集中于对它们的优化.

用一个简单的数值计算程序来掩饰gprof的用法:

collatz.c:

#include<

stdio.h>

/*ComputesthelengthofCollatzsequences*/

unsignedintstep(unsignedintx)

if(x%2==0)

{

return(x/2);

}

else

return(3*x+1);

unsignedintnseq(unsignedintx0)

unsignedinti=1,x;

if(x0==1||x0==0)

returni;

x=step(x0);

while(x!

=1&

&

x!

=0)

x=step(x);

i++;

intmain(void)

unsignedinti,m=0,im=0;

for(i=1;

i<

500000;

i++)

unsignedintk=nseq(i);

if(k>

m)

m=k;

im=i;

printf("

sequencelength=%ufor%u\n"

m,im);

return0;

先将collatz.c编译成目标文件collatz.o,gcc通过-pg选项来打开gprof支持:

$gcc-Wall-c-pgcollatz.c

$gcc-Wall-pg-ocollatzcollatz.o

注意:

两条命令都要加"

-pg"

选项。

前一条命令生成collatz.o目标文件。

后一条命令生成可执行文件,该可执行文件中包含了记录函数执行时间的指令。

生成collatz可执行文件后,现执行它,结果与一般程序的执行无疑。

但此时在PWD目录生成一个名为"

gmon.out"

的文件,gprof通过它来分析程序的执行。

如果不现执行程序,而直接用gprof来分析它,会提示“gmon.out:

Nosuchfileordirectory”。

gprof用法:

$gprof./collatz

转自:

Tags:

bintuils 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 家庭教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1