有没有办法删除GNU_STACK段

问题描述 投票:0回答:3

我正在尝试使用 gcc/binutils 创建最小可执行文件。 我的 ld 脚本如下:

OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
              "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64"); SEARCH_DIR("/usr/lib64/binutils/x86_64-pc-linux-gnu/2.35.164"); SEARCH_DIR("/usr/local/lib64"); SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib"); SEARCH_DIR("/usr/lib64/binutils/x86_64-pc-linux-gnu/2.35.1"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
SECTIONS
{
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
  .text           :
  {
    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
    *(.text.exit .text.exit.*)
    *(.text.startup .text.startup.*)
    *(.text.hot .text.hot.*)
    *(SORT(.text.sorted.*))
    *(.text .stub .text.* .gnu.linkonce.t.*)
    /* .gnu.warning sections are handled specially by elf.em.  */
    *(.gnu.warning)
  }

  .data           :
  {
    *(.data .data.* .gnu.linkonce.d.*)
    SORT(CONSTRUCTORS)
  }
  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
  }
}

对我来说一切都很好,除了我看到一个名为“GNU_STACK”、大小为 0 的额外段头。 标头当然增加了 56 个字节。有谁知道如何删除它?手工创建 elf 太疯狂了,我想使用 gcc/binutils 来完成。

linux gcc binutils
3个回答
1
投票

看来没办法了。最后我修改了 binutils 源以将其删除。


1
投票

注意:需要

GNU_STACK
ELF 程序头条目将堆栈标记为在旧系统(例如 32 位 x86、arm 和 powerpc)上不可执行。如果删除它,堆栈将自动被内核标记为可执行文件:

linux-5.17/arch/arm/kernel.elf.c#n80

在现代架构中不需要 GNU_STACK,因此应使用以下内容修改链接器脚本:

OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
              "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64"); SEARCH_DIR("/usr/lib64/binutils/x86_64-pc-linux-gnu/2.35.164"); SEARCH_DIR("/usr/local/lib64"); SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib"); SEARCH_DIR("/usr/lib64/binutils/x86_64-pc-linux-gnu/2.35.1"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");

PHDRS
{
    READONLY PT_LOAD FILEHDR PHDRS;
    READWRITE PT_LOAD;
}

SECTIONS
{
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
  .text           :
  {
    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
    *(.text.exit .text.exit.*)
    *(.text.startup .text.startup.*)
    *(.text.hot .text.hot.*)
    *(SORT(.text.sorted.*))
    *(.text .stub .text.* .gnu.linkonce.t.*)
    /* .gnu.warning sections are handled specially by elf.em.  */
    *(.gnu.warning)
  } : READONLY

  . = ALIGN(0x1000);

  .data           :
  {
    *(.data .data.* .gnu.linkonce.d.*)
    SORT(CONSTRUCTORS)
  } : READWRITE
  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
  }
}

根据需要更改

PHDRS
配置。

如果删除

GNU_STACK
条目,您可能应该使用
-Wtrampoline
-fno-trampolines
编译器标志:

3.8 请求或抑制警告的选项

3.17 代码生成约定选项


0
投票

patchelf 0.18.0 支持在二进制文件上打印、清除和设置可执行堆栈状态。

“--print-execstack” 打印 GNU_STACK 程序头的可执行标志的状态(如果存在)。

“--clear-execstack” 清除 GNU_STACK 程序头的可执行标志,或添加新头。

“--set-execstack” 设置 GNU_STACK 程序头的可执行标志,或添加新头。

© www.soinside.com 2019 - 2024. All rights reserved.