Chinaunix首页 | 论坛 | 博客
  • 博客访问: 360763
  • 博文数量: 64
  • 博客积分: 2975
  • 博客等级: 少校
  • 技术积分: 831
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-14 10:59
文章存档

2014年(2)

2012年(7)

2010年(40)

2009年(5)

2008年(8)

2007年(2)

分类: LINUX

2010-04-22 14:27:20

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   

 
阅读(3416) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~