是用C编译后生成的可执行文件可以复制并在任何不同的网络操作系统(UNIX)上运行



我是一名Java程序员,但我在C语言中几乎没有事情要做。因此,我从下面一个简单的示例开始。如果我编译了它并生成了一个可执行文件(hello),我可以在没有原始文件 (hello.c) 的情况下在任何 unix 平台上运行可执行文件 (hello)吗?还有没有办法从可执行文件中读取数据意味着,将可执行文件反编译为原始文件(hello.c)?

[oracle@oracleapps test]$ cat hello.c
#include <stdio.h>
int main(){
int i,data =0;
for(i=1;i<=64;i+=1){
data = i*2;
printf("data=%dn",data);
}
return 0;
}

编译

gcc -Wall -W -Werror hello.c -o hello
您可以在与编译

可执行文件的平台兼容的平台上运行生成的可执行文件。ABI 兼容性基本上意味着在两个(可能不同的)操作系统上使用相同的物理处理器架构和操作系统接口(加上调用约定)。例如, 您可以在 FreeBSD 系统上运行为 Linux 编译的二进制文件 (具有相同的处理器类型), 因为 FreeBSD 包含 Linux ABI 兼容性。但是,可能无法在所有其他类型的 Unice 上运行二进制文件,除非进行了一些黑客攻击。例如,你不能在linux上运行Mac OS X应用程序,但是这家伙有一个解决方案,可以在Linux上使用一些OS X命令行工具(包括GCC编译器本身)。

逆向工程:确实有反编译器旨在从机器代码生成C代码,但它们(还)不是很强大。原因是它们本质上非常难以编写。必须识别机器代码模式,即使这样,您也无法收集所有原始信息。例如,循环的类型、注释和非静态局部变量名称以及大多数类型在编译过程中都消失了。例如,如果您有一个如下所示的 C 源文件:

int main(int argc, char **argv)
{
    int i;
    for (i = 0; i < 10; i++)
    {
        printf("I is: %dn", i); /* Write the value of I */
    }
    return 0;
}

C 反编译器可能能够重建以下代码:

int main(int _var1, void *_var2)
{
    int _var3 = 0;
    while (_var3 < 10)
    {
        printf("I is: %dn", _var3);
        _var3 = _var3 + 1;
    }
    return 0;
}

但这将是一个相当高级的反编译器,例如这个。

不能在任何平台上运行可执行文件。

您可以在没有 .c 文件的其他计算机(或此计算机)上运行可执行文件。 如果是在同一硬件上运行的相同操作系统/发行版。

您可以使用反编译器来反汇编器来读取文件并将其视为汇编或 C——它们看起来不太像原始的 c 文件。

编译的文件是纯机器代码(加上一些元数据),因此它是自给自足的,因为它不需要存在源文件。缺点?机器代码既特定于操作系统,又特定于平台。通过平台,我们通常只指大致的CPU指令集,即"x86"或"PowerPC",但是使用某些编译器标志编译的某些代码可能需要特定的指令集扩展。操作系统依赖性不仅是由可执行文件的不同格式(例如ELF而不是PE)引起的,而且还是由使用特定于操作系统的服务或以特定于操作系统的方式(例如系统调用)的常见操作系统服务引起的。除此之外,几乎所有重要的代码都依赖于某些库(至少是 C 运行时库),因此如果没有兼容版本中的正确库,您可能无法运行可执行文件。因此,您的可执行文件可能不会在已有 10 年历史的专有 UNIX 上运行,并且可能无法在不同的 Linux 发行版上运行(尽管您的程序很有可能运行,因为它可能只取决于glibc)。

虽然机器代码可以很容易地反汇编,但结果是非常低级的,对许多人来说毫无用处。反编译为 C 几乎总是困难得多,尽管有尝试。算法可以恢复,仅仅是因为它们必须以某种方式在机器代码中编码。假设你没有为调试而编译,它永远不会恢复注释、格式、变量名等,所以即使是一个"完美"的反编译器也会产生与你输入的文件不同的 C 文件。

否...

每个平台可能具有不同的可执行格式要求、不同的硬件体系结构、由链接器确定的不同可执行内存布局等。 编译的可执行文件是其当前编译的平台的"本机",而不是其他平台。 不过,您可以在当前计算机上针对其他体系结构进行交叉编译。

例如,即使它们可能有很多相似之处,Linux x86 上的编译可执行文件也不能保证在 BSD 下运行,这取决于它的风格(即,你可能在 FreeBSD 下运行它,但通常不是 OSX 的达尔文版本的 BSD,甚至认为两台机器可能具有相同的底层硬件架构)。 你也不能在运行IRIX的SGI MIPS机器上编译一些东西,并在运行Solaris的Sun SPARC上运行它。

对于 C 程序,程序与编译

它所针对的环境相关联(通常与编译它的平台相同,除非您进行交叉编译)。 您可以将为一个版本的 Linux(和特定的硬件架构)构建的东西复制到另一台运行相同版本 Linux 的相同架构的机器上,你会没事的。 您通常可以在相关版本的 Linux 上运行它。 但是你不会得到在 IA32 机器上运行的 x86/64 代码,也不会在 PPC 机器上运行,也不会在 SPARC机器上运行。 如果基本操作系统足够相似,则可能会让 IA32 代码在 x86/64 计算机上运行。 你也许能或不能得到一些编译的东西,让 Debian 在 RedHat 下运行,反之亦然;这取决于程序使用的库。

Java通过编译一个与平台无关的字节码程序和一个特定于平台的JVM(JRE)在每个平台上运行它来避免这种情况。 这种WORM(一次写入,多次运行)行为是Java的一个关键卖点。

是的,你可以在任何运行qemu unix 上运行它。这与java程序相当,你可以在jvm运行的任何unix上运行。

最新更新