+/*
+ * Module validation
+ */
+static int
+is_module_valid(struct modctl* ctl)
+{
+ ASSERT(!MOD_FBT_PROBES_PROVIDED(ctl));
+ ASSERT(!MOD_FBT_INVALID(ctl));
+
+ if (0 == ctl->mod_address || 0 == ctl->mod_size) {
+ return FALSE;
+ }
+
+ if (0 == ctl->mod_loaded) {
+ return FALSE;
+ }
+
+ if (strstr(ctl->mod_modname, "CHUD") != NULL)
+ return FALSE;
+
+ /*
+ * If the user sets this, trust they know what they are doing.
+ */
+ if (gIgnoreFBTBlacklist) /* per boot-arg set in fbt_init() */
+ return TRUE;
+
+ /*
+ * These drivers control low level functions that when traced
+ * cause problems often in the sleep/wake paths as well as
+ * critical debug and panic paths.
+ * If somebody really wants to drill in on one of these kexts, then
+ * they can override blacklisting using the boot-arg above.
+ */
+
+ if (strstr(ctl->mod_modname, "AppleACPIEC") != NULL)
+ return FALSE;
+
+ if (strstr(ctl->mod_modname, "AppleACPIPlatform") != NULL)
+ return FALSE;
+
+ if (strstr(ctl->mod_modname, "AppleRTC") != NULL)
+ return FALSE;
+
+ if (strstr(ctl->mod_modname, "IOACPIFamily") != NULL)
+ return FALSE;
+
+ if (strstr(ctl->mod_modname, "AppleIntelCPUPowerManagement") != NULL)
+ return FALSE;
+
+ if (strstr(ctl->mod_modname, "AppleProfile") != NULL)
+ return FALSE;
+
+ if (strstr(ctl->mod_modname, "AppleIntelProfile") != NULL)
+ return FALSE;
+
+ if (strstr(ctl->mod_modname, "AppleEFI") != NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * FBT probe name validation
+ */
+static int
+is_symbol_valid(const char* name)
+{
+ /*
+ * If the user set this, trust they know what they are doing.
+ */
+ if (gIgnoreFBTBlacklist)
+ return TRUE;
+
+ if (LIT_STRNSTART(name, "dtrace_") && !LIT_STRNSTART(name, "dtrace_safe_")) {
+ /*
+ * Anything beginning with "dtrace_" may be called
+ * from probe context unless it explitly indicates
+ * that it won't be called from probe context by
+ * using the prefix "dtrace_safe_".
+ */
+ return FALSE;
+ }
+
+ if (LIT_STRNSTART(name, "fasttrap_") ||
+ LIT_STRNSTART(name, "fuword") ||
+ LIT_STRNSTART(name, "suword") ||
+ LIT_STRNEQL(name, "sprlock") ||
+ LIT_STRNEQL(name, "sprunlock") ||
+ LIT_STRNEQL(name, "uread") ||
+ LIT_STRNEQL(name, "uwrite")) {
+ return FALSE; /* Fasttrap inner-workings. */
+ }
+
+ if (LIT_STRNSTART(name, "dsmos_"))
+ return FALSE; /* Don't Steal Mac OS X! */
+
+ if (LIT_STRNSTART(name, "_dtrace"))
+ return FALSE; /* Shims in dtrace.c */
+
+ if (LIT_STRNSTART(name, "chud"))
+ return FALSE; /* Professional courtesy. */
+
+ if (LIT_STRNSTART(name, "hibernate_"))
+ return FALSE; /* Let sleeping dogs lie. */
+
+ if (LIT_STRNEQL(name, "_ZNK6OSData14getBytesNoCopyEv"))
+ return FALSE; /* Data::getBytesNoCopy, IOHibernateSystemWake path */
+
+ if (LIT_STRNEQL(name, "_ZN9IOService14newTemperatureElPS_") || /* IOService::newTemperature */
+ LIT_STRNEQL(name, "_ZN9IOService26temperatureCriticalForZoneEPS_")) { /* IOService::temperatureCriticalForZone */
+ return FALSE; /* Per the fire code */
+ }
+
+ /*
+ * Place no probes (illegal instructions) in the exception handling path!
+ */
+ if (LIT_STRNEQL(name, "t_invop") ||
+ LIT_STRNEQL(name, "enter_lohandler") ||
+ LIT_STRNEQL(name, "lo_alltraps") ||
+ LIT_STRNEQL(name, "kernel_trap") ||
+ LIT_STRNEQL(name, "interrupt") ||
+ LIT_STRNEQL(name, "i386_astintr")) {
+ return FALSE;
+ }
+
+ if (LIT_STRNEQL(name, "current_thread") ||
+ LIT_STRNEQL(name, "ast_pending") ||
+ LIT_STRNEQL(name, "fbt_perfCallback") ||
+ LIT_STRNEQL(name, "machine_thread_get_kern_state") ||
+ LIT_STRNEQL(name, "get_threadtask") ||
+ LIT_STRNEQL(name, "ml_set_interrupts_enabled") ||
+ LIT_STRNEQL(name, "dtrace_invop") ||
+ LIT_STRNEQL(name, "fbt_invop") ||
+ LIT_STRNEQL(name, "sdt_invop") ||
+ LIT_STRNEQL(name, "max_valid_stack_address")) {
+ return FALSE;
+ }
+
+ /*
+ * Voodoo.
+ */
+ if (LIT_STRNSTART(name, "machine_stack_") ||
+ LIT_STRNSTART(name, "mapping_") ||
+ LIT_STRNEQL(name, "tmrCvt") ||
+
+ LIT_STRNSTART(name, "tsc_") ||
+
+ LIT_STRNSTART(name, "pmCPU") ||
+ LIT_STRNEQL(name, "pmKextRegister") ||
+ LIT_STRNEQL(name, "pmMarkAllCPUsOff") ||
+ LIT_STRNEQL(name, "pmSafeMode") ||
+ LIT_STRNEQL(name, "pmTimerSave") ||
+ LIT_STRNEQL(name, "pmTimerRestore") ||
+ LIT_STRNEQL(name, "pmUnRegister") ||
+ LIT_STRNSTART(name, "pms") ||
+ LIT_STRNEQL(name, "power_management_init") ||
+ LIT_STRNSTART(name, "usimple_") ||
+ LIT_STRNSTART(name, "lck_spin_lock") ||
+ LIT_STRNSTART(name, "lck_spin_unlock") ||
+
+ LIT_STRNSTART(name, "rtc_") ||
+ LIT_STRNSTART(name, "_rtc_") ||
+ LIT_STRNSTART(name, "rtclock_") ||
+ LIT_STRNSTART(name, "clock_") ||
+ LIT_STRNSTART(name, "absolutetime_to_") ||
+ LIT_STRNEQL(name, "setPop") ||
+ LIT_STRNEQL(name, "nanoseconds_to_absolutetime") ||
+ LIT_STRNEQL(name, "nanotime_to_absolutetime") ||
+
+ LIT_STRNSTART(name, "etimer_") ||
+
+ LIT_STRNSTART(name, "commpage_") ||
+ LIT_STRNSTART(name, "pmap_") ||
+ LIT_STRNSTART(name, "ml_") ||
+ LIT_STRNSTART(name, "PE_") ||
+ LIT_STRNEQL(name, "kprintf") ||
+ LIT_STRNSTART(name, "lapic_") ||
+ LIT_STRNSTART(name, "act_machine") ||
+ LIT_STRNSTART(name, "acpi_") ||
+ LIT_STRNSTART(name, "pal_")){
+ return FALSE;
+ }
+
+ /*
+ * Avoid machine_ routines. PR_5346750.
+ */
+ if (LIT_STRNSTART(name, "machine_"))
+ return FALSE;
+
+ if (LIT_STRNEQL(name, "handle_pending_TLB_flushes"))
+ return FALSE;
+
+ /*
+ * Place no probes on critical routines. PR_5221096
+ */
+ if (bsearch( name, critical_blacklist, CRITICAL_BLACKLIST_COUNT, sizeof(name), _cmp ) != NULL)
+ return FALSE;
+
+ /*
+ * Place no probes that could be hit in probe context.
+ */
+ if (bsearch( name, probe_ctx_closure, PROBE_CTX_CLOSURE_COUNT, sizeof(name), _cmp ) != NULL) {
+ return FALSE;
+ }
+
+ /*
+ * Place no probes that could be hit on the way to the debugger.
+ */
+ if (LIT_STRNSTART(name, "kdp_") ||
+ LIT_STRNSTART(name, "kdb_") ||
+ LIT_STRNSTART(name, "kdbg_") ||
+ LIT_STRNSTART(name, "kdebug_") ||
+ LIT_STRNSTART(name, "kernel_debug") ||
+ LIT_STRNSTART(name, "debug_") ||
+ LIT_STRNEQL(name, "Debugger") ||
+ LIT_STRNEQL(name, "Call_DebuggerC") ||
+ LIT_STRNEQL(name, "lock_debugger") ||
+ LIT_STRNEQL(name, "unlock_debugger") ||
+ LIT_STRNEQL(name, "packA") ||
+ LIT_STRNEQL(name, "unpackA") ||
+ LIT_STRNEQL(name, "SysChoked")) {
+ return FALSE;
+ }
+
+
+ /*
+ * Place no probes that could be hit on the way to a panic.
+ */
+ if (NULL != strstr(name, "panic_") ||
+ LIT_STRNEQL(name, "panic") ||
+ LIT_STRNEQL(name, "preemption_underflow_panic")) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+