arthur-zhang / morning-up-up

78 stars 6 forks source link

1030 分享:ELF 文件格式与内存映射 #4

Open arthur-zhang opened 4 years ago

IKNOWLJT commented 4 years ago

1030

ELF 文件:

  1. ELF (Executable and Linkable Format)是一种为可执行文件,目标文件,共享链接库和内核转储(core dumps)准备的标准文件格式

    一个ELF文件由以下三部分组成:

    • ELF头(ELF header) - 描述文件的主要特性:类型,CPU架构,入口地址,现有部分的大小和偏移等等;
    • 程序头表(Program header table) - 列举了所有有效的段(segments)和他们的属性。 程序头表需要加载器将文件中的节加载到虚拟内存段中;
    • 节头表(Section header table) - 包含对节(sections)的描述。
    1. executable file: 可执行文件,wget, ls

    2. rlocatable:可重定位的目标文件.o 文件

    3. shared object : 共享链接库 .so 文件

    4. Core dump file .core:当前进程退出的core dump

       core dump 内存文件
       1. ulimit -c unlimited (注意要在执行程序的会话中设置,设置是会话级别的,开启新的会话不会生效)
       2. kill -s sigsegv `pidof a.out` 杀掉程序
       3. gdb core.pid 文件
    1. 文件格式的组成:(read, size)

    size 命令查看命令各个数据大小

    readelf -SW 查看文件存储的文件格式

    objdump -x

    1. .text section  代码段 只读 + 可执行
    2. .rodata section 只读存储,字符串常量 只读 + 可执行
    3. .debug* sction debug信息
    4. .bss   bss段存储没有初值的全局变量或默认为0的全局变量,属于静态内存分配。 可读可写 + 不可执行   
    5. .data  data存储已经初始化的全局变量,属于静态内存分配  可读可写 + 不可执行
    #include<stdio.h>
    #include<stdlib.h>
    //已赋值的全局变量, 可读可写 .data
    char *s[100] = {"1"};
    //虽然是const char *s2[100] , 但是因为*s的值是可改的,所以不是rodata ,是.data
    const char *s2[100] = {"2"};
    //未赋值的全局变量,可读可写,不占据空间 .bss
    int a;
    //已赋值的全局变量,可读可写,不占据空间 .bss (注意:初始化为0的全局变量还是被保存在BSS段)
    int b = 0;
    //已赋值的全局变量,可读可写,不占据空间 .data
    int c = 100;
    //未赋值的全局变量,可读可写,占据空间 .bss
    char d;
    //未赋值的全局变量,可读可写,不占据空间 .bss
    char str1[12];
    
    //静态常量 ,可读可执行 .rodata
    const int constData1 = 100;
    
    int main(){
        printf("s = %p\n",s);
        printf("s2 = %p\n",s2);
        printf("&a = %p\n",&a);
        printf("&b = %p\n",&b);
        printf("&c = %p\n",&c);
        printf("&d = %p\n",&d);
        // 局部变量,栈区域
        int data = 100;
        printf("&data = %p\n",&data);
        *s2 = "2";
        printf("&str1 = %p\n",&str1);
        printf("constData1 = %d\n",constData1);
        printf("&constData1 = %p\n",&constData1);
    
    }
    
    outPut

    image-20201030165358442

    1、执行文件中包含了text、rodata、data段的内容,不包含bss段内容(一堆未初始化的0放入执行文件没有意义)。
    2、堆和栈的内存增长方向是相反的:栈是从高地址向低地址生长,堆是从低地址向高地址生长。
    
wolfleave commented 4 years ago

ELF文件格式

Linux 可执行文件格式

可执行链接文件格式:ls, xx.out, xx.so, xx.core, xx.o

ulimit -c unlimit 取消core文件大小限制

kill -s sigsegv `pidof a.out` 发送信号给特定进程

readelf -l a.out  查看elf
size a.out        查看段大小
objdump -x a.out  查看程序变量位置
pmap -x `pidof a.out`     查看进程内存布局
smaps `pidof a.out`
cat /proc/`pidof a.out`/maps
cat /proc/`pidof a.out`/smaps

32个分节(section)

.text

.bss

.data

.rodata

ELF(可执行文件)——进程(运行时的可执行文件)——内存 文件格式映射为内存布局

image

gdb

gcc -g demo1.c

gdb a.out

b main 在main打断点

r 运行

n next,下一步

p a 打印a, p/x a 打印a的16进制,p/s a 字符串格式打印a

LinForTracy commented 4 years ago

image

Taaang commented 4 years ago

image

whx405831799 commented 4 years ago

image

wefun94 commented 4 years ago

(1)ELF是一种文件格式,用于存储linux程序, 主要包括 (1)目标文件(通常是.o); (2)可执行文件(我们的运行文件)
(3)动态库(.so)

ELF文件以 Section的形式进行存储。代码编译后的指令放在代码段(Code Section),全局变量和局部静态变量放到数据段(Data Section)

其中, .text段保存代码编译后的指令 .data段保存的是已经初始化了的全局静态变量和局部静态变量 .rodata段存放的是只读数据,包括const修饰的变量和字符串常量等 readelf -h a.out 可以查看文件头信息 readelf -S a.out 可以查看各段信息 objdump -x -s a.out 可以查看各段的数据