问题描述
我编写了以下程序来遍历内存中的所有图像并转储其字符串表.
I wrote the below program to iterate over all images in memory and dump their string tables.
#include <mach-o/dyld.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
uint32_t count = _dyld_image_count();
for (uint32_t i = 0 ; i < count ; i++) {
const char* imageName = _dyld_get_image_name(i);
printf("IMAGE[%u]=%s\n", i, imageName);
const struct mach_header* header = _dyld_get_image_header(i);
if (header->magic != MH_MAGIC_64)
continue;
struct mach_header_64* header64 = (struct mach_header_64*)header;
char *ptr = ((void*)header64) + sizeof(struct mach_header_64);
for (uint32_t j = 0; j < header64->ncmds; j++) {
struct load_command *lc = (struct load_command *)ptr;
ptr += lc->cmdsize;
if (lc->cmd != LC_SYMTAB)
continue;
struct symtab_command* symtab = (struct symtab_command*)lc;
printf("\t\tLC_SYMTAB.stroff=%u\n", symtab->stroff);
printf("\t\tLC_SYMTAB.strsize=%u\n", symtab->strsize);
if (symtab->strsize > 100*1024*1024) {
printf("\t\tHUH? Don't believe string table is over 100MiB in size!\n");
continue;
}
char *strtab = (((void*)header64) + symtab->stroff);
uint32_t off = 0;
while (off < symtab->strsize) {
char *e = &(strtab[off]);
if (e[0] != 0)
printf("\t\tSTR[%u]=\"%s\"\n", off, e);
off += strlen(e) + 1;
}
}
}
return 0;
}
对于某些图像来说,它似乎是随机工作的,但对于另一些图像,stroff/strsize具有无意义的值:
It seems to randomly work for some images, but for others the stroff/strsize have nonsensical values:
LC_SYMTAB.stroff=1266154560
LC_SYMTAB.strsize=143767728
这两个魔术值似乎总是相同的,但是我不确定这是否在某种程度上取决于系统,或者其他人是否会获得相同的特定值.
It seems to always be the same two magic values, but I'm not sure if this is system-dependent in some way or if other people will get the same specific values.
如果我注释掉strsize超过100MiB的支票,则打印字符串表段错误.
If I comment out the check for strsize being over 100MiB, then printing the string table segfaults.
大多数图像似乎都存在此问题,但有些则没有.当我运行它时,出现了38张中的29张图像的问题.
Most images seem to have this problem, but some don't. When I run it, I get the issue for 29 images out of 38.
我看不到任何模式可以做什么和不可以做什么.这是怎么回事?
I can't observe any pattern as to which do and which won't. What is going on here?
如果相关,我正在macOS 10.14.6上进行测试,并使用Apple LLVM版本10.0.1(clang-1001.0.46.4)进行编译.
If it is relevant, I am testing on macOS 10.14.6 and compiling with Apple LLVM version 10.0.1 (clang-1001.0.46.4).
推荐答案
如您所知,它们来自 dyld_shared_cache
.Xcode或任何最近的XNU源:
As you already worked out, those are from the dyld_shared_cache
. And the 0x80000000
flag is indeed documented, in the headers shipped with Xcode or any semi-recent XNU source:
#define MH_DYLIB_IN_CACHE 0x80000000 /* Only for use on dylibs. When this bit
is set, the dylib is part of the dyld
shared cache, rather than loose in
the filesystem. */
正如您还发现的那样,当将 stroff
/ strsize
值添加到 dyld_shared_cache
基数时,不会产生可用的结果.那是因为这些不是内存偏移量,而是 file 偏移量.对于所有Mach-O都是如此,通常情况下,非缓存二进制文件的段在文件和内存偏移中具有相同的相对位置.但这绝对不是共享缓存.
As you've also discovered, the stroff
/strsize
values do not yield usable results when added to the dyld_shared_cache
base. That is because those are not memory offsets, but file offsets. This is true for all Mach-O's, it's just often the case that the segments of non-cached binaries have the same relative position in file and memory offsets. But this is definitely not true for the shared cache.
要将文件偏移量转换为内存地址,您必须解析共享缓存头中的段.您可以在dyld中找到来源.
To translate the file offset into a memory address, you'll have to parse the segments in the shared cache header. You can find struct definitions in the dyld source.
这篇关于为什么LC_SYMTAB的stroff/strsize无效,而仅对于某些已加载的图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!