Linux下ELF文件格式

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/feilengcui008/article/details/44811085 In...
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/feilengcui008/article/details/44811085

In this article,I will talk about the ELF files for Linux,and their diffs as to comprehend the linking process in a diff view angle.There are many articles talking about that topic in the way of compiling->linking->loading->executing.I think once we understand the ELF files,then we can understand why and how and understand the whole process more precisely.

ELF(Executable and Linkable Format) is the default file format of executable files,object files,shared object files and core file for Linux.Why should we know about the ELF?I think there are at least the following reasons:

  • Guess what the back end of compilers(esp for c) wants to achieve(yeah,it’s “guess”,if you want to learn more about compilers,you should learn related theories more precisely)
  • Learn about the linking and loading process
  • Better understanding of the organization of our code,that’s helpful to debug and profiling(such the effects of static/local/global/extern,debug coredump file…)
  • guess how the OS loader loads the exec file to memory and run it(yeah,guess again^_^,I will analyze the loading process in some article later)
  • Better understanding of how the disk exec file mapped into memory space of process

I will choose the first three representative ELF files in Linux to analyze,that is the object files,executable files,and shared object files.Actually,the are very simmilar except some differences(bacause they share elf struct which is defined in the elf.h^_^)

Here is the code used for the analysis purpose of this article(main.c and print.c):

//main.c 
//note that we define diff kinds of vars so we can test where they are lied in within diff sections or segments,thus we can better understand the layout of c file

#include <stdio.h>

int main_global_unitialized;
int main_global_initialized = 1;
static int main_local_uninitialized;
static int main_local_uninitialized = 2;

extern void print(int);
void print1(int);
static void print2(int);

int main()
{
    int main_stack_uninitialized;
    int main_stack_initialized = 3;
    static main_func_local_uninitialized;
    static main_func_local_initialized = 4;
    print(2);
    print1(2);
    print2(2);
    return 0;
}

void print1(int a)
{
    fprintf(stdout, "%d\n", a);
}

static void print2(int a)
{
    fprintf(stdout, "%d\n", a);
}
//print.c
#include <stdio.h>

//in module vars
int print_global_uninitialized;
int print_global_initialized = 1;
static int print_local_static_uninitialized;
static int print_local_static_initialized = 2;

void print(int a)
{
    int print_stack_uninitialized;
    int print_stack_initialized = 3;
    static int print_func_local_static_uninitialized;
    static int print_func_local_static_initialized = 4;
    fprintf(stdout, "%d\n", a);
}

static void print2(int a)
{
    fprintf(stdout, "%d\n", a);
}

We use the above two souce files to generate the following file:

gcc -o print.o -c print.c
gcc -o main.o -c main.c
gcc -shared -fPIC -o print.so print.c
gcc -o exec main.o print.o
//and the tools we may use:
//readelf/objdump/nm/size...
//the platform is Linux tan 3.13.0-51-generic #84-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux

这里写图片描述


We will look into some diffs of the aboved mentioned 3 kinds of ELF files,we mainly use readelf.
Usually,ELF files (may) consists of the following parts:

  • file headers: describe file info such as start point,section header start poit etc
  • program header table: info of mapping sections to segments
  • section header table: section entry info
  • sections: each section contents such as .data .text etc

1.file headers

executable file headers:

这里写图片描述

object file headers:

这里写图片描述

shared object file headers:

这里写图片描述

As we can see,the file header of exec/.o/.so are almost the same except some options like type,start point…:

           #define EI_NIDENT 16
           typedef struct {
               //magic number denotes the file,16 byte,for ELF:7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
               unsigned char e_ident[EI_NIDENT]; 
               //ELF file type:exec/.o/.so/core/unknown
               uint16_t      e_type;
               uint16_t      e_machine;
               uint32_t      e_version;
               //_start point of the program
               Elf64_Addr     e_entry;
               //program header table offset,no for .o file
               Elf64_Off      e_phoff;
               //section header table offset
               Elf64_Off      e_shoff;
               uint32_t      e_flags;
               //header size
               uint16_t      e_ehsize;
               //entry size for program header table
               uint16_t      e_phentsize;
               //program entry numbers
               uint16_t      e_phnum;
               //entry size for section header table
               uint16_t      e_shentsize;
               //section entry number
               uint16_t      e_shnum;

               uint16_t      e_shstrndx;
           } Elf64_Ehdr;

Conclusions or diffs:
+ type is different
+ no start point for .o file
+ no program header for .o file


2.section header table

exec file section header table:

这里写图片描述
这里写图片描述

.so file section header table:

这里写图片描述
这里写图片描述

.o file section header table:

这里写图片描述

typedef struct {
    uint32_t   sh_name;// section name
    uint32_t   sh_type;//section type:RELA,STRTAB,SYMTAB...
    uint64_t   sh_flags;//rwe...
    Elf64_Addr sh_addr; //virtual address(no for .o file)
    Elf64_Off  sh_offset;
    uint64_t   sh_size;
    uint32_t   sh_link;
    uint32_t   sh_info;
    uint64_t   sh_addralign;//address align 
    uint64_t   sh_entsize;
} Elf64_Shdr;

Conclusions or diffs:
+ the sections of exec file and .so file are almost the same
+ more sections in exec and .so file than .o file since some sections like .fini/.init_array/.fini_array/.got/.got.plt/.init … are added during linking process
+ the virtual address of every section in .o file is 0,but not in exec and .so file


3.program header table

exec file program header:

这里写图片描述

.so file program header:

这里写图片描述

.o file program header:

这里写图片描述

typedef struct {
               uint32_t   p_type; //segment type
               uint32_t   p_flags; //permission
               Elf64_Off  p_offset; // offset
               Elf64_Addr p_vaddr; //virtual address
               Elf64_Addr p_paddr; //phisical address
               uint64_t   p_filesz; //size
               uint64_t   p_memsz;
               uint64_t   p_align;
           } Elf64_Phdr;

Conclusions or diffs:
+ there is no program header for .o file
+ some sections are divided into one segment according to the permisson flag


4.common sections explain

.intern 
#path for elf interpretor
#here is an article about changing the ld
#http://nixos.org/patchelf.html
.dynsym
#the dynamic linking symbol table
.dynstr
#strings needed for dynamic linking
.init
#executable instructions that contribute to the process initialization code(before main)
.plt
#procedure linkage table
#for GOT dynamic linker
.text
#executable instructions of a program
.fini
#executable instructions that contribute to the process termination code
.rodata
# read-only data
.dynamic
#dynamic linking information
.got
#global offset table
#for dynamic linker to resolve global elements
.data
# initialized data
.bss
#uninitialized data
.comment
#version control info
.shstrtab
#section names
.strtab
#string table
.symtab
#symble table
.debug
#debug info

for C++:

.ctors
#initialized pointers to the C++ constructor functions
.dtors
#initialized pointers to the C++ destructor functions

The sections contain important data for linking and relocation , while segments contain information that is necessary for runtime execution of the file.

About program header:http://www.sco.com/developers/gabi/latest/ch5.pheader.html
here is picture portraits the diff views for sections and segments:
这里写图片描述

5.code mapped into sections

In the last part we take a look at the symble table for our code in main.c and print.c and verify the scope of vars.

//get symble info use nm
nm exec | egrep "main|print"
----------------------------
the 3 columns:
--vaddress (dynamic linking is NULL)
--symble type and local or global
1.uppercase stands for global,lowercase is local
2.
B|b:uninitialized(BSS)
D|d:initialized data section
T|t:text (code) section
R|r: read only data section
...
--symble

这里写图片描述

So we can check the symbles in main.c and print.c,you can find how the code and data are mapper to each sections,and then organized into segments when linked into executable elf files,so it can be easily loaded into memory(actually mapped) by the OS loader(to some extent we can think it’s execve syscall)

6 to the end

In all,I talk about the three parts of the elf files in Linux especially some diffs between exec,.so and .o files and the organization for sections and segments.
If you want to know more precisely about these topics,you can refer to the following materials:

Ref:
some articles:
http://man7.org/linux/man-pages/man5/elf.5.html(man manual is so powerful^_^)
https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
http://www.sco.com/developers/gabi/latest/ch5.pheader.html
http://tech.meituan.com/linker.html
some books:
1.CSAPP
2.《程序员的自我修养》

相关文章
|
14天前
|
Linux 开发工具 Perl
在Linux中,有一个文件,如何删除包含“www“字样的字符?
在Linux中,如果你想删除一个文件中包含特定字样(如“www”)的所有字符或行,你可以使用多种文本处理工具来实现。以下是一些常见的方法:
38 5
|
14天前
|
安全 Linux 数据安全/隐私保护
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。
在 Linux 系统中,查找文件所有者是系统管理和安全审计的重要技能。本文介绍了使用 `ls -l` 和 `stat` 命令查找文件所有者的基本方法,以及通过文件路径、通配符和结合其他命令的高级技巧。还提供了实际案例分析和注意事项,帮助读者更好地掌握这一操作。
34 6
|
15天前
|
Linux
在 Linux 系统中,`find` 命令是一个强大的文件查找工具
在 Linux 系统中,`find` 命令是一个强大的文件查找工具。本文详细介绍了 `find` 命令的基本语法、常用选项和具体应用示例,帮助用户快速掌握如何根据文件名、类型、大小、修改时间等条件查找文件,并展示了如何结合逻辑运算符、正则表达式和排除特定目录等高级用法。
49 6
|
16天前
|
监控 Linux Perl
Linux 命令小技巧:显示文件指定行的内容
在 Linux 系统中,处理文本文件是一项常见任务。本文介绍了如何使用 head、tail、sed 和 awk 等命令快速显示文件中的指定行内容,帮助你高效处理文本文件。通过实际应用场景和案例分析,展示了这些命令在代码审查、日志分析和文本处理中的具体用途。同时,还提供了注意事项和技巧,帮助你更好地掌握这些命令。
33 4
|
21天前
|
网络协议 Linux
linux系统重要文件目录
本文介绍了Linux系统中的重要目录及其历史背景,包括根目录、/usr、/etc、/var/log和/proc等目录的结构和功能。其中,/etc目录下包含了许多关键配置文件,如网卡配置、DNS解析、主机名设置等。文章还详细解释了各目录和文件的作用,帮助读者更好地理解和管理Linux系统。
42 2
|
20天前
|
缓存 监控 Linux
|
23天前
|
Linux Shell 数据库
文件查找是Linux用户日常工作的重要技能介绍了几种不常见的文件查找方法
文件查找是Linux用户日常工作的重要技能。本文介绍了几种不常见的文件查找方法,包括使用`find`和`column`组合、`locate`和`mlocate`快速查找、编写Shell脚本、使用现代工具`fd`、结合`grep`搜索文件内容,以及图形界面工具如`Gnome Search Tool`和`Albert`。这些方法能显著提升文件查找的效率和准确性。
41 2
|
27天前
|
Linux 数据库
linux 全局搜索文件
在 Linux 系统中,全局搜索文件常用 `find`、`locate` 和 `grep` 命令。`find` 根据文件名、类型、大小、时间戳等条件搜索;`locate` 通过预构建的数据库快速查找文件;`grep` 在文件中搜索特定文本,常与 `find` 结合使用。选择合适的命令取决于具体需求。
|
1月前
|
Linux 开发工具 Perl
Linux命令替换目录下所有文件里有"\n"的字符为""如何操作?
【10月更文挑战第20天】Linux命令替换目录下所有文件里有"\n"的字符为""如何操作?
42 4
|
29天前
|
运维 安全 Linux
Linux文件清空的五种方法总结分享
每种方法各有优势,选择最合适的一种或几种,可以极大提高您的工作效率。更多有关Linux系统管理的技巧与资源,欢迎访问,持续提升您的运维技能。
67 1
下一篇
无影云桌面