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

2014年(2)

2012年(7)

2010年(40)

2009年(5)

2008年(8)

2007年(2)

分类: LINUX

2010-04-22 09:46:20

glibc 2.3 之crt1.o分析

1.crt1.o文件的组成
crt1.o在csu目录下(C StartUp code的缩写)

crt1.o是由以下命令生成的
gcc -nostdlib -nostartfiles -r -o crt1.o start.o abi-note.o init.o

start.o对应的源文件是sysdeps/i386/elf/start.S
abi-note.o对应的源文件是csu/abi-note.S
init.o对应的源文件是csu/init.c

2.start.S

/* Startup code compliant to the ELF i386 ABI.
   Copyright (C) 1995,1996,1997,1998,2000,2001 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

/* This is the canonical entry point, usually the first thing in the text
   segment.  The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
   point runs, most registers' values are unspecified, except for:

   %edx        Contains a function pointer to be registered with `atexit'.
        This is how the dynamic linker arranges to have DT_FINI
        functions called for shared libraries that have been loaded
        before this code runs.

   %esp        The stack contains the arguments and environment:
        0(%esp)            argc
        4(%esp)            argv[0]
        ...
        (4*argc)(%esp)        NULL
        (4*(argc+1))(%esp)    envp[0]
        ...
                    NULL
*/

#include "bp-sym.h"//提供宏 # define _BP_SYM(name) name

    .text
    .globl _start
    .type _start,@function
_start:
    /* Clear the frame pointer.  The ABI suggests this be done, to mark
       the outermost frame obviously. 按规定清除%ebp */
    xorl %ebp, %ebp

    /* Extract the arguments as encoded on the stack and set up
       the arguments for `main': argc, argv. 解析argc和argv参数 envp will be determined
       later in __libc_start_main. envp由__libc_start_main准备 */
    popl %esi        /* Pop the argument count. 取argc */
    movl %esp, %ecx        /* argv starts just at the current stack top.取argv */

    /* Before pushing the arguments align the stack to a 16-byte
    (SSE needs 16-byte alignment) boundary to avoid penalties from
    misaligned accesses.  Thanks to Edward Seidl
    for pointing this out.  */
    andl $0xfffffff0, %esp//向下对齐到16字节边界
    pushl %eax        /* Push garbage because we allocate
                   28 more bytes.  后面总共7个push指令,28字节,补上4字节,凑成32字节,组成一个cache line?*/

    /* Provide the highest stack address to the user code (for stacks
       which grow downwards).  最高栈址*/
    pushl %esp

    pushl %edx        /* Push address of the shared library
                   termination function.  共享库结束函数*/

    /* Push address of our own entry points to .fini and .init.  */
    pushl $_fini
    pushl $_init

    pushl %ecx        /* Push second argument: argv.  */
    pushl %esi        /* Push first argument: argc.  */

    pushl $BP_SYM (main)//main函数地址入栈

    /* Call the user's main function, and exit with its value.
       But let the libc call main.    */
    call BP_SYM (__libc_start_main)

    hlt            /* Crash if somehow `exit' does return.  __libc_start_main不会返回*/

/* To fulfill the System V/i386 ABI we need this symbol.规定需要这个符号  Yuck, it's so
   meaningless since we don't support machines < 80386.  */
    .section .rodata
    .globl _fp_hw
_fp_hw:    .long 3
    .size _fp_hw, 4
    .type _fp_hw,@object

/* Define a symbol for the first piece of initialized data.数据段开始  */
    .data
    .globl __data_start
__data_start:
    .long 0
    .weak data_start
    data_start = __data_start


3.__libc_start_main函数

在sysdeps/generic/libc-start.c中
函数原型是
extern int BP_SYM (__libc_start_main) (int (*main) (int, char **, char **),
                       int argc,
                       char *__unbounded *__unbounded ubp_av,
                       void (*init) (void),
                       void (*fini) (void),
                       void (*rtld_fini) (void),
                       void *__unbounded stack_end)
     __attribute__ ((noreturn));

c语言函数调用使用从后向前的方式入栈,如果要调用__libc_start_main,则
形参入栈顺序是
|<-高地址
stack_end
rtld_fini
fini
init
ubp_av
argc
main
|<-低地址

和前面的push指令正好可以对上

__libc_start_main的执行流程是
如果init不空,调用init
调用main
如果fini不空,调用fini

4.abi-note.S

/* Define an ELF note identifying the operating-system ABI that the
   executable was created for.定义一个ELF note用来标识可执行文件使用的操作系统ABI
   (Application Binary Interface)
   .  The ELF note information identifies a
   particular OS or coordinated development effort within which the
   ELF header's e_machine value plus (for dynamically linked programs)
   the PT_INTERP dynamic linker name and DT_NEEDED shared library
   names fully identify the runtime environment required by an
   executable.ELF note信息标识特定OS或相应的开发工具,在遵从这个ABI的OS或开发工具中,
   ELF头部e_machine值加上PT_INTERP动态
   连接器名和DT_NEEDED共享库名完全标志可执行文件需要的运行时环境。

   The general format of ELF notes is as follows.一般的ELF notes格式如下
   Offsets and lengths are bytes or (parenthetical references) to the
   values in other fields.偏移和长度是字节为单位,对于括号中的值,他们代表引用其他字段的值

offset    length    contents    
0    4    length of name
4    4    length of data
8    4    note type
12    (0)    vendor name
        - null-terminated ASCII string, padded to 4-byte alignment
12+(0)    (4)    note data,

   The GNU project and cooperating development efforts (including the
   Linux community) use note type 1 and a vendor name string of "GNU"
   for a note descriptor that indicates ABI requirements.  The note data
   GNU项目和相应的开发工具使用note类型1和和生成商名字串"GNU"指示ABI需求.
   is four 32-bit words.  The first of these is an operating system
   note data是4个32位字。
   number (0=Linux, 1=Hurd, 2=Solaris, ...) and the remaining three
   identify the earliest release of that OS that supports this ABI.
   第一个字代表操作系统(0为linux,1为hurd,2为solaris....),剩下的三字代表
   支持该ABI的最早操作系统版本.
   See abi-tags (top level) for details. */

#include
#include         /* OS-specific ABI tag value */
    
/* The linker (GNU ld 2.8 and later) recognizes an allocated section whose
   name begins with `.note' and creates a PT_NOTE program header entry
   pointing at it. */

    .section ".note.ABI-tag", "a"
    .align 4
    .long 1f - 0f        /* name length */
    .long 3f - 2f        /* data length */
    .long  1        /* note type */
0:    .asciz "GNU"        /* vendor name */
1:    .align 4        
2:    .long __ABI_TAG_OS    /* note data: the ABI tag */
    .long __ABI_TAG_VERSION
3:    .align 4        /* pad out section */

这些ABI_TAG值是

[root@mail /var/root/glibc-2.3/csu]# cat abi-tag.h
#define __ABI_TAG_OS 0
#ifndef __ABI_TAG_VERSION
# define __ABI_TAG_VERSION 2,0,0
#endif

5.init.c

#if defined USE_IN_LIBIO && defined __GNUC__ && __GNUC__ >= 2

#include <_G_config.h>

/* This records which stdio is linked against in the application.
记录哪个stdio被连接
*/
const int _IO_stdin_used = _G_IO_IO_FILE_VERSION;//0x20001

#endif

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