gcc-core-3.0之crtbegin.o和crtgend.o分析
1.crtbegin和crtend的组成
crtbegin和crtend都来自文件gcc/crtstuff.c
生成他们的命令是
./xgcc -B./ -B/usr/local/i686-pc-linux-gnu/bin/ -isystem /usr/local/i686-pc-linux-gnu/include -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -isystem ./include -I. -I. -I../../gcc -I../../gcc/. -I../../gcc/config -I../../gcc/../include -g0 \
-finhibit-size-directive -fno-inline-functions \
-fno-exceptions -fno-omit-frame-pointer \
-c ../../gcc/crtstuff.c -DCRT_BEGIN -o crtbegin.o//定义宏CRT_BEGIN,生成crtbegin.o
./xgcc -B./ -B/usr/local/i686-pc-linux-gnu/bin/ -isystem /usr/local/i686-pc-linux-gnu/include -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -isystem ./include -I. -I. -I../../gcc -I../../gcc/. -I../../gcc/config -I../../gcc/../include -g0 \
-finhibit-size-directive -fno-inline-functions \
-fno-exceptions -fno-omit-frame-pointer \
-c ../../gcc/crtstuff.c -DCRT_END -o crtend.o//定义宏CRT_END,生成crtend.o
由于crtstuff.c中既有crtbegin的代码,又有crtend,直接阅读crtstuff.c比较困难。可以用预处理
命令他们的代码分离开来。
2.crtbegin
./xgcc -B./ -B/usr/local/i686-pc-linux-gnu/bin/ -isystem /usr/local/i686-pc-linux-gnu/include -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -isystem ./include -I. -I. -I../../gcc -I../../gcc/. -I../../gcc/config -I../../gcc/../include -g0 \
-finhibit-size-directive -fno-inline-functions \
-fno-exceptions -fno-omit-frame-pointer \
-c ../../gcc/crtstuff.c -DCRT_BEGIN -E -o crtbegin.i
略过 前面的头文件
typedef void (*func_ptr) (void);//定义函数类型func_ptr
# 157 "../../gcc/crtstuff.c"
asm (".hidden\t__dso_handle");
void *__dso_handle = 0;
extern void __cxa_finalize (void *) __attribute__ ((weak));
# 189 "../../gcc/crtstuff.c"
static char __EH_FRAME_BEGIN__[];
static func_ptr __DTOR_LIST__[];//析构函数列表
static void
__do_global_dtors_aux (void)//执行全局析构辅助函数,静态
{
static func_ptr *p = __DTOR_LIST__ + 1;//跳过第一个元素,因为它为空(-1)
static int completed;//静态
func_ptr f;
if (__builtin_expect (completed, 0))//已完成
return;
while ((f = *p))//循环直到为0
{
p++;//从前往后
f ();//调用注册的函数
}
if (__deregister_frame_info_bases)
__deregister_frame_info_bases (__EH_FRAME_BEGIN__);
completed = 1;
}
static void __attribute__ ((__unused__))
fini_dummy (void)//静态
{
asm ("\t.section\t.fini");
__do_global_dtors_aux ();//调用__do_global_dtors_aux,生成的代码合并到.fini节中
asm ("\t.text");
}
static void
frame_dummy (void)//静态
{
static struct object object;
void *tbase, *dbase;
tbase = 0;
//将GOT地址存入tbase
__asm__ ("call\t.LPR%=\n" ".LPR%=:\n\t" "popl\t%0\n\t" "addl\t$_GLOBAL_OFFSET_TABLE_+[.-.LPR%=],%0" : "=d"(dbase));
if (__register_frame_info_bases)
__register_frame_info_bases (__EH_FRAME_BEGIN__, &object, tbase, dbase);
}
static void __attribute__ ((__unused__))
init_dummy (void)
{
asm ("\t.section\t.init");
frame_dummy ();//调用frame_dummy,生成的代码合并到.init节中
asm ("\t.text");
}
# 374 "../../gcc/crtstuff.c"
static func_ptr force_to_data[1] __attribute__ ((__unused__)) = { };
# 393 "../../gcc/crtstuff.c"
asm ("\t.section\t.ctors,\"aw\"");//以下存入.ctors节
static func_ptr __CTOR_LIST__[1] __attribute__ ((__unused__))
= { (func_ptr) (-1) };//static,静态变量,分配一个元素的func_ptr数组,值为-1,代表结束
asm ("\t.section\t.dtors,\"aw\"");//以下存入.dtors节
static func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };//static,静态变量,分配一个元素的func_ptr数组,值为-1,代表结束
asm ("\t.section\t.eh_frame,\"aw\"");//存入.eh_frame节
static
char __EH_FRAME_BEGIN__[] = { };//空,等价于char * __EH_FRAME_BEGIN__;
3.crtend
./xgcc -B./ -B/usr/local/i686-pc-linux-gnu/bin/ -isystem /usr/local/i686-pc-linux-gnu/include -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -isystem ./include -I. -I. -I../../gcc -I../../gcc/. -I../../gcc/config -I../../gcc/../include -g0 \
-finhibit-size-directive -fno-inline-functions \
-fno-exceptions -fno-omit-frame-pointer \
-c ../../gcc/crtstuff.c -DCRT_END -E -o crtend.i
# 89 "../../gcc/crtstuff.c"
extern void __register_frame_info (void *, struct object *)
__attribute__ ((weak));
extern void __register_frame_info_bases (void *, struct object *,
void *, void *)
__attribute__ ((weak));
extern void *__deregister_frame_info (void *)
__attribute__ ((weak));
extern void *__deregister_frame_info_bases (void *)
__attribute__ ((weak));
# 130 "../../gcc/crtstuff.c"
typedef void (*func_ptr) (void);
# 424 "../../gcc/crtstuff.c"
static func_ptr __CTOR_END__[];//构造函数表结尾
static void
__do_global_ctors_aux (void)//执行全局构造辅助函数
{
func_ptr *p;
for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)//跳过最后一个,从后向前调用,直到碰到-1
(*p) ();
}
static void __attribute__ ((__unused__))
init_dummy (void)
{
asm ("\t.section\t.init");
__do_global_ctors_aux ();//存入.init节
asm ("\t.text");
}
# 513 "../../gcc/crtstuff.c"
static func_ptr force_to_data[1] __attribute__ ((__unused__)) = { };
# 524 "../../gcc/crtstuff.c"
asm ("\t.section\t.ctors,\"aw\"");//存入.ctors节
static func_ptr __CTOR_END__[1] = { (func_ptr) 0 };//最后一个,值为0
asm ("\t.section\t.dtors,\"aw\"");//存入.dtors节
static func_ptr __DTOR_END__[1] __attribute__ ((__unused__))
= { (func_ptr) 0 };//最后一个,值为0
typedef unsigned int ui32 __attribute__ ((mode (SI)));
asm ("\t.section\t.eh_frame,\"aw\"");//存入.eh_frame节
static ui32 __FRAME_END__[] __attribute__ ((__unused__)) = { 0 };//__FRAME_END__
4.总结
注意所有的函数和变量都是static类型,这样虽然crtbegin和crtend中都有init_dummy,但连接不会出错
共用到两个函数数组
构造函数列表
__CTOR_LIST_(-1) crtbegin中
注册的构造函数1
注册的构造函数2
注册的构造函数3
__CTOR_END__(0) crtend中
析构函数列表
__DTOR_LIST__(-1) crtbegin中
注册的析构函数3
注册的析构函数2
注册的析构函数1
__DTOR_END__(0) crtend中
__do_global_ctors_aux,从后往前调用构造函数,由于要知道结束地址,所以放在了crtend中
__do_global_dtors_aux,从前往后调用注册的析构函数,由于只要知道起始地址,所有放在了crtbegin中了
5.看看最终的镜像
1.c
#include
int main()
{
printf("Hello World!\n");
return 0;
}
gcc 1.c -v
/usr/lib/gcc-lib/i386-redhat-linux/2.96/collect2 -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crt1.o /usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crti.o /usr/lib/gcc-lib/i386-redhat-linux/2.96/crtbegin.o -L/usr/lib/gcc-lib/i386-redhat-linux/2.96 -L/usr/lib/gcc-lib/i386-redhat-linux/2.96/../../.. /tmp/cc2s0nfJ.o -lgcc -lc -lgcc /usr/lib/gcc-lib/i386-redhat-linux/2.96/crtend.o /usr/lib/gcc-lib/i386-redhat-linux/2.96/../../../crtn.o
objdump -d a.out
对照连接命令中出现的.o顺序,看看能否下面的输出是否确实合并了按顺序合并同名段
a.out: file format elf32-i386
Disassembly of section .init:
080482e4 <_init>:
80482e4: 55 push %ebp
80482e5: 89 e5 mov %esp,%ebp
80482e7: 83 ec 08 sub $0x8,%esp
80482ea: e8 95 00 00 00 call 8048384
80482ef: 90 nop
|<---以上来自crti.o
80482f0: e8 2b 01 00 00 call 8048420 //来自crtbegin.o
80482f5: e8 86 01 00 00 call 8048480 <__do_global_ctors_aux>//来自crtend.o
|<--以下来自crtn.o
80482fa: c9 leave
80482fb: c3 ret
Disassembly of section .plt://procedure link table
080482fc <.plt>:
80482fc: ff 35 20 95 04 08 pushl 0x8049520
8048302: ff 25 24 95 04 08 jmp *0x8049524
8048308: 00 00 add %al,(%eax)
804830a: 00 00 add %al,(%eax)
804830c: ff 25 28 95 04 08 jmp *0x8049528
8048312: 68 00 00 00 00 push $0x0
8048317: e9 e0 ff ff ff jmp 80482fc <_init+0x18>
804831c: ff 25 2c 95 04 08 jmp *0x804952c
8048322: 68 08 00 00 00 push $0x8
8048327: e9 d0 ff ff ff jmp 80482fc <_init+0x18>
804832c: ff 25 30 95 04 08 jmp *0x8049530
8048332: 68 10 00 00 00 push $0x10
8048337: e9 c0 ff ff ff jmp 80482fc <_init+0x18>
804833c: ff 25 34 95 04 08 jmp *0x8049534
8048342: 68 18 00 00 00 push $0x18
8048347: e9 b0 ff ff ff jmp 80482fc <_init+0x18>
804834c: ff 25 38 95 04 08 jmp *0x8049538
8048352: 68 20 00 00 00 push $0x20
8048357: e9 a0 ff ff ff jmp 80482fc <_init+0x18>
Disassembly of section .text:
|<----以下来自crt1.o
08048360 <_start>:
8048360: 31 ed xor %ebp,%ebp
8048362: 5e pop %esi
8048363: 89 e1 mov %esp,%ecx
8048365: 83 e4 f0 and $0xfffffff0,%esp
8048368: 50 push %eax
8048369: 54 push %esp
804836a: 52 push %edx
804836b: 68 c0 84 04 08 push $0x80484c0
8048370: 68 e4 82 04 08 push $0x80482e4
8048375: 51 push %ecx
8048376: 56 push %esi
8048377: 68 60 84 04 08 push $0x8048460
804837c: e8 ab ff ff ff call 804832c <_init+0x48>
8048381: f4 hlt
8048382: 89 f6 mov %esi,%esi
|<---以下来自crti.o
08048384 :
8048384: 55 push %ebp
8048385: 89 e5 mov %esp,%ebp
8048387: 53 push %ebx
8048388: 50 push %eax
8048389: e8 00 00 00 00 call 804838e
804838e: 5b pop %ebx
804838f: 81 c3 8e 11 00 00 add $0x118e,%ebx
8048395: 8b 83 20 00 00 00 mov 0x20(%ebx),%eax
804839b: 85 c0 test %eax,%eax
804839d: 74 02 je 80483a1
804839f: ff d0 call *%eax
80483a1: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
80483a4: c9 leave
80483a5: c3 ret
80483a6: 89 f6 mov %esi,%esi
80483a8: 90 nop
80483a9: 90 nop
80483aa: 90 nop
80483ab: 90 nop
80483ac: 90 nop
80483ad: 90 nop
80483ae: 90 nop
80483af: 90 nop
//来自于crtbegin.o
080483b0 <__do_global_dtors_aux>:
80483b0: 55 push %ebp
80483b1: 89 e5 mov %esp,%ebp
80483b3: 83 ec 08 sub $0x8,%esp
80483b6: 8b 15 04 95 04 08 mov 0x8049504,%edx
80483bc: 85 d2 test %edx,%edx
80483be: 75 49 jne 8048409 <__do_global_dtors_aux+0x59>
80483c0: 8b 15 00 95 04 08 mov 0x8049500,%edx
80483c6: 8b 02 mov (%edx),%eax
80483c8: 85 c0 test %eax,%eax
80483ca: 74 1a je 80483e6 <__do_global_dtors_aux+0x36>
80483cc: 8d 74 26 00 lea 0x0(%esi,1),%esi
80483d0: 8d 42 04 lea 0x4(%edx),%eax
80483d3: a3 00 95 04 08 mov %eax,0x8049500
80483d8: ff 12 call *(%edx)
80483da: 8b 15 00 95 04 08 mov 0x8049500,%edx
80483e0: 8b 0a mov (%edx),%ecx
80483e2: 85 c9 test %ecx,%ecx
80483e4: 75 ea jne 80483d0 <__do_global_dtors_aux+0x20>
80483e6: b8 1c 83 04 08 mov $0x804831c,%eax
80483eb: 85 c0 test %eax,%eax
80483ed: 74 10 je 80483ff <__do_global_dtors_aux+0x4f>
80483ef: 83 ec 0c sub $0xc,%esp
80483f2: 68 08 95 04 08 push $0x8049508
80483f7: e8 20 ff ff ff call 804831c <_init+0x38>
80483fc: 83 c4 10 add $0x10,%esp
80483ff: b8 01 00 00 00 mov $0x1,%eax
8048404: a3 04 95 04 08 mov %eax,0x8049504
8048409: 89 ec mov %ebp,%esp
804840b: 5d pop %ebp
804840c: c3 ret
804840d: 8d 76 00 lea 0x0(%esi),%esi
//来自于crtbegin.o
08048410 :
8048410: 55 push %ebp
8048411: 89 e5 mov %esp,%ebp
8048413: 83 ec 08 sub $0x8,%esp
8048416: 89 ec mov %ebp,%esp
8048418: 5d pop %ebp
8048419: c3 ret
804841a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
//来自于crtbegin.o
08048420 :
8048420: 55 push %ebp
8048421: b8 0c 83 04 08 mov $0x804830c,%eax
8048426: 89 e5 mov %esp,%ebp
8048428: 83 ec 08 sub $0x8,%esp
804842b: 85 c0 test %eax,%eax
804842d: 74 15 je 8048444
804842f: 83 ec 08 sub $0x8,%esp
8048432: 68 08 96 04 08 push $0x8049608
8048437: 68 08 95 04 08 push $0x8049508
804843c: e8 cb fe ff ff call 804830c <_init+0x28>
8048441: 83 c4 10 add $0x10,%esp
8048444: 89 ec mov %ebp,%esp
8048446: 5d pop %ebp
8048447: c3 ret
8048448: 90 nop
8048449: 8d b4 26 00 00 00 00 lea 0x0(%esi,1),%esi
//来自于crtbegin.o
08048450 :
8048450: 55 push %ebp
8048451: 89 e5 mov %esp,%ebp
8048453: 83 ec 08 sub $0x8,%esp
8048456: 89 ec mov %ebp,%esp
8048458: 5d pop %ebp
8048459: c3 ret
804845a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
//来自于1.c
08048460 :
8048460: 55 push %ebp
8048461: 89 e5 mov %esp,%ebp
8048463: 83 ec 08 sub $0x8,%esp
8048466: 83 ec 0c sub $0xc,%esp
8048469: 68 e8 84 04 08 push $0x80484e8
804846e: e8 c9 fe ff ff call 804833c <_init+0x58>
8048473: 83 c4 10 add $0x10,%esp
8048476: b8 00 00 00 00 mov $0x0,%eax
804847b: c9 leave
804847c: c3 ret
804847d: 8d 76 00 lea 0x0(%esi),%esi
//来自于crtend.o
08048480 <__do_global_ctors_aux>:
8048480: 55 push %ebp
8048481: 89 e5 mov %esp,%ebp
8048483: 53 push %ebx
8048484: 83 ec 04 sub $0x4,%esp
8048487: a1 0c 95 04 08 mov 0x804950c,%eax
804848c: bb 0c 95 04 08 mov $0x804950c,%ebx
8048491: 83 f8 ff cmp $0xffffffff,%eax
8048494: 74 16 je 80484ac <__do_global_ctors_aux+0x2c>
8048496: 8d 76 00 lea 0x0(%esi),%esi
8048499: 8d bc 27 00 00 00 00 lea 0x0(%edi,1),%edi
80484a0: 83 eb 04 sub $0x4,%ebx
80484a3: ff d0 call *%eax
80484a5: 8b 03 mov (%ebx),%eax
80484a7: 83 f8 ff cmp $0xffffffff,%eax
80484aa: 75 f4 jne 80484a0 <__do_global_ctors_aux+0x20>
80484ac: 58 pop %eax
80484ad: 5b pop %ebx
80484ae: 5d pop %ebp
80484af: c3 ret
//来自于crtend.o
080484b0 :
80484b0: 55 push %ebp
80484b1: 89 e5 mov %esp,%ebp
80484b3: 83 ec 08 sub $0x8,%esp
80484b6: 89 ec mov %ebp,%esp
80484b8: 5d pop %ebp
80484b9: c3 ret
80484ba: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
Disassembly of section .fini:
080484c0 <_fini>:
80484c0: 55 push %ebp
80484c1: 89 e5 mov %esp,%ebp
80484c3: 53 push %ebx
80484c4: 52 push %edx
80484c5: e8 00 00 00 00 call 80484ca
80484ca: 5b pop %ebx
80484cb: 81 c3 52 10 00 00 add $0x1052,%ebx
80484d1: 8d 76 00 lea 0x0(%esi),%esi
//以上来自于crti.o
80484d4: e8 d7 fe ff ff call 80483b0 <__do_global_dtors_aux>//来自于crtbegin.o
//以下来自于crtn.o
80484d9: 8b 5d fc mov 0xfffffffc(%ebp),%ebx
80484dc: c9 leave
80484dd: c3 ret
阅读(3541) | 评论(0) | 转发(0) |