1 # 1 # 2 # gdb helper commands and functions for Linux 2 # gdb helper commands and functions for Linux kernel debugging 3 # 3 # 4 # common utilities 4 # common utilities 5 # 5 # 6 # Copyright (c) Siemens AG, 2011-2013 6 # Copyright (c) Siemens AG, 2011-2013 7 # 7 # 8 # Authors: 8 # Authors: 9 # Jan Kiszka <jan.kiszka@siemens.com> 9 # Jan Kiszka <jan.kiszka@siemens.com> 10 # 10 # 11 # This work is licensed under the terms of the 11 # This work is licensed under the terms of the GNU GPL version 2. 12 # 12 # 13 13 14 import gdb 14 import gdb 15 15 16 16 17 class CachedType: 17 class CachedType: 18 def __init__(self, name): 18 def __init__(self, name): 19 self._type = None 19 self._type = None 20 self._name = name 20 self._name = name 21 21 22 def _new_objfile_handler(self, event): 22 def _new_objfile_handler(self, event): 23 self._type = None 23 self._type = None 24 gdb.events.new_objfile.disconnect(self 24 gdb.events.new_objfile.disconnect(self._new_objfile_handler) 25 25 26 def get_type(self): 26 def get_type(self): 27 if self._type is None: 27 if self._type is None: 28 self._type = gdb.lookup_type(self. 28 self._type = gdb.lookup_type(self._name) 29 if self._type is None: 29 if self._type is None: 30 raise gdb.GdbError( 30 raise gdb.GdbError( 31 "cannot resolve type '{0}' 31 "cannot resolve type '{0}'".format(self._name)) 32 if hasattr(gdb, 'events') and hasa 32 if hasattr(gdb, 'events') and hasattr(gdb.events, 'new_objfile'): 33 gdb.events.new_objfile.connect 33 gdb.events.new_objfile.connect(self._new_objfile_handler) 34 return self._type 34 return self._type 35 35 36 36 37 long_type = CachedType("long") 37 long_type = CachedType("long") 38 ulong_type = CachedType("unsigned long") 38 ulong_type = CachedType("unsigned long") 39 uint_type = CachedType("unsigned int") 39 uint_type = CachedType("unsigned int") 40 atomic_long_type = CachedType("atomic_long_t") 40 atomic_long_type = CachedType("atomic_long_t") 41 size_t_type = CachedType("size_t") 41 size_t_type = CachedType("size_t") 42 struct_page_type = CachedType("struct page") 42 struct_page_type = CachedType("struct page") 43 43 44 def get_uint_type(): 44 def get_uint_type(): 45 global uint_type 45 global uint_type 46 return uint_type.get_type() 46 return uint_type.get_type() 47 47 48 def get_page_type(): 48 def get_page_type(): 49 global struct_page_type 49 global struct_page_type 50 return struct_page_type.get_type() 50 return struct_page_type.get_type() 51 51 52 def get_long_type(): 52 def get_long_type(): 53 global long_type 53 global long_type 54 return long_type.get_type() 54 return long_type.get_type() 55 55 56 def get_ulong_type(): 56 def get_ulong_type(): 57 global ulong_type 57 global ulong_type 58 return ulong_type.get_type() 58 return ulong_type.get_type() 59 59 60 def get_size_t_type(): 60 def get_size_t_type(): 61 global size_t_type 61 global size_t_type 62 return size_t_type.get_type() 62 return size_t_type.get_type() 63 63 64 def offset_of(typeobj, field): 64 def offset_of(typeobj, field): 65 element = gdb.Value(0).cast(typeobj) 65 element = gdb.Value(0).cast(typeobj) 66 return int(str(element[field].address).spl 66 return int(str(element[field].address).split()[0], 16) 67 67 68 68 69 def container_of(ptr, typeobj, member): 69 def container_of(ptr, typeobj, member): 70 return (ptr.cast(get_long_type()) - 70 return (ptr.cast(get_long_type()) - 71 offset_of(typeobj, member)).cast(t 71 offset_of(typeobj, member)).cast(typeobj) 72 72 73 73 74 class ContainerOf(gdb.Function): 74 class ContainerOf(gdb.Function): 75 """Return pointer to containing data struc 75 """Return pointer to containing data structure. 76 76 77 $container_of(PTR, "TYPE", "ELEMENT"): Given P 77 $container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the 78 data structure of the type TYPE in which PTR i 78 data structure of the type TYPE in which PTR is the address of ELEMENT. 79 Note that TYPE and ELEMENT have to be quoted a 79 Note that TYPE and ELEMENT have to be quoted as strings.""" 80 80 81 def __init__(self): 81 def __init__(self): 82 super(ContainerOf, self).__init__("con 82 super(ContainerOf, self).__init__("container_of") 83 83 84 def invoke(self, ptr, typename, elementnam 84 def invoke(self, ptr, typename, elementname): 85 return container_of(ptr, gdb.lookup_ty 85 return container_of(ptr, gdb.lookup_type(typename.string()).pointer(), 86 elementname.string 86 elementname.string()) 87 87 88 88 89 ContainerOf() 89 ContainerOf() 90 90 91 91 92 BIG_ENDIAN = 0 92 BIG_ENDIAN = 0 93 LITTLE_ENDIAN = 1 93 LITTLE_ENDIAN = 1 94 target_endianness = None 94 target_endianness = None 95 95 96 96 97 def get_target_endianness(): 97 def get_target_endianness(): 98 global target_endianness 98 global target_endianness 99 if target_endianness is None: 99 if target_endianness is None: 100 endian = gdb.execute("show endian", to 100 endian = gdb.execute("show endian", to_string=True) 101 if "little endian" in endian: 101 if "little endian" in endian: 102 target_endianness = LITTLE_ENDIAN 102 target_endianness = LITTLE_ENDIAN 103 elif "big endian" in endian: 103 elif "big endian" in endian: 104 target_endianness = BIG_ENDIAN 104 target_endianness = BIG_ENDIAN 105 else: 105 else: 106 raise gdb.GdbError("unknown endian 106 raise gdb.GdbError("unknown endianness '{0}'".format(str(endian))) 107 return target_endianness 107 return target_endianness 108 108 109 109 110 def read_memoryview(inf, start, length): 110 def read_memoryview(inf, start, length): 111 m = inf.read_memory(start, length) 111 m = inf.read_memory(start, length) 112 if type(m) is memoryview: 112 if type(m) is memoryview: 113 return m 113 return m 114 return memoryview(m) 114 return memoryview(m) 115 115 116 116 117 def read_u16(buffer, offset): 117 def read_u16(buffer, offset): 118 buffer_val = buffer[offset:offset + 2] 118 buffer_val = buffer[offset:offset + 2] 119 value = [0, 0] 119 value = [0, 0] 120 120 121 if type(buffer_val[0]) is str: 121 if type(buffer_val[0]) is str: 122 value[0] = ord(buffer_val[0]) 122 value[0] = ord(buffer_val[0]) 123 value[1] = ord(buffer_val[1]) 123 value[1] = ord(buffer_val[1]) 124 else: 124 else: 125 value[0] = buffer_val[0] 125 value[0] = buffer_val[0] 126 value[1] = buffer_val[1] 126 value[1] = buffer_val[1] 127 127 128 if get_target_endianness() == LITTLE_ENDIA 128 if get_target_endianness() == LITTLE_ENDIAN: 129 return value[0] + (value[1] << 8) 129 return value[0] + (value[1] << 8) 130 else: 130 else: 131 return value[1] + (value[0] << 8) 131 return value[1] + (value[0] << 8) 132 132 133 133 134 def read_u32(buffer, offset): 134 def read_u32(buffer, offset): 135 if get_target_endianness() == LITTLE_ENDIA 135 if get_target_endianness() == LITTLE_ENDIAN: 136 return read_u16(buffer, offset) + (rea 136 return read_u16(buffer, offset) + (read_u16(buffer, offset + 2) << 16) 137 else: 137 else: 138 return read_u16(buffer, offset + 2) + 138 return read_u16(buffer, offset + 2) + (read_u16(buffer, offset) << 16) 139 139 140 140 141 def read_u64(buffer, offset): 141 def read_u64(buffer, offset): 142 if get_target_endianness() == LITTLE_ENDIA 142 if get_target_endianness() == LITTLE_ENDIAN: 143 return read_u32(buffer, offset) + (rea 143 return read_u32(buffer, offset) + (read_u32(buffer, offset + 4) << 32) 144 else: 144 else: 145 return read_u32(buffer, offset + 4) + 145 return read_u32(buffer, offset + 4) + (read_u32(buffer, offset) << 32) 146 146 147 147 148 def read_ulong(buffer, offset): 148 def read_ulong(buffer, offset): 149 if get_long_type().sizeof == 8: 149 if get_long_type().sizeof == 8: 150 return read_u64(buffer, offset) 150 return read_u64(buffer, offset) 151 else: 151 else: 152 return read_u32(buffer, offset) 152 return read_u32(buffer, offset) 153 153 154 atomic_long_counter_offset = atomic_long_type. 154 atomic_long_counter_offset = atomic_long_type.get_type()['counter'].bitpos 155 atomic_long_counter_sizeof = atomic_long_type. 155 atomic_long_counter_sizeof = atomic_long_type.get_type()['counter'].type.sizeof 156 156 157 def read_atomic_long(buffer, offset): 157 def read_atomic_long(buffer, offset): 158 global atomic_long_counter_offset 158 global atomic_long_counter_offset 159 global atomic_long_counter_sizeof 159 global atomic_long_counter_sizeof 160 160 161 if atomic_long_counter_sizeof == 8: 161 if atomic_long_counter_sizeof == 8: 162 return read_u64(buffer, offset + atomi 162 return read_u64(buffer, offset + atomic_long_counter_offset) 163 else: 163 else: 164 return read_u32(buffer, offset + atomi 164 return read_u32(buffer, offset + atomic_long_counter_offset) 165 165 166 target_arch = None 166 target_arch = None 167 167 168 168 169 def is_target_arch(arch): 169 def is_target_arch(arch): 170 if hasattr(gdb.Frame, 'architecture'): 170 if hasattr(gdb.Frame, 'architecture'): 171 return arch in gdb.newest_frame().arch 171 return arch in gdb.newest_frame().architecture().name() 172 else: 172 else: 173 global target_arch 173 global target_arch 174 if target_arch is None: 174 if target_arch is None: 175 target_arch = gdb.execute("show ar 175 target_arch = gdb.execute("show architecture", to_string=True) 176 return arch in target_arch 176 return arch in target_arch 177 177 178 178 179 GDBSERVER_QEMU = 0 179 GDBSERVER_QEMU = 0 180 GDBSERVER_KGDB = 1 180 GDBSERVER_KGDB = 1 181 gdbserver_type = None 181 gdbserver_type = None 182 182 183 183 184 def get_gdbserver_type(): 184 def get_gdbserver_type(): 185 def exit_handler(event): 185 def exit_handler(event): 186 global gdbserver_type 186 global gdbserver_type 187 gdbserver_type = None 187 gdbserver_type = None 188 gdb.events.exited.disconnect(exit_hand 188 gdb.events.exited.disconnect(exit_handler) 189 189 190 def probe_qemu(): 190 def probe_qemu(): 191 try: 191 try: 192 return gdb.execute("monitor info v 192 return gdb.execute("monitor info version", to_string=True) != "" 193 except gdb.error: 193 except gdb.error: 194 return False 194 return False 195 195 196 def probe_kgdb(): 196 def probe_kgdb(): 197 try: 197 try: 198 thread_info = gdb.execute("info th 198 thread_info = gdb.execute("info thread 2", to_string=True) 199 return "shadowCPU" in thread_info !! 199 return "shadowCPU0" in thread_info 200 except gdb.error: 200 except gdb.error: 201 return False 201 return False 202 202 203 global gdbserver_type 203 global gdbserver_type 204 if gdbserver_type is None: 204 if gdbserver_type is None: 205 if probe_qemu(): 205 if probe_qemu(): 206 gdbserver_type = GDBSERVER_QEMU 206 gdbserver_type = GDBSERVER_QEMU 207 elif probe_kgdb(): 207 elif probe_kgdb(): 208 gdbserver_type = GDBSERVER_KGDB 208 gdbserver_type = GDBSERVER_KGDB 209 if gdbserver_type is not None and hasa 209 if gdbserver_type is not None and hasattr(gdb, 'events'): 210 gdb.events.exited.connect(exit_han 210 gdb.events.exited.connect(exit_handler) 211 return gdbserver_type 211 return gdbserver_type 212 212 213 213 214 def gdb_eval_or_none(expresssion): 214 def gdb_eval_or_none(expresssion): 215 try: 215 try: 216 return gdb.parse_and_eval(expresssion) 216 return gdb.parse_and_eval(expresssion) 217 except gdb.error: 217 except gdb.error: 218 return None 218 return None
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.