本篇文章主要介绍了" iOS 如何获取 Mach-O 的 UUID",主要涉及到方面的内容,对于IOS开发感兴趣的同学可以参考一下:
LC_UUID 一般简称为 UUID,是用来标示 Mach-O 文件的,做过崩溃堆栈符号化还原的同学应该都知道有 UUID 这个东西,你在进行符号解析的时候,就...
可以获取主 image 文件的路径,然后根据路径去获取 image 的 index,然后根据这个 index 去获取对应 image 的header,通过 header 找到 image 的 Load Commands,遍历找到类型为 LC_UUID 的 Load Command 即可获取 UUID。下面给出一部分代码,这个其实相当于第三个例子的一部分,所以可以从第三个中提炼出这部分代码。
// 获取主 image 的路径
static NSString* getExecutablePath()
{
NSBundle* mainBundle = [NSBundle mainBundle];
NSDictionary* infoDict = [mainBundle infoDictionary];
NSString* bundlePath = [mainBundle bundlePath];
NSString* executableName = infoDict[@"CFBundleExecutable"];
return [bundlePath stringByAppendingPathComponent:executableName];
}
// 获取 image 的 index
const uint32_t imageCount = _dyld_image_count();
for(uint32_t iImg = 0; iImg < imageCount; iImg++) {
const char* name = _dyld_get_image_name(iImg);
if (name == getExecutablePath()) return iImg;
}
// 根据 index 获取 header
const struct mach_header* header = _dyld_get_image_header(iImg);
// 获取 Load Command
static uintptr_t firstCmdAfterHeader(const struct mach_header* const header) {
switch(header->magic)
{
case MH_MAGIC:
case MH_CIGAM:
return (uintptr_t)(header + 1);
case MH_MAGIC_64:
case MH_CIGAM_64:
return (uintptr_t)(((struct mach_header_64*)header) + 1);
default:
// Header is corrupt
return 0;
}
}
// 遍历 Load Command即可
从上面代码中可以发现App image 的路径是在 mainBundle 中的,其实我们所依赖的自己的动态库也都在这个路径下,同时由于 Swift ABI 不稳定,它所依赖的系统动态库打包的时候也会放在这个路径之下,有兴趣的可以测试下。当然,如果你想,你也可以通过这种方式获取 APP 以及自己动态库的 UUID。
如何获取所有 Mach-O 的 UUID
当我们写完一个 APP,打包上架后,如果遇到崩溃就需要收集堆栈信息进行符号化还原,这时候每个动态库的 UUID 我们都需要,系统库的 UUID 也是需要的,这样可以提供给更多的信息,有利于我们迅速排查问题。如何获取 APP 以及所有动态库的 UUID 呢?
其实也很简单,就是获取到 APP 中所有的 image count,然后一个个遍历获取header、Load Command,进而找到所有 Mach-O 的 UUID,这里直接上代码