Esempio n. 1
0
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");
		}
	}
}
Esempio n. 2
0
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;
}
Esempio n. 3
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;
	}
}
Esempio n. 4
0
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;
}
Esempio n. 7
0
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;
}