可执行程序

可执行文件:状态机的描述

一个描述了状态机初始状态 + 迁移的数据结构

  1. 寄存器:大部分由ABI规定,操作系统负责设置。例如初始化pc。
  2. 地址空间:二进制文件+ABI共同决定。例如argv和envp的存储。
  3. 其他有用的信息(例如调试和core dump的信息)

可执行文件里面应该有什么?

可执行程序描述了状态机重置后的状态,那状态有什么呢?

无非就是寄存器和内存(地址空间)


操作系统上的可执行程序

需要满足以下条件:

  1. 具有执行(x)权限
    执行./a.c命令 (出现permission denied错误)
    但如果先执行 chmod +x a.c命令,会出现加载器不能正确识别题。

  2. 加载器能够识别的可执行文件


常见的可执行文件

就是操作系统里面的一个普通对象。

UNIX/Linux

  • a.out
  • ELF
  • She-bang

    She-bang是什么呢?其实就是一个“偷换参数”地execve。

1
2
#!/usr/bin/python3               #这是一个可执行文件
print('Hello')

再执行命令 chmod +x a.c。上面这个文件就可以执行了。
如果加载器这样一个程序的时候,如果它发现一个#!开头的,就会在execve偷换一下,把#!后面的填入execve的第一个参数,该文件名填入第二个参数。


从C代码到二进制文件

一段简单的C代码(main.c):

1
2
3
4
5
6
7
8
9
10
11
12
void hello();

int f(int a, int b)
{
return a + b;
}

int main()
{
hello();
}

gcc -O2 -c main.c得到main.o文件, 然后objdump -d main.o得到反汇编

1
2
3
4
5
6
7
8
0000000000000000 <main>:
0: f3 0f 1e fa endbr64
4: 48 83 ec 08 sub $0x8,%rsp
8: 31 c0 xor %eax,%eax
a: e8 00 00 00 00 call f <main+0xf>
f: 31 c0 xor %eax,%eax
11: 48 83 c4 08 add $0x8,%rsp
15: c3 ret

我们可以看到 0xa 地址处,由于不知道hello函数的地址,这里暂时填为 0

hello.c的代码块:

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
#include<stdint.h>
#include<assert.h>
int main();

void hello(){
char *p = (char*)main + 0xa + 1; //有上面汇编代码可以看出,代填
//hello地址为 main 的地址加上偏移再加上1(操作码1个字节)
int32_t offset = *(int32_t*)p;
assert( (char*)main + 0xf +offset == (char*)hello);
printf("hello \n");
}

解释一下:在我们的main函数要调用hello函数时,此时pc会指向这条call指令的下一条指令的地址,也就是pc指针会是(char*)main + 0xf,由于是相对寻址(call指令的语义),所以会跳转到pc + offset的位置,offset也就是待填地址处的值。而跳转后的地址要是hello的地址。

我们 readelf -a main.o 来看一下有什么输出信息,其中有一部分是这样的(这里复制过来格式有点不正确):

1
2
3
Relocation section '.rela.text.startup' at offset 0x1b8 contains 1 entry:
Offset Info Type Sym. Value Sym. Name+Addend
00000000000b 000600000004 R_X86_64_PLT32 0000000000000000 hello - 4

重新理解编译、链接流程

编译器

High-level semantics(高级C状态机) -> Low-level semantics(汇编状态机)

汇编器

Low-level semantics -> Binary semantics(状态机的容器)

  1. “一一对应”地翻译成二进制代码,sections, symbols, debug info……
  2. 不能决定的要留下“之后要怎么办”的信息(relocations重定位)

链接器

合并所有的容器,得到一个完整的状态机


可执行程序
http://example.com/2023/08/02/操作系统/jyy操作系统/可执行程序/
作者
LiuZhaocheng
发布于
2023年8月2日
许可协议