Gcc 如何插入特定的汇编指令并获取它们的参数
给定任何使用gcc编译的C/C++Gcc 如何插入特定的汇编指令并获取它们的参数,gcc,assembly,arm,llvm,instrumentation,Gcc,Assembly,Arm,Llvm,Instrumentation,给定任何使用gcc编译的C/C++source.C int func() { // bunch of code ... } 将导致某些程序集(示例) 。最终会变成二进制的source.obj 我想要的是能够指定:在每个汇编指令X之前,调用我的自定义函数并将指令X的参数作为参数传递 我只对给定的汇编指令是否执行感兴趣。如果我说我关心mult,我并不一定说我关心乘法是否发生在原始源代码中。我知道乘以2^N将产生移位指令。我明白了 假设我指定mov作为感兴趣的asm 生成的程序集将更
source.C
int func()
{
// bunch of code
...
}
将导致某些程序集(示例)
。最终会变成二进制的source.obj
我想要的是能够指定:在每个汇编指令X之前,调用我的自定义函数并将指令X的参数作为参数传递
我只对给定的汇编指令是否执行感兴趣。如果我说我关心mult
,我并不一定说我关心乘法是否发生在原始源代码中。我知道乘以2^N
将产生移位指令。我明白了
假设我指定mov作为感兴趣的asm
生成的程序集将更改为以下内容
func():
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #12
// custom code inserted here:
// I want to call another function with the arguments of **mov**
mov r3, #0
str r3, [fp, #-8]
// custom code inserted here:
// I want to call another function with the arguments of **mov**
mov r3, #55
sub sp, fp, #0
ldr fp, [sp], #4
bx lr
我理解自定义代码可能必须推/弹出它使用的任何寄存器,这取决于它对所使用寄存器的了解程度。自定义函数可以是
为什么
在每次执行指令X
时切换pin以进行实时分析。每次
X
的参数满足某些条件时都要记录。您的问题不清楚(即使有了额外的编辑;-finstrument函数
也不是在转换汇编代码,而是在优化和代码生成过程中改变编译器的工作方式;它在中间编译器表示上工作-可能在级别上,而不是在汇编程序或级别上)
也许您可以编写一些在该级别工作的代码(通过添加一个优化过程来转换适当的GIMPLE;顺便说一句,-finstrument functions
选项正在添加更多的过程)。这可能需要数月的工作(您需要了解GCC的内部结构),您将在编译器中添加自己的生成过程的插装
也许你在你的代码中。然后你可以使用一些预处理器宏在它周围插入一些代码
也许您想更改or(或GCC生成汇编代码的方式),然后您需要修补编译器本身(并在其中实现新目标)。这可能需要一年多的工作
请注意GCC所做的各种优化。有时您可能需要volatile asm
,而不仅仅是asm
My提供了许多幻灯片和链接,这些应该对您有所帮助
是否可以使用任何编译器执行此操作
两者都是,因此您可以研究它们的源代码并根据您的需要进行改进。但两者都非常复杂(数百万行源代码),您需要对它们进行几年的工作。当您这样做时,它们将有很大的发展
我想做的是选择一组汇编指令,比如{add
,jump
},然后告诉编译器在该集合中的任何指令之前插入我自己的自定义汇编代码片段
你应该在(例如)上读一些书,在和上读另一本书。你不能在编译器生成的汇编代码中任意插入一些指令(因为你插入的内容需要编译器管理的一些处理器资源,例如thru等等)
编辑后
//我想调用另一个参数为mov
mov r3, #0
这通常是不可能的(或非常困难的),因为调用另一个函数将使用r3
并破坏其内容
gcc-c source.c-o source.obj
是使用GCC的错误方法。您需要(特别是生产二进制文件)。如果您关心汇编程序代码,请使用GCC-O-Wall-fverbose asm-S source.c
(可能是-O2-march=native
而不是-O
),然后查看source.S
假设我指定mul作为感兴趣的asm
同样,这是错误的方法。您关心源代码或某些中间表示中的乘法。对于x*3
,可能不使用-O
而使用-O2
发出mul
在框架级别思考和工作而不是在汇编级别
例子
首先,看看GCC的源代码。它是免费软件。如果你想了解-finstrument functions
是如何工作的,花几个月的时间阅读GCC内部的内容(我提供了链接和参考资料),研究GCC的实际源代码,并询问gcc@gcc.gnu.org
之后
现在,假设您想计算并检测执行了多少次乘法(这与执行多少次IMUL
指令不同,例如,因为8*x
可能会被优化为移位机器代码指令)。当然,这取决于启用的优化,您将在GIMPLE级别工作。您可能会在每个GCC基本块的末尾增加一些计数器。因此,在每次BB退出后,您将插入额外的GIMPLE语句。这样一个简单的插装可能需要数月的工作
或者想象一下,如果可能的话,您希望对负载进行检测,以检测未定义的行为或解决问题。这就是正在做的。它需要花费数年的时间
事情比你所相信的要复杂得多
(GCC现在有大约一千万行源代码并非徒劳
如果您不关心C源代码,就不应该关心GCC。汇编代码可以由JVM实现、由ocamlopt
等生成(所有这些都不使用GCC),也可以由其他版本的GCC生成(不是您正在检测的版本)
因此,花几周时间阅读更多关于编译器的内容,然后问另一个问题。这个问题应该提到什么样的二进制或二进制代码
mov r3, #0