Linux内核分析

可执行程序,是怎么“动”起来的

2017-04-09  本文已影响55人  athorn

陈松 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000


ldd prints the shared objects (shared libraries) required by each program or shared object specified on the command line.

In the usual case, **ldd **invokes the standard dynamic linker (see ld.so(8)) with the **LD_TRACE_LOADED_OBJECTS **environment variable set to 1. This causes the dynamic linker to inspect the program's dynamic dependencies, and find (according to the rules described in ld.so(8)) and load the objects that satisfy those dependencies. For each dependency, **ldd **displays the location of the matching object and the (hexadecimal) address at which it is loaded. (The linux-vdso and ld-linux shared dependencies are special; see vdso(7) and ld.so(8).)

LD_TRACE_LOADED_OBJECTS If set (to any value), causes the program to list its dynamic dependencies, as if run by ldd(1), instead of running normally.

看看hello的结构:
ELF Header

thorn@ubuntu:~/LinuxKernel/menu$ readelf -h hello
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 03 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - GNU
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x8048736
  Start of program headers:          52 (bytes into file)
  Start of section headers:          724012 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         6
  Size of section headers:           40 (bytes)
  Number of section headers:         31
  Section header string table index: 28

section headers

thorn@ubuntu:~/LinuxKernel/menu$ readelf -S hello
There are 31 section headers, starting at offset 0xb0c2c:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .note.ABI-tag     NOTE            080480f4 0000f4 000020 00   A  0   0  4
  [ 2] .note.gnu.build-i NOTE            08048114 000114 000024 00   A  0   0  4
  [ 3] .rel.plt          REL             08048138 000138 000070 08  AI  0  23  4
  [ 4] .init             PROGBITS        080481a8 0001a8 000023 00  AX  0   0  4
  [ 5] .plt              PROGBITS        080481d0 0001d0 0000e0 00  AX  0   0 16
  [ 6] .text             PROGBITS        080482b0 0002b0 07201c 00  AX  0   0 16
  [ 7] __libc_freeres_fn PROGBITS        080ba2d0 0722d0 000a6d 00  AX  0   0 16
  [ 8] __libc_thread_fre PROGBITS        080bad40 072d40 00009e 00  AX  0   0 16
  [ 9] .fini             PROGBITS        080bade0 072de0 000014 00  AX  0   0  4
  [10] .rodata           PROGBITS        080bae00 072e00 01a88c 00   A  0   0 32
  [11] __libc_subfreeres PROGBITS        080d568c 08d68c 000028 00   A  0   0  4
  [12] __libc_atexit     PROGBITS        080d56b4 08d6b4 000004 00   A  0   0  4
  [13] __libc_thread_sub PROGBITS        080d56b8 08d6b8 000004 00   A  0   0  4
  [14] .eh_frame         PROGBITS        080d56bc 08d6bc 0129d0 00   A  0   0  4
  [15] .gcc_except_table PROGBITS        080e808c 0a008c 0000b1 00   A  0   0  1
  [16] .tdata            PROGBITS        080e9f5c 0a0f5c 000010 00 WAT  0   0  4
  [17] .tbss             NOBITS          080e9f6c 0a0f6c 000018 00 WAT  0   0  4
  [18] .init_array       INIT_ARRAY      080e9f6c 0a0f6c 000008 00  WA  0   0  4
  [19] .fini_array       FINI_ARRAY      080e9f74 0a0f74 000008 00  WA  0   0  4
  [20] .jcr              PROGBITS        080e9f7c 0a0f7c 000004 00  WA  0   0  4
  [21] .data.rel.ro      PROGBITS        080e9f80 0a0f80 000070 00  WA  0   0 32
  [22] .got              PROGBITS        080e9ff0 0a0ff0 000008 04  WA  0   0  4
  [23] .got.plt          PROGBITS        080ea000 0a1000 000044 04  WA  0   0  4
  [24] .data             PROGBITS        080ea060 0a1060 000f20 00  WA  0   0 32
  [25] .bss              NOBITS          080eaf80 0a1f80 000e0c 00  WA  0   0 32
  [26] __libc_freeres_pt NOBITS          080ebd8c 0a1f80 000018 00  WA  0   0  4
  [27] .comment          PROGBITS        00000000 0a1f80 000034 01  MS  0   0  1
  [28] .shstrtab         STRTAB          00000000 0b0ae0 00014c 00      0   0  1
  [29] .symtab           SYMTAB          00000000 0a1fb4 007e50 10     30 848  4
  [30] .strtab           STRTAB          00000000 0a9e04 006cdc 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

当然还有很多其他的如符号表、字符串表等等信息。

开始挖ELF的加载过程,怎么动起来的。
exec代码如下:

int Exec(int argc, char *argv[])
{
        int pid;
        /* fork another process */
        pid = fork();
        if (pid < 0)
        {
                /* error occurred */
                fprintf(stderr,"Fork Failed!");
                exit(-1);
        }
        else if (pid == 0)
        {
                /*       child process  */
        printf("This is Child Process!\n");
                execlp("/hello","hello",NULL);
        }
        else
        {
                /*      parent process   */
        printf("This is Parent Process!\n");
                /* parent will wait for the child to complete*/
                wait(NULL);
                printf("Child Complete!\n");
        }
}

搭建好执行环境:


设置了以下断点:


执行exec,和我们之前的系统调用一样,停在了sys_execve

-- 注:有必要研究下这个系内核的文件系统是怎么实现的,在QEMU下用-initrd roofs.img的原理



真正start的时候,还是在调度的时候,也即是把新的进程准备好,放到调度队列之后。

上一篇下一篇

猜你喜欢

热点阅读