繁体   English   中英

将函数写入二进制文件?

[英]Writing functions to binary files?

令我颇为奇怪的是,由于在适当的情况下C ++可以将函数作为参数传递,这表明可以指向处理该函数的任何内部代码,然后将其写入并读入二进制文件作为其可执行文件。码。

这显然来自某人,虽然我可能具有C ++的深厚背景,但我对如何在堆中管理内​​存,尤其是如何将可执行的机器代码放入图片中的复杂内部结构并不熟悉。

我假设由于可以将引用传递给函数,因此可以获取它指向的数据并将其写入某个地方。 我不知道。

有人想告诉我这是否可能吗? 如果是这样,您能举个例子吗? 如果没有,请告诉我原因! 我喜欢更深入地了解C ++内部实际工作方式。

20年前,您的建议可能是新鲜且有用的。 人们通过按需从文件中加载代码,然后调用它,然后卸载来节省内存。 那就是所谓的叠加。 它在某种程度上是可用的,但是以平台和平台API标准化的形式来管理它。 共享库(在POSIX系统中为.so,在Windows中为.dll)背后的机制是该库的文件包含某些功能所在的标签,它们的名称以及有关如何初始化堆栈和数据段的数据。 程序加载后,可以由系统自动完成。 否则,您可以手动加载库并加载指向函数的指针。 例如,在Windows上将由Linux上的LoadLibrary()和GetProcAddress(),dlopen()和dlsym()来实现。

为什么现在无法使用高级语言:安全性,防止数据段中的恶意代码。 运行时库通常会处理它。 仍然可以使用汇编程序,但是您将挑战防病毒和系统安全措施。 我想,通过仔细的编程,您可以创建自己的“链接器”,并且可以创建自己的库并加载。

不,您不能真正做到这一点。 有很多原因,但这是一个简单而直观的原因:函数可以调用其他函数。 如果您能够将函数写入磁盘并进行还原,则不会考虑其依赖性(它调用的函数,它更新的全局变量等)。 它不会工作。

如果要从磁盘读取功能,最好使用Lua之类的脚本语言来表达它们。 这是一种经过验证的解决方案,已用于许多商业产品中,例如视频游戏和Adobe Lightroom。

虽然函数指针是函数的入口点,并且可以读取并复制该内存,但第一个问题是没有可靠的方法来确定该代码的长度,因此您无法确定要复制多少获得整个功能,仅此而已。

另一个问题是要达到什么实际目的? 根据平台的不同,代码可能无法重定位,并具有指向其他代码的链接。 二进制文件不包含任何符号信息。 最好的办法是将其反汇编,但是在整个链接的可执行文件的上下文之外,这样做可能不是很有用。

如果您的目标是将功能与主要可执行文件分离,并在以后能够加载和运行它们,那么这就是DLL和共享库的用途。

如果您只想观察与函数相关的二进制文件,那么最好在调试器中完成-它将具有反汇编视图模式,该模式将显示原始二进制文件(以十六进制形式),带有符号链接的汇编代码以及相应的C源代码。 如果您的目的仅仅是研究源代码与二进制机器码之间的关系,那么这将更有意义。

以下是您可能如何做的事情-即使没有实际的理由也可以这样做。 它对编译器的行为进行了假设,在某些情况下可能是无效的。 它假定例如,该编译器将相邻的功能连续地在存储器中并在增加存储器地址,使function2 立即是function1在存储器中。 这里function2仅作为一个结束标记function1 ,并且可以是伪。

int function1()
{
    ...

    return 0 ;
}

void function2() 
{
}

#include <stddef.h>

int main()
{
    ptrdiff_t function1_length = (char*)function2 - (char*)function1 ;

    FILE* fp = fopen( "function1.bin", "wb" ) ;
    fwrite( function1, function1_length, 1, fp ) ;
    fclose( fp ) ;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM