void KernelPatcher::onKextSummariesUpdated() { if (that) { // macOS 10.12 generates an interrupt during this call but unlike 10.11 and below // it never stops handling interrupts hanging forever inside hndl_allintrs. // This happens even with cpus=1, and the reason is not fully understood. // // For this reason on 10.12 and above the outer function is routed, and so far it // seems to cause fewer issues. Regarding syncing: // - the only place modifying gLoadedKextSummaries is updateLoadedKextSummaries; // - updateLoadedKextSummaries is called from load/unload separately; // - sKextSummariesLock is not exported or visible. // As a result no syncing should be necessary but there are guards for future // changes and in case of any misunderstanding. if (getKernelVersion() >= KernelVersion::Sierra) { if (OSIncrementAtomic(&updateSummariesEntryCount) != 0) { panic("onKextSummariesUpdated entered another time"); } that->orgUpdateLoadedKextSummaries(); } DBGLOG("patcher @ invoked at kext loading/unloading"); if (that->khandlers.size() > 0 && that->loadedKextSummaries) { auto num = (*that->loadedKextSummaries)->numSummaries; if (num > 0) { OSKextLoadedKextSummary &last = (*that->loadedKextSummaries)->summaries[num-1]; DBGLOG("patcher @ last kext is %llX and its name is %.*s", last.address, KMOD_MAX_NAME, last.name); // We may add khandlers items inside the handler for (size_t i = 0; i < that->khandlers.size(); i++) { if (!strncmp(that->khandlers[i]->id, last.name, KMOD_MAX_NAME)) { DBGLOG("patcher @ caught the right kext at %llX, invoking handler", last.address); that->khandlers[i]->address = last.address; that->khandlers[i]->size = last.size; that->khandlers[i]->handler(that->khandlers[i]); // Remove the item that->khandlers.erase(i); break; } } } else { SYSLOG("patcher @ no kext is currently loaded, this should not happen"); } } if (getKernelVersion() >= KernelVersion::Sierra && OSDecrementAtomic(&updateSummariesEntryCount) != 1) { panic("onKextSummariesUpdated left another time"); } } }
int sectionToSlave(int cpuf, int fd, int * EntryPoint) { int i = 0, err = 0; int BootSection = -2; int LastSection = -2; unsigned long ramStart = 0; unsigned char kernelVersion = getKernelVersion(); if(kernelVersion == 23 || kernelVersion == 24) { cop_properties_t cop; err = ioctl(cpuf,STCOP_GET_PROPERTIES,&cop); if(err < 0) { printf("error ioctl STCOP_GET_PROPERTIES\n"); return 1; } printf("base_address 0x%.8lx\n", cop.cp_ram_start); ramStart = cop.cp_ram_start; } for(i = 0; i < IndexCounter; i++) { if(IndexTable[i].Size > 0 && (IndexTable[i].Flags & SEC_LOAD == SEC_LOAD)) { if (0 == strncmp(".boot", IndexTable[i].Name, 5)) { /* defer the loading of the (relocatable) .boot section until we know where to * relocate it to. */ BootSection = i; continue; } err = writeToSlave(cpuf, fd, IndexTable[i].DestinationAddress - ramStart, IndexTable[i].SourceAddress, IndexTable[i].Size); if(err != 0) return 1; LastSection = i; } } if(BootSection != -2) { //Add relocated .boot unsigned int Alignment = 8; unsigned int DestinationAddress = (IndexTable[LastSection].DestinationAddress + IndexTable[LastSection].Size + (1 << Alignment)) & ~((1 << Alignment) - 1); err = writeToSlave(cpuf, fd, DestinationAddress - ramStart, IndexTable[BootSection].SourceAddress, IndexTable[BootSection].Size); if(err != 0) return 1; *EntryPoint = DestinationAddress; } else { //We allready have the EntryPoint } return 0; }
void KernelPatcher::setupKextListening() { // We have already done this if (that) return; loadedKextSummaries = reinterpret_cast<OSKextLoadedKextSummaryHeader **>(solveSymbol(KernelID, "_gLoadedKextSummaries")); if (loadedKextSummaries) { DBGLOG("patcher @ _gLoadedKextSummaries address %p", loadedKextSummaries); } else { code = Error::NoSymbolFound; return; } bool hookOuter = getKernelVersion() >= KernelVersion::Sierra; mach_vm_address_t s = solveSymbol(KernelID, hookOuter ? "__ZN6OSKext25updateLoadedKextSummariesEv" : "_OSKextLoadedKextSummariesUpdated"); if (s) { DBGLOG("patcher @ kext summaries (%d) address %llX value %llX", hookOuter, s, *reinterpret_cast<uint64_t *>(s)); } else { code = Error::NoSymbolFound; return; } if (hookOuter) { orgUpdateLoadedKextSummaries = reinterpret_cast<void(*)(void)>( routeFunction(s, reinterpret_cast<mach_vm_address_t>(onKextSummariesUpdated), true, true) ); } else { routeFunction(s, reinterpret_cast<mach_vm_address_t>(onKextSummariesUpdated)); } if (getError() == Error::NoError) { // Allow static functions to access the patcher body that = this; } }
void GLPlatform::detect(OpenGLPlatformInterface platformInterface) { m_platformInterface = platformInterface; m_vendor = (const char*)glGetString(GL_VENDOR); m_renderer = (const char*)glGetString(GL_RENDERER); m_version = (const char*)glGetString(GL_VERSION); // Parse the OpenGL version const QList<QByteArray> versionTokens = m_version.split(' '); if (versionTokens.count() > 0) { const QByteArray version = QByteArray(m_version); m_glVersion = parseVersionString(version); if (platformInterface == EglPlatformInterface) { // only EGL can have OpenGLES, GLX is OpenGL only if (version.startsWith("OpenGL ES")) { // from GLES 2: "Returns a version or release number of the form OpenGL<space>ES<space><version number><space><vendor-specific information>." // from GLES 3: "Returns a version or release number." and "The version number uses one of these forms: major_number.minor_number major_number.minor_number.release_number" m_gles = true; } } } if (!isGLES() && m_glVersion >= kVersionNumber(3, 0)) { int count; glGetIntegerv(GL_NUM_EXTENSIONS, &count); for (int i = 0; i < count; i++) { const char *name = (const char *) glGetStringi(GL_EXTENSIONS, i); m_extensions.insert(name); } } else { const QByteArray extensions = (const char *) glGetString(GL_EXTENSIONS); m_extensions = QSet<QByteArray>::fromList(extensions.split(' ')); } // Parse the Mesa version const int mesaIndex = versionTokens.indexOf("Mesa"); if (mesaIndex != -1) { const QByteArray version = versionTokens.at(mesaIndex + 1); m_mesaVersion = parseVersionString(version); } if (platformInterface == EglPlatformInterface) { if (isGLES()) { m_supportsGLSL = true; m_textureNPOT = true; } else { m_supportsGLSL = m_extensions.contains("GL_ARB_shader_objects") && m_extensions.contains("GL_ARB_fragment_shader") && m_extensions.contains("GL_ARB_vertex_shader"); m_textureNPOT = m_extensions.contains("GL_ARB_texture_non_power_of_two"); } } else if (platformInterface == GlxPlatformInterface) { m_supportsGLSL = m_extensions.contains("GL_ARB_shader_objects") && m_extensions.contains("GL_ARB_fragment_shader") && m_extensions.contains("GL_ARB_vertex_shader"); m_textureNPOT = m_extensions.contains("GL_ARB_texture_non_power_of_two"); } m_serverVersion = getXServerVersion(); m_kernelVersion = getKernelVersion(); m_glslVersion = 0; m_glsl_version.clear(); if (m_supportsGLSL) { // Parse the GLSL version m_glsl_version = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); m_glslVersion = parseVersionString(m_glsl_version); } m_chipset = QByteArrayLiteral("Unknown"); m_preferBufferSubData = false; // Mesa classic drivers // ==================================================== // Radeon if (m_renderer.startsWith("Mesa DRI R")) { // Sample renderer string: Mesa DRI R600 (RV740 94B3) 20090101 x86/MMX/SSE2 TCL DRI2 const QList<QByteArray> tokens = m_renderer.split(' '); const QByteArray chipClass = tokens.at(2); m_chipset = tokens.at(3).mid(1, -1); // Strip the leading '(' if (chipClass == "R100") // Vendor: Tungsten Graphics, Inc. m_driver = Driver_R100; else if (chipClass == "R200") // Vendor: Tungsten Graphics, Inc. m_driver = Driver_R200; else if (chipClass == "R300") // Vendor: DRI R300 Project m_driver = Driver_R300C; else if (chipClass == "R600") // Vendor: Advanced Micro Devices, Inc. m_driver = Driver_R600C; m_chipClass = detectRadeonClass(m_chipset); } // Intel else if (m_renderer.contains("Intel")) { // Vendor: Tungsten Graphics, Inc. // Sample renderer string: Mesa DRI Mobile Intel® GM45 Express Chipset GEM 20100328 2010Q1 QByteArray chipset; if (m_renderer.startsWith("Intel(R) Integrated Graphics Device")) chipset = "IGD"; else chipset = m_renderer; m_driver = Driver_Intel; m_chipClass = detectIntelClass(chipset); } // Gallium drivers // ==================================================== else if (m_renderer.contains("Gallium")) { // Sample renderer string: Gallium 0.4 on AMD RV740 const QList<QByteArray> tokens = m_renderer.split(' '); m_galliumVersion = parseVersionString(tokens.at(1)); m_chipset = (tokens.at(3) == "AMD" || tokens.at(3) == "ATI") ? tokens.at(4) : tokens.at(3); // R300G if (m_vendor == QByteArrayLiteral("X.Org R300 Project")) { m_chipClass = detectRadeonClass(m_chipset); m_driver = Driver_R300G; } // R600G else if (m_vendor == "X.Org" && (m_renderer.contains("R6") || m_renderer.contains("R7") || m_renderer.contains("RV6") || m_renderer.contains("RV7") || m_renderer.contains("RS780") || m_renderer.contains("RS880") || m_renderer.contains("CEDAR") || m_renderer.contains("REDWOOD") || m_renderer.contains("JUNIPER") || m_renderer.contains("CYPRESS") || m_renderer.contains("HEMLOCK") || m_renderer.contains("PALM") || m_renderer.contains("EVERGREEN") || m_renderer.contains("SUMO") || m_renderer.contains("SUMO2") || m_renderer.contains("BARTS") || m_renderer.contains("TURKS") || m_renderer.contains("CAICOS") || m_renderer.contains("CAYMAN"))) { m_chipClass = detectRadeonClass(m_chipset); m_driver = Driver_R600G; } // Nouveau else if (m_vendor == "nouveau") { m_chipClass = detectNVidiaClass(m_chipset); m_driver = Driver_Nouveau; } // softpipe else if (m_vendor == "VMware, Inc." && m_chipset == "softpipe" ) { m_driver = Driver_Softpipe; } // llvmpipe else if (m_vendor == "VMware, Inc." && m_chipset == "llvmpipe") { m_driver = Driver_Llvmpipe; } // SVGA3D else if (m_vendor == "VMware, Inc." && m_chipset.contains("SVGA3D")) { m_driver = Driver_VMware; } } // Properietary drivers // ==================================================== else if (m_vendor == "ATI Technologies Inc.") { m_chipClass = detectRadeonClass(m_renderer); m_driver = Driver_Catalyst; if (versionTokens.count() > 1 && versionTokens.at(2)[0] == '(') m_driverVersion = parseVersionString(versionTokens.at(1)); else if (versionTokens.count() > 0) m_driverVersion = parseVersionString(versionTokens.at(0)); else m_driverVersion = 0; } else if (m_vendor == "NVIDIA Corporation") { m_chipClass = detectNVidiaClass(m_renderer); m_driver = Driver_NVidia; int index = versionTokens.indexOf("NVIDIA"); if (versionTokens.count() > index) m_driverVersion = parseVersionString(versionTokens.at(index + 1)); else m_driverVersion = 0; } else if (m_renderer == "Software Rasterizer") { m_driver = Driver_Swrast; } // Virtual Hardware // ==================================================== else if (m_vendor == "Humper" && m_renderer == "Chromium") { // Virtual Box m_driver = Driver_VirtualBox; const int index = versionTokens.indexOf("Chromium"); if (versionTokens.count() > index) m_driverVersion = parseVersionString(versionTokens.at(index + 1)); else m_driverVersion = 0; } // Driver/GPU specific features // ==================================================== if (isRadeon()) { // R200 technically has a programmable pipeline, but since it's SM 1.4, // it's too limited to to be of any practical value to us. if (m_chipClass < R300) m_supportsGLSL = false; m_limitedGLSL = false; m_limitedNPOT = false; if (m_chipClass < R600) { if (driver() == Driver_Catalyst) m_textureNPOT = m_limitedNPOT = false; // Software fallback else if (driver() == Driver_R300G) m_limitedNPOT = m_textureNPOT; m_limitedGLSL = m_supportsGLSL; } if (m_chipClass < R300) { // fallback to XRender for R100 and R200 m_recommendedCompositor = XRenderCompositing; } else if (m_chipClass < R600) { // XRender due to NPOT limitations not supported by KWin's shaders m_recommendedCompositor = XRenderCompositing; } else { m_recommendedCompositor = OpenGL2Compositing; } if (driver() == Driver_R600G || (driver() == Driver_R600C && m_renderer.contains("DRI2"))) { m_looseBinding = true; } } if (isNvidia()) { if (m_driver == Driver_NVidia && m_chipClass < NV40) m_supportsGLSL = false; // High likelihood of software emulation if (m_driver == Driver_NVidia) { m_looseBinding = true; m_preferBufferSubData = true; } if (m_chipClass < NV40) { m_recommendedCompositor = XRenderCompositing; } else { m_recommendedCompositor = OpenGL2Compositing; } m_limitedNPOT = m_textureNPOT && m_chipClass < NV40; m_limitedGLSL = m_supportsGLSL && m_chipClass < G80; } if (isIntel()) { if (m_chipClass < I915) m_supportsGLSL = false; m_limitedGLSL = m_supportsGLSL && m_chipClass < I965; // see https://bugs.freedesktop.org/show_bug.cgi?id=80349#c1 m_looseBinding = false; if (m_chipClass < I915) { m_recommendedCompositor = XRenderCompositing; } else { m_recommendedCompositor = OpenGL2Compositing; } } if (isMesaDriver() && platformInterface == EglPlatformInterface) { // According to the reference implementation in // mesa/demos/src/egl/opengles1/texture_from_pixmap // the mesa egl implementation does not require a strict binding (so far). m_looseBinding = true; } if (isSoftwareEmulation()) { if (m_driver < Driver_Llvmpipe) { // we recommend XRender m_recommendedCompositor = XRenderCompositing; // Software emulation does not provide GLSL m_limitedGLSL = m_supportsGLSL = false; } else { // llvmpipe does support GLSL m_recommendedCompositor = OpenGL2Compositing; m_limitedGLSL = false; m_supportsGLSL = true; } } if (m_chipClass == UnknownChipClass && m_driver == Driver_Unknown) { // we don't know the hardware. Let's be optimistic and assume OpenGL compatible hardware m_recommendedCompositor = OpenGL2Compositing; m_supportsGLSL = true; } if (isVirtualBox()) { m_virtualMachine = true; m_recommendedCompositor = OpenGL2Compositing; } if (isVMware()) { m_virtualMachine = true; m_recommendedCompositor = OpenGL2Compositing; } // and force back to shader supported on gles, we wouldn't have got a context if not supported if (isGLES()) { m_supportsGLSL = true; m_limitedGLSL = false; } }
HRESULT CaPerfDataWriter::setModulesPath() { HRESULT ret = S_OK; char modules_path[OS_MAX_PATH]; getKernelVersion(); if (m_kVersion.empty()) { return E_FAIL; } snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", m_rootDir.c_str(), m_kVersion.c_str()); m_kModulesPath = modules_path; setModulesAbsolutePath(m_kModulesPath); if (! m_kModuleNameMap.size()) { return E_FAIL; } // Now iterate over the map and to m_kModuleAddrMap for (kModuleNameMap::iterator it = m_kModuleNameMap.begin(), itEnd = m_kModuleNameMap.end(); it != itEnd; ++it) { m_kModuleAddrMap.insert(kModuleAddrMap::value_type(it->second.m_startAddress, it->second)); } if (! m_kModuleAddrMap.size()) { return E_FAIL; } // Now set the end address kModuleAddrMap::iterator aiter = m_kModuleAddrMap.begin(), aiterEnd = m_kModuleAddrMap.end(); kModule* prev = &(aiter->second); gtUInt64 endAddr = ~0ULL; while (++aiter != aiterEnd) { kModule* curr = &(aiter->second); endAddr = curr->m_startAddress - 1; prev->setEndAddress(endAddr); OS_OUTPUT_FORMAT_DEBUG_LOG(OS_DEBUG_LOG_EXTENSIVE, L"addr(0x%lx , 0x%lx)", prev->m_startAddress, prev->m_endAddress); prev = curr; } // set endAddress for last entry if (prev) { endAddr = ~0ULL; prev->setEndAddress(endAddr); } return ret; }
bool Configuration::getBootArguments() { if (readArguments) return !isDisabled; isDisabled = false; char tmp[16]; isDisabled |= PE_parse_boot_argn(bootargOff, tmp, sizeof(tmp)); if (!PE_parse_boot_argn(bootargForce, tmp, sizeof(tmp))) { isDisabled |= PE_parse_boot_argn("-s", tmp, sizeof(tmp)); isDisabled |= PE_parse_boot_argn("-x", tmp, sizeof(tmp)); if (!KernelPatcher::compatibleKernel(minKernel, maxKernel)) { if (!PE_parse_boot_argn(bootargBeta, tmp, sizeof(tmp))) { SYSLOG("config @ automatically disabling on an unsupported operating system"); isDisabled = true; } else if (!isDisabled) { SYSLOG("config @ force enabling on an unsupported operating system due to beta flag"); } } } else if (!isDisabled) { SYSLOG("config @ force enabling due to force flag"); } ADDPR(debugEnabled) = PE_parse_boot_argn(bootargDebug, tmp, sizeof(tmp)); allowDecompress = !PE_parse_boot_argn(bootargLowMem, tmp, sizeof(tmp)); installOrRecovery |= PE_parse_boot_argn("rp0", tmp, sizeof(tmp)); installOrRecovery |= PE_parse_boot_argn("rp", tmp, sizeof(tmp)); installOrRecovery |= PE_parse_boot_argn("container-dmg", tmp, sizeof(tmp)); installOrRecovery |= PE_parse_boot_argn("root-dmg", tmp, sizeof(tmp)); installOrRecovery |= PE_parse_boot_argn("auth-root-dmg", tmp, sizeof(tmp)); preferSlowMode = getKernelVersion() <= KernelVersion::Mavericks || installOrRecovery; if (PE_parse_boot_argn(bootargSlow, tmp, sizeof(tmp))) { preferSlowMode = true; } else if (PE_parse_boot_argn(bootargFast, tmp, sizeof(tmp))) { preferSlowMode = false; } if (!preferSlowMode && getKernelVersion() <= KernelVersion::Mavericks) { // Since vm_shared_region_map_file interface is a little different if (!isDisabled) SYSLOG("config @ enforcing -liluslow on Mavericks and lower"); preferSlowMode = true; } if (!preferSlowMode && installOrRecovery) { // Since vdyld shared cache is not available if (!isDisabled) SYSLOG("config @ enforcing -liluslow in installer or recovery"); preferSlowMode = true; } readArguments = true; DBGLOG("config @ boot arguments disabled %d, debug %d, slow %d, decompress %d", isDisabled, ADDPR(debugEnabled), preferSlowMode, allowDecompress); if (isDisabled) { SYSLOG("init @ found a disabling argument or no arguments, exiting"); } else { // Decide on booter if (!preferSlowMode) { policyOps.mpo_cred_check_label_update_execve = reinterpret_cast<mpo_cred_check_label_update_execve_t *>(policyCredCheckLabelUpdateExecve); } else { policyOps.mpo_mount_check_remount = policyCheckRemount; } } return !isDisabled; }
bool KernelPatcher::compatibleKernel(uint32_t min, uint32_t max) { return (min == KernelAny || min <= getKernelVersion()) && (max == KernelAny || max >= getKernelVersion()); }
bool UserPatcher::hookMemoryAccess() { // 10.12 and newer mach_vm_address_t kern = patcher->solveSymbol(KernelPatcher::KernelID, "_cs_validate_range"); if (patcher->getError() == KernelPatcher::Error::NoError) { orgCodeSignValidateRangeWrapper = reinterpret_cast<t_codeSignValidateRangeWrapper>( patcher->routeFunction(kern, reinterpret_cast<mach_vm_address_t>(codeSignValidateRangeWrapper), true, true) ); if (patcher->getError() != KernelPatcher::Error::NoError) { SYSLOG("user @ failed to hook _cs_validate_range"); patcher->clearError(); return false; } } else if (static_cast<void>(patcher->clearError()), static_cast<void>(kern = patcher->solveSymbol(KernelPatcher::KernelID, "_cs_validate_page")), patcher->getError() == KernelPatcher::Error::NoError) { orgCodeSignValidatePageWrapper = reinterpret_cast<t_codeSignValidatePageWrapper>( patcher->routeFunction(kern, reinterpret_cast<mach_vm_address_t>(codeSignValidatePageWrapper), true, true) ); if (patcher->getError() != KernelPatcher::Error::NoError) { SYSLOG("user @ failed to hook _cs_validate_page"); patcher->clearError(); return false; } } else { SYSLOG("user @ failed to resolve _cs_validate function"); patcher->clearError(); return false; } orgCurrentMap = reinterpret_cast<t_currentMap>(patcher->solveSymbol(KernelPatcher::KernelID, "_current_map")); if (patcher->getError() != KernelPatcher::Error::NoError) { SYSLOG("user @ failed to resolve _current_map"); patcher->clearError(); return false; } orgGetMapMin = reinterpret_cast<t_getMapMin>(patcher->solveSymbol(KernelPatcher::KernelID, "_get_map_min")); if (patcher->getError() != KernelPatcher::Error::NoError) { SYSLOG("user @ failed to resolve _get_map_min"); patcher->clearError(); return false; } orgGetTaskMap = reinterpret_cast<t_getTaskMap>(patcher->solveSymbol(KernelPatcher::KernelID, "_get_task_map")); if (patcher->getError() != KernelPatcher::Error::NoError) { SYSLOG("user @ failed to resolve _get_task_map"); patcher->clearError(); return false; } orgVmMapCheckProtection = reinterpret_cast<t_vmMapCheckProtection>(patcher->solveSymbol(KernelPatcher::KernelID, "_vm_map_check_protection")); if (patcher->getError() != KernelPatcher::Error::NoError) { SYSLOG("user @ failed to resolve _vm_map_check_protection"); patcher->clearError(); return false; } orgVmMapReadUser = reinterpret_cast<t_vmMapReadUser>(patcher->solveSymbol(KernelPatcher::KernelID, "_vm_map_read_user")); if (patcher->getError() != KernelPatcher::Error::NoError) { SYSLOG("user @ failed to resolve _vm_map_read_user"); patcher->clearError(); return false; } orgVmMapWriteUser = reinterpret_cast<t_vmMapWriteUser>(patcher->solveSymbol(KernelPatcher::KernelID, "_vm_map_write_user")); if (patcher->getError() != KernelPatcher::Error::NoError) { SYSLOG("user @ failed to resolve _vm_map_write_user"); patcher->clearError(); return false; } // On 10.12.1 b4 Apple decided not to let current_map point to the current process // For this reason we have to obtain the map with the other methods if (getKernelVersion() >= KernelVersion::Sierra) { kern = patcher->solveSymbol(KernelPatcher::KernelID, "_proc_exec_switch_task"); if (patcher->getError() == KernelPatcher::Error::NoError) { orgProcExecSwitchTask = reinterpret_cast<t_procExecSwitchTask>( patcher->routeFunction(kern, reinterpret_cast<mach_vm_address_t>(procExecSwitchTask), true, true) ); if (patcher->getError() != KernelPatcher::Error::NoError) { SYSLOG("user @ failed to hook _proc_exec_switch_task"); patcher->clearError(); return false; } } else { DBGLOG("user @ failed to resolve _proc_exec_switch_task"); patcher->clearError(); // This is not an error, early 10.12 versions have no such function } } if (patchDyldSharedCache) { kern = patcher->solveSymbol(KernelPatcher::KernelID, "_vm_shared_region_map_file"); if (patcher->getError() == KernelPatcher::Error::NoError) { orgVmSharedRegionMapFile = reinterpret_cast<t_vmSharedRegionMapFile>( patcher->routeFunction(kern, reinterpret_cast<mach_vm_address_t>(vmSharedRegionMapFile), true, true) ); if (patcher->getError() != KernelPatcher::Error::NoError) { SYSLOG("user @ failed to hook _vm_shared_region_map_file"); patcher->clearError(); return false; } } else { SYSLOG("user @ failed to resolve _vm_shared_region_map_file"); patcher->clearError(); return false; } kern = patcher->solveSymbol(KernelPatcher::KernelID, "_vm_shared_region_slide"); if (patcher->getError() == KernelPatcher::Error::NoError) { orgVmSharedRegionSlide = reinterpret_cast<t_vmSharedRegionSlide>( patcher->routeFunction(kern, reinterpret_cast<mach_vm_address_t>(vmSharedRegionSlide), true, true) ); if (patcher->getError() != KernelPatcher::Error::NoError) { SYSLOG("user @ failed to hook _vm_shared_region_slide"); patcher->clearError(); return false; } } else { SYSLOG("user @ failed to resolve _vm_shared_region_slide"); patcher->clearError(); return false; } } return true; }