xref: /xnu-8019.80.24/tools/lldbmacros/core/xnu_lldb_init.py (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
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