linux - 最小的 x86_64 Hello World ELF 二进制文件是什么?

标签 linux x86-64 elf instruction-set

我尝试手动编写尽可能小的 x86_64 ELF hello world 程序,但在尝试运行它时收到段错误。

gdb 说:在启动过程中程序以信号 SIGSEGV 终止,段错误。

这是十六进制转储:

00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0200 3e00 0100 0000 7800 0000 0000 0000  ..>.....x.......
00000020: 4000 0000 0000 0000 0000 0000 0000 0000  @...............
00000030: 0000 0000 4000 3800 0100 0000 0000 0000  ....@.8.........
00000040: 0100 0000 0500 0000 0000 0000 0000 0000  ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000060: 3100 0000 0000 0000 3100 0000 0000 0000  1.......1.......
00000070: 0200 0000 0000 0000 b801 0000 00bf 0100  ................
00000080: 0000 be9a 0000 00ba 0a00 0000 0f05 b83c  ..."...........<
00000090: 0000 00bf 0000 0000 0f05 4865 6c6c 6f2c  ..........Hello,
000000a0: 2057 6f72 6c64 210a 00                    World!..

这是 readelf -a 的输出:

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)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x78
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0

There are no sections in this file.

There are no section groups in this file.

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000031 0x0000000000000031  R E    0x2

There is no dynamic section in this file.

There are no relocations in this file.
No processor specific unwind information to decode

Dynamic symbol information is not available for displaying symbols.

No version information found in this file.

代码如下:

0xb8 0x01 0x00 0x00 0x00 /* mov %rax, 1 ; sys_write */
0xbf 0x01 0x00 0x00 0x00 /* mov %rdi, 1 ; STDOUT */
0xbe 0x9a 0x00 0x00 0x00 /* mov %rsi, 0x9a ; address of string */
0xba 0x0a 0x00 0x00 0x00 /* mov %rdi, 15 ; size of string */
0x0f 0x05                /* syscall */

0xb8 0x3c 0x00 0x00 0x00 /* mov %rax, 60 ; sys_exit */
0xbf 0x00 0x00 0x00 0x00 /* mov %rdi, 0 ; exit status */
0x0f 0x05                /* syscall */

“Hello, World!\n”字符串紧随其后。 我一直在用this MOV instruction . 尝试使用程序头偏移量、对齐方式和虚拟地址字段没有产生任何结果。 manpage这部分有点困惑。我还尝试将此二进制文件与用汇编语言编写的二进制文件进行比较,但我发现没有任何用处。

现在回答我的问题:您能告诉我错误是什么和/或我该如何调试这个二进制文件吗?

最佳答案

I tried to write the smallest possible x86_64 ELF hello world program by hand

您应该为您的程序提供一个源代码,以便我们修复它。

gdb says: During startup program terminated with signal SIGSEGV

这是 GDB 告诉你它调用了 fork/execve 来创建目标程序,并期望内核通知 GDB 该程序现在可以调试了。取而代之的是,内核通知 GDB 该程序已通过 SIGSEGV 终止,还没有到达它的第一条指令

GDB 没有预料到这一点。为什么会这样?

当内核查看您的可执行文件并说“我无法从中创建正在运行的程序”时,就会发生这种情况。

为什么会这样?因为这个 LOAD 段:

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000031 0x0000000000000031  R E    0x2

要求内核将文件中偏移量 00x31 字节映射到虚拟地址 0。但是内核(理所当然地)拒绝了这种无意义的请求,并在从 execve 返回之前用 SIGSEGV 终止了程序。

您可能可以通过制作文件 ET_DYN 而不是 ET_EXEC 来避免这种情况——这会将您的程序头的含义从“将此段映射到 0”更改为“将此段映射到任何地方”。

您绝对可以通过保留 ET_EXEC 来避免这种情况,但将段的 .p_vaddr.p_paddr 更改为类似 0x10000.

TL;DR:您的程序和文件头必须对内核有意义,否则您将永远无法启动。

关于linux - 最小的 x86_64 Hello World ELF 二进制文件是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72930779/

相关文章:

ruby - 如何卸载旧版本的 Ruby,这是明智之举吗?

linux - 使用 im2dcm 进行 Bash 脚本图像处理

linux - 尝试执行二进制文件时出现 "No such file or directory"错误

c - 结构成员的默认对齐方式

c - 为什么这些 "exported"变量是双重定义的?

linux - 什么是 '! -e "/etc/httpd "' in Perl in ' if' 条件

c++ - 在 Linux 上使用纯 C 项目中用 C++ 编写的库?

assembly - 如何用汇编语言编写 "Hello World"应用程序?

windows - 在 Windows 平台上为 powerPC 提取和检测 elf 文件

linux - 链接器如何将程序头添加到可重定位文件?