xref: /openbmc/linux/scripts/gdb/linux/utils.py (revision b664e06d)
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
69
70ContainerOf()
71
72
73BIG_ENDIAN = 0
74LITTLE_ENDIAN = 1
75target_endianness = None
76
77
78def get_target_endianness():
79    global target_endianness
80    if target_endianness is None:
81        endian = gdb.execute("show endian", to_string=True)
82        if "little endian" in endian:
83            target_endianness = LITTLE_ENDIAN
84        elif "big endian" in endian:
85            target_endianness = BIG_ENDIAN
86        else:
87            raise gdb.GdbError("unknown endianness '{0}'".format(str(endian)))
88    return target_endianness
89
90
91def read_memoryview(inf, start, length):
92    return memoryview(inf.read_memory(start, length))
93
94
95def read_u16(buffer):
96    value = [0, 0]
97
98    if type(buffer[0]) is str:
99        value[0] = ord(buffer[0])
100        value[1] = ord(buffer[1])
101    else:
102        value[0] = buffer[0]
103        value[1] = buffer[1]
104
105    if get_target_endianness() == LITTLE_ENDIAN:
106        return value[0] + (value[1] << 8)
107    else:
108        return value[1] + (value[0] << 8)
109
110
111def read_u32(buffer):
112    if get_target_endianness() == LITTLE_ENDIAN:
113        return read_u16(buffer[0:2]) + (read_u16(buffer[2:4]) << 16)
114    else:
115        return read_u16(buffer[2:4]) + (read_u16(buffer[0:2]) << 16)
116
117
118def read_u64(buffer):
119    if get_target_endianness() == LITTLE_ENDIAN:
120        return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32)
121    else:
122        return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32)
123
124
125target_arch = None
126
127
128def is_target_arch(arch):
129    if hasattr(gdb.Frame, 'architecture'):
130        return arch in gdb.newest_frame().architecture().name()
131    else:
132        global target_arch
133        if target_arch is None:
134            target_arch = gdb.execute("show architecture", to_string=True)
135        return arch in target_arch
136
137
138GDBSERVER_QEMU = 0
139GDBSERVER_KGDB = 1
140gdbserver_type = None
141
142
143def get_gdbserver_type():
144    def exit_handler(event):
145        global gdbserver_type
146        gdbserver_type = None
147        gdb.events.exited.disconnect(exit_handler)
148
149    def probe_qemu():
150        try:
151            return gdb.execute("monitor info version", to_string=True) != ""
152        except gdb.error:
153            return False
154
155    def probe_kgdb():
156        try:
157            thread_info = gdb.execute("info thread 2", to_string=True)
158            return "shadowCPU0" in thread_info
159        except gdb.error:
160            return False
161
162    global gdbserver_type
163    if gdbserver_type is None:
164        if probe_qemu():
165            gdbserver_type = GDBSERVER_QEMU
166        elif probe_kgdb():
167            gdbserver_type = GDBSERVER_KGDB
168        if gdbserver_type is not None and hasattr(gdb, 'events'):
169            gdb.events.exited.connect(exit_handler)
170    return gdbserver_type
171
172
173def gdb_eval_or_none(expresssion):
174    try:
175        return gdb.parse_and_eval(expresssion)
176    except gdb.error:
177        return None
178
179
180def dentry_name(d):
181    parent = d['d_parent']
182    if parent == d or parent == 0:
183        return ""
184    p = dentry_name(d['d_parent']) + "/"
185    return p + d['d_iname'].string()
186