我试图手动编写尽可能小的x86\u 64 ELF hello world程序,但在try 运行时遇到了分段错误.

gdb表示:During startup program terminated with signal SIGSEGV, Segmentation fault.

这是hexdump:

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"字符串紧跟其后.

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

推荐答案

我试图手工编写尽可能小的x86\u 64 ELF hello world程序

你应该为你的程序提供一个source,这样我们可以修复它.

gdb表示:During startup program terminated with signal SIGSEGV

这是GDB告诉您它调用了fork/execve来创建目标程序,并期望内核通知GDB该程序现在已准备好进行调试.相反,内核通知GDB该程序已与SIGSEGVwithout ever reaching its first instruction一起死亡.

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相关问答推荐

在Bluez/Linux中,周期性与连续蓝牙设备发现的已知缺陷是什么?

Linux TTY 操作顺序

命令行中使用`..`为什么会导致权限被拒绝错误?

Linux BlueZ 5.65 hcitool 结合服务 UUID 和制造数据广告

在 Linux 上的 std::threads 中创建子进程

如何拆分和计算 Bash 中单词的出现次数?

从另一个文件中的大文件中查找行的最快方法

将特定列转换为行

如何重新安装最新的 cmake 版本?

如何在 shell 脚本中只读取一个字符

在使用文件时截断文件 (Linux)

在亚马逊 ec2 linux 微型实例上的 virtualenv 中安装 scipy 时遇到问题

使远程目录保持最新

如何对 /dev/random 或 /dev/urandom 进行 base64 编码?

如何在 Linux 中使用单行命令获取 Java 版本

我可以告诉 Linux 不要换出特定进程的内存吗?

ngrok 如何在防火墙后工作?

如何在 IE 中使用 Linux 进行测试

在linux中将制表符分隔的文件转换为csv的最快方法

如何用逗号而不是空格分割列表