IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 小湿妹问沃什么是可执行程序?(全网最简洁,必看,错过后悔终生!!!) -> 正文阅读

[系统运维]小湿妹问沃什么是可执行程序?(全网最简洁,必看,错过后悔终生!!!)

? ? ? ? 相信很多同学知道Windows下的可执行程序是*.exe,但是除了*.exe之外,Windows下动态库*.dll和*.lib也是可执行程序。不过,小湿妹问沃的是什么是Linux下的可执行程序?

? ? ? ? 为了不让小湿妹伤心,师兄沃再次拿起《程序员的自我修养》第三章肝了一晚上,呕心沥血才完美回答出小湿妹的问题,回答让小湿妹十分满意,对师兄好感爆棚。好了,吹牛到此为止,正经脸(咳咳咳? ^_^),接下来让我们来看看师兄回答了什么,让小湿妹万分满意?

一、目标文件格式

? ? ? ? 现在PC平台流行的可执行文件格式(executable)主要是Windows下的PE(Portable Executable)和Linux下的ELF(Executable Linkable Format),它们都是COFF(Common file format)格式的变种。其中,Windows下可执行文件还包括动态链接库(DLL,Dynamic Linking Library)和静态链接库(lib,Static Linking Library),Linux下动态链接库(*.so)和静态链接库(*.a)以及目标文件object(*.o)。在Windows下可执行文件按PE-COFF格式存储,Linux下按照ELF格式存储。ELF可以理解为是一系列的目标文件或者加上链接库组合而成的文件包。下面是ELF文件类型和说明。

表格1-1 ELF文件类型和说明
ELF文件类型说明实例

可重定位文件

(Relocatable File)

这类文件包含了代码和数据,可以被用来链接成可执行文件或共享目标文件,静态链接库也可以归类为这一类

Linux的*.o文件

Windows的*.obj文件

可执行文件

(Executable File)

这类文件包含了可以直接执行的程序,它的代表就是ELF可执行文件,它们一般都没有扩展名

比如/bin/bash文件

Windows的*.exe文件

共享目标文件

(Shared Object File)

这类文件包含了代码和数据,可以在一下两种情况使用,

一种是连接器可以使用这种文件跟其它的可重定位文件和共享目标文件链接,产生新的目标文件;

另一种是动态链接器可以将几个这种共享目标文件与可执行文件结合,作为进程映像的一部分来运行。

Linux的*.so,如/lib/glibc-2.5.so

Windows的DLL

核心转存储文件

(Core Dump File)

当进程意外中职生时,系统可以将该进程的地址空间的内容及终止时的一些其他信息转存储到核心转存储文件Linux下的Core dump
  • 小知识:Unix的可执行程序是*.out;COFF主要贡献在目标文件引入“段”机制。

二、目标文件结构

2.1样例代码

我们先给小湿妹上一段经典代码,惊呆小湿妹一脸。

(注:文本分析的是ubuntu20.04 x86 64位系统下的ELF文件)

#include <iostream>

int globalVar1 = 100;
int globalVar2;

void fun1(int var)
{
    std::cout<<var<<std::endl;
}

struct St
{
    St() : var(200) {}
    ~St() {}

    int getVar() const {return var;}

private:
    int var;
};

int main(int arc, char* argv[]) {

    static int staticVar1 = 666;
    static int staticVar2;
    int var1 = 555;
    int var2;
    fun1(staticVar1 + staticVar1 + var1 + var2);

    return 0;
}

2.2生成可执行文件

编译成main.o文件命令如下:(-c表示只编译不链接)

g++ -c main.cpp -o main.o

编译成main文件命令如下:

g++ main.cpp -o main

2.3分析main.o文件

Linux下查看和操作目标文件许多工具,比如hexdump、objdum、objcopy、readelf,本文主要介绍ELF的文件结构,故主要用objdump工具足够,具体文件结构里面每个部分将在下一篇文章结合源码详细分析。

查看main.o内部结构命令

objdump -h main.o
图1-1? main.o文件结构

?? ? ? ? 通过图1-1可知,可执行文件结构主要分为几大部分“.text段”、“.data段”、“.bss段”、“.rodata段”、“其它信息段”,即如下结构图:

结构图1-1? main.o内存分布图

? ? ? ? 由结构图1-1可知,可知执行文件main.o主要结构分为文件头header、.text段、.data段、.bss段、其它信息段(.rodata段、.init_arrary段、.comment段、other段等)。其中左侧红色数据位对应“段”的大小,右边蓝色数字表示文件偏移地址。

ELF header:ELF文件头,定义了ELF魔数、文件机器字节长度、数据存储方式、版本、运行平台、ABI版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址、程序头入口地址和长度、段表的位置和长度及段的数量等;(具体代码定义参考Linux系统库“/usr/inlcude//elf.h”)

  • .text:代码段,存放程序运行时相关需要的代码
  • .data:数据段,保存已经初始化了的全局变量、全局静态变量、局部静态变量,比如globalVar1和staticVar1,一共8字节
  • .bss:存放的是未初始化的全局变量、全局静态变量、局部静态变量,比如globalVar2和staticVar2,var2一共12(0x0c)字节
  • .rodata:只读数据段,由于cout::endl本质是一个"\n"常量字符,大小为1,故带只读数据段大小只有1字节
  • .init_arrary:初始化数组段,有类似ctor效果
  • .comment:注释段,一般存放注释代码文本段
  • .other:其它段包含符号表、gnu版本号等等

2.4段.text、.data和.rodata、.bss段分析

2.4.1代码段.text分析

objdum中的-s可以显示所有段十六进制数,-d可以将所有段包含的指令反汇编,下面敲入命令查看代码如下:

objdump -s -d main.o

显示结果:

tjq@ubuntu:~/eclipse-workspace/Test1/src$ objdump -s -d main.o

main.o:     文件格式 elf64-x86-64

Contents of section .text:
 0000 f30f1efa 554889e5 4883ec10 897dfc8b  ....UH..H....}..
 0010 45fc89c6 488d3d00 000000e8 00000000  E...H.=.........
 0020 4889c248 8b050000 00004889 c64889d7  H..H......H..H..
 0030 e8000000 0090c9c3 f30f1efa 554889e5  ............UH..
 0040 4883ec20 897dec48 8975e0c7 45f82b02  H.. .}.H.u..E.+.
 0050 00008b05 00000000 8d14008b 45f801c2  ............E...
 0060 8b45fc01 d089c7e8 00000000 b8000000  .E..............
 0070 00c9c3f3 0f1efa55 4889e548 83ec1089  .......UH..H....
 0080 7dfc8975 f8837dfc 01753281 7df8ffff  }..u..}..u2.}...
 0090 00007529 488d3d00 000000e8 00000000  ..u)H.=.........
 00a0 488d1500 00000048 8d350000 0000488b  H......H.5....H.
 00b0 05000000 004889c7 e8000000 0090c9c3  .....H..........
 00c0 f30f1efa 554889e5 beffff00 00bf0100  ....UH..........
 00d0 0000e89c ffffff5d c3                 .......].       
Contents of section .data:
 0000 64000000 9a020000                    d.......        
Contents of section .rodata:
 0000 00                                   .               
Contents of section .init_array:
 0000 00000000 00000000                    ........        
Contents of section .comment:
 0000 00474343 3a202855 62756e74 7520392e  .GCC: (Ubuntu 9.
 0010 332e302d 31377562 756e7475 317e3230  3.0-17ubuntu1~20
 0020 2e303429 20392e33 2e3000             .04) 9.3.0.     
Contents of section .note.gnu.property:
 0000 04000000 10000000 05000000 474e5500  ............GNU.
 0010 020000c0 04000000 03000000 00000000  ................
Contents of section .eh_frame:
 0000 14000000 00000000 017a5200 01781001  .........zR..x..
 0010 1b0c0708 90010000 1c000000 1c000000  ................
 0020 00000000 38000000 00450e10 8602430d  ....8....E....C.
 0030 066f0c07 08000000 1c000000 3c000000  .o..........<...
 0040 00000000 3b000000 00450e10 8602430d  ....;....E....C.
 0050 06720c07 08000000 1c000000 5c000000  .r..........\...
 0060 00000000 4d000000 00450e10 8602430d  ....M....E....C.
 0070 0602440c 07080000 1c000000 7c000000  ..D.........|...
 0080 00000000 19000000 00450e10 8602430d  .........E....C.
 0090 06500c07 08000000                    .P......        

Disassembly of section .text:

0000000000000000 <_Z4fun1i>:
   0:	f3 0f 1e fa          	endbr64 
   4:	55                   	push   %rbp
   5:	48 89 e5             	mov    %rsp,%rbp
   8:	48 83 ec 10          	sub    $0x10,%rsp
   c:	89 7d fc             	mov    %edi,-0x4(%rbp)
   f:	8b 45 fc             	mov    -0x4(%rbp),%eax
  12:	89 c6                	mov    %eax,%esi
  14:	48 8d 3d 00 00 00 00 	lea    0x0(%rip),%rdi        # 1b <_Z4fun1i+0x1b>
  1b:	e8 00 00 00 00       	callq  20 <_Z4fun1i+0x20>
  20:	48 89 c2             	mov    %rax,%rdx
  23:	48 8b 05 00 00 00 00 	mov    0x0(%rip),%rax        # 2a <_Z4fun1i+0x2a>
  2a:	48 89 c6             	mov    %rax,%rsi
  2d:	48 89 d7             	mov    %rdx,%rdi
  30:	e8 00 00 00 00       	callq  35 <_Z4fun1i+0x35>
  35:	90                   	nop
  36:	c9                   	leaveq 
  37:	c3                   	retq   

0000000000000038 <main>:
  38:	f3 0f 1e fa          	endbr64 
  3c:	55                   	push   %rbp
  3d:	48 89 e5             	mov    %rsp,%rbp
  40:	48 83 ec 20          	sub    $0x20,%rsp
  44:	89 7d ec             	mov    %edi,-0x14(%rbp)
  47:	48 89 75 e0          	mov    %rsi,-0x20(%rbp)
  4b:	c7 45 f8 2b 02 00 00 	movl   $0x22b,-0x8(%rbp)
  52:	8b 05 00 00 00 00    	mov    0x0(%rip),%eax        # 58 <main+0x20>
  58:	8d 14 00             	lea    (%rax,%rax,1),%edx
  5b:	8b 45 f8             	mov    -0x8(%rbp),%eax
  5e:	01 c2                	add    %eax,%edx
  60:	8b 45 fc             	mov    -0x4(%rbp),%eax
  63:	01 d0                	add    %edx,%eax
  65:	89 c7                	mov    %eax,%edi
  67:	e8 00 00 00 00       	callq  6c <main+0x34>
  6c:	b8 00 00 00 00       	mov    $0x0,%eax
  71:	c9                   	leaveq 
  72:	c3                   	retq   

0000000000000073 <_Z41__static_initialization_and_destruction_0ii>:
  73:	f3 0f 1e fa          	endbr64 
  77:	55                   	push   %rbp
  78:	48 89 e5             	mov    %rsp,%rbp
  7b:	48 83 ec 10          	sub    $0x10,%rsp
  7f:	89 7d fc             	mov    %edi,-0x4(%rbp)
  82:	89 75 f8             	mov    %esi,-0x8(%rbp)
  85:	83 7d fc 01          	cmpl   $0x1,-0x4(%rbp)
  89:	75 32                	jne    bd <_Z41__static_initialization_and_destruction_0ii+0x4a>
  8b:	81 7d f8 ff ff 00 00 	cmpl   $0xffff,-0x8(%rbp)
  92:	75 29                	jne    bd <_Z41__static_initialization_and_destruction_0ii+0x4a>
  94:	48 8d 3d 00 00 00 00 	lea    0x0(%rip),%rdi        # 9b <_Z41__static_initialization_and_destruction_0ii+0x28>
  9b:	e8 00 00 00 00       	callq  a0 <_Z41__static_initialization_and_destruction_0ii+0x2d>
  a0:	48 8d 15 00 00 00 00 	lea    0x0(%rip),%rdx        # a7 <_Z41__static_initialization_and_destruction_0ii+0x34>
  a7:	48 8d 35 00 00 00 00 	lea    0x0(%rip),%rsi        # ae <_Z41__static_initialization_and_destruction_0ii+0x3b>
  ae:	48 8b 05 00 00 00 00 	mov    0x0(%rip),%rax        # b5 <_Z41__static_initialization_and_destruction_0ii+0x42>
  b5:	48 89 c7             	mov    %rax,%rdi
  b8:	e8 00 00 00 00       	callq  bd <_Z41__static_initialization_and_destruction_0ii+0x4a>
  bd:	90                   	nop
  be:	c9                   	leaveq 
  bf:	c3                   	retq   

00000000000000c0 <_GLOBAL__sub_I_globalVar1>:
  c0:	f3 0f 1e fa          	endbr64 
  c4:	55                   	push   %rbp
  c5:	48 89 e5             	mov    %rsp,%rbp
  c8:	be ff ff 00 00       	mov    $0xffff,%esi
  cd:	bf 01 00 00 00       	mov    $0x1,%edi
  d2:	e8 9c ff ff ff       	callq  73 <_Z41__static_initialization_and_destruction_0ii>
  d7:	5d                   	pop    %rbp
  d8:	c3                   	retq 

由上面反汇编代码可知,代码段包含了全局函数void fun1(),主函数main,类代码指令、静态变量globalVar1;.text代码段的前四个字节是f3 0f 1e fa;函数fun1和main的第一条指令为push %rbp,该两函数最后返回指令为retq。

2.4.2.数据段data和只读数据段.rodata分析

执行命令查看数据段指令和反汇编代码

objdump -x -s -d main.o

输出结果:

......
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         000000d9  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000008  0000000000000000  0000000000000000  0000011c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          0000000c  0000000000000000  0000000000000000  00000124  2**2
                  ALLOC
  3 .rodata       00000001  0000000000000000  0000000000000000  00000124  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .init_array   00000008  0000000000000000  0000000000000000  00000128  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, DATA
......     
Contents of section .data:
 0000 64000000 9a020000                    d.......        
Contents of section .rodata:
 0000 00                                   .               
Contents of section .init_array:
 0000 00000000 00000000                    ........        
Contents of section .comment:
 0000 00474343 3a202855 62756e74 7520392e  .GCC: (Ubuntu 9.
 0010 332e302d 31377562 756e7475 317e3230  3.0-17ubuntu1~20
 0020 2e303429 20392e33 2e3000             .04) 9.3.0.  
......

从上面代码可以看出.data数据段有两个已经初始化了全局变量值0x00000064、0x0000029a,这两个十六进制数转化为十进制数分别是100和666,刚好和全局变量globalVar1=100和staticVar1=666对的上。

2.4.3未初始化数据段.bss分析

还是通过敲下面命令查看.bss段的十六进制数和反汇编代码

objdump -x -s -d main.o

输出结果显示:

......
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         000000d9  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000008  0000000000000000  0000000000000000  0000011c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          0000000c  0000000000000000  0000000000000000  00000124  2**2
                  ALLOC
......
SYMBOL TABLE:
0000000000000000 l    df *ABS*	0000000000000000 main.cpp
0000000000000000 l    d  .text	0000000000000000 .text
0000000000000000 l    d  .data	0000000000000000 .data
0000000000000000 l    d  .bss	0000000000000000 .bss  
0000000000000000 l    d  .rodata	0000000000000000 .rodata
0000000000000000 l     O .rodata	0000000000000001 _ZStL19piecewise_construct
0000000000000004 l     O .bss	0000000000000001 _ZStL8__ioinit
0000000000000004 l     O .data	0000000000000004 _ZZ4mainE10staticVar1
0000000000000008 l     O .bss	0000000000000004 _ZZ4mainE10staticVar2
0000000000000073 l     F .text	000000000000004d _Z41__static_initialization_and_destruction_0ii
00000000000000c0 l     F .text	0000000000000019 _GLOBAL__sub_I_globalVar1
0000000000000000 l    d  .init_array	0000000000000000 .init_array
0000000000000000 l    d  .note.GNU-stack	0000000000000000 .note.GNU-stack
0000000000000000 l    d  .note.gnu.property	0000000000000000 .note.gnu.property
0000000000000000 l    d  .eh_frame	0000000000000000 .eh_frame
0000000000000000 l    d  .comment	0000000000000000 .comment
0000000000000000 g     O .data	0000000000000004 globalVar1
0000000000000000 g     O .bss	0000000000000004 globalVar2
0000000000000000 g     F .text	0000000000000038 _Z4fun1i
0000000000000000         *UND*	0000000000000000 _ZSt4cout
0000000000000000         *UND*	0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000000000         *UND*	0000000000000000 _ZNSolsEi
0000000000000000         *UND*	0000000000000000 _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000000000         *UND*	0000000000000000 _ZNSolsEPFRSoS_E
0000000000000038 g     F .text	000000000000003b main
0000000000000000         *UND*	0000000000000000 _ZNSt8ios_base4InitC1Ev
0000000000000000         *UND*	0000000000000000 .hidden __dso_handle
0000000000000000         *UND*	0000000000000000 _ZNSt8ios_base4InitD1Ev
0000000000000000         *UND*	0000000000000000 __cxa_atexit
......

由上面的符号表可知,未初始化的全局变量globalVar2、局部静态变量staticVar2、类St都在.bss段,而非静态局部变量var2不在.bss段里面,var2非静态局部变量应该在栈内存中,此处没有体现。

2.5总结

ELF文件的结构主要为ELF文件头、代码段、数据段(.data和rodata)、BSS段与程序运行密切相关的其它段,同时还可以自定义段,比如.mp3,通过objcopy工具将该段插入ELF数据段中。

看到这里,小湿妹对师兄的回答非常满意,一双勾魂迷妹眼让师兄心肝砰砰乱跳,血流加速,此时师妹似乎下定了什么决心,羞红着脸颊,决定最后问师兄一个问题:“请问ELF头的内容是什么?段又是怎么定义的呢?”

师兄听完后,决定今夜不眠不休,爆了几个肝,也要为小湿妹答疑解惑!好了,具体结果,请听下回分解。哈哈哈~~(^_^)

三、参考文献

《程序员的自我修养——编译、装载与库》俞甲子 石凡 潘爱民 著, 电子工业出版社,? page:55-95

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-09-02 11:48:00  更:2021-09-02 11:49:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 12:28:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码