分析linux文件常用的命令

为了分析linux编译产生后的obj文件,常常需要一些命令来辅助,今天记录如下。

常见的命令主要有:

gcc:        由c文件或者s文件,编译得到object文件

ld:          连接object文件,得到elf格式可执行文件

nm:        查看.o或.so里面的标号、函数名等

hexdump:以十六进制对文件进行查看,可以是各种文件,包括.c

readelf:    查看elf格式文件信息

objdump:display information from object files,可以查看.o文件、可执行文件、.so文件、.a文件

objcopy: copy and translate object files,复制obj文件段落,生成新的obj文件,可以删除某些无用的段

ldd:        print shared library dependencies

一、gcc

比较基本,略

二、ld

这个命令平时用不到。但是在连接内核时是必须的,以对各个段的存放位置进行管理;注意在编写开发板程序时

可以利用该命令和连接脚本对代码的存放地址进行控制,而对于一般的linux程序,gcc命令都提供了默认的连接脚本。

    1. -o:Set output file name

         2.-l:指定用使用库的名称,如-lc,则是指定使用libc.so或libc.a库文件

         3.-L:指定使用库的目录,如-L/home/lib,则是指定使用的库在该目录下

         4.-T:Read linker script,指定连接脚本,如-Tarm_at09.ld

     5. -m:Set emulation

     6. -s:Strip all symbols,把.o里面的很多调试信息去掉,可以比较bootsect.o和bootsect的大小看出

         7. -e:Set start address

         8. --oformat: Specify target of output file

看linux2.4.16的Makefile中的bootsect.s和setup.s的ld命令:

bootsect: bootsect.o
 $(LD) -Ttext 0x0 -s --oformat binary -o $@ $<

setup: setup.o
 $(LD) -Ttext 0x0 -s --oformat binary -e begtext -o $@ $<

 

 

例如linux2.4.16的vmlinux.lds如下:

OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)  //入口点指向bootsect.s
SECTIONS
{
  . = 0xC0000000 + 0x100000;
  _text = .;   /* Text and read-only data */
  .text : {
 *(.text)
 *(.fixup)
 *(.gnu.warning)
 } = 0x9090
  .text.lock : { *(.text.lock) } /* out-of-line lock text */

  _etext = .;   /* End of text section */

  .rodata : { *(.rodata) *(.rodata.*) }
  .kstrtab : { *(.kstrtab) }

  . = ALIGN(16);  /* Exception table */
  __start___ex_table = .;
  __ex_table : { *(__ex_table) }
  __stop___ex_table = .;

  __start___ksymtab = .; /* Kernel symbol table */
  __ksymtab : { *(__ksymtab) }
  __stop___ksymtab = .;

  .data : {   /* Data */
 *(.data)
 CONSTRUCTORS
 }

  _edata = .;   /* End of data section */

  . = ALIGN(8192);  /* init_task */
  .data.init_task : { *(.data.init_task) }

  . = ALIGN(4096);  /* Init code and data */
  __init_begin = .;
  .text.init : { *(.text.init) }
  .data.init : { *(.data.init) }
  . = ALIGN(16);
  __setup_start = .;
  .setup.init : { *(.setup.init) }
  __setup_end = .;
  __initcall_start = .;
  .initcall.init : { *(.initcall.init) }
  __initcall_end = .;
  . = ALIGN(4096);
  __init_end = .;

  . = ALIGN(4096);
  .data.page_aligned : { *(.data.idt) }

  . = ALIGN(32);
  .data.cacheline_aligned : { *(.data.cacheline_aligned) }

  __bss_start = .;  /* BSS */
  .bss : {
 *(.bss)
 }
  _end = . ;

  /* Sections to be discarded */
  /DISCARD/ : {
 *(.text.exit)
 *(.data.exit)
 *(.exitcall.exit)
 }

  /* Stabs debugging sections.  */
  .stab 0 : { *(.stab) }
  .stabstr 0 : { *(.stabstr) }
  .stab.excl 0 : { *(.stab.excl) }
  .stab.exclstr 0 : { *(.stab.exclstr) }
  .stab.index 0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment 0 : { *(.comment) }
}

三、nm

List symbols in [file(s)] (a.out by default).

查找文件里面的标示符号,如.s里面的标号、.c里面的函数名,一般针对.o和.so文件。默认是按字母顺序进行显示

-p:按符号出现顺序进行显示,不排序

-g:只显示外部可以使用的符号。如.s里面用.global _start来标记的符号

 

 
四、hexdump
五、readelf
可以查看elf的各种section信息,symbol信息等等,需要慢慢品味。
下面这个例子就可以看出vmlinux是可以直接加载到内存执行的,而bzImage就不是elf文件,是vmlinux压缩的结果。
 

六、objdump

很多选项和readelf有相同的效果,但适用范围更广泛

七、objcopy

八、ldd

 

 
作为最后的总结,截一个图(From: writeos-1.0-2.pdf):
 

 

posted @ 2013-12-21 21:15  ritahunter  阅读(190)  评论(0)    收藏  举报