gcc - 位置无关的可执行文件和固定入口点地址

标签 gcc position-independent-code

可以从虚拟地址空间内的任意地址加载和运行位置无关的 ELF 可执行文件。
我尝试构建以下简单程序:
pie.c

#include <stdio.h>

void main(void)
{
    printf("hello, pie!\n");
}
构建命令:
gcc pie.c -o pie -pie
可执行文件的 ELF header 是:
:
ELF Header:
  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:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x530 <================= FIXED entry point
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6440 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         29
  Section header string table index: 28
所以入口点地址是固定的。
它是符号_start那里:
0000000000000530 T _start
所以这意味着 _start必须放在 0x530 .
这与位置独立不矛盾吗?
添加 1 - 10:44 上午 8/16/2021
我试图在没有 -pie 的情况下构建相同的程序旗帜:
gcc pie.c -o pie_not
生成的 ELF 头是:
pie_not :
ELF Header:
  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:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x530  <============ Still the same value as with -pie flag
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6440 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         29
  Section header string table index: 28
我进一步比较了构建结果piepie_not .它们的二进制文件是相同的。
那么操作系统如何判断哪一个应该被视为位置无关代码呢?
添加 2 - 2021 年 8 月 16 日上午 10:56
我想我想通了。
似乎gcc使用-pie默认情况下。为了避免它,我必须添加 -no-pie明确地标记。
gcc pie.c -o pie_not -no-pie
而生成的 ELF 头是这样的:
pie_not :
ELF Header:
  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:                              EXEC (Executable file) <==== File type also changed!!!
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400400 <===== Entry point address changed!
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6376 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         29
  Section header string table index: 28
我相信加载器依赖于 ELF header 中的 Type 来决定如何处理二进制文件。

最佳答案

对于位置无关的可执行文件,ELF header 中的入口点地址不用作入口点的绝对地址。相反,它被用作随机选择的基地址的偏移量。
所以在你的例子中,如果基地址被随机选择为 0x567812340000 ,那么执行将从绝对地址 0x567812340530 开始.

关于gcc - 位置无关的可执行文件和固定入口点地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68792831/

相关文章:

linux - 共享库如何找到 GOT 部分?

c - 在 MCU 上放置独立代码 - 一切正常,除了 vsnprintf - vsnprintf 的 C 替代品?

gcc - 在 C++ Builder 中使用 GCC 生成的汇编程序

c++ - 处理 POSIX 信号 : how to get stack trace without using backtrace_symbols?

c - 如果我不小心在 ARM 上运行 x86 二进制文件,如何显示错误消息?

assembly - 什么决定了内存重映射操作后的位置无关性?

c - 如何强制 gcc 直接在 PIC 代码中调用函数?

linux - GCC:在程序/库运行期间打印使用的功能

c - i = i + j; 和有什么区别?我+=j;用c语言?

c - 为什么用-fpic和-pie编译的程序会有重定位表?