如何在C/C ++中存储和调用已编译的函数? [英] How to store and call a compiled function in C / C++?

查看:94
本文介绍了如何在C/C ++中存储和调用已编译的函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于非常低级别的优化目的,如果我可以将已编译的函数直接存储在变量中,而不是指向函数的指针,则对我很有用.也就是说,如果我有一个函数foo,我想使一个char缓冲区足够大,以容纳为foo生成的机器指令,然后通过以某种方式告诉C将执行跳转到该缓冲区的内容,从而实际上可以调用foo. (假设我有一个内在的编译器,以确保char缓冲区适合于我的体系结构).理想情况下,我想做到这一点,以尽量减少程序集的使用(我意识到可能需要这样做).

For very low level optimization purposes it would be useful to me if I could store a compiled function inside a variable directly, not a pointer to a function. That is, if I have a function foo, I want to make a char buffer large enough to hold the machine instructions generated for foo, and then be able to in effect call foo by somehow telling C to jump execution to the contents of that buffer (assume that I have a compiler intrinsic to make sure the char buffer is aligned properly for my architecture). Ideally, I'd like to do this keeping assembly usage to a minimum (I realize some might be required).

到目前为止,我最好的解决方案是编译一个程序,该程序具有我要与GCC进行汇编的功能,然后编译为机器代码,然后使用输出程序集中的地址从可执行文件中提取所需的机器代码,然后使用我程序中的缓冲区手动填充缓冲区,然后使用内联汇编程序跳转到缓冲区的起始地址.比我想要的还要麻烦和手动.

My best solution so far would be to compile a program that has just the function I want to assembly with GCC, then compile to machine code, then use the addresses from the outputted assembly to extract the desired machine code from the executable, then manually fill the buffer with that in my program, then use inline assembly to jump to the starting address of the buffer. That's more hackish and manual work than I would like though.

我不需要在运行时编译新函数,只需让缓冲区包含与运行时不同的已编译函数相对应的指令即可.例如.我可能有3个编译函数和1个缓冲区.这3个函数在编译时是已知的,但是在运行时,缓冲区可能在不同的时间对应于3个函数中的任何一个.

I don't need to compile new functions at runtime, just have the buffer contain instructions corresponding to different already compiled functions during runtime. E.g. I might have 3 compiled functions, and 1 buffer. The 3 functions are known at compile time, but at runtime the buffer may correspond to any one of the 3 at different times.

为了阐明将要获得的收益:我有一个结构,该缓冲区将成为该结构的成员,并具有指向该结构实例的各种指针.每个结构的缓冲区可能包含不同的编译函数.如果要使用函数指针而不是缓冲区,则必须加载该结构的函数指针,然后解引用该函数指针.使用缓冲区,我可以将程序计数器跳到结构基数的偏移量(缓冲区的相对位置).这是间接的少一层.对于非常小的功能,这可以节省开支.

To clarify what there would be to gain: I have a struct of which this buffer will be a member, and various pointers to instances of that struct. Each struct's buffer may contain a different compiled function. If I were to use a function pointer instead of the buffer, I would have to load the struct's function pointer, then deref the function pointer. With the buffer, I can just jump the program counter to an offset (the buffer's relative location) of the base of the struct. It's one less level of indirection. For very tiny functions, this can be a savings.

进一步说明:

带有功能指针:

  1. 从& struct + offsetof(pointer)加载指针
  2. 跳转到指针中包含的位置

带有包含机器代码的缓冲区:

With a buffer that contains machine code:

  1. 跳转到& struct + offsetof(buffer)

第二个是更少的步骤.

推荐答案

我不确定为什么要排除函数指针-如果您没有在运行时修改代码,那么我就不会想到包含函数的缓冲区可以做到函数指针无法做到.

I'm not sure why you are excluding function pointers - if you aren't modifying the code at runtime, then I can't think of anything that a buffer containing a function could do that a function pointer couldn't.

也就是说,您有一个指向包含函数的缓冲区的指针,只需将指向该缓冲区的指针转换为正确的函数指针类型并进行调用.当然,如果您的操作系统/CPU支持它,则还必须清除NX标志,以防止您运行不可执行的代码.

That being said, one you have a pointer to a buffer containing your function, just cast a pointer to that buffer to the right function pointer type and call that. Of course if your operating system / CPU supports it, you'll also have to clear the NX flag that prevent you from running non-executable code.

此外,您不能假设您可以复制包含可执行数据的缓冲区,就好像它们包含常规数据一样-您必须修复分支和跳转以及其他内存访问.

Also, you can't assume that you can copy buffers containing executable data around as if they contained regular data - you'll have to fix up branches and jumps and other memory accesses.

我明白了您的意思,但是我认为您将无法找到一种将函数放入缓冲区的符合标准的方法-C ++很少谈到内存结构以及函数存储的位置.抽象概念.您可能会遇到很多麻烦,或者使用可以在编译时进行汇编并在运行时从文件中加载的单独的汇编文件.

I see what you're getting at, but I don't think you'll be able to find a standard-compliant way to get a function into a buffer - C++ says very little about memory structure and where functions are stored is a rather abstract concept. You may be stuck with a bunch of hacks, or else using separate assembly files that can be assembled at compile time and loaded from the files at run-time.

另一方面,我认为您可能发现对函数指针(可能为4-8字节)进行双重解引用比在高速缓存中丢失能够保存最大函数的缓冲区丢失要快得多.将需要.具有附加函数的结构与类上的虚函数有很多相似之处.大多数(全部?)C ++编译器都有一个用vtable实现虚拟函数的原因,而不是为类的每个实例存储整个函数定义,这是有原因的.这并不是说不可能将整个函数存储在缓冲区中而获得性能上的提高,但这并不像看起来那样简单.

On another note - I think that you may find that it is faster to do the double dereferencing of storing the function pointer (4-8 bytes likely) than suffer the cache misses of storing a buffer capable of holding the largest function you will need. Your struct with an attached function has many similarities with virtual functions on classes. There are reasons why most (all?) C++ compilers implement virtual functions with a vtable rather than store the entire function definition for every instance of the class. That's not to say it's not possible that you'll get a performance increase out of storing the whole function in a buffer, it's just not as straight-forward as it may seem to be.

这篇关于如何在C/C ++中存储和调用已编译的函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆