assembly 在Windows和Linux(x86)上使用相同的二进制代码

j2datikz  于 2022-11-13  发布在  Windows
关注(0)|答案(7)|浏览(157)

我想把一堆C++文件编译成原始机器代码,然后用C语言编写的依赖于平台的启动程序运行它。

fread(buffer, 1, len, file);
a=((*int(*)(int))buffer)(b);

我如何告诉g++输出原始代码?
函数调用是否有效?如何使其有效?
我认为Linux和Windows的调用约定不同。这是一个问题吗?我该如何解决它?
编辑:我知道PE和ELF会阻止可执行文件的直接启动,但这正是我使用启动程序的目的。

ldxq2e6h

ldxq2e6h1#

有一种(相对)简单的方法可以实现这些,那就是“位置无关代码”。
这意味着你可以把一些源代码编译成一个二进制代码,无论你把它放在地址空间的什么地方,它都可以执行。如果你在一个文件中有这样一段x86二进制代码,并且它是mmap()(或者Windows的等价物),那么你就可以在Linux和Windows中调用它。
已经提到的限制当然仍然存在--即,二进制代码必须限制自己使用在两个平台上相同的调用约定/可以在两个平台上表示(对于32位x86,这将在堆栈上传递参数并在EAX中返回值),当然,代码必须完全自包含-没有DLL函数调用,因为解析这些函数依赖于系统,也没有系统调用。
例如:
1.您需要与位置无关的代码
1.您必须创建没有任何外部依赖项的自包含代码
1.必须从目标文件中提取机器代码。
然后mmap()那个文件,初始化一个函数指针,和(*myblob)(someArgs)可能做的一样。
如果您使用的是gcc,-ffreestanding -nostdinc -fPIC选项应该可以给予前两个选项的大部分功能,然后使用objdump从ELF对象文件中提取二进制blob。

ukqbszuj

ukqbszuj2#

从理论上讲,其中一些是可以实现的。但是,在这个过程中有太多的陷阱,这并不是一个真正实用的解决方案。

  • 系统调用格式完全不兼容
  • DEP将阻止数据作为代码执行
  • 内存布局不同
  • 在运行代码之前,您需要有效地动态“重新链接”代码。
  • ...等等...
dddzy1tm

dddzy1tm3#

同一个可执行文件不能同时在Windows和Linux上运行。
您可以独立于平台编写代码(STL、Boost和Qt可以帮助您),然后在Linux上用G++编译以输出Linux二进制文件,在Windows平台上的编译器上也是如此。
编辑:另外,也许这两篇文章可能会对你有所帮助:
一个
两个

50few1ms

50few1ms4#

你为什么不看看wine呢?它是用于在Linux上使用windows可执行文件的。另一个解决方案是使用Java或.NET字节码。
您可以在Linux上运行.NET可执行文件(需要mono运行时)
还可以查看Agner的objconv(反汇编、将PE可执行文件转换为ELF等)http://www.agner.org/optimize/#objconv

wwodge7n

wwodge7n5#

实际上有人发现了这一点,它被称为αcτµαlly pδrταblε εxεcµταblε(APE)并使用Cosmopolitan C库。要点是有一种方法可以使Windows PE可执行文件头被忽略并被视为shell脚本。MacOS也是如此,允许您定义单个可执行文件。此外,他们还弄清楚了如何将ZIP偷运到其中,以便它可以在运行时增量压缩文件的各个部分/解压缩。
https://justine.lol/ape.htmlhttps://github.com/jart/cosmopolitan显示器
在Linux和Windows上运行的一个相同Lua二进制文件的示例:https://ahgamut.github.io/2021/02/27/ape-cosmo/

6ju8rftf

6ju8rftf6#

这样做会相当复杂。这不仅仅是发出cpu命令的问题,编译器还依赖于许多链接到代码中的库。这些库必须在运行时匹配,否则编译器将无法工作。
例如,STL库是一系列的模板和库函数,编译器将内联一些结构,并为其他结构调用该库,它必须是完全相同的库才能工作。
现在,从理论上讲,您可以避免使用任何库,而只编写基础知识,但即使在那里,编译器也可能会对它们的工作方式、涉及的数据对齐类型、调用约定等做出假设。
不要误解我的意思,它可以工作。看看WINE项目和其他在Linux上使用的Windows原生驱动程序。我只是说,这不是你可以快速和轻松地完成的事情。
更好的方法是在每个平台上重新编译。

4uqofj5v

4uqofj5v7#

只有当您的Linux系统上有WINE可用时才能实现这一点。否则,可执行文件格式的差异将阻止您在Linux上运行Windows代码。

相关问题