zoukankan      html  css  js  c++  java
  • ELF二进制目标文件详解

    以下内容为<<linux内核编程>>笔记

    链接程序

    找出所有引用的外部模块并链接起来,这些外部模块或函数库一般来自于开发者,操作系统和C运行库。

    链接程序取出这些函数库,修订指针位置(重定位),并交叉引用模块中的符号解析,最终产生一个可执行模块。符号可以是全局的也可以是局部的。全局符号可以在模块内部定义,或由另一模块外部引用。

    静态库是在链接时被找到并复制的,而动态库和共享库是在运行时才装载的,并让所有的进程共享。linux提供的系统调用dlopen(),dlsym(),dlclose(),用于加载/打开共享库,查找库中的符号,然后关闭共享库

    ELF二进制目标文件

    可执行ELF目标文件包括:ELF头,程序头表(用于加载的节),第1节,第2节。。。。节头表(可选)

    1.ELF文件头

    typedef struct elf32_hdr{
      unsigned char e_ident[EI_NIDENT]; //标识该文件是否为ELF文件
      Elf32_Half    e_type;  //指定目标文件类型,例如可执行文件,重定位文件,共享的目标文件
      Elf32_Half    e_machine;   //被编译文件所在系统的体系结构
      Elf32_Word    e_version; //目标文件的版本
      Elf32_Addr    e_entry;  /* Entry point */  //程序的起始地址
      Elf32_Off     e_phoff;   //保存程序头表在文件中的偏移量
      Elf32_Off     e_shoff;   //保存节头表在文件中的偏移量
      Elf32_Word    e_flags;   //保存于特定与处理器的标志
      Elf32_Half    e_ehsize;  //字段保存ELF头的大小
      Elf32_Half    e_phentsize;  //保存程序头表中的每一项的大小
      Elf32_Half    e_phnum;  //程序头中表项的个数
      Elf32_Half    e_shentsize;  //节头表中每一项的大小
      Elf32_Half    e_shnum;   //保存节头中项的数量,表明该文件中有多少节
      Elf32_Half    e_shstrndx;  //保存节头中节字符串的索引
    } Elf32_Ehdr;
    

    2 节头表

    typedef struct elf32_shdr {
      Elf32_Word    sh_name;   //包含节名
      Elf32_Word    sh_type;   //包含节的内容
      Elf32_Word    sh_flags;  //各种属性的内容
      Elf32_Addr    sh_addr;   //节在内存映像中的地址 
      Elf32_Off     sh_offset; //保存ELF文件中这一节中初始字节的偏移量
      Elf32_Word    sh_size;   //包含节的大小
      Elf32_Word    sh_link;   //表链接的索引
      Elf32_Word    sh_info;   //包含附加信息
      Elf32_Word    sh_addralign;  //包含地址对其的约束
      Elf32_Word    sh_entsize;  //节中每项的大小
    } Elf32_Shdr;
    

    3 非可执行ELF文件的节

    bss  为初始化的数据
    .data  已初始化的数据
    .hash  符号散列表
    .init   初始化代码
    .symtab 符号表
    .text  可执行的指令
    .plt  过程链接表
    .rodata 只读数据
    .dynamic 动态链接信息
    等等

    4 程序头表

    typedef struct elf64_phdr {
      Elf64_Word p_type;    //描述该段的类型
      Elf64_Word p_flags;   //以p_type而定
      Elf64_Off p_offset;   //该段的开始相对于文件开始的偏移量
      Elf64_Addr p_vaddr;   //段虚拟地址
      Elf64_Addr p_paddr;   //段的虚拟地址  
      Elf64_Xword p_filesz; //文件映像中该段的字节数
      Elf64_Xword p_memsz;  //内存映像中该段的字节数
      Elf64_Xword p_align;  //描述要对齐的段在内存中如何对齐,该值是2的整数次幂        
    } Elf64_Phdr;
    

    通过这些信息,系统函数exec()和链接程序合作,为可执行程序在内存中创建进程映像,该过程如下:
    1. 将可执行文件的段加入内存
    2. 加载所有需要的共享库
    3. 需要时重定向可执行文件及其共享对象
    4. 将控制权交给程序

  • 相关阅读:
    自定义GridView分页控件
    ASP.NET中JSON的序列化和反序列化 C#的JSON数据格式转换方法
    C# 中 Struct 与 Class 的区别,以及两者的适用场合
    IEnumerable
    谈谈C#中的三个关键词new , virtual , override
    常见通信协议
    当base-package="controller.*"时,可见packageSearchPath为"classpath*:controller/*/**/*.class": 当base-package="controller.**"时,可见packageSearchPath为"classpath*:controller/**/**/*.class":
    DO,DTO和VO的使用
    mysql 字符
    mysql sql 分析
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3223835.html
Copyright © 2011-2022 走看看