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

2014年(2)

2012年(7)

2010年(40)

2009年(5)

2008年(8)

2007年(2)

分类: LINUX

2010-04-22 11:28:10

glibc 2.3之crti.o和crtn.o分析

1.crti.o和crtn.o的组成
crti.o和crtn.o也在csu目录下

crti.o来之crti.S,crtn.o来之crtn.S

而crti.S和crtn.S则都来之initfini.s

initfini.s则来之与sysdeps/generic/initfini.c

我们看看具体是如何生成这些文件的

gcc ../sysdeps/generic/initfini.c -c -O -Wall -Winline -Wstrict-prototypes -Wwrite-strings -g    -g0 -fPIC -fno-inline-functions -march=i386 -mcpu=i386  -I../include -I.  -I.. -I../libio  -I../sysdeps/i386/elf -I../linuxthreads/sysdeps/unix/sysv/linux/i386 -I../linuxthreads/sysdeps/unix/sysv/linux -I../linuxthreads/sysdeps/pthread -I../sysdeps/pthread -I../linuxthreads/sysdeps/unix/sysv -I../linuxthreads/sysdeps/unix -I../linuxthreads/sysdeps/i386/i686 -I../linuxthreads/sysdeps/i386 -I../sysdeps/unix/sysv/linux/i386 -I../sysdeps/unix/sysv/linux -I../sysdeps/gnu -I../sysdeps/unix/common -I../sysdeps/unix/mman -I../sysdeps/unix/inet -I../sysdeps/unix/sysv/i386 -I../sysdeps/unix/sysv -I../sysdeps/unix/i386 -I../sysdeps/unix -I../sysdeps/posix -I../sysdeps/i386/i686/fpu -I../sysdeps/i386/i686 -I../sysdeps/i386/i486 -I../sysdeps/i386/fpu -I../sysdeps/i386 -I../sysdeps/wordsize-32 -I../sysdeps/ieee754/ldbl-96 -I../sysdeps/ieee754/dbl-64 -I../sysdeps/ieee754/flt-32 -I../sysdeps/ieee754 -I../sysdeps/generic/elf -I../sysdeps/generic  -I /lib/modules/2.4.20-8smp/build/include -D_LIBC_REENTRANT -include ../include/libc-symbols.h      -DHAVE_INITFINI -S -g0 -fPIC -fno-inline-functions -march=i386 -mcpu=i386 -finhibit-size-directive \
        -fno-exceptions -o initfini.s //生成initfini.s
sed -n -e '1,/@HEADER_ENDS/p' \
       -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \
       -e '/@TRAILER_BEGINS/,$p' initfini.s > crti.S//根据initfini.s生成crti.S
sed -n -e '/@TESTS_BEGIN/,/@TESTS_END/p' initfini.s | \
        gawk -f defs.awk > defs.h
gcc crti.S -c  -I../include -I.  -I.. -I../libio  -I../sysdeps/i386/elf -I../linuxthreads/sysdeps/unix/sysv/linux/i386 -I../linuxthreads/sysdeps/unix/sysv/linux -I../linuxthreads/sysdeps/pthread -I../sysdeps/pthread -I../linuxthreads/sysdeps/unix/sysv -I../linuxthreads/sysdeps/unix -I../linuxthreads/sysdeps/i386/i686 -I../linuxthreads/sysdeps/i386 -I../sysdeps/unix/sysv/linux/i386 -I../sysdeps/unix/sysv/linux -I../sysdeps/gnu -I../sysdeps/unix/common -I../sysdeps/unix/mman -I../sysdeps/unix/inet -I../sysdeps/unix/sysv/i386 -I../sysdeps/unix/sysv -I../sysdeps/unix/i386 -I../sysdeps/unix -I../sysdeps/posix -I../sysdeps/i386/i686/fpu -I../sysdeps/i386/i686 -I../sysdeps/i386/i486 -I../sysdeps/i386/fpu -I../sysdeps/i386 -I../sysdeps/wordsize-32 -I../sysdeps/ieee754/ldbl-96 -I../sysdeps/ieee754/dbl-64 -I../sysdeps/ieee754/flt-32 -I../sysdeps/ieee754 -I../sysdeps/generic/elf -I../sysdeps/generic  -I /lib/modules/2.4.20-8smp/build/include -D_LIBC_REENTRANT -include ../include/libc-symbols.h      -DHAVE_INITFINI -DASSEMBLER  -I. -DGAS_SYNTAX  -g0  -o crti.o
sed -n -e '1,/@HEADER_ENDS/p' \
       -e '/@_.*_EPILOG_BEGINS/,/@_.*_EPILOG_ENDS/p' \
       -e '/@TRAILER_BEGINS/,$p' initfini.s > crtn.S//根据initfini.s生成crtn.S
gcc crtn.S -c  -I../include -I.  -I.. -I../libio  -I../sysdeps/i386/elf -I../linuxthreads/sysdeps/unix/sysv/linux/i386 -I../linuxthreads/sysdeps/unix/sysv/linux -I../linuxthreads/sysdeps/pthread -I../sysdeps/pthread -I../linuxthreads/sysdeps/unix/sysv -I../linuxthreads/sysdeps/unix -I../linuxthreads/sysdeps/i386/i686 -I../linuxthreads/sysdeps/i386 -I../sysdeps/unix/sysv/linux/i386 -I../sysdeps/unix/sysv/linux -I../sysdeps/gnu -I../sysdeps/unix/common -I../sysdeps/unix/mman -I../sysdeps/unix/inet -I../sysdeps/unix/sysv/i386 -I../sysdeps/unix/sysv -I../sysdeps/unix/i386 -I../sysdeps/unix -I../sysdeps/posix -I../sysdeps/i386/i686/fpu -I../sysdeps/i386/i686 -I../sysdeps/i386/i486 -I../sysdeps/i386/fpu -I../sysdeps/i386 -I../sysdeps/wordsize-32 -I../sysdeps/ieee754/ldbl-96 -I../sysdeps/ieee754/dbl-64 -I../sysdeps/ieee754/flt-32 -I../sysdeps/ieee754 -I../sysdeps/generic/elf -I../sysdeps/generic  -I /lib/modules/2.4.20-8smp/build/include -D_LIBC_REENTRANT -include ../include/libc-symbols.h      -DHAVE_INITFINI -DASSEMBLER  -I. -DGAS_SYNTAX  -g0  -o crtn.o

2.initfini.c(sysdeps/generic)

/* Special .init and .fini section support. 特别的.init和.fini节支持
  */

/* This file is compiled into assembly code which is then munged by a sed
   script into two files: crti.s and crtn.s.
这个文件被编译成汇编代码,然后被一个sed脚本分割成两个文件crti.s和crtn.s

   * crti.s puts a function prologue at the beginning of the
   .init and .fini sections and defines global symbols for
   those addresses, so they can be called as functions.
   crti.s将一个函数的初始化部分放在.init和.fini节的开始处,定义这些地址
   的全局符号,这样他们就能被当作函数来调用.
   
   * crtn.s puts the corresponding function epilogues
   in the .init and .fini sections.
   crtn.s将相应的结束部分放在.init和.fini节中
    */

#include

/* We use embedded asm for .section unconditionally, as this makes it
   easier to insert the necessary directives into crtn.S. */
#define SECTION(x) asm (".section " x )

/* Embed an #include to pull in the alignment and .end directives. */
asm ("\n#include \"defs.h\"");

/* The initial common code ends here. */
asm ("\n/*@HEADER_ENDS*/");

/* To determine whether we need .end and .align: */
asm ("\n/*@TESTS_BEGIN*/");
extern void dummy (void (*foo) (void));
void
dummy (void (*foo) (void))
{
  if (foo)
    (*foo) ();
}
asm ("\n/*@TESTS_END*/");

/* The beginning of _init:  */
asm ("\n/*@_init_PROLOG_BEGINS*/");

static void
call_gmon_start(void)
{
  extern void __gmon_start__ (void) __attribute__ ((weak)); /*weak_extern (__gmon_start__);*/
  void (*gmon_start) (void) = __gmon_start__;

  if (gmon_start)//gmon_start存在
    gmon_start ();//调用
}

SECTION (".init");//.init节
extern void _init (void);
void
_init (void)
{
  /* We cannot use the normal constructor mechanism in gcrt1.o because it
     appears before crtbegin.o in the link, so the header elt of .ctors
     would come after the elt for __gmon_start__.  One approach is for   
     gcrt1.o to reference a symbol which would be defined by some library
     module which has a constructor; but then user code's constructors
     would come first, and not be profiled.  */
  call_gmon_start ();

  asm ("ALIGN");
  asm("END_INIT");
  /* Now the epilog. */
  asm ("\n/*@_init_PROLOG_ENDS*/");
  asm ("\n/*@_init_EPILOG_BEGINS*/");
  SECTION(".init");
}
asm ("END_INIT");

/* End of the _init epilog, beginning of the _fini prolog. */
asm ("\n/*@_init_EPILOG_ENDS*/");
asm ("\n/*@_fini_PROLOG_BEGINS*/");

SECTION (".fini");
extern void _fini (void);
void
_fini (void)
{

  /* End of the _fini prolog. */
  asm ("ALIGN");
  asm ("END_FINI");
  asm ("\n/*@_fini_PROLOG_ENDS*/");

  {
    /* Let GCC know that _fini is not a leaf function by having a dummy
       function call here.  We arrange for this call to be omitted from
       either crt file.  让gcc生成pic代码?*/
    extern void i_am_not_a_leaf (void);
    i_am_not_a_leaf ();
  }

  /* Beginning of the _fini epilog. */
  asm ("\n/*@_fini_EPILOG_BEGINS*/");
  SECTION (".fini");
}
asm ("END_FINI");

/* End of the _fini epilog.  Any further generated assembly (e.g. .ident)
   is shared between both crt files. */
asm ("\n/*@_fini_EPILOG_ENDS*/");
asm ("\n/*@TRAILER_BEGINS*/");

/* End of file. */

这个文件需要对比生成的initfini.s看

3.initfini.s(csu)

    .file    "initfini.c"
#APP
   
#include "defs.h"
   
/*@HEADER_ENDS*/
   
/*@TESTS_BEGIN*/
#NO_APP
    .text
.globl dummy
    .type    dummy,@function
dummy:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    movl    8(%ebp), %eax
    testl    %eax, %eax
    je    .L1
    call    *%eax
.L1:
    leave
    ret
#APP
   
/*@TESTS_END*/
   
/*@_init_PROLOG_BEGINS*/
#NO_APP
    .type    call_gmon_start,@function
call_gmon_start:
    pushl    %ebp
    movl    %esp, %ebp
    pushl    %ebx
    subl    $4, %esp
    call    .L5
.L5:
    popl    %ebx
    addl    $_GLOBAL_OFFSET_TABLE_+[.-.L5], %ebx
    movl    __gmon_start__@GOT(%ebx), %eax
    testl    %eax, %eax
    je    .L3
    call    *%eax
.L3:
    movl    -4(%ebp), %ebx
    leave
    ret
#APP
    .section .init
#NO_APP
.globl _init
    .type    _init,@function
_init:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    call    call_gmon_start
#APP
    ALIGN
    END_INIT
   
/*@_init_PROLOG_ENDS*/
   
/*@_init_EPILOG_BEGINS*/
    .section .init
#NO_APP
    leave
    ret
#APP
    END_INIT
   
/*@_init_EPILOG_ENDS*/
   
/*@_fini_PROLOG_BEGINS*/
    .section .fini
#NO_APP
.globl _fini
    .type    _fini,@function
_fini:
    pushl    %ebp
    movl    %esp, %ebp
    pushl    %ebx
    subl    $4, %esp
    call    .L8
.L8:
    popl    %ebx
    addl    $_GLOBAL_OFFSET_TABLE_+[.-.L8], %ebx
#APP
    ALIGN
    END_FINI
   
/*@_fini_PROLOG_ENDS*/
#NO_APP
    call    i_am_not_a_leaf@PLT
#APP
   
/*@_fini_EPILOG_BEGINS*/
    .section .fini
#NO_APP
    movl    -4(%ebp), %ebx
    leave
    ret
#APP
    END_FINI
   
/*@_fini_EPILOG_ENDS*/
   
/*@TRAILER_BEGINS*/
    .weak    __gmon_start__
    .ident    "GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"


4.crti.S
    .file    "initfini.c"
#APP
   
#include "defs.h"
   
/*@HEADER_ENDS*/
/*@_init_PROLOG_BEGINS*/
#NO_APP
    .type    call_gmon_start,@function
call_gmon_start:
    pushl    %ebp
    movl    %esp, %ebp
    pushl    %ebx
    subl    $4, %esp
    call    .L5
.L5:
    popl    %ebx
    addl    $_GLOBAL_OFFSET_TABLE_+[.-.L5], %ebx
    movl    __gmon_start__@GOT(%ebx), %eax
    testl    %eax, %eax
    je    .L3
    call    *%eax
.L3:
    movl    -4(%ebp), %ebx
    leave
    ret
#APP
    .section .init
#NO_APP
.globl _init
    .type    _init,@function
_init:
    pushl    %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    call    call_gmon_start
#APP
    ALIGN
    END_INIT
   
/*@_init_PROLOG_ENDS*/
/*@_fini_PROLOG_BEGINS*/
    .section .fini
#NO_APP
.globl _fini
    .type    _fini,@function
_fini:
    pushl    %ebp
    movl    %esp, %ebp
    pushl    %ebx
    subl    $4, %esp
    call    .L8
.L8:
    popl    %ebx
    addl    $_GLOBAL_OFFSET_TABLE_+[.-.L8], %ebx
#APP
    ALIGN
    END_FINI
   
/*@_fini_PROLOG_ENDS*/
/*@TRAILER_BEGINS*/
    .weak    __gmon_start__
    .ident    "GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"

5.crtn.S

    .file    "initfini.c"
#APP
   
#include "defs.h"
   
/*@HEADER_ENDS*/
/*@_init_EPILOG_BEGINS*/
    .section .init
#NO_APP
    leave
    ret
#APP
    END_INIT
   
/*@_init_EPILOG_ENDS*/
/*@_fini_EPILOG_BEGINS*/
    .section .fini
#NO_APP
    movl    -4(%ebp), %ebx
    leave
    ret
#APP
    END_FINI
   
/*@_fini_EPILOG_ENDS*/
/*@TRAILER_BEGINS*/
    .weak    __gmon_start__
    .ident    "GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"

6.defs.h
[root@mail /var/root/glibc-2.3/csu]# cat defs.h
#define END_INIT
#define END_FINI
#define ALIGN
#include
weak_extern (__gmon_start__)

7. defs.awk
[root@mail /var/root/glibc-2.3/csu]# cat defs.awk
/^[     ]*\.endp/        { need_endp = 1 }
/^[     ]*\.end/         { need_end = 1 }
/^[     ]*\.align/ { if($2 > max) max = $2; }

END {
    if(need_endp)
    {
        print "#define END_INIT .endp _init";
        print "#define END_FINI .endp _fini";
    } else if(need_end)
    {
        print "#define END_INIT .end _init";
        print "#define END_FINI .end _fini";
    }
    else
    {
        print "#define END_INIT";
        print "#define END_FINI";
    }
    if(max)
        print "#define ALIGN .align", max;
    else
        print "#define ALIGN";

    print "#include ";
    print "weak_extern (__gmon_start__)";
}


7.总结

可见crti和crtn就是将两个函数init和fini分别切成两截,他们的前半截放入crti,后半截放入crtn.

为什么要这么做呢?

如果有某些工作需要在main之间完成和main之后完成,那么,就可以将相应的代码放入目标文件的
.init和.fini节。在ld链接时,会按照给定的目标文件顺序,依次合并同名节。
这样就能将相应代码插入_init函数和_fini函数中,从而达到目的。




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