基本上,我试图找到一种可靠的方法来获取 C 函数的长度(以字节为单位)。
一些人建议使用函数的地址和紧随其后的另一个函数的地址。我不想使用这种方法,因为我认为它不可靠。编译器可以移动一些东西,这看起来有点黑客行为。
我提出的解决方案是在函数的开头和结尾使用两个标签。我已经声明了标签:
__asm__ __volatile__("func_start/end:");
现在,我的问题是,我无法将这些标签的地址放回到 C 中的变量中。
这是我已经尝试过的一些代码:
unsigned int addr, len;
__asm__ __volatile__("mov $func_start, %[address]\n\t"\
"mov $func_end, %[length]\n\t"\
: [address]"=r"(addr), [length]"=r"(len));
__asm__ __volatile__("mov %0, $func_start \n\t"\
"mov %1, $func_end\n\t"\
: "=r"(addr), "=r"(len));
这两个示例在编译期间都会给出错误“ARM register Expected”。由于我对 ARM 汇编不太有经验(更不用说 x86),所以我不确定出了什么问题。我尝试将以下 x86 代码移植到 ARM:
__asm__ __volatile__("movl $enc_start, %0\n\t"\
"movl $enc_end, %1\n\t"\
: "=r"(addr), "=r"(len));
我显然在这里做错了什么。如果有人能解释我做错了什么,我将不胜感激。我已经被这个问题困扰了几个星期了。谢谢!
最佳答案
没有可靠的方法来获取函数的长度,因为函数的长度没有明确定义的含义。
C 实现可以内联函数。它可能会在某些地方内联该函数,并在另一个地方提供非内联版本。该函数可能在其入口点之前有代码。该函数可能在其退出点之后有代码。一个函数可能有多个退出点。调用的其他例程可能内联在函数内部。该函数可能与其他函数共享代码(例如,两个函数执行相同的操作,除了一个函数在开始之前对其参数执行一些轻微的操作外,可能会为大多数通用代码提供两个单独的入口点)。一个函数可能在一个地方有一些代码,在另一个地方有其他代码,中间还有其他函数的代码。即使编译器将函数编写为单个代码序列,函数也可能会被链接器分解为 block 并重新排列。 (OS X 就是这样做的。)
如果您想在上述情况下坚持下去,您可以尝试:
#include <stdio.h>
static void foo(void)
{
__asm__ __volatile__("_foo_start:");
printf("Hello, world.\n");
__asm__ __volatile__("_foo_end:");
}
int main(void)
{
extern const char foo_start[], foo_end[];
printf("Difference = 0x%tx.\n", foo_end - foo_start);
foo();
return 0;
}
当然,C 标准不支持它。
关于c - 通过ARM(使用GCC)获取C中汇编标签的地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17304933/