通过写入__FILE__动态更改运行代码?

时间:2017-02-11 18:41:03

标签: c

我知道了一种使用__FILE__宏在C中打印正在运行的代码的源代码的方法。因此,我可以寻找位置并使用putchar()来改变文件的内容。

是否可以使用此方法动态更改正在运行的代码?

3 个答案:

答案 0 :(得分:7)

  

是否可以使用此方法动态更改正在运行的代码?

,因为一旦编译了一个程序,它就不再依赖于源文件了。

如果您想了解如何更改已在流程内部运行的流程的行为,您需要了解正在使用的体系结构的程序集,系统上的可执行文件格式以及流程系统上的API,至少。

答案 1 :(得分:4)

计算机并不像我们那样理解代码。它编译或解释它并加载到内存中。我们修改代码只是更改文件。需要编译它并将其与其他库链接并将其加载到内存中。

ptrace()是一个用于将代码注入正在运行的程序的系统调用。您可以调查并实现您想要做的任何事情。

在正在运行的程序中

Inject hello world。我之前的某个时候尝试过并测试过它。

答案 2 :(得分:4)

正如大多数其他答案所解释的那样,实际上,大多数C实现都是compiler。因此,正在运行的executablesource code只有间接(和延迟)关系,因为源代码必须由compiler处理才能生成该可执行文件。

请记住,编程语言是(不是软件,而是......)规范,在某些报告中编写。阅读n1570C11的规范草案。 C的大多数实现都是命令行编译器(例如GCC领域中的Clang/LLVM& free software),即使您might找到interpreters

但是,对于某些operating systems(特别是POSIX,例如MacOSX和Linux),您可以dynamically load一些plugin。或者您可以通过其他方式创建(例如JIT compilationlibgccjitLLVMlibjitGNU lightning库, fresh < / em> function和动态获取指向它的指针(这不符合C标准,其中函数指针应指向您的某些现有函数程序)。

在Linux上,您可以生成(在您自己的程序运行时,与-rdynamic链接以使其名称可以从插件中使用,并使用-ldl库来获取动态加载程序)一些C代码一些临时源文件,例如/tmp/gencode.c,通过例如/tmp/gencode.so插件的命令运行编译(使用例如system(3)popen(3))发出的代码作为gcc -O1 -g -Wall -fPIC -shared /tmp/gencode.c -o /tmp/gencode.so插件
.c,然后使用dlopen(3)动态加载该插件,在dlsym(3)加载的插件中查找函数指针(来自某些传统名称),并间接调用该函数指针。我的manydl.c程序显示可以生成数十万个生成的C文件和加载的插件。我在GCC MELT中使用了类似的技巧。另请参阅thisthat。请注意,您并非真的&#34; self-modify&#34; C代码,你更广泛地生成额外的 C代码,编译它(作为一些插件等等),然后加载它 - 作为扩展或插件 - 然后使用它。

(出于实用的原因,包括易于调试,我不建议覆盖一些现有的C文件,但只是在一些新的临时dlopen中发布新的C代码file-来自某个内部AST - 类似的表示 - 您稍后会提供给编译器)

  

是否可以动态更改正在运行的代码?

一般情况下(至少在Linux和大多数POSIX系统上),机器代码位于code segment的只读virtual address space中,因此您无法更改或覆盖它;但你可以通过函数指针(在你的C代码中)使用间接调用来调用新加载的代码(例如来自 params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, params.bottomMargin + ScreenUtils.getNavigationBarHeight(activity)); - ed插件)。

但是,您可能还会阅读homoiconic种语言,metaprogrammingmulti-staged programming,并尝试使用Common Lisp(例如使用其SBCL实现,它将编译为机器每REPL次互动和每次eval)的代码。我还建议阅读SICP(一个优秀且免费提供的编程介绍,以及与元编程方法相关的一些章节)

PS。 Windows中也可以动态加载插件 - 我不知道LoadLibrary,但是模型非常不同(且不兼容)。阅读Levine的linkers and loaders