在64位Linux

时间:2017-08-17 07:53:01

标签: linux linux-kernel binary segmentation-fault elf

你可能听说过kragen的一个项目StoneKnifeForth:https://github.com/kragen/stoneknifeforth。它是一个Python程序,充当一个小的Forth解释器和一个充当Forth编译器的Forth程序。因此,您可以使用这两个一起构建Forth编译器二进制文件。

在将StoneKnifeForth移植到C ++(https://github.com/tekknolagi/stoneknifecpp)之后,我注意到StoneKnifeForth(或者各种)在64位Linux上生成的所有二进制文件都是段错误。也就是说,如果你克隆stoneknifecpp并运行:

make
./l01compiler  # produced by the Forth program

您将获得以下内容:

willow% ./l01compiler                 
[1]    31614 segmentation fault  ./l01compiler

显然,这不是一个非常有趣的错误信息,所以我想我会把它分开:

willow% strace ./l01compiler
execve("./l01compiler", ["./l01compiler"], [/* 110 vars */]) = -1 EPERM (Operation not permitted)
--- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
+++ killed by SIGSEGV +++
[1]    31615 segmentation fault (core dumped)  strace ./l01compiler

得到了......更多信息。看起来ELF标题错误以某种方式,除了以下两个有趣的花絮:

  • 在32位qemu
  • 下运行良好
  • 如果我sudo ./l01compiler
  • ,它运行正常

我有点不知道为什么会这样,即使在互联网上搜索32位和64位Linux内核之间的ELF标头格式之间可能存在差异等等。如果有人有任何信息,我会很高兴

我附上了标题:

willow% readelf -h l01compiler   
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x1e39
  Start of program headers:          52 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         1
  Size of section headers:           40 (bytes)
  Number of section headers:         0
  Section header string table index: 0

1 个答案:

答案 0 :(得分:1)

非常感谢Tom Hebb(tchebb)确认我的怀疑并弄明白这一点。从this commit可以看出,问题是起源地址太低了。它与32位或64位无关,而是与早期内核与新内核相关。

较新的内核增加了 PolicyNumber AgentName Premium Transaction Type A Brien 1,000 New Business 1 A Brien -1,000 Cancelled 1 B Michael 500 New Business 0 C David 600 New Business 0 D Tom 800 New Business 1 D Tom -800 Endorsement 1 sysctl参数,这意味着旧的源会禁止程序启动。这解释了为什么vm.mmap_min_addr有效。正如Tom解释的那样,“除非你使用KVM支持调用qemu,否则qemu是一个模拟器而不是虚拟机管理程序,所以它模拟软件中的整个地址空间和虚拟内存子系统,并且可能不会强加任何加载地址限制。”