Blame view

kernel/linux-rt-4.4.41/scripts/gdb/linux/utils.py 4.17 KB
5113f6f70   김현기   kernel add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  #
  # gdb helper commands and functions for Linux kernel debugging
  #
  #  common utilities
  #
  # Copyright (c) Siemens AG, 2011-2013
  #
  # Authors:
  #  Jan Kiszka <jan.kiszka@siemens.com>
  #
  # This work is licensed under the terms of the GNU GPL version 2.
  #
  
  import gdb
  
  
  class CachedType:
      def __init__(self, name):
          self._type = None
          self._name = name
  
      def _new_objfile_handler(self, event):
          self._type = None
          gdb.events.new_objfile.disconnect(self._new_objfile_handler)
  
      def get_type(self):
          if self._type is None:
              self._type = gdb.lookup_type(self._name)
              if self._type is None:
                  raise gdb.GdbError(
                      "cannot resolve type '{0}'".format(self._name))
              if hasattr(gdb, 'events') and hasattr(gdb.events, 'new_objfile'):
                  gdb.events.new_objfile.connect(self._new_objfile_handler)
          return self._type
  
  
  long_type = CachedType("long")
  
  
  def get_long_type():
      global long_type
      return long_type.get_type()
  
  
  def offset_of(typeobj, field):
      element = gdb.Value(0).cast(typeobj)
      return int(str(element[field].address).split()[0], 16)
  
  
  def container_of(ptr, typeobj, member):
      return (ptr.cast(get_long_type()) -
              offset_of(typeobj, member)).cast(typeobj)
  
  
  class ContainerOf(gdb.Function):
      """Return pointer to containing data structure.
  
  $container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the
  data structure of the type TYPE in which PTR is the address of ELEMENT.
  Note that TYPE and ELEMENT have to be quoted as strings."""
  
      def __init__(self):
          super(ContainerOf, self).__init__("container_of")
  
      def invoke(self, ptr, typename, elementname):
          return container_of(ptr, gdb.lookup_type(typename.string()).pointer(),
                              elementname.string())
  
  ContainerOf()
  
  
  BIG_ENDIAN = 0
  LITTLE_ENDIAN = 1
  target_endianness = None
  
  
  def get_target_endianness():
      global target_endianness
      if target_endianness is None:
          endian = gdb.execute("show endian", to_string=True)
          if "little endian" in endian:
              target_endianness = LITTLE_ENDIAN
          elif "big endian" in endian:
              target_endianness = BIG_ENDIAN
          else:
              raise gdb.GdbError("unknown endianness '{0}'".format(str(endian)))
      return target_endianness
  
  
  def read_u16(buffer):
      if get_target_endianness() == LITTLE_ENDIAN:
          return ord(buffer[0]) + (ord(buffer[1]) << 8)
      else:
          return ord(buffer[1]) + (ord(buffer[0]) << 8)
  
  
  def read_u32(buffer):
      if get_target_endianness() == LITTLE_ENDIAN:
          return read_u16(buffer[0:2]) + (read_u16(buffer[2:4]) << 16)
      else:
          return read_u16(buffer[2:4]) + (read_u16(buffer[0:2]) << 16)
  
  
  def read_u64(buffer):
      if get_target_endianness() == LITTLE_ENDIAN:
          return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32)
      else:
          return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32)
  
  
  target_arch = None
  
  
  def is_target_arch(arch):
      if hasattr(gdb.Frame, 'architecture'):
          return arch in gdb.newest_frame().architecture().name()
      else:
          global target_arch
          if target_arch is None:
              target_arch = gdb.execute("show architecture", to_string=True)
          return arch in target_arch
  
  
  GDBSERVER_QEMU = 0
  GDBSERVER_KGDB = 1
  gdbserver_type = None
  
  
  def get_gdbserver_type():
      def exit_handler(event):
          global gdbserver_type
          gdbserver_type = None
          gdb.events.exited.disconnect(exit_handler)
  
      def probe_qemu():
          try:
              return gdb.execute("monitor info version", to_string=True) != ""
          except:
              return False
  
      def probe_kgdb():
          try:
              thread_info = gdb.execute("info thread 2", to_string=True)
              return "shadowCPU0" in thread_info
          except:
              return False
  
      global gdbserver_type
      if gdbserver_type is None:
          if probe_qemu():
              gdbserver_type = GDBSERVER_QEMU
          elif probe_kgdb():
              gdbserver_type = GDBSERVER_KGDB
          if gdbserver_type is not None and hasattr(gdb, 'events'):
              gdb.events.exited.connect(exit_handler)
      return gdbserver_type