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 "shadowCPU" 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