如何让bash从stdin执行ELF二进制文件?

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

由于一些不明原因,我正在尝试编写一个bash脚本,它生成一些源代码和gcc使用它

... whatever ... | gcc -x c -o /dev/stdout

现在,我想在编译上执行结果。我怎么能做到这一点?请不要使用文件。

bash pipeline execution
2个回答
2
投票

正如Charles Duffy所说,要执行二进制文件,你必须告诉你的操作系统(这似乎是一个Unix变种)来加载和执行某些东西 - 而Unix系统只需要文件来直接执行它们。

你可以做的是有一个进程准备一个包含ELF二进制文件的内存区域,分叉并跳转到该区域 - 但即使这是有问题的,考虑到有CPU支持来完全抑制该操作(R ^ X)。基本上,你需要的是一个运行时链接器,而shell不会(也不应该)包含类似的东西。

让我们放弃Bash要求(这听起来好像你正试图在比我脾气暴躁的应用程序中找到一个明显的漏洞):

通常,要求ELF(文件格式)并同时避免文件有点复杂。 GCC生成机器代码。如果您只想执行已知的机器代码,请将其放入某个缓冲区,构建一个指向该函数的函数指针并调用它。就那么简单。但是,您显然没有执行ELF二进制文件或加载共享对象(dlopen)的过程所具有的所有良好的重定位和动态链接。

如果你想要那样的话,我会看看像LLVM这样的方向 - 我知道,事实上,有人建立“我在运行时编译C ++并执行它”,LLVM作为执行实例,并作为编译器进行操作。最后,你的gcc|something真的只是JIT - 一项古老的技术:)


0
投票

如果您的目标是根本不写入文件系统,那么bash和任何其他UNIX程序都无法帮助您从管道执行ELF - execve只需要一条常规文件的路径作为其filename并且将失败(将errno设置为EACCES)如果您传递一个特殊文件(设备或命名管道)或目录。

但是,如果您的目标只是不留下任何永久性碎片,那么您只需创建文件,执行它,然后立即删除它:

... whatever ... | gcc -x c -o ./temppath.out
temppath.out &
rm temppath.out

与Windows不同,UNIX不会阻止您在执行二进制文件时删除它 - 该进程将在内部保存到该文件的硬链接,然后在终止时释放该硬链接,从而从磁盘中删除该文件。这实际上是UNIX程序中相对常见的模式 - 程序有时会在其运行时目录中创建一个文件,打开它,然后将其与文件系统取消链接,从而创建一个持续程序生命周期的临时文件(通常为内存映射区域)。

而且,实际上,大多数构建系统都有工具使这种“后续删除”模式非常简单 - 源代码控制系统通常会将一个或多个目录标记为忽略,以防止意外提交,然后构建系统可以存储所有的临时工,包括临时二进制文件,都在那里。如果需要,“干净”命令可以从磁盘擦除所有这些临时对象。

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