linux中ELF文件的示例分析
这篇文章给大家分享的是有关linux中ELF文件的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
示例程序
我们的示例程序如下:
#includeint main(int argc,char *argv[]) { printf("hello shouwangxiansheng\n"); return 0 ; }
编译:
$ gcc -o hello hello.c
得到hello可执行文件。
查看文件类型
file命令可以用来查看文件类型:
$ file hello hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=8f1de0f59bdfe9aaff85ade6898173aa436b296a, not stripped
从结果中,我们可以知道,它是ELF可执行文件,且是64位程序,有动态链接,最后的not stripped也表明了它保留了符号表信息或者调试信息。
如果不是可执行文件,它的信息是怎样的呢?举个例子:
$ file hello.c hello.c: C source, UTF-8 Unicode text
看到了吧。
查看ELF头
readelf用于查看ELF文件,而:
$ readelf -h hello ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 (略)
可以看到它是EXEC,即可执行文件,且小端程序,运行于X86-64。在交叉编译的时候,这个文件头的信息也非常有用。例如你在x86的机器上交叉编译出powerpc的可执行文件,在powerpc上却不被识别,不能运行,不如用readelf看看它的Machine字段,是不是没有编译好。
查找ELF文件中的字符串
例如,你在文件中写入了版本号或者特殊字符串,可以通过strings命令搜索到:
$ strings hello|grep shouwang hello shouwangxiansheng
查看ELF文件各段大小
$ size hello text data bss dec hex filename 1210 552 8 1770 6ea hello
这里可以看到代码段,数据段各自占多少,必要时候还可以根据需要优化代码,减少磁盘空间占用。
查看链接的动态库
运行时出现找不到动态库?不如看看它链接了哪些库吧:
$ ldd hello linux-vdso.so.1 => (0x00007ffd16386000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f507e083000) /lib64/ld-linux-x86-64.so.2 (0x00007f507e44d000)
可以看到它链接的动态库是/lib/x86_64-linux-gnu/libc.so.6,而如果该文件不存在,则运行时将会出错。这里也可以参考《动态库的制作和使用》。
查看符号表
新加的函数或者全局变量不知道有没有编译进去?如何看看符号表里有没有吧(前提是符号表没有被去掉):
$ nm hello |grep main #符号表中查找main函数 U __libc_start_main@@GLIBC_2.2.5 0000000000400526 T main
如果没有找到或者前面是U,没有地址,表明在这个elf文件中没有定义这个函数。
链接出问题的时候很有用。
为ELF文件瘦身
前面通过file查看文件时,看到有not stripped的字样,由于它里面包含了一些符号表信息,因为文件会稍大,如果去掉,二进制文件将会变小,但是里面的符号表信息也就没有了,将会影响问题定位。
$ ls -lh hello #瘦身前 -rwxrwxr-x 1 root root 8.4K $ strip hello $ ls -lh hello #瘦身后 -rwxrwxr-x 1 root root 6.2K
可以看到,瘦身后二进制文件变得更小。当可执行文件越大时,瘦身效果就会更明显了。当然放心,这不会影响程序的正常运行,只是对调试和问题定位有影响。
这个时候再看符号表:
$ nm hello nm: hello: no symbols
打印文件校验和
二进制文件传输过程中有没有被损坏或者是否是同一个版本,看看校验和以及程序块计数吧:
$ sum hello 33513 7
当然你也可以使用:
$ md5sum hello 521efed706c3b485dd3b5e96e48b138a hello
来比对md5值。
感谢各位的阅读!关于"linux中ELF文件的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!