如何完全摆脱 .dynsym、.dynstr 和 .dynamic 部分?

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

我有一个静态链接的二进制文件,我正在尝试缩小它的大小。我不明白为什么它会发出动态部分,而且我认为它不应该这样做。

我认为 -fpic -fPIC 应该摆脱所有重定位,但还剩下一些。 start.s 包含

call main
但它位于同一段内,因此也不应该在那里重定位。

我的Makefile:

hello: start.s hello.c Makefile
        gcc -o hello -nostartfiles -nostdlib -Wl,--no-dynamic-linker -fpic -fPIC -fno-asynchronous-unwind-tables -s start.s hello.c
        strip -R .comment hello

objdump -x

的结果
hello:     file format elf64-x86-64
hello
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000001000

Program Header:
    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**12
         filesz 0x0000000000000261 memsz 0x0000000000000261 flags r--
    LOAD off    0x0000000000001000 vaddr 0x0000000000001000 paddr 0x0000000000001000 align 2**12
         filesz 0x00000000000000bb memsz 0x00000000000000bb flags r-x
    LOAD off    0x0000000000002000 vaddr 0x0000000000002000 paddr 0x0000000000002000 align 2**12
         filesz 0x0000000000000010 memsz 0x0000000000000010 flags r--
    LOAD off    0x0000000000002f30 vaddr 0x0000000000003f30 paddr 0x0000000000003f30 align 2**12
         filesz 0x00000000000000d0 memsz 0x00000000000000d0 flags rw-
 DYNAMIC off    0x0000000000002f30 vaddr 0x0000000000003f30 paddr 0x0000000000003f30 align 2**3
         filesz 0x00000000000000d0 memsz 0x00000000000000d0 flags rw-
    NOTE off    0x0000000000000200 vaddr 0x0000000000000200 paddr 0x0000000000000200 align 2**2
         filesz 0x0000000000000024 memsz 0x0000000000000024 flags r--
   STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
         filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
   RELRO off    0x0000000000002f30 vaddr 0x0000000000003f30 paddr 0x0000000000003f30 align 2**0
         filesz 0x00000000000000d0 memsz 0x00000000000000d0 flags r--

Dynamic Section:
  GNU_HASH             0x0000000000000228
  STRTAB               0x0000000000000260
  SYMTAB               0x0000000000000248
  STRSZ                0x0000000000000001
  SYMENT               0x0000000000000018
  DEBUG                0x0000000000000000
  FLAGS_1              0x0000000008000000

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .note.gnu.build-id 00000024  0000000000000200  0000000000000200  00000200  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .gnu.hash     0000001c  0000000000000228  0000000000000228  00000228  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .dynsym       00000018  0000000000000248  0000000000000248  00000248  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .dynstr       00000001  0000000000000260  0000000000000260  00000260  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .text         000000bb  0000000000001000  0000000000001000  00001000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  5 .rodata       0000000f  0000000000002000  0000000000002000  00002000  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .eh_frame     00000000  0000000000002010  0000000000002010  00002010  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .dynamic      000000d0  0000000000003f30  0000000000003f30  00002f30  2**3
                  CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
no symbols
gcc elf strip
1个回答
0
投票

经过几个小时的研究,我得到了一个可行的答案。这个

ld
脚本有效。

SECTIONS {
#   . = 0x10000;
    . = 0;
    .text : { *(.text) *(.rodata) }
    .note.gnu.build-id : { *(.note.gnu.build-id) }
    .data : ALIGN(4096) { *(.data) }
    .bss : ALIGN(4096) { *(.bss) }
    /DISCARD/ : { *(.dynsym) *(.dynstr) *(.dynamic) *(.gnu.hash) }
    /DISCARD/ : { *(.comment) }
}

构建命令是

gcc -o hello -Wl,-T,merge.ld -Wl,--no-dynamic-linker -fpic -fno-asynchronous-unwind-tables -pie -nostartfiles -nostdlib -s start.s hello.c

如果全局变量中有任何初始化的指针,这将会爆炸。为什么?因为我们是可搬迁的,而且我们没有任何搬迁,所以实际上没有办法表达这一点。

const char *message = "Hello, World";

是毒药。

const char message[] = "Hello, World";

还好。

如果您需要初始化全局指针才能工作;通过将

. = 0;
更改为
. = 0x10000;
行并从构建指令中删除
-fpic -fpie
来放弃 ASLR。

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