为什么用dlopen动态加载私有库/System/Library/PrivateFrameworks/FrontBoard.framework/FrontBoard会报错:out of adress space,而加载其他的私有库例如 /System/Library/PrivateFrameworks/StoreServices.framework/StoreServices却又可以加载成功呢?如果确实没办法打算把不能加载的bin转成dylib来加载,不知是否可行
进程确实有/System/Library/Frameworks/Healthkit.framework/healthd,我用dlopen动态加载始终还是error:
dlopen(/System/Library/Frameworks/Healthkit.framework/healthd,1):no suitable image found . Did find :/System/Library/Frameworks/Healthkit.framework/healthd: out of address space
有大神给点提示信息吗
dlopen是用来加载dylib, 不是加载bin的
为什么有些bin可以用dlopen加载成功呢,这是什么情况
系统的bin 32位的可以, 64位基本不行, 只要有PAGEZERO就不行
输出错误信息是在dyld.cpp,
ImageLoader* loadPhase5open(const char* path, const LoadContext& context, const struct stat& stat_buf, std::vector<const char*>* exceptions)
抛出是在 ImageLoaderMachO.cpp
uintptr_t ImageLoaderMachO::reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context)
{
vm_address_t addr = 0;
vm_size_t size = length;
// in PIE programs, load initial dylibs after main executable so they don't have fixed addresses either
if ( fgNextPIEDylibAddress != 0 ) {
// add small (0-3 pages) random padding between dylibs
addr = fgNextPIEDylibAddress + (__stack_chk_guard/fgNextPIEDylibAddress & (sizeof(long)-1))*dyld_page_size;
//dyld::log("padding 0x%08llX, guard=0x%08llX\n", (long long)(addr - fgNextPIEDylibAddress), (long long)(__stack_chk_guard));
kern_return_t r = vm_alloc(&addr, size, VM_FLAGS_FIXED | VM_MAKE_TAG(VM_MEMORY_DYLIB));
if ( r == KERN_SUCCESS ) {
fgNextPIEDylibAddress = addr + size;
return addr;
}
fgNextPIEDylibAddress = 0;
}
kern_return_t r = vm_alloc(&addr, size, VM_FLAGS_ANYWHERE | VM_MAKE_TAG(VM_MEMORY_DYLIB));
if ( r != KERN_SUCCESS )
throw "out of address space";
return addr;
}
调用时
reserveAnAddressRange(highAddr-lowAddr, context);
highAddr 和 lowAddr 的计算
uintptr_t lowAddr = (unsigned long)(-1);
uintptr_t highAddr = 0;
for(unsigned int i=0, e=segmentCount(); i < e; ++i) {
const uintptr_t segLow = segPreferredLoadAddress(i);
const uintptr_t segHigh = dyld_page_round(segLow + segSize(i));
if ( segLow < highAddr ) {
if ( dyld_page_size > 4096 )
dyld::throwf("can't map segments into 16KB pages");
else
dyld::throwf("overlapping segments");
}
if ( segLow < lowAddr )
lowAddr = segLow;
if ( segHigh > highAddr )
highAddr = segHigh;
if ( needsToSlide || !imageHasPreferredLoadAddress || inPIE || !reserveAddressRange(segPreferredLoadAddress(i), segSize(i)) )
needsToSlide = true;
}
所以有PAGEZERO的就爆炸了
1 个赞
Thanks!刚学着去啃了下dyld开源代码(虽然不怎么看得懂
有现成工具去掉pagezero实现你的需求
1 个赞
请问后来这个问题解决了吗。。我现在也遇到了这个问题
前面的回复不是给解决方法了吗
具体看大神文章详细解答:黑科技:把第三方 iOS 应用转成动态库 - Jun's Blog