zoukankan      html  css  js  c++  java
  • 内核设计作业七

    可执行程序的装载

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

    实验部分

    • 重新克隆一个menu

    • 修改Makefile文件并make rootfs

    • 开始gdb跟踪,加载符号表和输入端口号

    • 设置断点

    • 跟踪调试

    总结部分

    预处理、编译、链接和目标文件格式

    1、可执行文件是怎么得来的

    (以C语言代码为例)

    编译器预处理(.c)——>编程汇编代码——>(.asm)——>(汇编器)编译成目标代码(.o)——>链接成可执行文件(a.out)

    shiyanlou:~/ $ cd Code                                                
    shiyanlou:Code/ $ vi hello.c                                          
    shiyanlou:Code/ $ gcc -E -o hello.cpp hello.c -m32 //预处理           
    shiyanlou:Code/ $ vi hello.cpp  //替换宏定义                           
    shiyanlou:Code/ $ gcc -x cpp-output -S -o hello.s hello.cpp -m32 //编译成汇编代码     
    shiyanlou:Code/ $ vi hello.s                                          
    shiyanlou:Code/ $ gcc -x assembler -c hello.s -o hello.o -m32         
    shiyanlou:Code/ $ vi hello.o  //链接成一个可执行文件                                         
    shiyanlou:Code/ $ gcc -o hello hello.o -m32                           
    shiyanlou:Code/ $ vi hello  //可执行的二进制文件                                          
    shiyanlou:Code/ $ gcc -o hello.static hello.o -m32 -static      
    shiyanlou:Code/ $ ls -l                                               
    

    可执行文件加载到内存执行

    预处理负责把include的文件包含进来以及宏替换等工作

    2、目标文件的格式ELF

    ABI:应用程序二进制接口

    目标文件适应到某一种CPU体系结构

    ·一个可重定位文件
    ·一个可执行文件
    ·一个共享文件
    

    一个ELF头在文件的开始保存了路线图,描述了该文件的组织情况

    程序头表:告诉系统如何来创建一个进程的内存映象

    section头表:包含了描述文件section的信息

    3、静态链接的ELF可执行文件和进程的地址空间

    可执行文件加载带内存中开始执行的第一行代码

    一般静态链接会将所有的代码都放在一个代码段,动态链接的进程会有多个代码段

    可执行程序、共享库和动态链接

    1、装载可执行程序之前的工作

    • 命令行参数和shell环境,一般我们执行一个程序的Shell环境,我们的实验直接使用execve系统调用。

        •$ ls -l /usr/bin 列出/usr/bin下的目录信息
        •Shell本身不限制命令行参数的个数,命令行参数的个数受限于命令自身
        	•例如,int main(int argc, char *argv[])
        	•又如, int main(int argc, char *argv[], char *envp[])
        •Shell会调用execve将命令行参数和环境参数传递给可执行程序的main函数
        •int execve(const char * filename,char * const argv[ ],char * const envp[ ]);
        •库函数exec*都是execve的封装例程
      

    shell程序——>execve——>sys_execve 然后在初始化新程序堆栈时拷贝进去

    函数先调用参数传递,在系统调用参数传递

    • execve系统调用返回到用户态从哪里开始执行

        通过修改内核堆栈中的EIP值作为新程序的起点
      

    装载时动链接和运行链接应用举例

    动态链接分为可执行程序装载时动态链接和运行时动态链接

    • 准备.so文件

        shlibexample.h (1.3 KB) - Interface of Shared Lib Example
        shlibexample.c (1.2 KB) - Implement of Shared Lib Example
      
    • 编译成libshlibexample.so文件(生成共享库文件)

        1.$ gcc -shared shlibexample.c -o libshlibexample.so -m32
      

    dllibexample.h (1.3 KB) - Interface of Dynamical Loading Lib Example

    dllibexample.c (1.3 KB) - Implement of Dynamical Loading Lib Example

    • 编译成libdllibexample.so文件

        1.$ gcc -shared dllibexample.c -o libdllibexample.so -m32
      
    • 分别以共享库和动态加载共享库的方式使用libshlibexample.so文件和libdllibexample.so文件

        main.c  (1.9 KB) - Main program
      
    • 编译main,注意这里只提供shlibexample的-L(库对应的接口头文件所在目录)和-l(库名,如libshlibexample.so去掉lib和.so的部分),并没有提供dllibexample的相关信息,只是指明了-ldl

    可执行程序的装载

    1、相关关键问题分析

    execve和fork都是特殊一点的系统调用,他们的区别在于

    fork要返回两次,子程序是从ret_from_fork开始执行然后返回用户态
    而execve独特的地方在于:陷入内核态,把当前进程的可执行程序覆盖掉,返回的已经是新的可执行程序
    

    2、sys_execve系统调用处理过程

    ELF可执行文件被默认映射到0x8048000这个地址
    需要动态链接的可执行文件去加载链接器ld
    elf_entry:指向可执行文件里规定的头部(main函数对应的位置);如果是动态链接,就是动态链接器的起点(用户态的起点),将cpu控制权交给ld来加载依赖库并完成动态链接
    start_thread:把我们返回用户态的位置从0x8048000的下一条变成我们规定的entry的位置
    
    • 对于ELF格式的可执行文件fmt->load_ binary(bprm);执行的应该是load_elf_binary其内部是和ELF文件格式解析的部分需要和ELF文件格式标准结合起来阅读

    3、庄生梦蝶

    庄周(调用execve的可执行程序)入睡(调用execve陷入内核)

    醒来(系统调用execve返回用户态)发现自己是蝴蝶(被execve加载的可执行程序)

    4、浅析动态链接的可执行程序的装载

    动态链接库的依赖关系会形成一个图

    可以关注ELF格式中的.interp和.dynamic

    动态链接的过程主要不是内核而是由动态链接器来完成的

  • 相关阅读:
    yolo_to_onnx ValueError: need more tan 1 value to unpack
    yolo_to_onnx killed
    C++ 实现二维矩阵的加减乘等运算
    Leetcode 1013. Partition Array Into Three Parts With Equal Sum
    Leetcode 1014. Best Sightseeing Pair
    Leetcode 121. Best Time to Buy and Sell Stock
    Leetcode 219. Contains Duplicate II
    Leetcode 890. Find and Replace Pattern
    Leetcode 965. Univalued Binary Tree
    Leetcode 700. Search in a Binary Search Tree
  • 原文地址:https://www.cnblogs.com/javajy/p/5361821.html
Copyright © 2011-2022 走看看