1*a325d9c4SApple OSS Distributionsfrom __future__ import absolute_import 2*a325d9c4SApple OSS Distributionsfrom __future__ import print_function 3*a325d9c4SApple OSS Distributionsimport os 4*a325d9c4SApple OSS Distributionsimport sys 5*a325d9c4SApple OSS Distributionsimport re 6*a325d9c4SApple OSS Distributionsimport subprocess 7*a325d9c4SApple OSS Distributions 8*a325d9c4SApple OSS DistributionsPY3 = sys.version_info > (3,) 9*a325d9c4SApple OSS Distributions 10*a325d9c4SApple OSS Distributionsdef GetSettingsValues(debugger, setting_variable_name): 11*a325d9c4SApple OSS Distributions """ Queries the lldb internal settings 12*a325d9c4SApple OSS Distributions params: 13*a325d9c4SApple OSS Distributions debugger : lldb.SBDebugger instance 14*a325d9c4SApple OSS Distributions setting_variable_name: str - string name of the setting(eg prompt) 15*a325d9c4SApple OSS Distributions returns: 16*a325d9c4SApple OSS Distributions [] : Array of strings. Empty array if setting is not found/set 17*a325d9c4SApple OSS Distributions """ 18*a325d9c4SApple OSS Distributions retval = [] 19*a325d9c4SApple OSS Distributions settings_val_list = debugger.GetInternalVariableValue(setting_variable_name, debugger.GetInstanceName()) 20*a325d9c4SApple OSS Distributions for s in settings_val_list: 21*a325d9c4SApple OSS Distributions retval.append(str(s)) 22*a325d9c4SApple OSS Distributions return retval 23*a325d9c4SApple OSS Distributions 24*a325d9c4SApple OSS Distributionsdef GetSymbolsFilePathFromModule(m): 25*a325d9c4SApple OSS Distributions """ Get a file path from a module. 26*a325d9c4SApple OSS Distributions params: m - lldb.target.module 27*a325d9c4SApple OSS Distributions returns: 28*a325d9c4SApple OSS Distributions str : path to first file based symbol. Note this might be dir path inside sources. 29*a325d9c4SApple OSS Distributions """ 30*a325d9c4SApple OSS Distributions for s in m.symbols: 31*a325d9c4SApple OSS Distributions if s.type == 8: 32*a325d9c4SApple OSS Distributions return os.path.dirname(str(s.name)) 33*a325d9c4SApple OSS Distributions return "" 34*a325d9c4SApple OSS Distributions 35*a325d9c4SApple OSS Distributionsdef GetSourcePathSettings(binary_path, symbols_path): 36*a325d9c4SApple OSS Distributions """ Parse the binary path and symbols_path to find if source-map setting is applicable 37*a325d9c4SApple OSS Distributions params: 38*a325d9c4SApple OSS Distributions binary_path: str path of the kernel module 39*a325d9c4SApple OSS Distributions symbols_path: str path of the symbols stored in binary. Use 40*a325d9c4SApple OSS Distributions returns: 41*a325d9c4SApple OSS Distributions str : string command to set the source-map setting. 42*a325d9c4SApple OSS Distributions """ 43*a325d9c4SApple OSS Distributions retval = "" 44*a325d9c4SApple OSS Distributions train_re = re.compile(r"dsyms/([a-zA-Z]+)/") 45*a325d9c4SApple OSS Distributions _t_arr = train_re.findall(binary_path) 46*a325d9c4SApple OSS Distributions train = '' 47*a325d9c4SApple OSS Distributions if _t_arr: 48*a325d9c4SApple OSS Distributions train = _t_arr[0] 49*a325d9c4SApple OSS Distributions if not train: 50*a325d9c4SApple OSS Distributions return retval 51*a325d9c4SApple OSS Distributions new_path = "~rc/Software/{}/Projects/".format(train) 52*a325d9c4SApple OSS Distributions new_path = os.path.expanduser(new_path) 53*a325d9c4SApple OSS Distributions new_path = os.path.normpath(new_path) 54*a325d9c4SApple OSS Distributions common_path_re = re.compile("(^.*?Sources/)(xnu.*?)/.*$") 55*a325d9c4SApple OSS Distributions _t_arr = common_path_re.findall(symbols_path) 56*a325d9c4SApple OSS Distributions srcpath = "" 57*a325d9c4SApple OSS Distributions projpath = "xnu" 58*a325d9c4SApple OSS Distributions if _t_arr: 59*a325d9c4SApple OSS Distributions srcpath = "".join(_t_arr[0]) 60*a325d9c4SApple OSS Distributions projpath = _t_arr[0][-1] 61*a325d9c4SApple OSS Distributions else: 62*a325d9c4SApple OSS Distributions return retval 63*a325d9c4SApple OSS Distributions 64*a325d9c4SApple OSS Distributions new_path = new_path + os.path.sep + projpath 65*a325d9c4SApple OSS Distributions cmd = "settings append target.source-map {} {}" 66*a325d9c4SApple OSS Distributions retval = cmd.format(srcpath, new_path) 67*a325d9c4SApple OSS Distributions return retval 68*a325d9c4SApple OSS Distributions 69*a325d9c4SApple OSS Distributionsdef CheckLLDB(debugger): 70*a325d9c4SApple OSS Distributions """ Checks compatibility with current debugger. """ 71*a325d9c4SApple OSS Distributions 72*a325d9c4SApple OSS Distributions # Collect lldb_host version 73*a325d9c4SApple OSS Distributions ver_str = debugger.GetVersionString() 74*a325d9c4SApple OSS Distributions lldb_ver = re.search("^lldb.*-(.*)$", ver_str, re.MULTILINE).group(1) 75*a325d9c4SApple OSS Distributions ver = tuple(map(int, lldb_ver.split('.'))) 76*a325d9c4SApple OSS Distributions 77*a325d9c4SApple OSS Distributions # Display warning when running in Python 3 mode. 78*a325d9c4SApple OSS Distributions if PY3: 79*a325d9c4SApple OSS Distributions print("#" * 30) 80*a325d9c4SApple OSS Distributions print("WARNING! Python version 3 is not supported for xnu lldbmacros.") 81*a325d9c4SApple OSS Distributions print("Please restart your debugging session with the following workaround") 82*a325d9c4SApple OSS Distributions 83*a325d9c4SApple OSS Distributions if ver[0] == 1205: 84*a325d9c4SApple OSS Distributions print("\ndefaults write com.apple.dt.lldb DefaultPythonVersion 2\n") 85*a325d9c4SApple OSS Distributions 86*a325d9c4SApple OSS Distributions if ver[0] == 1300 and ver[1] == 2: 87*a325d9c4SApple OSS Distributions print("\ndefaults write com.apple.dt.lldb LegacyPythonVersion 2\n") 88*a325d9c4SApple OSS Distributions print("\nOR relaunch lldb session with env LLDB_DEFAULT_PYTHON_VERSION=2\n") 89*a325d9c4SApple OSS Distributions 90*a325d9c4SApple OSS Distributions if ver[0] == 1300 and ver[1] == 0: 91*a325d9c4SApple OSS Distributions release = subprocess.check_output(['sw_vers', '-releaseType']) 92*a325d9c4SApple OSS Distributions release = release.strip(b'\n') 93*a325d9c4SApple OSS Distributions 94*a325d9c4SApple OSS Distributions if release == b'Internal': 95*a325d9c4SApple OSS Distributions print("\nRelaunch lldb with xcrun from internal SDK\n") 96*a325d9c4SApple OSS Distributions print("\n xcrun -sdk <internal SDK> lldb\n") 97*a325d9c4SApple OSS Distributions else: 98*a325d9c4SApple OSS Distributions print("\nThis LLDB cannot debug kernel. Check KDK documentation.") 99*a325d9c4SApple OSS Distributions 100*a325d9c4SApple OSS Distributions print("#" * 30) 101*a325d9c4SApple OSS Distributions print("\n") 102*a325d9c4SApple OSS Distributions return False 103*a325d9c4SApple OSS Distributions 104*a325d9c4SApple OSS Distributions return True 105*a325d9c4SApple OSS Distributions 106*a325d9c4SApple OSS Distributionsdef __lldb_init_module(debugger, internal_dict): 107*a325d9c4SApple OSS Distributions 108*a325d9c4SApple OSS Distributions if not CheckLLDB(debugger): 109*a325d9c4SApple OSS Distributions return 110*a325d9c4SApple OSS Distributions 111*a325d9c4SApple OSS Distributions debug_session_enabled = False 112*a325d9c4SApple OSS Distributions if "DEBUG_XNU_LLDBMACROS" in os.environ and len(os.environ['DEBUG_XNU_LLDBMACROS']) > 0: 113*a325d9c4SApple OSS Distributions debug_session_enabled = True 114*a325d9c4SApple OSS Distributions prev_os_plugin = "".join(GetSettingsValues(debugger, 'target.process.python-os-plugin-path')) 115*a325d9c4SApple OSS Distributions print("Loading kernel debugging from %s" % __file__) 116*a325d9c4SApple OSS Distributions print("LLDB version %s" % debugger.GetVersionString()) 117*a325d9c4SApple OSS Distributions self_path = "{}".format(__file__) 118*a325d9c4SApple OSS Distributions base_dir_name = self_path[:self_path.rfind("/")] 119*a325d9c4SApple OSS Distributions core_os_plugin = base_dir_name + "/lldbmacros/core/operating_system.py" 120*a325d9c4SApple OSS Distributions osplugin_cmd = "settings set target.process.python-os-plugin-path \"%s\"" % core_os_plugin 121*a325d9c4SApple OSS Distributions intel_whitelist = ['hndl_allintrs', 'hndl_alltraps', 'trap_from_kernel', 'hndl_double_fault', 'hndl_machine_check'] 122*a325d9c4SApple OSS Distributions arm_whitelist = ['_fleh_prefabt', '_ExceptionVectorsBase', '_ExceptionVectorsTable', '_fleh_undef', '_fleh_dataabt', '_fleh_irq', '_fleh_decirq', '_fleh_fiq_generic', '_fleh_dec'] 123*a325d9c4SApple OSS Distributions whitelist_trap_cmd = "settings set target.trap-handler-names %s %s" % (' '.join(intel_whitelist), ' '.join(arm_whitelist)) 124*a325d9c4SApple OSS Distributions xnu_debug_path = base_dir_name + "/lldbmacros/xnu.py" 125*a325d9c4SApple OSS Distributions xnu_load_cmd = "command script import \"%s\"" % xnu_debug_path 126*a325d9c4SApple OSS Distributions disable_optimization_warnings_cmd = "settings set target.process.optimization-warnings false" 127*a325d9c4SApple OSS Distributions 128*a325d9c4SApple OSS Distributions # Single stepping support 129*a325d9c4SApple OSS Distributions report_all_threads_cmd = "settings set target.process.experimental.os-plugin-reports-all-threads false" 130*a325d9c4SApple OSS Distributions step_mode_cmd = "settings set target.process.run-all-threads true" 131*a325d9c4SApple OSS Distributions 132*a325d9c4SApple OSS Distributions source_map_cmd = "" 133*a325d9c4SApple OSS Distributions try: 134*a325d9c4SApple OSS Distributions source_map_cmd = GetSourcePathSettings(base_dir_name, GetSymbolsFilePathFromModule(debugger.GetTargetAtIndex(0).modules[0]) ) 135*a325d9c4SApple OSS Distributions except Exception as e: 136*a325d9c4SApple OSS Distributions pass 137*a325d9c4SApple OSS Distributions if debug_session_enabled : 138*a325d9c4SApple OSS Distributions if len(prev_os_plugin) > 0: 139*a325d9c4SApple OSS Distributions print("\nDEBUG_XNU_LLDBMACROS is set. Skipping the setting of OS plugin from dSYM.\nYou can manually set the OS plugin by running\n" + osplugin_cmd) 140*a325d9c4SApple OSS Distributions else: 141*a325d9c4SApple OSS Distributions print(osplugin_cmd) 142*a325d9c4SApple OSS Distributions debugger.HandleCommand(osplugin_cmd) 143*a325d9c4SApple OSS Distributions print("\nDEBUG_XNU_LLDBMACROS is set. Skipping the load of xnu debug framework.\nYou can manually load the framework by running\n" + xnu_load_cmd) 144*a325d9c4SApple OSS Distributions else: 145*a325d9c4SApple OSS Distributions print(osplugin_cmd) 146*a325d9c4SApple OSS Distributions debugger.HandleCommand(osplugin_cmd) 147*a325d9c4SApple OSS Distributions print(whitelist_trap_cmd) 148*a325d9c4SApple OSS Distributions debugger.HandleCommand(whitelist_trap_cmd) 149*a325d9c4SApple OSS Distributions print(xnu_load_cmd) 150*a325d9c4SApple OSS Distributions debugger.HandleCommand(xnu_load_cmd) 151*a325d9c4SApple OSS Distributions print(disable_optimization_warnings_cmd) 152*a325d9c4SApple OSS Distributions debugger.HandleCommand(disable_optimization_warnings_cmd) 153*a325d9c4SApple OSS Distributions print(report_all_threads_cmd) 154*a325d9c4SApple OSS Distributions debugger.HandleCommand(report_all_threads_cmd) 155*a325d9c4SApple OSS Distributions print(step_mode_cmd) 156*a325d9c4SApple OSS Distributions debugger.HandleCommand(step_mode_cmd) 157*a325d9c4SApple OSS Distributions if source_map_cmd: 158*a325d9c4SApple OSS Distributions print(source_map_cmd) 159*a325d9c4SApple OSS Distributions debugger.HandleCommand(source_map_cmd) 160*a325d9c4SApple OSS Distributions 161*a325d9c4SApple OSS Distributions load_kexts = True 162*a325d9c4SApple OSS Distributions if "XNU_LLDBMACROS_NOBUILTINKEXTS" in os.environ and len(os.environ['XNU_LLDBMACROS_NOBUILTINKEXTS']) > 0: 163*a325d9c4SApple OSS Distributions load_kexts = False 164*a325d9c4SApple OSS Distributions builtinkexts_path = os.path.join(os.path.dirname(self_path), "lldbmacros", "builtinkexts") 165*a325d9c4SApple OSS Distributions if os.access(builtinkexts_path, os.F_OK): 166*a325d9c4SApple OSS Distributions kexts = os.listdir(builtinkexts_path) 167*a325d9c4SApple OSS Distributions if len(kexts) > 0: 168*a325d9c4SApple OSS Distributions print("\nBuiltin kexts: %s\n" % kexts) 169*a325d9c4SApple OSS Distributions if load_kexts == False: 170*a325d9c4SApple OSS Distributions print("XNU_LLDBMACROS_NOBUILTINKEXTS is set, not loading:\n") 171*a325d9c4SApple OSS Distributions for kextdir in kexts: 172*a325d9c4SApple OSS Distributions script = os.path.join(builtinkexts_path, kextdir, kextdir.split('.')[-1] + ".py") 173*a325d9c4SApple OSS Distributions import_kext_cmd = "command script import \"%s\"" % script 174*a325d9c4SApple OSS Distributions print("%s" % import_kext_cmd) 175*a325d9c4SApple OSS Distributions if load_kexts: 176*a325d9c4SApple OSS Distributions debugger.HandleCommand(import_kext_cmd) 177*a325d9c4SApple OSS Distributions 178*a325d9c4SApple OSS Distributions print("\n") 179*a325d9c4SApple OSS Distributions 180