获取C++函数的"size"(长度)?
Get the "size" (length) of a C++ function?
可能重复:
如何获得以字节为单位的函数长度?
我正在制作一个Hooking程序,该程序将用于将一个方法插入内存的指定部分。
我需要得到一个局部C++函数的长度,我已经使用了一个强制转换来获得一个函数的位置,但我该如何获得长度?
int GetFuncLen()
{
int i = 0;
while((DWORD*)Function+i<max)
{
if((DWORD*)Function+i==0xC3)
{
return i;
}
i++;
}
}
工作?
您的代码似乎是特定于操作系统、编译器和机器体系结构的。
(我对Windows一无所知)
如果未定义max
,则可能是错误的。
它是特定于操作系统的(可能仅限于Windows),因为DWORD
不是标准的C++类型。您可以使用intptr_t
(来自<cstdint>
标头)。
您的代码是特定于编译器的,因为您假设每个编译的函数都有一个定义良好的唯一结束,并且不与其他一些函数共享任何代码。(一些编译器能够进行这样的优化,例如,使用跳转指令使两个函数共享一个公共的尾声或代码块)。
您的代码是特定于机器的,因为您假设最后一条指令是RET
编码的0xC3
,而这是特定于x86&x86-64(无法在Alpha或ARM上工作,据传Windows已经或将要在其上移植)。此外,该字节可能出现在其他指令或内联常量中(正如Mat所评论的)。
我不确定二元函数在哪里结束的概念是否有明确的含义。但如果是这样,我希望链接器可能知道它。在一些系统上,例如在具有ELF可执行文件的Linux上,编译器和链接器会产生每个函数的大小。
也许你最好在给定地址附近找到这个符号。我不知道Windows是否有这样的功能(在Linux上,<dlfcn.h>
中的dladdrGNU函数可能很有用)。也许你的操作系统提供了一个等效的?
编号。有几个原因。
1) 如果0xC3位于预期新指令的位置,则它只是一条"ret"指令。很容易有其他指令在其操作数中包含0xc3字节,并且您只能获得部分代码。
2) 在任何给定的函数中都可以有多个"ret"指令,这取决于编译器及其设置。同样,你只能得到函数的一部分。
3) 函数经常使用像"switch"语句这样的结构,这些结构使用位于ret指令之后的"跳转表"。同样,你只能得到函数的一部分。
而且你想做的事情无论如何都不太可能奏效。
最大的问题是,各种汇编指令通常会使用偏移量而不是绝对地址来引用内存的特定区域。因此,尽管极小的函数可能会工作,但任何调用其他函数的函数都可能失败。
假设您正试图将这些函数加载到外部进程中,并且您正试图在Windows上执行此操作,则更好的解决方案是使用DLL注入将DLL加载到目标进程中。
如果您真的需要注入内存,那么您将需要针对特定平台的汇编语言解析器来更新相关指令的所有内存地址,这是一项非常复杂的任务。或者,你可以用汇编语言编写函数,并确保除了引用自己代码的部分之外,你没有对任何事情使用相对偏移,这有点容易,但对你能做的事情更具限制性http://msdn.microsoft.com/en-us/library/s20kdbse(v=VS.71).aspx).
我认为,如果你定义一个部分,在其中声明一个变量,在其中定义你的函数,然后在其中定义另一个变量——那么这两个变量的地址将覆盖你的函数。
更好的方法是将两个变量和函数放在单独的部分中,然后使用部分合并来控制它们在结果代码中的显示顺序(请参阅如何在Visual Studio项目中引用用户定义的段的开头?)
正如其他人所指出的,你可能无法用它做任何有用的事情,而且它根本不可移植。
唯一可靠的方法是使用函数长度的虚数编译代码(但不运行它),对其进行反汇编,并手动计算长度,然后取该数字并将其替换为虚数,然后重新编译程序。
当我需要这样做的时候,我只是猜测函数应该有多大。只要你的猜测不太小(也不太大),你就应该没有问题。
您可以使用
- objdump
以获取具有外部链接的对象的大小。否则,您可以获取编译器的汇编输出(例如gcc-S)并手动进行汇编,您将有机会查看长度字段的名称:
.file "test.cpp"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.6.0-3~ppa1) 4.6.1 20110409 (prerelease)"
.section .note.GNU-stack,"",@progbits
参见.size main, .-main
评估:它计算函数大小
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 从C字符串中获取奇怪的字符串长度
- 大于65535的C++数组[size]引发不一致的溢出
- 如何在数组中找到字符串的长度
- 获取字符串的长度并将其分配给数组
- 数组长度,为什么从命令行获取时不能使用它?
- 为什么(-1)%vector::size()总是返回0
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 在一定长度后从数组中打印时缺少整数
- 为什么这个 c++ 代码打印出长度 5,当我打印出字符串时,程序会自动终止?
- 在C++中查找范围的长度
- 带有指定长度字符* 参数的 std::regex_search 在 VS2017 中不起作用?
- 如何创建长度由常量参数指定的数组
- 求最长递增子序列C++的长度
- 如何在 nlohmann 的 json 库中获取数组长度?
- 使用C++进行运行长度解压缩
- 为什么向量不支持 size 作为成员变量,就像 Java 类中的长度变量一样,而是函数 size()?
- 在 c++ 中,std::string::size() 不计算修改后的字符串长度
- 获取C++函数的"size"(长度)?
- 标准::位集中<size>的可变位长度