可执行文件运行

动态链接可执行文件运行

_start 定义于glibc/sysdeps/i386/start.S  
__libc_start_main 定义于glibc/​csu/​libc-start.c
__libc_csu_init定义于glibc/​csu/​elf-init.c
__libc_init_first定义于glibc/​csu/​init-first.c
__gmon_start__定义于glibc/​csu/​gmon-start.c
exit定义于 glibc/stdlib/exit.c
frame_dummy __do_global_dtors_aux  register_tm_clones deregister_tm_clones都定义于gcc/libgcc/crtstuff.c.)

一个包含一些特殊函数的c程序 excute.c :

#include <stdio.h>
#include <stdlib.h>
#include <elf.h>

extern int* __libc_stack_end;
extern char **__environ;
extern int __libc_enable_secure;
//extern unsigned int * __stack_chk_guard;
extern int __libc_argc;
extern unsigned int *_GLOBAL_OFFSET_TABLE_;
extern void (**__init_array_start)();
void preinit_array(){
    puts(__FUNCTION__);
}
__attribute__((section(".preinit_array"))) typeof(preinit_array) *__preinit_array = preinit_array;
__attribute__((constructor))void construct(){
    puts(__FUNCTION__);
}
__attribute__((constructor))void construct1(){
    puts(__FUNCTION__);
}
void init_array(){
    puts(__FUNCTION__);
}
__attribute__((section(".init_array"))) typeof(init_array) *__init=init_array;

void at_exit1(){
    puts(__FUNCTION__);
}
__attribute__((destructor))void destruct1(){
    puts(__FUNCTION__);
}

void fini_array(){
    puts(__FUNCTION__);
}
__attribute__((section(".fini_array"))) typeof(fini_array) *__fini=fini_array;
int main(int argc,char *argv[],char *envp[])
{
    atexit(at_exit1);
    return 0;

}

生成的可执行文件汇编结果

excute:     文件格式 elf32-i386

Contents of section .interp:
 8048154 2f6c6962 2f6c642d 6c696e75 782e736f  /lib/ld-linux.so
 8048164 2e3200                               .2.             
Contents of section .note.ABI-tag:
 8048168 04000000 10000000 01000000 474e5500  ............GNU.
 ...........
Contents of section .note.gnu.build-id:
 8048188 04000000 14000000 03000000 474e5500  ............GNU.
 ...........
Contents of section .gnu.hash:
 80481ac 02000000 05000000 01000000 05000000  ................
 ...........
Contents of section .dynsym:
 80481cc 00000000 00000000 00000000 00000000  ................
 ...........
Contents of section .dynstr:
 804822c 006c6962 632e736f 2e36005f 494f5f73  .libc.so.6._IO_s
 ...........
Contents of section .gnu.version:
 ...........
Contents of section .gnu.version_r:
 ...........
Contents of section .rel.dyn:
 80482cc fc9f0408 06030000                    ........        
Contents of section .rel.plt:
 80482d4 0ca00408 07010000 10a00408 07020000  ................
 80482e4 14a00408 07030000 18a00408 07040000  ................
Contents of section .init:
 80482f4 5383ec08 e8a30000 0081c303 1d00008b  S...............
 8048304 83fcffff ff85c074 05e83e00 000083c4  .......t..>.....
 8048314 085bc3                               .[.             
Contents of section .plt:
 8048320 ff3504a0 0408ff25 08a00408 00000000  .5.....%........
 8048330 ff250ca0 04086800 000000e9 e0ffffff  .%....h.........
 8048340 ff2510a0 04086808 000000e9 d0ffffff  .%....h.........
 8048350 ff2514a0 04086810 000000e9 c0ffffff  .%....h.........
 8048360 ff2518a0 04086818 000000e9 b0ffffff  .%....h.........
Contents of section .text:
 8048370 31ed5e89 e183e4f0 50545268 90850408  1.^.....PTRh....
 ...........
 Contents of section .eh_frame_hdr:
 804863c 011b033b 60000000 0b000000 e4fcffff  ...;`...........
 ...........
Contents of section .eh_frame:
 80486a0 14000000 00000000 017a5200 017c0801  .........zR..|..
 ...........
Contents of section .preinit_array:
 8049ee4 6b840408                             k...            
Contents of section .init_array:
 8049ee8 40840408 84840408 9d840408           @...........    
Contents of section .fini_array:
 8049ef4 20840408 cf840408 e8840408            ...........    
Contents of section .jcr:
 8049f00 00000000                             ....            
Contents of section .dynamic:
 8049f04 01000000 01000000 0c000000 f4820408  ................
 ...........
Contents of section .got:
 8049ffc 00000000                             ....            
Contents of section .got.plt:
 804a000 049f0408 00000000 00000000 36830408  ............6...
 804a010 46830408 56830408 66830408           F...V...f...    
Contents of section .data:
 804a01c 00000000 00000000                    ........        

Disassembly of section .init:

080482f4 <_init>:
 80482f4:   53                      push   %ebx
 80482f5:   83 ec 08                sub    $0x8,%esp
 80482f8:   e8 a3 00 00 00          call   80483a0 <__x86.get_pc_thunk.bx>
 80482fd:   81 c3 03 1d 00 00       add    $0x1d03,%ebx
 8048303:   8b 83 fc ff ff ff       mov    -0x4(%ebx),%eax
 8048309:   85 c0                   test   %eax,%eax
 804830b:   74 05                   je     8048312 <_init+0x1e>
 804830d:   e8 3e 00 00 00          call   8048350 <__gmon_start__@plt>
 8048312:   83 c4 08                add    $0x8,%esp
 8048315:   5b                      pop    %ebx
 8048316:   c3                      ret    

Disassembly of section .plt:

08048320 <__cxa_atexit@plt-0x10>:
 8048320:   ff 35 04 a0 04 08       pushl  0x804a004
 8048326:   ff 25 08 a0 04 08       jmp    *0x804a008
 804832c:   00 00                   add    %al,(%eax)
    ...

08048330 <__cxa_atexit@plt>:
 8048330:   ff 25 0c a0 04 08       jmp    *0x804a00c
 8048336:   68 00 00 00 00          push   $0x0
 804833b:   e9 e0 ff ff ff          jmp    8048320 <_init+0x2c>

08048340 <puts@plt>:
 8048340:   ff 25 10 a0 04 08       jmp    *0x804a010
 8048346:   68 08 00 00 00          push   $0x8
 804834b:   e9 d0 ff ff ff          jmp    8048320 <_init+0x2c>

08048350 <__gmon_start__@plt>:
 8048350:   ff 25 14 a0 04 08       jmp    *0x804a014
 8048356:   68 10 00 00 00          push   $0x10
 804835b:   e9 c0 ff ff ff          jmp    8048320 <_init+0x2c>

08048360 <__libc_start_main@plt>:
 8048360:   ff 25 18 a0 04 08       jmp    *0x804a018
 8048366:   68 18 00 00 00          push   $0x18
 804836b:   e9 b0 ff ff ff          jmp    8048320 <_init+0x2c>

Disassembly of section .text:

08048370 <_start>:

080483a0 <__x86.get_pc_thunk.bx>:
 80483a0:   8b 1c 24                mov    (%esp),%ebx
 80483a3:   c3                      ret    
 80483a4:   66 90                   xchg   %ax,%ax
 80483a6:   66 90                   xchg   %ax,%ax
 80483a8:   66 90                   xchg   %ax,%ax
 80483aa:   66 90                   xchg   %ax,%ax
 80483ac:   66 90                   xchg   %ax,%ax
 80483ae:   66 90                   xchg   %ax,%ax

080483b0 <deregister_tm_clones>:
 80483b0:   b8 27 a0 04 08          mov    $0x804a027,%eax
 80483b5:   2d 24 a0 04 08          sub    $0x804a024,%eax
 80483ba:   83 f8 06                cmp    $0x6,%eax
 80483bd:   76 1a                   jbe    80483d9 <deregister_tm_clones+0x29>
 80483bf:   b8 00 00 00 00          mov    $0x0,%eax
 80483c4:   85 c0                   test   %eax,%eax
 80483c6:   74 11                   je     80483d9 <deregister_tm_clones+0x29>
 80483c8:   55                      push   %ebp
 80483c9:   89 e5                   mov    %esp,%ebp
 80483cb:   83 ec 14                sub    $0x14,%esp
 80483ce:   68 24 a0 04 08          push   $0x804a024
 80483d3:   ff d0                   call   *%eax
 80483d5:   83 c4 10                add    $0x10,%esp
 80483d8:   c9                      leave  
 80483d9:   f3 c3                   repz ret 
 80483db:   90                      nop
 80483dc:   8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi

080483e0 <register_tm_clones>:
 80483e0:   b8 24 a0 04 08          mov    $0x804a024,%eax
 80483e5:   2d 24 a0 04 08          sub    $0x804a024,%eax
 80483ea:   c1 f8 02                sar    $0x2,%eax
 80483ed:   89 c2                   mov    %eax,%edx
 80483ef:   c1 ea 1f                shr    $0x1f,%edx
 80483f2:   01 d0                   add    %edx,%eax
 80483f4:   d1 f8                   sar    %eax
 80483f6:   74 1b                   je     8048413 <register_tm_clones+0x33>
 80483f8:   ba 00 00 00 00          mov    $0x0,%edx
 80483fd:   85 d2                   test   %edx,%edx
 80483ff:   74 12                   je     8048413 <register_tm_clones+0x33>
 8048401:   55                      push   %ebp
 8048402:   89 e5                   mov    %esp,%ebp
 8048404:   83 ec 10                sub    $0x10,%esp
 8048407:   50                      push   %eax
 8048408:   68 24 a0 04 08          push   $0x804a024
 804840d:   ff d2                   call   *%edx
 804840f:   83 c4 10                add    $0x10,%esp
 8048412:   c9                      leave  
 8048413:   f3 c3                   repz ret 
 8048415:   8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
 8048419:   8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi

08048420 <__do_global_dtors_aux>:
 8048420:   80 3d 24 a0 04 08 00    cmpb   $0x0,0x804a024
 8048427:   75 13                   jne    804843c <__do_global_dtors_aux+0x1c>
 8048429:   55                      push   %ebp
 804842a:   89 e5                   mov    %esp,%ebp
 804842c:   83 ec 08                sub    $0x8,%esp
 804842f:   e8 7c ff ff ff          call   80483b0 <deregister_tm_clones>
 8048434:   c6 05 24 a0 04 08 01    movb   $0x1,0x804a024
 804843b:   c9                      leave  
 804843c:   f3 c3                   repz ret 
 804843e:   66 90                   xchg   %ax,%ax

08048440 <frame_dummy>:
 8048440:   b8 00 9f 04 08          mov    $0x8049f00,%eax
 8048445:   8b 10                   mov    (%eax),%edx
 8048447:   85 d2                   test   %edx,%edx
 8048449:   75 05                   jne    8048450 <frame_dummy+0x10>
 804844b:   eb 93                   jmp    80483e0 <register_tm_clones>
 804844d:   8d 76 00                lea    0x0(%esi),%esi
 8048450:   ba 00 00 00 00          mov    $0x0,%edx
 8048455:   85 d2                   test   %edx,%edx
 8048457:   74 f2                   je     804844b <frame_dummy+0xb>
 8048459:   55                      push   %ebp
 804845a:   89 e5                   mov    %esp,%ebp
 804845c:   83 ec 14                sub    $0x14,%esp
 804845f:   50                      push   %eax
 8048460:   ff d2                   call   *%edx
 8048462:   83 c4 10                add    $0x10,%esp
 8048465:   c9                      leave  
 8048466:   e9 75 ff ff ff          jmp    80483e0 <register_tm_clones>

0804846b <preinit_array>:
 804846b:   55                      push   %ebp
 804846c:   89 e5                   mov    %esp,%ebp
 804846e:   83 ec 08                sub    $0x8,%esp
 8048471:   83 ec 0c                sub    $0xc,%esp
 8048474:   68 f0 85 04 08          push   $0x80485f0
 8048479:   e8 c2 fe ff ff          call   8048340 <puts@plt>
 804847e:   83 c4 10                add    $0x10,%esp
 8048481:   90                      nop
 8048482:   c9                      leave  
 8048483:   c3                      ret    

08048484 <construct>:
 8048484:   55                      push   %ebp
 8048485:   89 e5                   mov    %esp,%ebp
 8048487:   83 ec 08                sub    $0x8,%esp
 804848a:   83 ec 0c                sub    $0xc,%esp
 804848d:   68 00 86 04 08          push   $0x8048600
 8048492:   e8 a9 fe ff ff          call   8048340 <puts@plt>
 8048497:   83 c4 10                add    $0x10,%esp
 804849a:   90                      nop
 804849b:   c9                      leave  
 804849c:   c3                      ret    

0804849d <init_array>:
 804849d:   55                      push   %ebp
 804849e:   89 e5                   mov    %esp,%ebp
 80484a0:   83 ec 08                sub    $0x8,%esp
 80484a3:   83 ec 0c                sub    $0xc,%esp
 80484a6:   68 0c 86 04 08          push   $0x804860c
 80484ab:   e8 90 fe ff ff          call   8048340 <puts@plt>
 80484b0:   83 c4 10                add    $0x10,%esp
 80484b3:   90                      nop
 80484b4:   c9                      leave  
 80484b5:   c3                      ret    

080484b6 <at_exit1>:
 80484b6:   55                      push   %ebp
 80484b7:   89 e5                   mov    %esp,%ebp
 80484b9:   83 ec 08                sub    $0x8,%esp
 80484bc:   83 ec 0c                sub    $0xc,%esp
 80484bf:   68 18 86 04 08          push   $0x8048618
 80484c4:   e8 77 fe ff ff          call   8048340 <puts@plt>
 80484c9:   83 c4 10                add    $0x10,%esp
 80484cc:   90                      nop
 80484cd:   c9                      leave  
 80484ce:   c3                      ret    

080484cf <destruct1>:
 80484cf:   55                      push   %ebp
 80484d0:   89 e5                   mov    %esp,%ebp
 80484d2:   83 ec 08                sub    $0x8,%esp
 80484d5:   83 ec 0c                sub    $0xc,%esp
 80484d8:   68 24 86 04 08          push   $0x8048624
 80484dd:   e8 5e fe ff ff          call   8048340 <puts@plt>
 80484e2:   83 c4 10                add    $0x10,%esp
 80484e5:   90                      nop
 80484e6:   c9                      leave  
 80484e7:   c3                      ret    

080484e8 <fini_array>:
 80484e8:   55                      push   %ebp
 80484e9:   89 e5                   mov    %esp,%ebp
 80484eb:   83 ec 08                sub    $0x8,%esp
 80484ee:   83 ec 0c                sub    $0xc,%esp
 80484f1:   68 30 86 04 08          push   $0x8048630
 80484f6:   e8 45 fe ff ff          call   8048340 <puts@plt>
 80484fb:   83 c4 10                add    $0x10,%esp
 80484fe:   90                      nop
 80484ff:   c9                      leave  
 8048500:   c3                      ret    

08048501 <main>:
 8048501:   8d 4c 24 04             lea    0x4(%esp),%ecx
 8048505:   83 e4 f0                and    $0xfffffff0,%esp
 8048508:   ff 71 fc                pushl  -0x4(%ecx)
 804850b:   55                      push   %ebp
 804850c:   89 e5                   mov    %esp,%ebp
 804850e:   51                      push   %ecx
 804850f:   83 ec 04                sub    $0x4,%esp
 8048512:   83 ec 0c                sub    $0xc,%esp
 8048515:   68 b6 84 04 08          push   $0x80484b6
 804851a:   e8 81 00 00 00          call   80485a0 <atexit>
 804851f:   83 c4 10                add    $0x10,%esp
 8048522:   b8 00 00 00 00          mov    $0x0,%eax
 8048527:   8b 4d fc                mov    -0x4(%ebp),%ecx
 804852a:   c9                      leave  
 804852b:   8d 61 fc                lea    -0x4(%ecx),%esp
 804852e:   c3                      ret    
 804852f:   90                      nop

08048530 <__libc_csu_init>:

08048590 <__libc_csu_fini>:
 8048590:   f3 c3                   repz ret 
 8048592:   66 90                   xchg   %ax,%ax
 8048594:   66 90                   xchg   %ax,%ax
 8048596:   66 90                   xchg   %ax,%ax
 8048598:   66 90                   xchg   %ax,%ax
 804859a:   66 90                   xchg   %ax,%ax
 804859c:   66 90                   xchg   %ax,%ax
 804859e:   66 90                   xchg   %ax,%ax

080485a0 <atexit>:
 80485a0:   53                      push   %ebx
 80485a1:   e8 fa fd ff ff          call   80483a0 <__x86.get_pc_thunk.bx>
 80485a6:   81 c3 5a 1a 00 00       add    $0x1a5a,%ebx
 80485ac:   83 ec 08                sub    $0x8,%esp
 80485af:   8d 83 20 00 00 00       lea    0x20(%ebx),%eax
 80485b5:   85 c0                   test   %eax,%eax
 80485b7:   74 17                   je     80485d0 <atexit+0x30>
 80485b9:   8b 00                   mov    (%eax),%eax
 80485bb:   83 ec 04                sub    $0x4,%esp
 80485be:   50                      push   %eax
 80485bf:   6a 00                   push   $0x0
 80485c1:   ff 74 24 1c             pushl  0x1c(%esp)
 80485c5:   e8 66 fd ff ff          call   8048330 <__cxa_atexit@plt>
 80485ca:   83 c4 18                add    $0x18,%esp
 80485cd:   5b                      pop    %ebx
 80485ce:   c3                      ret    
 80485cf:   90                      nop
 80485d0:   31 c0                   xor    %eax,%eax
 80485d2:   eb e7                   jmp    80485bb <atexit+0x1b>

Disassembly of section .fini:

080485d4 <_fini>:
 80485d4:   53                      push   %ebx
 80485d5:   83 ec 08                sub    $0x8,%esp
 80485d8:   e8 c3 fd ff ff          call   80483a0 <__x86.get_pc_thunk.bx>
 80485dd:   81 c3 23 1a 00 00       add    $0x1a23,%ebx
 80485e3:   83 c4 08                add    $0x8,%esp
 80485e6:   5b                      pop    %ebx
 80485e7:   c3                      ret    

当目标文件运行时,在可执行文件的段头表的指导下,加载器加载可执行文件的相关部分加载到代码段和数据段,然后跳转到_start的地址,_start的启动代码是定义在crt1.o中,在从.text和.init节调用了初始化例程后,启动atexit注册的函数,附加一系列在调用exit时应该调用的程序,exit函数运行atexit注册的函数然后调用_exit将控制返回给操作系统.启动main程序,返回之后启动代码调用_exit程序,将控制返回给操作系统.
elf运行
运行流程:

  1. shell 加载可执行文件到内存 并完成部分初始化工作 待研究
  2. 跳入_start
  3. 跳入__libc_start_main
    1. 调用__libc_init_first
    2. 调用__libc_csu_init
    3. 调用main
    4. 调用exit 不再返回

跳入_start

/* 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
*/

start:
    /* Clear the frame pointer.  The ABI suggests this be done, to mark
       the outermost frame obviously.  */
    xorl %ebp, %ebp

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

    /* 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 <seidl@janed.com>
    for pointing this out.  */
    andl $0xfffffff0, %esp
    pushl %eax      /* Push garbage because we allocate
                   28 more bytes.  */

    /* 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 $__libc_csu_fini
    pushl $__libc_csu_init

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

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

08048370 <_start>:
 8048370:   31 ed                   xor    %ebp,%ebp
 8048372:   5e                      pop    %esi
 8048373:   89 e1                   mov    %esp,%ecx
 8048375:   83 e4 f0                and    $0xfffffff0,%esp
 8048378:   50                      push   %eax
 8048379:   54                      push   %esp
 804837a:   52                      push   %edx
 804837b:   68 90 85 04 08          push   $0x8048590
 8048380:   68 30 85 04 08          push   $0x8048530
 8048385:   51                      push   %ecx
 8048386:   56                      push   %esi
 8048387:   68 01 85 04 08          push   $0x8048501
 804838c:   e8 cf ff ff ff          call   8048360 <__libc_start_main@plt>
 8048391:   f4                      hlt    
 8048392:   66 90                   xchg   %ax,%ax
 8048394:   66 90                   xchg   %ax,%ax
 8048396:   66 90                   xchg   %ax,%ax
 8048398:   66 90                   xchg   %ax,%ax
 804839a:   66 90                   xchg   %ax,%ax
 804839c:   66 90                   xchg   %ax,%ax
 804839e:   66 90                   xchg   %ax,%ax

所以跳入_start相当于调用函数

     __libc_start_main(int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
         int argc, char **argv,
         __typeof (main) init,
         void (*fini) (void),
         void (*rtld_fini) (void), void *stack_end)

跳入__libc_start_main:

将libc_start.c单独编译

gcc -m32 -E libc-start.c -I../sysdeps/generic
注 并不清楚编译选项
玄学事件: 一旦-o选项或者将输出重定向就报错 也是没谁了….

 int    __libc_start_main (int (*main) (int, char **, char ** ),int argc, char **argv,__typeof (main) init,void (*fini) (void),void (*rtld_fini) (void), void *stack_end)
{
  int result;
  __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
  char **ev = &argv[argc + 1];
  __environ = ev;
  __libc_stack_end = stack_end;
    {
      extern const Elf32_Ehdr __ehdr_start  __attribute__ ((weak, visibility ("hidden")));
      if (&__ehdr_start != ((void *)0)) {
         ((__ehdr_start.e_phentsize == sizeof *_dl_phdr) ? (void) (0) : __assert_fail ("__ehdr_start.e_phentsize == sizeof *_dl_phdr", "./src/libc-start.c", 175, __PRETTY_FUNCTION__));
          _dl_phdr = (const void *) &__ehdr_start + __ehdr_start.e_phoff;
          _dl_phnum = __ehdr_start.e_phnum;
        }
    }
      /* Perform IREL{,A} relocations.  */
  apply_irel ();
    /* Initialize the thread library at least a bit since the libgcc
     functions are using thread functions if these are available and
     we need to setup errno.  */
  __pthread_initialize_minimal ();
    /* Set up the stack checker's canary.  */
  uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random);
  __stack_chk_guard = stack_chk_guard;
   /* Set up the pointer guard value.  */
  uintptr_t pointer_chk_guard = _dl_setup_pointer_guard(_dl_random,stack_chk_guard);
  __pointer_chk_guard_local = pointer_chk_guard;
    /* Register the destructor of the program, if any.  */
  if (__builtin_expect ((rtld_fini != ((void *)0)), 1))
        __cxa_atexit ((void (*) (void *)) rtld_fini,((void *)0),((void *)0));
   /* Call the initializer of the libc.  This is only needed here if we
     are compiling for the static library in which case we haven't
     run the constructors in `_dl_start_user'.  */
  __libc_init_first (argc, argv, __environ);
  /* Register the destructor of the program, if any.  */
  if (fini)
        __cxa_atexit ((void (*) (void *)) fini,((void *)0),((void *)0));
  /* Some security at this point.  Prevent starting a SUID binary where
     the standard file descriptors are not opened.  We have to do this
     only for statically linked applications since otherwise the dynamic
     loader did the work already.  */
  if (__builtin_expect (__libc_enable_secure, 0))
        __libc_check_standard_fds ();
  if (init)
        (*init) (argc, argv, __environ );
  _dl_debug_initialize (0, LM_ID_BASE);
  result = main (argc, argv, __environ );
  exit (result);
}

功能为: (摘自http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html)

Takes care of some security problems with setuid setgid programs
Starts up threading
Registers the fini (our program), and rtld_fini (run-time loader) arguments to get run by at_exit to run the program’s and the loader’s cleanup routines
Calls the init argument
Calls the main with the argc and argv arguments passed to it and with the global __environ argument as detailed above.
Calls exit with the return value of main

所以_libc_start_main的执行过程为

    call  __libc_init_first;
    call  __libc_csu_init;
    call main
    call exit
1. 调用__libc_init_first:
void
__libc_init_first (int argc, char **argv, char **envp)
{
#ifdef USE_NONOPTION_FLAGS
  extern void __getopt_clean_environment (char **);
#endif

  __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;

  /* Make sure we don't initialize twice.  */
  if (!__libc_multiple_libcs)
    {
      /* Set the FPU control word to the proper default value if the
     kernel would use a different value.  */
      if (__fpu_control != GLRO(dl_fpu_control))
    __setfpucw (__fpu_control);
    }

  /* Save the command-line arguments.  */
  __libc_argc = argc;
  __libc_argv = argv;
  __environ = envp;

#ifndef SHARED
  __libc_init_secure ();

  /* First the initialization which normally would be done by the
     dynamic linker.  */
  _dl_non_dynamic_init ();
#endif

#ifdef VDSO_SETUP
  VDSO_SETUP ();
#endif

  __init_misc (argc, argv, envp);

#ifdef USE_NONOPTION_FLAGS
  /* This is a hack to make the special getopt in GNU libc working.  */
  __getopt_clean_environment (envp);
#endif

  /* Initialize ctype data.  */
  __ctype_init ();

}

调用_libc_init_first的作用为?待研究


2. 调用__libc_csu_init:
void __libc_csu_init (int argc, char **argv, char **envp)
{
    /*
    *这只是静态可执行文件中,但是动态可执行文件中__preinit_不是在此时执行  
    *经过gdb的运行验证 preinit是在动态链接时执行的  早于_start 
    */
#ifndef LIBC_NONSHARED
  /* For static executables, preinit happens right before init.  */
  {
    const size_t size = __preinit_array_end - __preinit_array_start;
    size_t i;
    for (i = 0; i < size; i++)
      (*__preinit_array_start [i]) (argc, argv, envp);
  }
#endif
  _init ();
  const size_t size = __init_array_end - __init_array_start;
  for (size_t i = 0; i < size; i++)
      (*__init_array_start [i]) (argc, argv, envp);
}

08048530 <__libc_csu_init>:
 8048530:   55                      push   %ebp
 8048531:   57                      push   %edi
 8048532:   31 ff                   xor    %edi,%edi
 8048534:   56                      push   %esi
 8048535:   53                      push   %ebx
 8048536:   e8 65 fe ff ff          call   80483a0 <__x86.get_pc_thunk.bx>
 804853b:   81 c3 c5 1a 00 00       add    $0x1ac5,%ebx        //ebx存储着.got段的地址
 8048541:   83 ec 0c                sub    $0xc,%esp       
 8048544:   8b 6c 24 20             mov    0x20(%esp),%ebp
 8048548:   8d b3 f4 fe ff ff       lea    -0x10c(%ebx),%esi    //esi存储着.fini_array的地址 __init_array_end
 804854e:   e8 a1 fd ff ff          call   80482f4 <_init>
 8048553:   8d 83 e8 fe ff ff       lea    -0x118(%ebx),%eax    //%eax中存储着.init_array的地址 __init_array_start
 8048559:   29 c6                   sub    %eax,%esi
 804855b:   c1 fe 02                sar    $0x2,%esi       //esi 存储着init_array的大小
 804855e:   85 f6                   test   %esi,%esi
 8048560:   74 23                   je     8048585 <__libc_csu_init+0x55>
 8048562:   8d b6 00 00 00 00       lea    0x0(%esi),%esi
 8048568:   83 ec 04                sub    $0x4,%esp
 804856b:   ff 74 24 2c             pushl  0x2c(%esp)
 804856f:   ff 74 24 2c             pushl  0x2c(%esp)
 8048573:   55                      push   %ebp
 8048574:   ff 94 bb e8 fe ff ff    call   *-0x118(%ebx,%edi,4)
 804857b:   83 c7 01                add    $0x1,%edi
 804857e:   83 c4 10                add    $0x10,%esp
 8048581:   39 f7                   cmp    %esi,%edi
 8048583:   75 e3                   jne    8048568 <__libc_csu_init+0x38>
 8048585:   83 c4 0c                add    $0xc,%esp
 8048588:   5b                      pop    %ebx
 8048589:   5e                      pop    %esi
 804858a:   5f                      pop    %edi
 804858b:   5d                      pop    %ebp
 804858c:   c3                      ret    
 804858d:   8d 76 00                lea    0x0(%esi),%esi

Contents of section .preinit_array:
 8049ee4 6b840408(preinit地址)                             k...            
Contents of section .init_array: 
 8049ee8 40840408(frame_dummy) 84840408(construct ) 9d840408(init_array)           @...........    

__libc_csu_init先后执行_init和__init_array中定义的函数
此处__init_array_start为.init_array段的开始位置__init_array_end为.fini_array的开始地址
所以__libc_cus_init相当于执行了

    call  _init
    call frame_dummy  //?作用待研究
    call construct 
    call init_array (可以定义多个)
    (相当于执行了在.init_array储存的函数指针)
1. 调用_init:
Disassembly of section .init:

080482f4 <_init>:
 80482f4:   53                      push   %ebx
 80482f5:   83 ec 08                sub    $0x8,%esp
 80482f8:   e8 a3 00 00 00          call   80483a0 <__x86.get_pc_thunk.bx>
 80482fd:   81 c3 03 1d 00 00       add    $0x1d03,%ebx
 8048303:   8b 83 fc ff ff ff       mov    -0x4(%ebx),%eax
 8048309:   85 c0                   test   %eax,%eax
 804830b:   74 05                   je     8048312 <_init+0x1e>
 804830d:   e8 3e 00 00 00          call   8048350 <__gmon_start__@plt>
 8048312:   83 c4 08                add    $0x8,%esp
 8048315:   5b                      pop    %ebx
 8048316:   c3                      ret    

gmon_start:用于辅助gprof分析程序所用的 一般不会执行(除非gcc编译时 开启-pg选项) 关于其的介绍可以参考http://www.cnblogs.com/lenolix/archive/2010/12/13/1904868.html

void
__gmon_start__ (void)
{
  /* Protect from being called more than once.  Since crti.o is linked
     into every shared library, each of their init functions will call us.  */
  static int called;

  if (called)
    return;

  called = 1;

  /* Start keeping profiling records.  */
  __monstartup ((u_long) TEXT_START, (u_long) &etext);

  /* Call _mcleanup before exiting; it will write out gmon.out from the
     collected data.  */
  atexit (&_mcleanup);
}
调用.init_array段中函数
  1. frame_dummy:
08048440 <frame_dummy>:
 8048440:   b8 00 9f 04 08          mov    $0x8049f00,%eax  //.jcr段的数据
 8048445:   8b 10                   mov    (%eax),%edx
 8048447:   85 d2                   test   %edx,%edx
 8048449:   75 05                   jne    8048450 <frame_dummy+0x10>
 804844b:   eb 93                   jmp    80483e0 <register_tm_clones>
 804844d:   8d 76 00                lea    0x0(%esi),%esi
 8048450:   ba 00 00 00 00          mov    $0x0,%edx
 8048455:   85 d2                   test   %edx,%edx
 8048457:   74 f2                   je     804844b <frame_dummy+0xb>
 8048459:   55                      push   %ebp
 804845a:   89 e5                   mov    %esp,%ebp
 804845c:   83 ec 14                sub    $0x14,%esp
 804845f:   50                      push   %eax
 8048460:   ff d2                   call   *%edx
 8048462:   83 c4 10                add    $0x10,%esp
 8048465:   c9                      leave  
 8048466:   e9 75 ff ff ff          jmp    80483e0 <register_tm_clones>

由汇编代码分析有:其作用在于检查是否.jcr段中的数据为0 为0 则直接跳入register_tm_clones; 不为0则陷入死循环?

register_tm_clones:

080483e0 <register_tm_clones>:
 80483e0:   b8 24 a0 04 08          mov    $0x804a024,%eax
 80483e5:   2d 24 a0 04 08          sub    $0x804a024,%eax
 80483ea:   c1 f8 02                sar    $0x2,%eax
 80483ed:   89 c2                   mov    %eax,%edx
 80483ef:   c1 ea 1f                shr    $0x1f,%edx
 80483f2:   01 d0                   add    %edx,%eax
 80483f4:   d1 f8                   sar    %eax
 80483f6:   74 1b                   je     8048413 <register_tm_clones+0x33>
 80483f8:   ba 00 00 00 00          mov    $0x0,%edx
 80483fd:   85 d2                   test   %edx,%edx
 80483ff:   74 12                   je     8048413 <register_tm_clones+0x33>
 8048401:   55                      push   %ebp
 8048402:   89 e5                   mov    %esp,%ebp
 8048404:   83 ec 10                sub    $0x10,%esp
 8048407:   50                      push   %eax
 8048408:   68 24 a0 04 08          push   $0x804a024
 804840d:   ff d2                   call   *%edx
 804840f:   83 c4 10                add    $0x10,%esp
 8048412:   c9                      leave  
 8048413:   f3 c3                   repz ret 
 8048415:   8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
 8048419:   8d bc 27 00 00 00 00    lea    0x0(%edi,%eiz,1),%edi

作用为:?


3.调用main函数

返回值赋予result 作为exit的参数


4.调用exit函数

void
exit (int status)
{
  __run_exit_handlers (status, &__exit_funcs, true);
}
libc_hidden_def (exit)

0002edd0 <exit>:
   2edd0:   53                      push   %ebx
   2edd1:   e8 0f 43 0f 00          call   1230e5 <__frame_state_for+0x375>
   2edd6:   81 c3 2a 82 18 00       add    $0x18822a,%ebx
   2eddc:   83 ec 0c                sub    $0xc,%esp
   2eddf:   8d 83 1c 04 00 00       lea    0x41c(%ebx),%eax
   2ede5:   6a 01                   push   $0x1
   2ede7:   50                      push   %eax
   2ede8:   ff 74 24 1c             pushl  0x1c(%esp)
   2edec:   e8 bf fe ff ff          call   2ecb0 <__libc_secure_getenv+0x30>
   2edf1:   66 90                   xchg   %ax,%ax
   2edf3:   66 90                   xchg   %ax,%ax
   2edf5:   66 90                   xchg   %ax,%ax
   2edf7:   66 90                   xchg   %ax,%ax
   2edf9:   66 90                   xchg   %ax,%ax
   2edfb:   66 90                   xchg   %ax,%ax
   2edfd:   66 90                   xchg   %ax,%ax
   2edff:   90                      nop


/* Call all functions registered with `atexit' and `on_exit',
   in the reverse of the order in which they were registered
   perform stdio cleanup, and terminate program execution with STATUS.  */
void
attribute_hidden
__run_exit_handlers (int status, struct exit_function_list **listp,
             bool run_list_atexit)
{
  /* First, call the TLS destructors.  */
#ifndef SHARED
  if (&__call_tls_dtors != NULL)
#endif
    __call_tls_dtors ();

  /* We do it this way to handle recursive calls to exit () made by
     the functions registered with `atexit' and `on_exit'. We call
     everyone on the list and use the status value in the last
     exit (). */
  while (*listp != NULL)
    {
      struct exit_function_list *cur = *listp;

      while (cur->idx > 0)
    {
      const struct exit_function *const f =
        &cur->fns[--cur->idx];
      switch (f->flavor)
        {
          void (*atfct) (void);
          void (*onfct) (int status, void *arg);
          void (*cxafct) (void *arg, int status);

        case ef_free:
        case ef_us:
          break;
        case ef_on:
          onfct = f->func.on.fn;
#ifdef PTR_DEMANGLE
          PTR_DEMANGLE (onfct);
#endif
          onfct (status, f->func.on.arg);
          break;
        case ef_at:
          atfct = f->func.at;
#ifdef PTR_DEMANGLE
          PTR_DEMANGLE (atfct);
#endif
          atfct ();
          break;
        case ef_cxa:
          cxafct = f->func.cxa.fn;
#ifdef PTR_DEMANGLE
          PTR_DEMANGLE (cxafct);
#endif
          cxafct (f->func.cxa.arg, status);
          break;
        }
    }

      *listp = cur->next;
      if (*listp != NULL)
    /* Don't free the last element in the chain, this is the statically
       allocate element.  */
    free (cur);
    }

  if (run_list_atexit)
    RUN_HOOK (__libc_atexit, ());

  _exit (status);
}

__run_exit_handlers的汇编代码:
   2ecb1:   57                      push   %edi
   2ecb2:   56                      push   %esi
   2ecb3:   53                      push   %ebx
   2ecb4:   e8 2c 44 0f 00          call   1230e5 <__frame_state_for+0x375>
   2ecb9:   81 c3 47 83 18 00       add    $0x188347,%ebx
   2ecbf:   83 ec 1c                sub    $0x1c,%esp
   2ecc2:   8b 44 24 38             mov    0x38(%esp),%eax
   2ecc6:   8b 74 24 30             mov    0x30(%esp),%esi
   2ecca:   8b 7c 24 34             mov    0x34(%esp),%edi
   2ecce:   89 44 24 0c             mov    %eax,0xc(%esp)
   2ecd2:   e8 39 06 00 00          call   2f310 <__call_tls_dtors>
   2ecd7:   8b 2f                   mov    (%edi),%ebp
   2ecd9:   85 ed                   test   %ebp,%ebp
   2ecdb:   74 42                   je     2ed1f <__libc_secure_getenv+0x9f>
   2ecdd:   8d 76 00                lea    0x0(%esi),%esi
   2ece0:   8b 45 04                mov    0x4(%ebp),%eax           //从此处开始while 循环
   2ece3:   89 c2                   mov    %eax,%edx
   2ece5:   c1 e2 04                shl    $0x4,%edx
   2ece8:   85 c0                   test   %eax,%eax
   2ecea:   8d 4c 15 f8             lea    -0x8(%ebp,%edx,1),%ecx
   2ecee:   74 22                   je     2ed12 <__libc_secure_getenv+0x92>
   2ecf0:   8b 11                   mov    (%ecx),%edx
   2ecf2:   83 e8 01                sub    $0x1,%eax
   2ecf5:   89 45 04                mov    %eax,0x4(%ebp)
   2ecf8:   83 fa 03                cmp    $0x3,%edx
   2ecfb:   0f 84 9f 00 00 00       je     2eda0 <__libc_secure_getenv+0x120>
   2ed01:   83 fa 04                cmp    $0x4,%edx
   2ed04:   74 72                   je     2ed78 <__libc_secure_getenv+0xf8>
   2ed06:   83 fa 02                cmp    $0x2,%edx
   2ed09:   74 45                   je     2ed50 <__libc_secure_getenv+0xd0>
   2ed0b:   83 e9 10                sub    $0x10,%ecx
   2ed0e:   85 c0                   test   %eax,%eax
   2ed10:   75 de                   jne    2ecf0 <__libc_secure_getenv+0x70>
   2ed12:   8b 45 00                mov    0x0(%ebp),%eax
   2ed15:   85 c0                   test   %eax,%eax
   2ed17:   89 07                   mov    %eax,(%edi)
   2ed19:   0f 85 99 00 00 00       jne    2edb8 <__libc_secure_getenv+0x138>
   2ed1f:   80 7c 24 0c 00          cmpb   $0x0,0xc(%esp)
   2ed24:   74 19                   je     2ed3f <__libc_secure_getenv+0xbf>    //此处结束
   2ed26:   8d bb ac df ff ff       lea    -0x2054(%ebx),%edi
   2ed2c:   8d ab b0 df ff ff       lea    -0x2050(%ebx),%ebp
   2ed32:   39 ef                   cmp    %ebp,%edi
   2ed34:   73 09                   jae    2ed3f <__libc_secure_getenv+0xbf>
   2ed36:   ff 17                   call   *(%edi)
   2ed38:   83 c7 04                add    $0x4,%edi
   2ed3b:   39 ef                   cmp    %ebp,%edi
   2ed3d:   72 f7                   jb     2ed36 <__libc_secure_getenv+0xb6>
   2ed3f:   83 ec 0c                sub    $0xc,%esp
   2ed42:   56                      push   %esi
   2ed43:   e8 2c 4f 08 00          call   b3c74 <_exit>
   2ed48:   90                      nop
   2ed49:   8d b4 26 00 00 00 00    lea    0x0(%esi,%eiz,1),%esi
   2ed50:   c1 e0 04                shl    $0x4,%eax
   2ed53:   83 ec 08                sub    $0x8,%esp
   2ed56:   01 e8                   add    %ebp,%eax
   2ed58:   8b 50 0c                mov    0xc(%eax),%edx
   2ed5b:   ff 70 10                pushl  0x10(%eax)
   2ed5e:   56                      push   %esi
   2ed5f:   c1 ca 09                ror    $0x9,%edx
   2ed62:   65 33 15 18 00 00 00    xor    %gs:0x18,%edx
   2ed69:   ff d2                   call   *%edx
   2ed6b:   83 c4 10                add    $0x10,%esp
   2ed6e:   e9 6d ff ff ff          jmp    2ece0 <__libc_secure_getenv+0x60>
   2ed73:   90                      nop
   2ed74:   8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
   2ed78:   c1 e0 04                shl    $0x4,%eax
   2ed7b:   83 ec 08                sub    $0x8,%esp
   2ed7e:   01 e8                   add    %ebp,%eax
   2ed80:   8b 50 0c                mov    0xc(%eax),%edx
   2ed83:   56                      push   %esi
   2ed84:   ff 70 10                pushl  0x10(%eax)
   2ed87:   c1 ca 09                ror    $0x9,%edx
   2ed8a:   65 33 15 18 00 00 00    xor    %gs:0x18,%edx
   2ed91:   ff d2                   call   *%edx
   2ed93:   83 c4 10                add    $0x10,%esp
   2ed96:   e9 45 ff ff ff          jmp    2ece0 <__libc_secure_getenv+0x60>
   2ed9b:   90                      nop
   2ed9c:   8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
   2eda0:   c1 e0 04                shl    $0x4,%eax
   2eda3:   8b 44 05 0c             mov    0xc(%ebp,%eax,1),%eax
   2eda7:   c1 c8 09                ror    $0x9,%eax
   2edaa:   65 33 05 18 00 00 00    xor    %gs:0x18,%eax
   2edb1:   ff d0                   call   *%eax
   2edb3:   e9 28 ff ff ff          jmp    2ece0 <__libc_secure_getenv+0x60>
   2edb8:   83 ec 0c                sub    $0xc,%esp
   2edbb:   55                      push   %ebp
   2edbc:   e8 1f 87 fe ff          call   174e0 <free@plt>
   2edc1:   83 c4 10                add    $0x10,%esp
   2edc4:   e9 0e ff ff ff          jmp    2ecd7 <__libc_secure_getenv+0x57>
   2edc9:   8d b4 26 00 00 00 00    lea    0x0(%esi,%eiz,1),%esi


/* Call the destructors.  This is called either when a thread returns from the
   initial function or when the process exits via the exit function.  */
void
__call_tls_dtors (void)
{
  while (tls_dtor_list)
    {
      struct dtor_list *cur = tls_dtor_list;
      dtor_func func = cur->func;
#ifdef PTR_DEMANGLE
      PTR_DEMANGLE (func);
#endif

      tls_dtor_list = tls_dtor_list->next;
      func (cur->obj);

      /* Ensure that the MAP dereference happens before
     l_tls_dtor_count decrement.  That way, we protect this access from a
     potential DSO unload in _dl_close_worker, which happens when
     l_tls_dtor_count is 0.  See CONCURRENCY NOTES for more detail.  */
      atomic_fetch_add_release (&cur->map->l_tls_dtor_count, -1);
      free (cur);
    }
}
libc_hidden_def (__call_tls_dtors)

__call_tls_dtors 的汇编代码:
   2f310:   55                      push   %ebp
   2f311:   57                      push   %edi
   2f312:   8d 3d 20 00 00 00       lea    0x20,%edi
   2f318:   56                      push   %esi
   2f319:   53                      push   %ebx
   2f31a:   e8 c6 3d 0f 00          call   1230e5 <__frame_state_for+0x375>
   2f31f:   81 c3 e1 7c 18 00       add    $0x187ce1,%ebx
   2f325:   83 ec 0c                sub    $0xc,%esp
   2f328:   8d 83 7c fe ff ff       lea    -0x184(%ebx),%eax
   2f32e:   e8 9d 81 fe ff          call   174d0 <___tls_get_addr@plt>
   2f333:   8b 34 07                mov    (%edi,%eax,1),%esi
   2f336:   8b 83 b0 fe ff ff       mov    -0x150(%ebx),%eax
   2f33c:   85 f6                   test   %esi,%esi
   2f33e:   8d a8 c4 04 00 00       lea    0x4c4(%eax),%ebp
   2f344:   75 37                   jne    2f37d <__call_tls_dtors+0x6d>
   2f346:   e9 95 00 00 00          jmp    2f3e0 <__call_tls_dtors+0xd0>
   2f34b:   90                      nop
   2f34c:   8d 74 26 00             lea    0x0(%esi,%eiz,1),%esi
   2f350:   83 ec 0c                sub    $0xc,%esp
   2f353:   8b 83 b0 fe ff ff       mov    -0x150(%ebx),%eax
   2f359:   55                      push   %ebp
   2f35a:   ff 90 fc 07 00 00       call   *0x7fc(%eax)
   2f360:   89 34 24                mov    %esi,(%esp)
   2f363:   e8 78 81 fe ff          call   174e0 <free@plt>
   2f368:   8d 83 7c fe ff ff       lea    -0x184(%ebx),%eax
   2f36e:   e8 5d 81 fe ff          call   174d0 <___tls_get_addr@plt>
   2f373:   83 c4 10                add    $0x10,%esp
   2f376:   8b 34 07                mov    (%edi,%eax,1),%esi
   2f379:   85 f6                   test   %esi,%esi
   2f37b:   74 63                   je     2f3e0 <__call_tls_dtors+0xd0>
   2f37d:   8d 83 7c fe ff ff       lea    -0x184(%ebx),%eax
   2f383:   e8 48 81 fe ff          call   174d0 <___tls_get_addr@plt>
   2f388:   8b 56 0c                mov    0xc(%esi),%edx
   2f38b:   83 ec 0c                sub    $0xc,%esp
   2f38e:   89 14 07                mov    %edx,(%edi,%eax,1)
   2f391:   ff 76 04                pushl  0x4(%esi)
   2f394:   ff 16                   call   *(%esi)
   2f396:   8b 83 b0 fe ff ff       mov    -0x150(%ebx),%eax
   2f39c:   89 2c 24                mov    %ebp,(%esp)
   2f39f:   ff 90 f8 07 00 00       call   *0x7f8(%eax)
   2f3a5:   8b 56 08                mov    0x8(%esi),%edx
   2f3a8:   83 c4 10                add    $0x10,%esp
   2f3ab:   8b 82 48 02 00 00       mov    0x248(%edx),%eax
   2f3b1:   83 e8 01                sub    $0x1,%eax
   2f3b4:   85 c0                   test   %eax,%eax
   2f3b6:   89 82 48 02 00 00       mov    %eax,0x248(%edx)
   2f3bc:   75 92                   jne    2f350 <__call_tls_dtors+0x40>
   2f3be:   0f b6 82 94 01 00 00    movzbl 0x194(%edx),%eax
   2f3c5:   83 e0 03                and    $0x3,%eax
   2f3c8:   3c 02                   cmp    $0x2,%al
   2f3ca:   75 84                   jne    2f350 <__call_tls_dtors+0x40>
   2f3cc:   83 a2 04 02 00 00 f7    andl   $0xfffffff7,0x204(%edx)
   2f3d3:   e9 78 ff ff ff          jmp    2f350 <__call_tls_dtors+0x40>
   2f3d8:   90                      nop
   2f3d9:   8d b4 26 00 00 00 00    lea    0x0(%esi,%eiz,1),%esi
   2f3e0:   83 c4 0c                add    $0xc,%esp
   2f3e3:   5b                      pop    %ebx
   2f3e4:   5e                      pop    %esi
   2f3e5:   5f                      pop    %edi
   2f3e6:   5d                      pop    %ebp
   2f3e7:   c3                      ret    
   2f3e8:   66 90                   xchg   %ax,%ax
   2f3ea:   66 90                   xchg   %ax,%ax
   2f3ec:   66 90                   xchg   %ax,%ax
   2f3ee:   66 90                   xchg   %ax,%ax

/* The function `_exit' should take a status argument and simply
   terminate program execution, using the low-order 8 bits of the
   given integer as status.  */
void
_exit (int status)
{
  status &= 0xff;
  abort ();
}
libc_hidden_def (_exit)

根据gdb的运行结果分析

while循环中首先调用的是atexit中注册的函数 然后是一个函数调用了ldlinuxso.txt(objdump -d ld-linux.so得到的文件)在17171-17448的指令
然后在循环中按照在.fini_array段中由后向前的顺序执行fini_array和destruct,__do_global_dtors_aux

 Contents of section .fini_array:
 8049ef4 20840408(__do_global_dtors_aux) cf840408(destruct1) e8840408(fini_array)

之后位于ld-linux.so中的指令执行了_fini
返回__run_exit_handlers 调用_exit

    f370:   8b 45 e0                mov    -0x20(%ebp),%eax
    f373:   8b 4d e4                mov    -0x1c(%ebp),%ecx
    f376:   8b 34 88                mov    (%eax,%ecx,4),%esi
    f379:   0f b6 86 94 01 00 00    movzbl 0x194(%esi),%eax
    f380:   a8 08                   test   $0x8,%al
    f382:   0f 84 80 00 00 00       je     f408 <_dl_rtld_di_serinfo+0x6c68>
    f388:   83 e0 f7                and    $0xfffffff7,%eax
    f38b:   88 86 94 01 00 00       mov    %al,0x194(%esi)
    f391:   8b 86 88 00 00 00       mov    0x88(%esi),%eax
    f397:   85 c0                   test   %eax,%eax
    f399:   0f 84 e1 00 00 00       je     f480 <_dl_rtld_di_serinfo+0x6ce0>
    f39f:   f6 83 00 fd ff ff 02    testb  $0x2,-0x300(%ebx)
    f3a6:   0f 85 f4 00 00 00       jne    f4a0 <_dl_rtld_di_serinfo+0x6d00>
    f3ac:   8b 3e                   mov    (%esi),%edi
    f3ae:   03 78 04                add    0x4(%eax),%edi
    f3b1:   8b 86 90 00 00 00       mov    0x90(%esi),%eax
    f3b7:   8b 40 04                mov    0x4(%eax),%eax
    f3ba:   89 f9                   mov    %edi,%ecx
    f3bc:   c1 e8 02                shr    $0x2,%eax
    f3bf:   85 c0                   test   %eax,%eax
    f3c1:   74 19                   je     f3dc <_dl_rtld_di_serinfo+0x6c3c>
    f3c3:   89 75 d8                mov    %esi,-0x28(%ebp)
    f3c6:   89 cf                   mov    %ecx,%edi
    f3c8:   89 c6                   mov    %eax,%esi
 >   f3ca:  8d b6 00 00 00 00       lea    0x0(%esi),%esi  //入口地址 从函数跳入存储
    f3d0:   ff 54 b7 fc             call   *-0x4(%edi,%esi,4)
    f3d4:   83 ee 01                sub    $0x1,%esi
    f3d7:   75 f7                   jne    f3d0 <_dl_rtld_di_serinfo+0x6c30>  //这个循环逆序执行了.fini_array中存储的函数地址 
    f3d9:   8b 75 d8                mov    -0x28(%ebp),%esi
    f3dc:   8b 56 54                mov    0x54(%esi),%edx
    f3df:   85 d2                   test   %edx,%edx
    f3e1:   74 07                   je     f3ea <_dl_rtld_di_serinfo+0x6c4a>
    f3e3:   8b 06                   mov    (%esi),%eax
    f3e5:   03 42 04                add    0x4(%edx),%eax
    f3e8:   ff d0                   call   *%eax
    f3ea:   8b 7d d4                mov    -0x2c(%ebp),%edi
    f3ed:   85 ff                   test   %edi,%edi
    f3ef:   75 17                   jne    f408 <_dl_rtld_di_serinfo+0x6c68>
    f3f1:   8b 8b c8 fe ff ff       mov    -0x138(%ebx),%ecx
    f3f7:   8d 05 00 fd ff ff       lea    0xfffffd00,%eax
    f3fd:   89 45 d8                mov    %eax,-0x28(%ebp)
    f400:   85 c9                   test   %ecx,%ecx
    f402:   0f 85 d8 00 00 00       jne    f4e0 <_dl_rtld_di_serinfo+0x6d40>
    f408:   83 45 e4 01             addl   $0x1,-0x1c(%ebp)
    f40c:   83 ae 90 01 00 00 01    subl   $0x1,0x190(%esi)
    f413:   8b 45 e4                mov    -0x1c(%ebp),%eax
    f416:   3b 45 dc                cmp    -0x24(%ebp),%eax
    f419:   0f 85 51 ff ff ff       jne    f370 <_dl_rtld_di_serinfo+0x6bd0>
    f41f:   83 6d d0 01             subl   $0x1,-0x30(%ebp)
    f423:   83 6d c4 4c             subl   $0x4c,-0x3c(%ebp)
    f427:   8b 45 d0                mov    -0x30(%ebp),%eax
    f42a:   83 f8 ff                cmp    $0xffffffff,%eax
    f42d:   0f 85 3d fe ff ff       jne    f270 <_dl_rtld_di_serinfo+0x6ad0>
    f433:   8b 55 d4                mov    -0x2c(%ebp),%edx
    f436:   85 d2                   test   %edx,%edx
    f438:   75 2a                   jne    f464 <_dl_rtld_di_serinfo+0x6cc4>
    f43a:   8b 83 c8 fe ff ff       mov    -0x138(%ebx),%eax
    f440:   85 c0                   test   %eax,%eax
    f442:   74 20                   je     f464 <_dl_rtld_di_serinfo+0x6cc4>
    f444:   8b 45 c8                mov    -0x38(%ebp),%eax
    f447:   c7 45 d4 01 00 00 00    movl   $0x1,-0x2c(%ebp)
    f44e:   8b 84 18 c0 04 00 00    mov    0x4c0(%eax,%ebx,1),%eax
    f455:   89 45 e4                mov    %eax,-0x1c(%ebp)
    f458:   83 e8 01                sub    $0x1,%eax
    f45b:   89 45 d0                mov    %eax,-0x30(%ebp)
    f45e:   0f 89 cb fd ff ff       jns    f22f <_dl_rtld_di_serinfo+0x6a8f>
    f464:   f6 83 00 fd ff ff 80    testb  $0x80,-0x300(%ebx)
    f46b:   0f 85 13 01 00 00       jne    f584 <_dl_rtld_di_serinfo+0x6de4>
    f471:   8d 65 f4                lea    -0xc(%ebp),%esp
    f474:   5b                      pop    %ebx
    f475:   5e                      pop    %esi
    f476:   5f                      pop    %edi
    f477:   5d                      pop    %ebp
    f478:   c3                      ret    

__libc_csu_fini : 已经不再使用

/* This function should not be used anymore.  We run the executable's
   destructor now just like any other.  We cannot remove the function,
   though.  */
void
__libc_csu_fini (void)
{
  size_t i = __fini_array_end - __fini_array_start;
  while (i-- > 0)
    (*__fini_array_start [i]) ();
  _fini ();
}

参考:
1. how linux Program Startup

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值