Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | import os import re def GetSettingsValues(debugger, setting_variable_name): """ Queries the lldb internal settings params: debugger : lldb.SBDebugger instance setting_variable_name: str - string name of the setting(eg prompt) returns: [] : Array of strings. Empty array if setting is not found/set """ retval = [] settings_val_list = debugger.GetInternalVariableValue(setting_variable_name, debugger.GetInstanceName()) for s in settings_val_list: retval.append(str(s)) return retval def GetSymbolsFilePathFromModule(m): """ Get a file path from a module. params: m - lldb.target.module returns: str : path to first file based symbol. Note this might be dir path inside sources. """ for s in m.symbols: if s.type == 8: return os.path.dirname(str(s.name)) return "" def GetSourcePathSettings(binary_path, symbols_path): """ Parse the binary path and symbols_path to find if source-map setting is applicable params: binary_path: str path of the kernel module symbols_path: str path of the symbols stored in binary. Use returns: str : string command to set the source-map setting. """ retval = "" train_re = re.compile(r"dsyms/([a-zA-Z]+)/") _t_arr = train_re.findall(binary_path) train = '' if _t_arr: train = _t_arr[0] if not train: return retval new_path = "~rc/Software/{}/Projects/".format(train) new_path = os.path.expanduser(new_path) new_path = os.path.normpath(new_path) common_path_re = re.compile("(^.*?Sources/)(xnu.*?)/.*$") _t_arr = common_path_re.findall(symbols_path) srcpath = "" projpath = "xnu" if _t_arr: srcpath = "".join(_t_arr[0]) projpath = _t_arr[0][-1] else: return retval new_path = new_path + os.path.sep + projpath cmd = "settings append target.source-map {} {}" retval = cmd.format(srcpath, new_path) return retval def CheckMissingLibs(debugger): """ Check that required modules are installed. """ # Convert LLDB version string to version tuple. # A version string may be of form: lldb_host-1403.2.6.11 (iPhoneOS) # Code below only matches 1403.2.6.11 and ignores rest of the string. ver_str = debugger.GetVersionString() lldb_ver = re.search("^lldb.*-([0-9.]+)", ver_str, re.MULTILINE).group(1) ver = tuple(map(int, lldb_ver.split('.'))) # Display correct command to install missing packages. if ver[1] == 2: cmd_fmt = "Please install {mod:s}: xcrun --sdk <sdk> python3 -m pip install --user --ignore-installed {mod:s}" else: cmd_fmt = "Please install {mod:s}: xcrun pip3 install --user --ignore-installed {mod:s}" try: import macholib except: print(cmd_fmt.format(mod="macholib")) return False return True def __lldb_init_module(debugger, internal_dict): if not CheckMissingLibs(debugger): print("Can't load LLDB macros. Please install dependencies first.") return debug_session_enabled = False if "DEBUG_XNU_LLDBMACROS" in os.environ and len(os.environ['DEBUG_XNU_LLDBMACROS']) > 0: debug_session_enabled = True prev_os_plugin = "".join(GetSettingsValues(debugger, 'target.process.python-os-plugin-path')) print("Loading kernel debugging from %s" % __file__) print("LLDB version %s" % debugger.GetVersionString()) self_path = "{}".format(__file__) base_dir_name = self_path[:self_path.rfind("/")] core_os_plugin = base_dir_name + "/lldbmacros/core/operating_system.py" osplugin_cmd = "settings set target.process.python-os-plugin-path \"%s\"" % core_os_plugin intel_whitelist = ['hndl_allintrs', 'hndl_alltraps', 'trap_from_kernel', 'hndl_double_fault', 'hndl_machine_check'] arm_whitelist = ['_fleh_prefabt', '_ExceptionVectorsBase', '_ExceptionVectorsTable', '_fleh_undef', '_fleh_dataabt', '_fleh_irq', '_fleh_decirq', '_fleh_fiq_generic', '_fleh_dec'] whitelist_trap_cmd = "settings set target.trap-handler-names %s %s" % (' '.join(intel_whitelist), ' '.join(arm_whitelist)) xnu_debug_path = base_dir_name + "/lldbmacros/xnu.py" xnu_load_cmd = "command script import \"%s\"" % xnu_debug_path disable_optimization_warnings_cmd = "settings set target.process.optimization-warnings false" # Single stepping support report_all_threads_cmd = "settings set target.process.experimental.os-plugin-reports-all-threads false" step_mode_cmd = "settings set target.process.run-all-threads true" source_map_cmd = "" try: source_map_cmd = GetSourcePathSettings(base_dir_name, GetSymbolsFilePathFromModule(debugger.GetTargetAtIndex(0).modules[0]) ) except Exception as e: pass if debug_session_enabled : if len(prev_os_plugin) > 0: 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) else: print(osplugin_cmd) debugger.HandleCommand(osplugin_cmd) 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) else: print(osplugin_cmd) debugger.HandleCommand(osplugin_cmd) print(whitelist_trap_cmd) debugger.HandleCommand(whitelist_trap_cmd) print(xnu_load_cmd) debugger.HandleCommand(xnu_load_cmd) print(disable_optimization_warnings_cmd) debugger.HandleCommand(disable_optimization_warnings_cmd) print(report_all_threads_cmd) debugger.HandleCommand(report_all_threads_cmd) print(step_mode_cmd) debugger.HandleCommand(step_mode_cmd) if source_map_cmd: print(source_map_cmd) debugger.HandleCommand(source_map_cmd) load_kexts = True if "XNU_LLDBMACROS_NOBUILTINKEXTS" in os.environ and len(os.environ['XNU_LLDBMACROS_NOBUILTINKEXTS']) > 0: load_kexts = False builtinkexts_path = os.path.join(os.path.dirname(self_path), "lldbmacros", "builtinkexts") if os.access(builtinkexts_path, os.F_OK): kexts = os.listdir(builtinkexts_path) if len(kexts) > 0: print("\nBuiltin kexts: %s\n" % kexts) if not load_kexts: print("XNU_LLDBMACROS_NOBUILTINKEXTS is set, not loading:\n") for kextdir in kexts: # Python does not handle well modules that contain '-' in their names. # Remap such scripts to use '_' instead. script_name = kextdir.split('.')[-1].replace('-', '_') + ".py" script = os.path.join(builtinkexts_path, kextdir, script_name) import_kext_cmd = "command script import \"%s\"" % script print("%s" % import_kext_cmd) if load_kexts: debugger.HandleCommand(import_kext_cmd) print("\n") |