• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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")
38ulong_type = CachedType("unsigned long")
39uint_type = CachedType("unsigned int")
40atomic_long_type = CachedType("atomic_long_t")
41size_t_type = CachedType("size_t")
42struct_page_type = CachedType("struct page")
43
44def get_uint_type():
45    global uint_type
46    return uint_type.get_type()
47
48def get_page_type():
49    global struct_page_type
50    return struct_page_type.get_type()
51
52def get_long_type():
53    global long_type
54    return long_type.get_type()
55
56def get_ulong_type():
57    global ulong_type
58    return ulong_type.get_type()
59
60def get_size_t_type():
61    global size_t_type
62    return size_t_type.get_type()
63
64def offset_of(typeobj, field):
65    element = gdb.Value(0).cast(typeobj)
66    return int(str(element[field].address).split()[0], 16)
67
68
69def container_of(ptr, typeobj, member):
70    return (ptr.cast(get_long_type()) -
71            offset_of(typeobj, member)).cast(typeobj)
72
73
74class ContainerOf(gdb.Function):
75    """Return pointer to containing data structure.
76
77$container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the
78data structure of the type TYPE in which PTR is the address of ELEMENT.
79Note that TYPE and ELEMENT have to be quoted as strings."""
80
81    def __init__(self):
82        super(ContainerOf, self).__init__("container_of")
83
84    def invoke(self, ptr, typename, elementname):
85        return container_of(ptr, gdb.lookup_type(typename.string()).pointer(),
86                            elementname.string())
87
88
89ContainerOf()
90
91
92BIG_ENDIAN = 0
93LITTLE_ENDIAN = 1
94target_endianness = None
95
96
97def get_target_endianness():
98    global target_endianness
99    if target_endianness is None:
100        endian = gdb.execute("show endian", to_string=True)
101        if "little endian" in endian:
102            target_endianness = LITTLE_ENDIAN
103        elif "big endian" in endian:
104            target_endianness = BIG_ENDIAN
105        else:
106            raise gdb.GdbError("unknown endianness '{0}'".format(str(endian)))
107    return target_endianness
108
109
110def read_memoryview(inf, start, length):
111    m = inf.read_memory(start, length)
112    if type(m) is memoryview:
113        return m
114    return memoryview(m)
115
116
117def read_u16(buffer, offset):
118    buffer_val = buffer[offset:offset + 2]
119    value = [0, 0]
120
121    if type(buffer_val[0]) is str:
122        value[0] = ord(buffer_val[0])
123        value[1] = ord(buffer_val[1])
124    else:
125        value[0] = buffer_val[0]
126        value[1] = buffer_val[1]
127
128    if get_target_endianness() == LITTLE_ENDIAN:
129        return value[0] + (value[1] << 8)
130    else:
131        return value[1] + (value[0] << 8)
132
133
134def read_u32(buffer, offset):
135    if get_target_endianness() == LITTLE_ENDIAN:
136        return read_u16(buffer, offset) + (read_u16(buffer, offset + 2) << 16)
137    else:
138        return read_u16(buffer, offset + 2) + (read_u16(buffer, offset) << 16)
139
140
141def read_u64(buffer, offset):
142    if get_target_endianness() == LITTLE_ENDIAN:
143        return read_u32(buffer, offset) + (read_u32(buffer, offset + 4) << 32)
144    else:
145        return read_u32(buffer, offset + 4) + (read_u32(buffer, offset) << 32)
146
147
148def read_ulong(buffer, offset):
149    if get_long_type().sizeof == 8:
150        return read_u64(buffer, offset)
151    else:
152        return read_u32(buffer, offset)
153
154atomic_long_counter_offset = atomic_long_type.get_type()['counter'].bitpos
155atomic_long_counter_sizeof = atomic_long_type.get_type()['counter'].type.sizeof
156
157def read_atomic_long(buffer, offset):
158    global atomic_long_counter_offset
159    global atomic_long_counter_sizeof
160
161    if atomic_long_counter_sizeof == 8:
162        return read_u64(buffer, offset + atomic_long_counter_offset)
163    else:
164        return read_u32(buffer, offset + atomic_long_counter_offset)
165
166target_arch = None
167
168
169def is_target_arch(arch):
170    if hasattr(gdb.Frame, 'architecture'):
171        return arch in gdb.newest_frame().architecture().name()
172    else:
173        global target_arch
174        if target_arch is None:
175            target_arch = gdb.execute("show architecture", to_string=True)
176        return arch in target_arch
177
178
179GDBSERVER_QEMU = 0
180GDBSERVER_KGDB = 1
181gdbserver_type = None
182
183
184def get_gdbserver_type():
185    def exit_handler(event):
186        global gdbserver_type
187        gdbserver_type = None
188        gdb.events.exited.disconnect(exit_handler)
189
190    def probe_qemu():
191        try:
192            return gdb.execute("monitor info version", to_string=True) != ""
193        except gdb.error:
194            return False
195
196    def probe_kgdb():
197        try:
198            thread_info = gdb.execute("info thread 2", to_string=True)
199            return "shadowCPU0" in thread_info
200        except gdb.error:
201            return False
202
203    global gdbserver_type
204    if gdbserver_type is None:
205        if probe_qemu():
206            gdbserver_type = GDBSERVER_QEMU
207        elif probe_kgdb():
208            gdbserver_type = GDBSERVER_KGDB
209        if gdbserver_type is not None and hasattr(gdb, 'events'):
210            gdb.events.exited.connect(exit_handler)
211    return gdbserver_type
212
213
214def gdb_eval_or_none(expresssion):
215    try:
216        return gdb.parse_and_eval(expresssion)
217    except gdb.error:
218        return None
219