为了分析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
Linux常用命令
最新推荐文章于 2023-01-01 10:36:24 发布