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
阅读(2597) | 评论(0) | 转发(0) |