Objective-C 中__builtin_frame_address包括哪些信息
时间: 2024-03-18 15:42:51 浏览: 63
在Objective-C中,`__builtin_frame_address`函数返回当前函数调用堆栈中某个帧的地址。通过这个地址,可以获取以下信息:
- 函数的返回地址:返回地址指向当前函数调用结束后要返回的地址,通常是调用该函数的下一条指令的地址。
- 函数的参数:在当前函数调用堆栈中,参数通常是在当前帧的上一个帧中保存的。可以通过指针运算获取参数的地址和值。
- 函数的局部变量:在当前函数调用堆栈中,局部变量通常是在当前帧中保存的。可以通过指针运算获取局部变量的地址和值。
需要注意的是,获取函数参数和局部变量的地址和值需要对应的参数和类型信息,否则可能会出现错误的结果。同时,使用`__builtin_frame_address`函数获取函数调用堆栈的信息可能会有一定的限制,具体取决于编译器和平台的实现。
相关问题
``` int __lg(unsigned long long __n) { return sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); }```如何写成一个正常的函数
这段代码是一个内联汇编函数,用于计算一个无符号长整型 `unsigned long long` 变量 `__n` 的二进制补码表示中最右边的连续零位的数量,减去1,得到其对应的底数2的对数(即比特位数)。这是通过`__builtin_clzll`内置函数实现的,该函数返回从最低有效位到第一个连续的1之间的0的个数。
如果将其转换为标准C++函数的形式,可以这样编写:
```cpp
#include <climits> // 包含clzll函数
size_t log2ULL(unsigned long long n) {
static_assert(sizeof(unsigned long long) == CHAR_BIT * sizeof(size_t), "Assuming sizeof(long long) is a multiple of sizeof(size_t)");
return sizeof(unsigned long long) * CHAR_BIT - 1 - __builtin_clzll(n);
}
```
这里,我们创建了一个名为`log2ULL`的常规函数,它首先进行了一个条件检查(`static_assert`),确认`long long`类型的字节数是`size_t`字节数的整数倍,然后直接调用`__builtin_clzll`并做了相应的计算。
Dl_info不全时怎么通过__builtin_return_address获得objective-c的方法名
如果 `Dl_info` 结构体中没有找到符号信息,你可以尝试从返回地址中提取方法名。在 ARM 架构中,返回地址的最后两位代表着 Thumb 模式下的偏移量,如果最后一位是 1,代表着该地址位于 Thumb 模式下,需要进行对齐。而在 x86 架构中,返回地址直接指向函数的入口地址。
具体来说,你可以使用以下代码片段:
```objective-c
void *returnAddr = __builtin_return_address(0);
NSString *symbolName = nil;
#if defined(__arm__)
returnAddr = (void *)((uintptr_t)returnAddr & ~0x1);
#endif
Dl_info info;
if (dladdr(returnAddr, &info) && info.dli_sname) {
symbolName = [NSString stringWithUTF8String:info.dli_sname];
} else {
// Assuming the return address is a pointer to a function call instruction,
// we can go back one more word to get the actual function pointer.
void **funcPtr = (void **)returnAddr - 1;
// Assuming the function pointer points to the beginning of the function,
// we can get the address of the symbol name by going back one more word.
char **symPtr = (char **)*funcPtr - 1;
// Check if the symbol name is a valid string.
if (symPtr && *symPtr) {
symbolName = [NSString stringWithUTF8String:*symPtr];
}
}
NSString *methodName = NSStringFromSelector(NSSelectorFromString(symbolName));
```
其中,我们首先对 ARM 架构下的返回地址进行对齐,然后尝试从 `Dl_info` 结构体中获取符号名。如果获取失败,我们假设返回地址是一个指向函数调用指令的指针,从中提取函数指针,再从函数指针中提取符号名,最后转换为方法名。注意,此方法只适用于 Objective-C 方法,如果你需要获取 C 函数名,可以使用 `*funcPtr` 直接获取。
阅读全文