如何在Linux中创建静态链接的位置无关的可执行ELF? [英] How to create a statically linked position independent executable ELF in Linux?

查看:230
本文介绍了如何在Linux中创建静态链接的位置无关的可执行ELF?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个独立于Linux的独立x86_64 hello世界:

I have a working position independent Linux freestanding x86_64 hello world:

main.S

.text
.global _start
_start:
asm_main_after_prologue:
    /* Write */
    mov $1, %rax    /* syscall number */
    mov $1, %rdi    /* stdout */
    lea msg(%rip), %rsi  /* buffer */
    mov $len, %rdx  /* len */
    syscall

    /* Exit */
    mov $60, %rax   /* syscall number */
    mov $0, %rdi    /* exit status */
    syscall
msg:
    .ascii "hello\n"
len = . - msg

我可以用它组装并运行:

which I can assemble and run with:

as -o main.o main.S
ld -o main.out main.o
./main.out

由于将其链接为PIE,每次看到它都会加载到随机地址,从而带来一些乐趣.

Since it is position independent due to the RIP relative load, now I wanted to link it as a PIE and see it get loaded at random addresses every time to have some fun.

首先,我尝试过:

ld -pie -o main.out main.o

但随后运行失败并显示以下信息:

but then running it fails with:

-bash: ./main.out: No such file or directory

readelf -Wa表示出于某种原因使用了奇怪的解释器/lib/ld64.so.1而不是常规的解释器/lib64/ld-linux-x86-64.so.2.

and readelf -Wa says that a weird interpreter /lib/ld64.so.1 was used instead of the regular one /lib64/ld-linux-x86-64.so.2 for some reason.

然后,我得知他实际上是推荐的系统V AMD64 ABI 解释器名称位于5.2.1程序解释器".

I then learnt that his is actually the recommended System V AMD64 ABI interpreter name at 5.2.1 "Program Interpreter".

无论如何,我然后尝试通过以下方法强制解决问题:

In any case, I then try to force matters with:

ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o main.out main.o

现在可以正常工作:我得到hello,并且每次根据GDB将可执行文件加载到另一个地址.

and now it works: I get hello and the executable gets loaded to a different address every time according to GDB.

最后,作为最后一步,我还希望将该可执行文件静态链接,以使事情变得更加微不足道,并有可能摆脱明确的-dynamic-linker.

Finally, as a final step, I wanted to also make that executable be statically linked to make things even more minimal, and possibly get rid of the explicit -dynamic-linker.

那是我做不到的,这就是为什么我在这里问.

That's what I could not do, and this is why I'm asking here.

如果我尝试以下任一方法:

If I try either of:

ld -static -pie -o main.out main.o
ld -static -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -o main.out main.o

-static似乎没有什么区别:我仍然得到动态可执行文件.

-static does not seem to make any difference: I still get dynamic executables.

快速浏览 fs/binfmt_elf.c 我看到了一条有趣的评论:

After quickly glancing at the kernel 5.0 source code in fs/binfmt_elf.c I saw this interesting comment:

         * There are effectively two types of ET_DYN
         * binaries: programs (i.e. PIE: ET_DYN with INTERP)
         * and loaders (ET_DYN without INTERP, since they
         * _are_ the ELF interpreter). The loaders must

所以我想当我实现自己想要的功能时,我将拥有一个有效的解释器,因此,我将使用自己的最小hello世界作为另一个程序的解释器.

so I guess when I achieve what I want, I will have a valid interpreter, and I'm so going to use my own minimal hello world as the interpreter of another program.

我稍后可能会尝试的一件事是看看某些libc实现如何编译其加载程序并复制它.

One thing I might try later on is see how some libc implementation compiles its loader and copy it.

相关问题:与编译位置无关具有64位计算机上的静态链接库的可执行文件,但其中提到了一个外部库,因此希望它是最小化和可回答的.

Related question: Compile position-independent executable with statically linked library on 64 bit machine but that mentions an external library, so hopefully this is more minimal and answerable.

在Ubuntu 18.10中进行了测试.

Tested in Ubuntu 18.10.

推荐答案

您要将--no-dynamic-linker添加到链接命令:

You want to add --no-dynamic-linker to your link command:

$ ld main.o -o main.out -pie --no-dynamic-linker

$ file main.out
main.out: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, not stripped

$ ./main.out
hello

所以我想当我实现自己想要的功能时,我将拥有一个有效的解释器,因此,我将使用自己的最小hello世界作为另一个程序的解释器.

so I guess when I achieve what I want, I will have a valid interpreter, and I'm so going to use my own minimal hello world as the interpreter of another program.

我不确定我是否理解您的正确说法.如果您要表示main.out将自己作为其解释器,那是错误的.

I am not sure I understood what you are saying correctly. If you meant that main.out would have itself as its interpreter, that's wrong.

P.S. GLIBC-2.27 添加了对-static-pie的支持,因此您不再必须求助于汇编以获得静态链接的PIE二进制文件.但是您必须使用最新的GCC和GLIBC.

P.S. GLIBC-2.27 added support for -static-pie, so you no longer have to resort to assembly to get a statically linked PIE binary. But you'll have to use very recent GCC and GLIBC.

这篇关于如何在Linux中创建静态链接的位置无关的可执行ELF?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆