• Linux ELF文件学习


    本文主要通过代码,了解Linux ELF文件的相关知识。

    ELF文件

    ELF(Executable Linkable Format)是Linux平台的可执行文件。

    ELF文件的类型:

    • 可重定位类型

      • 包含代码和数据,用来链接成可执行文件或共享目标文件, linux的.o文件
    • 可执行文件

      • 可以直接执行的程序
    • 共享目标文件

      • .so文件
    • 核心转储文件

      • core dump文件,系统意外时转储文件。

    源码

    SimpleSection.c

    #include <stdio.h>
    #include <stdlib.h>
    
    // 全局变量,data区, 4字节
    int global_int_var = 1;
    // 全局变量,未初始化,bss区, 4字节
    int global_uninit_var;
    
    void func1(int i)
    {
    	// 里面有一个"%d\n"字符串,在rodata区, 共4字节
    	printf("%d\n", i);
    }
    
    int main(void)
    {
    	// 静态变量,data区, 4字节
    	static int static_var = 1;
    	// 静态变量,未初始化,bss区, 4字节 
    	static int static_var2;
    	// 局部变量, 栈区
    	int a = 1;
    	// 局部变量, 栈区
    	int b;
    	// 静态变量,未初始化,64位系统,占用8字节
    	static int *static_ptr = NULL;
    	// 局部变量,栈区
    	int *p;
    	// malloc申请的空间,堆区
    	p = malloc(sizeof(int));
    
    	free(p);
    
    	// 函数调用时,也会进行入栈出栈操作,一些局部变量都需要保存在占中
    	func1(static_var + static_var2 + a + b);
    
    	return 0;
    }
    

    编译文件

    只编译本文件方便分析,不连接其他的库。

    编译使用的是ubuntu64位系统。

    gcc -c SimpleSection.c -o SimpleSection.o

    objdump查看段信息

    objdump -h SimpleSection.o

    #                    文件格式
    SimpleSection.o:     file format elf64-x86-64
                      
    Sections:
    #                 大小      虚拟地址          逻辑地址          文件偏移  段边界对齐字数
    Idx Name          Size      VMA               LMA               File off  Algn
      0 .text         0000007e  0000000000000000  0000000000000000  00000040  2**0
                      CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
      1 .data         00000008  0000000000000000  0000000000000000  000000c0  2**2
                      CONTENTS, ALLOC, LOAD, DATA
      2 .bss          00000010  0000000000000000  0000000000000000  000000c8  2**3
                      ALLOC
      3 .rodata       00000004  0000000000000000  0000000000000000  000000c8  2**0
                      CONTENTS, ALLOC, LOAD, READONLY, DATA
      4 .comment      00000027  0000000000000000  0000000000000000  000000cc  2**0
                      CONTENTS, READONLY
      5 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000f3  2**0
                      CONTENTS, READONLY
      6 .note.gnu.property 00000020  0000000000000000  0000000000000000  000000f8  2**3
                      CONTENTS, ALLOC, LOAD, READONLY, DATA
      7 .eh_frame     00000058  0000000000000000  0000000000000000  00000118  2**3
                      CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
    
    

    查看elf文件头

    readelf -h SimpleSection.o

    ELF Header:
    # elf魔数
      Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
      Class:                             ELF64
      Data:                              2's complement, little endian
      Version:                           1 (current)
      OS/ABI:                            UNIX - System V
      ABI Version:                       0
    # 文件类型
      Type:                              REL (Relocatable file)
      Machine:                           Advanced Micro Devices X86-64
      Version:                           0x1
      Entry point address:               0x0
      Start of program headers:          0 (bytes into file)
      Start of section headers:          1208 (bytes into file)
      Flags:                             0x0
    # 文件头的大小
      Size of this header:               64 (bytes)
      Size of program headers:           0 (bytes)
      Number of program headers:         0
      Size of section headers:           64 (bytes)
    # 段表成员个数
      Number of section headers:         14
      Section header string table index: 13
    

    查看elf段表

    段表在ELF文件中位置有ELF文件头的"e_shoff"成员决定。

    ELF文件的段结构就是由段表决定,编译器、链接器和装载器都是通过段表来定位和访问各个端的属性。

    readelf -S SimpleSection.o

    There are 14 section headers, starting at offset 0x4b8:
    
    Section Headers:
      [Nr] Name              Type             Address           Offset
           Size              EntSize          Flags  Link  Info  Align
      [ 0]                   NULL             0000000000000000  00000000
           0000000000000000  0000000000000000           0     0     0
      [ 1] .text             PROGBITS         0000000000000000  00000040
           000000000000007e  0000000000000000  AX       0     0     1
      [ 2] .rela.text        RELA             0000000000000000  00000368
           00000000000000a8  0000000000000018   I      11     1     8
      [ 3] .data             PROGBITS         0000000000000000  000000c0
           0000000000000008  0000000000000000  WA       0     0     4
      [ 4] .bss              NOBITS           0000000000000000  000000c8
           0000000000000010  0000000000000000  WA       0     0     8
      [ 5] .rodata           PROGBITS         0000000000000000  000000c8
           0000000000000004  0000000000000000   A       0     0     1
      [ 6] .comment          PROGBITS         0000000000000000  000000cc
           0000000000000027  0000000000000001  MS       0     0     1
      [ 7] .note.GNU-stack   PROGBITS         0000000000000000  000000f3
           0000000000000000  0000000000000000           0     0     1
      [ 8] .note.gnu.pr[...] NOTE             0000000000000000  000000f8
           0000000000000020  0000000000000000   A       0     0     8
      [ 9] .eh_frame         PROGBITS         0000000000000000  00000118
           0000000000000058  0000000000000000   A       0     0     8
      [10] .rela.eh_frame    RELA             0000000000000000  00000410
           0000000000000030  0000000000000018   I      11     9     8
      [11] .symtab           SYMTAB           0000000000000000  00000170
           0000000000000180  0000000000000018          12     9     8
      [12] .strtab           STRTAB           0000000000000000  000002f0
           0000000000000078  0000000000000000           0     0     1
      [13] .shstrtab         STRTAB           0000000000000000  00000440
           0000000000000074  0000000000000000           0     0     1
    Key to Flags:
      W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
      L (link order), O (extra OS processing required), G (group), T (TLS),
      C (compressed), x (unknown), o (OS specific), E (exclude),
      D (mbind), l (large), p (processor specific)
    

    重定位表

    有一个".rel.text"段,链接器在处理目标文件时,需要对目标文件中某些部位进行重定位,即代码段和数据段中那些对绝对地址的引用位置。

    自定义段

    通过attribute((section("name")))把变量或者函数放到以"name"作为段名的段中。

    __attribute__((section(".var_section"))) 
    int var_test;
    
    __attribute__((section(".func_section"))) 
    int func_test()
    {   
    	printf("helloworld\n");
    }
    
    

    通过objdump查看,可以发现多了两个段

      3 .var_section  00000004  0000000000000000  0000000000000000  000000c8  2**2
                      CONTENTS, ALLOC, LOAD, DATA
      5 .func_section 0000001a  0000000000000000  0000000000000000  000000db  2**0
                      CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
    
    

    本文参考

    《程序员的自我修养》

    https://blog.csdn.net/SlowIsFastLemon/article/details/103593719

  • 相关阅读:
    [自用] 数论和组合计数类数学相关(定理&证明&板子)
    OI回忆录?
    [UOJ310] 黎明前的巧克力
    [总结] 后缀自动机学习笔记
    [总结] 动态点分治学习笔记
    [HEOI2018] 秘密袭击coat
    [51nod1355] 斐波那契的最小公倍数
    [SRM601] WinterAndSnowmen
    [总结] 二项式反演学习笔记
    [Luogu4705] 玩游戏
  • 原文地址:https://www.cnblogs.com/helloworldtoyou/p/16583930.html
Copyright © 2020-2023  润新知