binutils工具集

binutils工具集,第1张

GNU binutils是一个二进制工具集。主要包括:

ld:gnu链接器;

as:gnu汇编器。

也包括:

addr2line:把地址转化为文件名和行号;

nm:列出目标文件的符号列表;

objdump:显示目标文件信息;

readelf:显示elf格式的文件信息;

objcopy:拷贝部分section以生成新的可执行文件,elf->hex,elf->bin等;

ar:创建,修改,解压一个静态库文件;

size:显示目标文件的节大小;

strings:从目标文件中列出可打印的字符串;

c++filt:过滤c++符号为可识别的c符号;

ranlib:生成库文件中的.o文件索引;

strip:丢弃程序文件中的符号信息。

以上就是binutils工具集,它们大都使用BFD,二进制文件描述符库。为了更低等级的 *** 作,它们很多也使用opcodes库来汇编以及反汇编机器指令。

那么那几个比较重要呢?

很显然有:objdump,readelf,以及addr2line和nm。因为当报错,需要debug时,需要用到它们。ld和as当然也非常重要,但它们用于编译链接,而且命令复杂得单独剔出来讲解。

次重要有:objcopy,ar,size,string,因为它们很少用到,一般是写到makefile中。

最次的有:c++filt,ranlib,strip,因为它们的功能完全可以被上面重要的binutils替代。

addr2line:

addr2line 0x401110 -f -e test.elf

addr2line 0x401110 --demangle -f -e test.elf

从而获得该地址所在有的符号和源码文件名。使用addr2line的前提是程序文件中存在符号表,即编译时有-g调试参数。

它可以结合nm使用,效果最佳。

nm -n test.elf

nm --demangle -n test.elf

通过nm可以找到对应的符号,以及符号的地址和符号所放的位置。

然后通过符号的地址,使用addr2line找到符号所在源码文件名。

nm中符号符号所放的位置如下:

objdump -D –S test.elf

objcopy –j .text test.elf onlytest.elf

objcopy -R .text test.elf notext.elf

objcopy --strip-debug test.elf == strip test.elf

ar crs libtest.a foo.o bar.o ====ranlib libtest.a仅添加索引类似

最后,怎么使用二进制工具不重要,重要的是你大概知道每个工具有什么用,需要用到的时候可以尽快通过—help找到用法。更重要的是要了解elf原理,了解BFD,opcodes等等原理性质的东西。

   在PC上,需要得到两个版本的Qt,分别是:Qt-4.5.2和QtEmbedded-4.5.2-arm。前者包括了QtDesigner等基本工具,用于在PC上对程序的开发调试,使能确保程序放到板子上之前就符合设计的要求;然后用后者的库将调试好的程序编译成能在arm-linux平台上运行的程序。

    Qt-4.5.2用从网上下载到的qt-x11-opensource-src-4.5.2.tar.gz编译后安装得到;QtEmbedded-4.5.2-arm用qt-embedded-linux-opensource-src-4.5.2.tar.gz编译后安装得到,Qt-embedded-linux-opensource-src-4.5.2.tar.gz还可以编译成Qt Embedded-4.5.2-X86,但不需要。在编译qt-embedded-linux-opensource-src-4.5.2.tar.gz之前,必须准备好arm-linux-gcc交叉编译工具,用的是arm-linux-gcc-3.4.1。

所以先要准备好的软件包有:

Pc的 *** 作系统是:LINUX-ubuntu8.04。

下面是具体编译安装过程:

1、Qt-4.5.2的获得将qt-x11-opensource-src-4.5.2.tar.gz复制到目录:/home/chh/Project/qt,

2、然后解压:

#tar zxvf qt-x11-opensource-src-4.5.2.tar.gz

得到一个新目录:qt-x11-opensource-src-4.5.2

cd进入这个目录,准备开始编译。

3、在终端中这样 *** 作:

#./configure –qvfb     //编译配置,此过程大概历时几分钟;  #make                  //正式编译,过程漫长,大概2个多小时;  #cd tools/qvfb            //进入此目录,准备对它进行编译  #make                   //编译,几分钟  #cd ../..                  //回到qt-x11-opensource-src-4.5.2主目录,准备安装  #make install        //安装,十几分钟吧;

4、此步必须以root身份完成,否则无法建立目录

5、可以在/usr/local/下看到一个Trolltech目录,进入该目录发现Qt-4.5.2目录已经出现,进入里面的bin目录,Designer等工具已经可以使用了。

6、编译过程相当费时,所以可以直接拷贝已经编译过的源码,直接make install。

7、至此,Qt-4.5.2的安装已经顺利完成。

    QtEmbedded-4.5.2-arm的获得

在编译安装qt-embedded-linux-opensource-src-4.5.2之前,必须先配置好arm-linux-gcc,将arm-linux-gcc-3.4.1.tar.bz2解压到目录:/usr/local下,此时local下出现一个名为arm的目录,然后配置好环境变量:在/etc/profile添加一句:export PATH=$PATH:/usr/local/arm/3.4.1/bin,保存后#source /etc/profile一下,让它即时生效。 否则下面的编译过程会提示找不到arm-linux-gcc命令。  现在可以开始编译了:

将qt-embedded-linux-opensource-src-4.5.2.tar.gz复制到目录:/home/chh/Project/qt, 然后解压:#tar zxvf qt-embedded-linux-opensource-src.tar.gz,   得到新目录qt-embedded-linux-opensource-src-4.5.2。

    进入qt-embedded-linux-opensource-src-4.5.2目录,首先进行configure。 这里的参数很重要,必不可少的是-embedded arm,所以最简单的配置信息可以这样:

./configure \  -embedded arm

然后回车,就开始configure了,参数设置和参考文章一样,裁减了很多,减少了编译时间:

./configure \  -release \  -shared \  -fast \  -no-largefile \  -qt-sql-sqlite \  -no-qt3support \  -no-xmlpatterns \  -no-mmx \  -no-3dnow \  -no-sse \  -no-sse2 \  -no-svg \  -no-webkit \  -qt-zlib \  -qt-gif \  -qt-libtiff \  -qt-libpng \  -qt-libmng \  -qt-libjpeg \  -make libs \  -xplatform qws/linux-arm-g++ \  -nomake tools \  -nomake examples \  -nomake docs \  -nomake demo \  -no-nis \  -no-cups \  -no-iconv \  -no-dbus \  -no-openssl \  -embedded arm \  -little-endian \  -qt-freetype \  -depths 16,18 \  -qt-gfx-linuxfb \  -no-gfx-transformed \  -no-gfx-multiscreen \  -no-gfx-vnc \  -no-gfx-qvfb \  -qt-kbd-usb \  -no-glib

之后就可以编译了,#make,漫长等待后再 #make install。Make install还是需要root权限。

     完成后,在/usr/local/Trolltech下多了一个目录:Qt Embedded-4.5.2-arm。

具体步骤如下:

#! /bin/sh

set -x

#

# 一般gzip压缩包的magic值为0x8b1f后跟0x0008,或者0x0808。

# 这里就是要找出这个偏移。

# 119116,就是这个偏移,这个偏移在不同的bzImage里是不同的,所以,这里需要手动调整一下。

# 解压后的文件即vmlinux.bin

od -h -A d bzImage | grep --color -m 3 -A 1 -i 8b1f

dd if=bzImage bs=1 skip=11916 | gunzip >vmlinux.bin

# 调用我写的一个python脚本,生成gnu linker script。

./genlds.py >vmlinux.elf.lds

# 构造 ELF 信息,结果文件为vmlinux.elf

ld -m elf_x86_64 --format binary --oformat elf64-x86-64 -T vmlinux.elf.lds vmlinux.bin -o vmlinux.elf

# 如果是32位系统,可以用以下命令

#ld -m elf_i386 --format binary --oformat elf32-i386 -T vmlinux.elf.lds vmlinux.bin -o vmlinux.elf

# 删除在上一步生成的多余符号。

objcopy --strip-symbol _binary_vmlinux_bin_start --strip-symbol _binary_vmlinux_bin_end --strip-symbol _binary_vmlinux_bin_size vmlinux.elf

# 设置 .text section标志,否则objdump -d不能正常工作,只能用objdump -D。

objcopy --set-section-flag .text=alloc,readonly,code vmlinux.elf

# 以后只是出于验证目的。

# 以schedule函数作为一个样本,检查在vmlinux.elf文件里是不是包括了正确的偏移。

grep --color "[tT] schedule$" System.map

readelf -s vmlinux.elf | grep " schedule$" --color

genlds.py内容如下:

#! /usr/bin/python

import sys

#将 形如 fffffff8989 的字符串转换为数字形式。

def to_no(hexstr):

ret = 0

start = -1

len_hexstr = len(hexstr)

while start>=-len_hexstr:

c = hexstr[start]

if c in "0123456789":

n = ord(c) - ord('0')

elif c in "abcdef":

n = ord(c) - ord('a') + 0xa

elif c in "ABCDEF":

n = ord(c) - ord('A') + 0xa

ret |= long(n<<((-start-1)*4))

start -= 1

return ret

# 计算addr-base

def sym_offset(addr, base):

if base == "missing-base":

return "missing-offset"

addr = to_no(addr)

base = to_no(base)

return hex(int(addr-base))

lines = file("System.map").readlines()

result=""

# 求.text的开始地址

base="missing-base"

for line in lines:

line = line.strip()

addr, type, sym = line.split(" ")

if type in "tT":

if sym in ("startup_64", "startup_32"):

base = addr

break

# 生成lds中的符号行。

for line in lines:

line = line.strip()

addr, type, sym = line.split(" ")

if type in "tT":

offset = sym_offset(addr, base)

result+="\t%s = %s/* orig: 0x%s */\n" % (sym, offset, addr)

# 生成需要的脚本

template="""

OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")

OUTPUT_ARCH(i386:x86-64)

SECTIONS

{

. = 0x%s

.text . : {

*(.data)

%s}

}

"""

print template % (base, result)

以下是反汇编的出来部分结果:

ffffffff80466ca0 <interruptible_sleep_on>:

ffffffff80466ca0: 55 push %rbp

ffffffff80466ca1: 48 ba ff ff ff ff ff mov $0x7fffffffffffffff,%rdx

ffffffff80466ca8: ff ff 7f

ffffffff80466cab: be 01 00 00 00 mov $0x1,%esi

ffffffff80466cb0: 48 89 e5 mov %rsp,%rbp

ffffffff80466cb3: c9 leaveq

ffffffff80466cb4: e9 c7 fe ff ff jmpq ffffffff80466b80 <__sched_text_start>

ffffffff80466cb9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)

ffffffff80466cc0 <schedule>:

ffffffff80466cc0: 55 push %rbp

ffffffff80466cc1: 48 c7 c0 80 ef 62 80 mov $0xffffffff8062ef80,%rax

ffffffff80466cc8: 48 c7 c2 00 b4 62 80 mov $0xffffffff8062b400,%rdx

ffffffff80466ccf: 48 89 e5 mov %rsp,%rbp

ffffffff80466cd2: 41 57 push %r15

ffffffff80466cd4: 41 56 push %r14

ffffffff80466cd6: 41 55 push %r13

ffffffff80466cd8: 41 54 push %r12

ffffffff80466cda: 53 push %rbx

ffffffff80466cdb: 48 81 ec 98 00 00 00 sub $0x98,%rsp

ffffffff80466ce2: 48 c7 85 78 ff ff ff movq $0xffffffff8062ef80,-0x88(%rbp)

ffffffff80466ce9: 80 ef 62 80


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11398417.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-15
下一篇 2023-05-15

发表评论

登录后才能评论

评论列表(0条)

保存