为什么我的简单“main”程序的 ELF 标头说它是“DYN(共享目标文件)”而不是可执行文件?

One*_*Day 4 c++ g++ elf readelf

这是一个非常简单的 C++ 程序:

// main.cpp
int main() {}
Run Code Online (Sandbox Code Playgroud)

Makefile生成以下命令来编译程序。

? make
g++ -O0 -fverbose-asm  -o main main.cpp
Run Code Online (Sandbox Code Playgroud)

我检查命令file以查看它是一个 ELF 可执行文件:

? file main
main: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=921d352e49a0e4262aece7e72418290189520782, for GNU/Linux 3.2.0, not stripped
Run Code Online (Sandbox Code Playgroud)

一切似乎都很好,直到我尝试检查 ELF 标头

? readelf -e main
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
...
  Type:                              DYN (Shared object file)
Run Code Online (Sandbox Code Playgroud)

这里的维基百科,似乎有不同类型的文件,例如EXEC. 为什么它说我的简单主程序是共享对象而不是 ELF 标头上的可执行文件?

从我对.so's的有限知识范围来看,我认为它们是链接但直到运行时才加载的库。在这种情况下,这有什么意义?

额外的信息:

? g++ --version
g++ (Arch Linux 9.3.0-1) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.

? readelf --version
GNU readelf (GNU Binutils) 2.34
Copyright (C) 2020 Free Software Foundation, Inc.

? lsb_release -a
LSB Version:    1.4
Distributor ID: Arch
Description:    Arch Linux
Release:    rolling
Codename:   n/a
Run Code Online (Sandbox Code Playgroud)

Mik*_*ski 5

编译为“位置无关可执行文件”(带有-pie/ -fPIE)的可执行文件应在运行时重新定位到随机地址。为了实现这一点,他们使用了 DYN 类型。

您的 g++ 版本配置为--enable-default-pie,因此默认设置为-pie-fPIE。您可以禁用此功能,并通过链接生成一个普通的可执行文件-no-pie