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