aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/gdb/linux
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/gdb/linux')
-rw-r--r--scripts/gdb/linux/.gitignore2
-rw-r--r--scripts/gdb/linux/Makefile11
-rw-r--r--scripts/gdb/linux/__init__.py1
-rw-r--r--scripts/gdb/linux/cpus.py135
-rw-r--r--scripts/gdb/linux/dmesg.py65
-rw-r--r--scripts/gdb/linux/modules.py103
-rw-r--r--scripts/gdb/linux/symbols.py177
-rw-r--r--scripts/gdb/linux/tasks.py100
-rw-r--r--scripts/gdb/linux/utils.py156
9 files changed, 750 insertions, 0 deletions
diff --git a/scripts/gdb/linux/.gitignore b/scripts/gdb/linux/.gitignore
new file mode 100644
index 000000000000..52e4e61140d1
--- /dev/null
+++ b/scripts/gdb/linux/.gitignore
@@ -0,0 +1,2 @@
1*.pyc
2*.pyo
diff --git a/scripts/gdb/linux/Makefile b/scripts/gdb/linux/Makefile
new file mode 100644
index 000000000000..6cf1ecf61057
--- /dev/null
+++ b/scripts/gdb/linux/Makefile
@@ -0,0 +1,11 @@
1always := gdb-scripts
2
3SRCTREE := $(shell cd $(srctree) && /bin/pwd)
4
5$(obj)/gdb-scripts:
6ifneq ($(KBUILD_SRC),)
7 $(Q)ln -fsn $(SRCTREE)/$(obj)/*.py $(objtree)/$(obj)
8endif
9 @:
10
11clean-files := *.pyc *.pyo $(if $(KBUILD_SRC),*.py)
diff --git a/scripts/gdb/linux/__init__.py b/scripts/gdb/linux/__init__.py
new file mode 100644
index 000000000000..4680fb176337
--- /dev/null
+++ b/scripts/gdb/linux/__init__.py
@@ -0,0 +1 @@
# nothing to do for the initialization of this package
diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
new file mode 100644
index 000000000000..4297b83fedef
--- /dev/null
+++ b/scripts/gdb/linux/cpus.py
@@ -0,0 +1,135 @@
1#
2# gdb helper commands and functions for Linux kernel debugging
3#
4# per-cpu tools
5#
6# Copyright (c) Siemens AG, 2011-2013
7#
8# Authors:
9# Jan Kiszka <jan.kiszka@siemens.com>
10#
11# This work is licensed under the terms of the GNU GPL version 2.
12#
13
14import gdb
15
16from linux import tasks, utils
17
18
19MAX_CPUS = 4096
20
21
22def get_current_cpu():
23 if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU:
24 return gdb.selected_thread().num - 1
25 elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB:
26 tid = gdb.selected_thread().ptid[2]
27 if tid > (0x100000000 - MAX_CPUS - 2):
28 return 0x100000000 - tid - 2
29 else:
30 return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu']
31 else:
32 raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
33 "supported with this gdb server.")
34
35
36def per_cpu(var_ptr, cpu):
37 if cpu == -1:
38 cpu = get_current_cpu()
39 if utils.is_target_arch("sparc:v9"):
40 offset = gdb.parse_and_eval(
41 "trap_block[{0}].__per_cpu_base".format(str(cpu)))
42 else:
43 try:
44 offset = gdb.parse_and_eval(
45 "__per_cpu_offset[{0}]".format(str(cpu)))
46 except gdb.error:
47 # !CONFIG_SMP case
48 offset = 0
49 pointer = var_ptr.cast(utils.get_long_type()) + offset
50 return pointer.cast(var_ptr.type).dereference()
51
52
53cpu_mask = {}
54
55
56def cpu_mask_invalidate(event):
57 global cpu_mask
58 cpu_mask = {}
59 gdb.events.stop.disconnect(cpu_mask_invalidate)
60 if hasattr(gdb.events, 'new_objfile'):
61 gdb.events.new_objfile.disconnect(cpu_mask_invalidate)
62
63
64def cpu_list(mask_name):
65 global cpu_mask
66 mask = None
67 if mask_name in cpu_mask:
68 mask = cpu_mask[mask_name]
69 if mask is None:
70 mask = gdb.parse_and_eval(mask_name + ".bits")
71 if hasattr(gdb, 'events'):
72 cpu_mask[mask_name] = mask
73 gdb.events.stop.connect(cpu_mask_invalidate)
74 if hasattr(gdb.events, 'new_objfile'):
75 gdb.events.new_objfile.connect(cpu_mask_invalidate)
76 bits_per_entry = mask[0].type.sizeof * 8
77 num_entries = mask.type.sizeof * 8 / bits_per_entry
78 entry = -1
79 bits = 0
80
81 while True:
82 while bits == 0:
83 entry += 1
84 if entry == num_entries:
85 return
86 bits = mask[entry]
87 if bits != 0:
88 bit = 0
89 break
90
91 while bits & 1 == 0:
92 bits >>= 1
93 bit += 1
94
95 cpu = entry * bits_per_entry + bit
96
97 bits >>= 1
98 bit += 1
99
100 yield cpu
101
102
103class PerCpu(gdb.Function):
104 """Return per-cpu variable.
105
106$lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the
107given CPU number. If CPU is omitted, the CPU of the current context is used.
108Note that VAR has to be quoted as string."""
109
110 def __init__(self):
111 super(PerCpu, self).__init__("lx_per_cpu")
112
113 def invoke(self, var_name, cpu=-1):
114 var_ptr = gdb.parse_and_eval("&" + var_name.string())
115 return per_cpu(var_ptr, cpu)
116
117
118PerCpu()
119
120
121class LxCurrentFunc(gdb.Function):
122 """Return current task.
123
124$lx_current([CPU]): Return the per-cpu task variable for the given CPU
125number. If CPU is omitted, the CPU of the current context is used."""
126
127 def __init__(self):
128 super(LxCurrentFunc, self).__init__("lx_current")
129
130 def invoke(self, cpu=-1):
131 var_ptr = gdb.parse_and_eval("&current_task")
132 return per_cpu(var_ptr, cpu).dereference()
133
134
135LxCurrentFunc()
diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py
new file mode 100644
index 000000000000..3c947f0c5dad
--- /dev/null
+++ b/scripts/gdb/linux/dmesg.py
@@ -0,0 +1,65 @@
1#
2# gdb helper commands and functions for Linux kernel debugging
3#
4# kernel log buffer dump
5#
6# Copyright (c) Siemens AG, 2011, 2012
7#
8# Authors:
9# Jan Kiszka <jan.kiszka@siemens.com>
10#
11# This work is licensed under the terms of the GNU GPL version 2.
12#
13
14import gdb
15import string
16
17from linux import utils
18
19
20class LxDmesg(gdb.Command):
21 """Print Linux kernel log buffer."""
22
23 def __init__(self):
24 super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA)
25
26 def invoke(self, arg, from_tty):
27 log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16)
28 log_first_idx = int(gdb.parse_and_eval("log_first_idx"))
29 log_next_idx = int(gdb.parse_and_eval("log_next_idx"))
30 log_buf_len = int(gdb.parse_and_eval("log_buf_len"))
31
32 inf = gdb.inferiors()[0]
33 start = log_buf_addr + log_first_idx
34 if log_first_idx < log_next_idx:
35 log_buf_2nd_half = -1
36 length = log_next_idx - log_first_idx
37 log_buf = inf.read_memory(start, length)
38 else:
39 log_buf_2nd_half = log_buf_len - log_first_idx
40 log_buf = inf.read_memory(start, log_buf_2nd_half) + \
41 inf.read_memory(log_buf_addr, log_next_idx)
42
43 pos = 0
44 while pos < log_buf.__len__():
45 length = utils.read_u16(log_buf[pos + 8:pos + 10])
46 if length == 0:
47 if log_buf_2nd_half == -1:
48 gdb.write("Corrupted log buffer!\n")
49 break
50 pos = log_buf_2nd_half
51 continue
52
53 text_len = utils.read_u16(log_buf[pos + 10:pos + 12])
54 text = log_buf[pos + 16:pos + 16 + text_len]
55 time_stamp = utils.read_u64(log_buf[pos:pos + 8])
56
57 for line in memoryview(text).tobytes().splitlines():
58 gdb.write("[{time:12.6f}] {line}\n".format(
59 time=time_stamp / 1000000000.0,
60 line=line))
61
62 pos += length
63
64
65LxDmesg()
diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py
new file mode 100644
index 000000000000..a1504c4f1900
--- /dev/null
+++ b/scripts/gdb/linux/modules.py
@@ -0,0 +1,103 @@
1#
2# gdb helper commands and functions for Linux kernel debugging
3#
4# module tools
5#
6# Copyright (c) Siemens AG, 2013
7#
8# Authors:
9# Jan Kiszka <jan.kiszka@siemens.com>
10#
11# This work is licensed under the terms of the GNU GPL version 2.
12#
13
14import gdb
15
16from linux import cpus, utils
17
18
19module_type = utils.CachedType("struct module")
20
21
22def module_list():
23 global module_type
24 module_ptr_type = module_type.get_type().pointer()
25 modules = gdb.parse_and_eval("modules")
26 entry = modules['next']
27 end_of_list = modules.address
28
29 while entry != end_of_list:
30 yield utils.container_of(entry, module_ptr_type, "list")
31 entry = entry['next']
32
33
34def find_module_by_name(name):
35 for module in module_list():
36 if module['name'].string() == name:
37 return module
38 return None
39
40
41class LxModule(gdb.Function):
42 """Find module by name and return the module variable.
43
44$lx_module("MODULE"): Given the name MODULE, iterate over all loaded modules
45of the target and return that module variable which MODULE matches."""
46
47 def __init__(self):
48 super(LxModule, self).__init__("lx_module")
49
50 def invoke(self, mod_name):
51 mod_name = mod_name.string()
52 module = find_module_by_name(mod_name)
53 if module:
54 return module.dereference()
55 else:
56 raise gdb.GdbError("Unable to find MODULE " + mod_name)
57
58
59LxModule()
60
61
62class LxLsmod(gdb.Command):
63 """List currently loaded modules."""
64
65 _module_use_type = utils.CachedType("struct module_use")
66
67 def __init__(self):
68 super(LxLsmod, self).__init__("lx-lsmod", gdb.COMMAND_DATA)
69
70 def invoke(self, arg, from_tty):
71 gdb.write(
72 "Address{0} Module Size Used by\n".format(
73 " " if utils.get_long_type().sizeof == 8 else ""))
74
75 for module in module_list():
76 ref = 0
77 module_refptr = module['refptr']
78 for cpu in cpus.cpu_list("cpu_possible_mask"):
79 refptr = cpus.per_cpu(module_refptr, cpu)
80 ref += refptr['incs']
81 ref -= refptr['decs']
82
83 gdb.write("{address} {name:<19} {size:>8} {ref}".format(
84 address=str(module['module_core']).split()[0],
85 name=module['name'].string(),
86 size=str(module['core_size']),
87 ref=str(ref)))
88
89 source_list = module['source_list']
90 t = self._module_use_type.get_type().pointer()
91 entry = source_list['next']
92 first = True
93 while entry != source_list.address:
94 use = utils.container_of(entry, t, "source_list")
95 gdb.write("{separator}{name}".format(
96 separator=" " if first else ",",
97 name=use['source']['name'].string()))
98 first = False
99 entry = entry['next']
100 gdb.write("\n")
101
102
103LxLsmod()
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
new file mode 100644
index 000000000000..cd5bea965d4e
--- /dev/null
+++ b/scripts/gdb/linux/symbols.py
@@ -0,0 +1,177 @@
1#
2# gdb helper commands and functions for Linux kernel debugging
3#
4# load kernel and module symbols
5#
6# Copyright (c) Siemens AG, 2011-2013
7#
8# Authors:
9# Jan Kiszka <jan.kiszka@siemens.com>
10#
11# This work is licensed under the terms of the GNU GPL version 2.
12#
13
14import gdb
15import os
16import re
17import string
18
19from linux import modules, utils
20
21
22if hasattr(gdb, 'Breakpoint'):
23 class LoadModuleBreakpoint(gdb.Breakpoint):
24 def __init__(self, spec, gdb_command):
25 super(LoadModuleBreakpoint, self).__init__(spec, internal=True)
26 self.silent = True
27 self.gdb_command = gdb_command
28
29 def stop(self):
30 module = gdb.parse_and_eval("mod")
31 module_name = module['name'].string()
32 cmd = self.gdb_command
33
34 # enforce update if object file is not found
35 cmd.module_files_updated = False
36
37 # Disable pagination while reporting symbol (re-)loading.
38 # The console input is blocked in this context so that we would
39 # get stuck waiting for the user to acknowledge paged output.
40 show_pagination = gdb.execute("show pagination", to_string=True)
41 pagination = show_pagination.endswith("on.\n")
42 gdb.execute("set pagination off")
43
44 if module_name in cmd.loaded_modules:
45 gdb.write("refreshing all symbols to reload module "
46 "'{0}'\n".format(module_name))
47 cmd.load_all_symbols()
48 else:
49 cmd.load_module_symbols(module)
50
51 # restore pagination state
52 gdb.execute("set pagination %s" % ("on" if pagination else "off"))
53
54 return False
55
56
57class LxSymbols(gdb.Command):
58 """(Re-)load symbols of Linux kernel and currently loaded modules.
59
60The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
61are scanned recursively, starting in the same directory. Optionally, the module
62search path can be extended by a space separated list of paths passed to the
63lx-symbols command."""
64
65 module_paths = []
66 module_files = []
67 module_files_updated = False
68 loaded_modules = []
69 breakpoint = None
70
71 def __init__(self):
72 super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
73 gdb.COMPLETE_FILENAME)
74
75 def _update_module_files(self):
76 self.module_files = []
77 for path in self.module_paths:
78 gdb.write("scanning for modules in {0}\n".format(path))
79 for root, dirs, files in os.walk(path):
80 for name in files:
81 if name.endswith(".ko"):
82 self.module_files.append(root + "/" + name)
83 self.module_files_updated = True
84
85 def _get_module_file(self, module_name):
86 module_pattern = ".*/{0}\.ko$".format(
87 module_name.replace("_", r"[_\-]"))
88 for name in self.module_files:
89 if re.match(module_pattern, name) and os.path.exists(name):
90 return name
91 return None
92
93 def _section_arguments(self, module):
94 try:
95 sect_attrs = module['sect_attrs'].dereference()
96 except gdb.error:
97 return ""
98 attrs = sect_attrs['attrs']
99 section_name_to_address = {
100 attrs[n]['name'].string() : attrs[n]['address']
101 for n in range(int(sect_attrs['nsections']))}
102 args = []
103 for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]:
104 address = section_name_to_address.get(section_name)
105 if address:
106 args.append(" -s {name} {addr}".format(
107 name=section_name, addr=str(address)))
108 return "".join(args)
109
110 def load_module_symbols(self, module):
111 module_name = module['name'].string()
112 module_addr = str(module['module_core']).split()[0]
113
114 module_file = self._get_module_file(module_name)
115 if not module_file and not self.module_files_updated:
116 self._update_module_files()
117 module_file = self._get_module_file(module_name)
118
119 if module_file:
120 gdb.write("loading @{addr}: {filename}\n".format(
121 addr=module_addr, filename=module_file))
122 cmdline = "add-symbol-file {filename} {addr}{sections}".format(
123 filename=module_file,
124 addr=module_addr,
125 sections=self._section_arguments(module))
126 gdb.execute(cmdline, to_string=True)
127 if not module_name in self.loaded_modules:
128 self.loaded_modules.append(module_name)
129 else:
130 gdb.write("no module object found for '{0}'\n".format(module_name))
131
132 def load_all_symbols(self):
133 gdb.write("loading vmlinux\n")
134
135 # Dropping symbols will disable all breakpoints. So save their states
136 # and restore them afterward.
137 saved_states = []
138 if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None:
139 for bp in gdb.breakpoints():
140 saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
141
142 # drop all current symbols and reload vmlinux
143 gdb.execute("symbol-file", to_string=True)
144 gdb.execute("symbol-file vmlinux")
145
146 self.loaded_modules = []
147 module_list = modules.module_list()
148 if not module_list:
149 gdb.write("no modules found\n")
150 else:
151 [self.load_module_symbols(module) for module in module_list]
152
153 for saved_state in saved_states:
154 saved_state['breakpoint'].enabled = saved_state['enabled']
155
156 def invoke(self, arg, from_tty):
157 self.module_paths = arg.split()
158 self.module_paths.append(os.getcwd())
159
160 # enforce update
161 self.module_files = []
162 self.module_files_updated = False
163
164 self.load_all_symbols()
165
166 if hasattr(gdb, 'Breakpoint'):
167 if not self.breakpoint is None:
168 self.breakpoint.delete()
169 self.breakpoint = None
170 self.breakpoint = LoadModuleBreakpoint(
171 "kernel/module.c:do_init_module", self)
172 else:
173 gdb.write("Note: symbol update on module loading not supported "
174 "with this gdb version\n")
175
176
177LxSymbols()
diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py
new file mode 100644
index 000000000000..e2037d9bb7eb
--- /dev/null
+++ b/scripts/gdb/linux/tasks.py
@@ -0,0 +1,100 @@
1#
2# gdb helper commands and functions for Linux kernel debugging
3#
4# task & thread tools
5#
6# Copyright (c) Siemens AG, 2011-2013
7#
8# Authors:
9# Jan Kiszka <jan.kiszka@siemens.com>
10#
11# This work is licensed under the terms of the GNU GPL version 2.
12#
13
14import gdb
15
16from linux import utils
17
18
19task_type = utils.CachedType("struct task_struct")
20
21def task_lists():
22 global task_type
23 task_ptr_type = task_type.get_type().pointer()
24 init_task = gdb.parse_and_eval("init_task").address
25 t = g = init_task
26
27 while True:
28 while True:
29 yield t
30
31 t = utils.container_of(t['thread_group']['next'],
32 task_ptr_type, "thread_group")
33 if t == g:
34 break
35
36 t = g = utils.container_of(g['tasks']['next'],
37 task_ptr_type, "tasks")
38 if t == init_task:
39 return
40
41def get_task_by_pid(pid):
42 for task in task_lists():
43 if int(task['pid']) == pid:
44 return task
45 return None
46
47
48class LxTaskByPidFunc(gdb.Function):
49 """Find Linux task by PID and return the task_struct variable.
50
51$lx_task_by_pid(PID): Given PID, iterate over all tasks of the target and
52return that task_struct variable which PID matches."""
53
54 def __init__(self):
55 super(LxTaskByPidFunc, self).__init__("lx_task_by_pid")
56
57 def invoke(self, pid):
58 task = get_task_by_pid(pid)
59 if task:
60 return task.dereference()
61 else:
62 raise gdb.GdbError("No task of PID " + str(pid))
63
64
65LxTaskByPidFunc()
66
67
68thread_info_type = utils.CachedType("struct thread_info")
69
70ia64_task_size = None
71
72
73def get_thread_info(task):
74 global thread_info_type
75 thread_info_ptr_type = thread_info_type.get_type().pointer()
76 if utils.is_target_arch("ia64"):
77 global ia64_task_size
78 if ia64_task_size is None:
79 ia64_task_size = gdb.parse_and_eval("sizeof(struct task_struct)")
80 thread_info_addr = task.address + ia64_task_size
81 thread_info = thread_info_addr.cast(thread_info_ptr_type)
82 else:
83 thread_info = task['stack'].cast(thread_info_ptr_type)
84 return thread_info.dereference()
85
86
87class LxThreadInfoFunc (gdb.Function):
88 """Calculate Linux thread_info from task variable.
89
90$lx_thread_info(TASK): Given TASK, return the corresponding thread_info
91variable."""
92
93 def __init__(self):
94 super(LxThreadInfoFunc, self).__init__("lx_thread_info")
95
96 def invoke(self, task):
97 return get_thread_info(task)
98
99
100LxThreadInfoFunc()
diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
new file mode 100644
index 000000000000..128c306db3ee
--- /dev/null
+++ b/scripts/gdb/linux/utils.py
@@ -0,0 +1,156 @@
1#
2# gdb helper commands and functions for Linux kernel debugging
3#
4# common utilities
5#
6# Copyright (c) Siemens AG, 2011-2013
7#
8# Authors:
9# Jan Kiszka <jan.kiszka@siemens.com>
10#
11# This work is licensed under the terms of the GNU GPL version 2.
12#
13
14import gdb
15
16
17class CachedType:
18 def __init__(self, name):
19 self._type = None
20 self._name = name
21
22 def _new_objfile_handler(self, event):
23 self._type = None
24 gdb.events.new_objfile.disconnect(self._new_objfile_handler)
25
26 def get_type(self):
27 if self._type is None:
28 self._type = gdb.lookup_type(self._name)
29 if self._type is None:
30 raise gdb.GdbError(
31 "cannot resolve type '{0}'".format(self._name))
32 if hasattr(gdb, 'events') and hasattr(gdb.events, 'new_objfile'):
33 gdb.events.new_objfile.connect(self._new_objfile_handler)
34 return self._type
35
36
37long_type = CachedType("long")
38
39
40def get_long_type():
41 global long_type
42 return long_type.get_type()
43
44
45def offset_of(typeobj, field):
46 element = gdb.Value(0).cast(typeobj)
47 return int(str(element[field].address).split()[0], 16)
48
49
50def container_of(ptr, typeobj, member):
51 return (ptr.cast(get_long_type()) -
52 offset_of(typeobj, member)).cast(typeobj)
53
54
55class ContainerOf(gdb.Function):
56 """Return pointer to containing data structure.
57
58$container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the
59data structure of the type TYPE in which PTR is the address of ELEMENT.
60Note that TYPE and ELEMENT have to be quoted as strings."""
61
62 def __init__(self):
63 super(ContainerOf, self).__init__("container_of")
64
65 def invoke(self, ptr, typename, elementname):
66 return container_of(ptr, gdb.lookup_type(typename.string()).pointer(),
67 elementname.string())
68
69ContainerOf()
70
71
72BIG_ENDIAN = 0
73LITTLE_ENDIAN = 1
74target_endianness = None
75
76
77def get_target_endianness():
78 global target_endianness
79 if target_endianness is None:
80 endian = gdb.execute("show endian", to_string=True)
81 if "little endian" in endian:
82 target_endianness = LITTLE_ENDIAN
83 elif "big endian" in endian:
84 target_endianness = BIG_ENDIAN
85 else:
86 raise gdb.GdgError("unknown endianness '{0}'".format(str(endian)))
87 return target_endianness
88
89
90def read_u16(buffer):
91 if get_target_endianness() == LITTLE_ENDIAN:
92 return ord(buffer[0]) + (ord(buffer[1]) << 8)
93 else:
94 return ord(buffer[1]) + (ord(buffer[0]) << 8)
95
96
97def read_u32(buffer):
98 if get_target_endianness() == LITTLE_ENDIAN:
99 return read_u16(buffer[0:2]) + (read_u16(buffer[2:4]) << 16)
100 else:
101 return read_u16(buffer[2:4]) + (read_u16(buffer[0:2]) << 16)
102
103
104def read_u64(buffer):
105 if get_target_endianness() == LITTLE_ENDIAN:
106 return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32)
107 else:
108 return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32)
109
110
111target_arch = None
112
113
114def is_target_arch(arch):
115 if hasattr(gdb.Frame, 'architecture'):
116 return arch in gdb.newest_frame().architecture().name()
117 else:
118 global target_arch
119 if target_arch is None:
120 target_arch = gdb.execute("show architecture", to_string=True)
121 return arch in target_arch
122
123
124GDBSERVER_QEMU = 0
125GDBSERVER_KGDB = 1
126gdbserver_type = None
127
128
129def get_gdbserver_type():
130 def exit_handler(event):
131 global gdbserver_type
132 gdbserver_type = None
133 gdb.events.exited.disconnect(exit_handler)
134
135 def probe_qemu():
136 try:
137 return gdb.execute("monitor info version", to_string=True) != ""
138 except:
139 return False
140
141 def probe_kgdb():
142 try:
143 thread_info = gdb.execute("info thread 2", to_string=True)
144 return "shadowCPU0" in thread_info
145 except:
146 return False
147
148 global gdbserver_type
149 if gdbserver_type is None:
150 if probe_qemu():
151 gdbserver_type = GDBSERVER_QEMU
152 elif probe_kgdb():
153 gdbserver_type = GDBSERVER_KGDB
154 if not gdbserver_type is None and hasattr(gdb, 'events'):
155 gdb.events.exited.connect(exit_handler)
156 return gdbserver_type