分类: LINUX
2009-09-27 10:07:00
对gcc编译生成的客户端主执行文件depagtd和cygwin编译生成的相同文件进行简单的分析,论
证两者可以互换使用。
使用工具:gcc, readelf,
objdump, BC。
Ia32版本:
Elf头分析:
主要不同有两点:
1、
program headers,gcc生成的有7个,cygwin生成的有6个。具体如下:
gcc比cygwin多了一个STACK Segment,在ELF的标准中查询没有这个program header, (http://www.caldera.com/developers/gabi/2003-12-17/ch5.pheader.html)猜测是redhat公司自己的扩展。它的offset,virtaddr,phyaddr,filesize等参数全部为0,而且在Section to Segment mapping中STACK没有映射任何section,所以不管在程序link和load时候这个Segment应该都不起作用。
2、 section headers,gcc生成的有27个,cygwin生成的有31个。具体如下:
cygwin比gcc多了四个section:debug_arranges;debug_info;debug_abbrev;debug_line,从名字来看,全部都是关于调试信息的section,在编译时并没有加-g参数,所以应该是在编译交叉编译器时候的缺省设定导致。反编译之后这几个section信息都是关于crosstool的版本信息。
可以看出,都是关于使用的交叉编译器的gcc,glibc的版本信息及编译交叉编译器工具crosstool信息,对程序的exec和load没有影响。
(背景知识参照:http://www.caldera.com/developers/gabi/2003-12-17/contents.html ;
http://blog.chinaunix.net/u3/94916/showart_1908331.html)
Te
Text段分析:
1、汇编后结果基本相同的例子:
2、汇编后结果有差异的例子:
以下面C语句为例分析差异:
openlog("depagtd", LOG_PID, LOG_DAEMON);
Linux从右向左参数压栈。
gccdump cygwindump
push $0x18 movl $0x18,0x8(%esp)
push $0x1 movl $0x1,0x4(%esp)
push $0x8056dc0 movl $0x80576e0 (%esp)
call 8049444
从syslog.h查到:
#define LOG_PID 0x01 /* log the pid with each message */
#define LOG_DAEMON (3<<3)
从elf只读数据段查到:
Contents of section .rodata: Contents of section .rodata:
8056db8 03000000 01000200 64657061 67746400 ........depagtd. 80576c0 03000000 01000200 00000000 00000000 ................
80576d0 00000000 00000000 00000000 00000000 ................
80576e0 64657061 67746400 5b455252 4f525d73 depagtd.[ERROR]s
差别主要在参数压栈的表示形式上不同,编译机上的gcc直接编译的程序,参数压栈时使用push指令,而cygwin中的交叉编译环境的gcc编译的程序,参数压栈时使用movl指令。(因为esp是栈指针)
关键地方的跳转指令和判断指令相同。
结论:可以使用交叉编译器生成的可执行文件代替原有编译器生成的可执行文件。