xref: /spdk/scripts/gdb_macros.py (revision ae7b5890ef728af40bd233a5011b924c482603bf)
1import gdb
2
3
4class SpdkTailqList(object):
5
6    def __init__(self, list_pointer, list_member, tailq_name_list):
7        self.list_pointer = list_pointer
8        self.tailq_name_list = tailq_name_list
9        self.list_member = list_member
10        self.list = gdb.parse_and_eval(self.list_pointer)
11
12    def __iter__(self):
13        curr = self.list['tqh_first']
14        while curr:
15            yield self.list_member(curr)
16            for tailq_name in self.tailq_name_list:
17                curr = curr[tailq_name]
18            curr = curr['tqe_next']
19
20
21class SpdkNormalTailqList(SpdkTailqList):
22
23    def __init__(self, list_pointer, list_member):
24        super(SpdkNormalTailqList, self).__init__(list_pointer, list_member,
25                                                  ['tailq'])
26
27
28class SpdkArr(object):
29
30    def __init__(self, arr_pointer, num_elements, element_type):
31        self.arr_pointer = arr_pointer
32        self.num_elements = num_elements
33        self.element_type = element_type
34
35    def __iter__(self):
36        for i in range(0, self.num_elements):
37            curr = (self.arr_pointer + i).dereference()
38            if (curr == 0x0):
39                continue
40            yield self.element_type(curr)
41
42
43class SpdkPrintCommand(gdb.Command):
44
45    def __init__(self, name, element_list):
46        self.element_list = element_list
47        gdb.Command.__init__(self, name,
48                             gdb.COMMAND_DATA,
49                             gdb.COMPLETE_SYMBOL,
50                             True)
51
52    def print_element_list(self, element_list):
53        first = True
54        for element in element_list:
55            if first:
56                first = False
57            else:
58                print("---------------")
59            print("\n" + str(element) + "\n")
60
61    def invoke(self, arg, from_tty):
62        self.print_element_list(self.element_list)
63
64
65class SpdkObject(object):
66
67    def __init__(self, gdb_obj):
68        self.obj = gdb_obj
69
70    def get_name(self):
71        return self.obj['name']
72
73    def __str__(self):
74        s = "SPDK object of type %s at %s" % (self.type_name, str(self.obj))
75        s += '\n((%s*) %s)' % (self.type_name, str(self.obj))
76        s += '\nname %s' % self.get_name()
77        return s
78
79
80class IoDevice(SpdkObject):
81
82    type_name = 'struct io_device'
83
84
85class IoDevices(SpdkTailqList):
86
87    def __init__(self):
88        super(IoDevices, self).__init__('g_io_devices', IoDevice, ['tailq'])
89
90
91class spdk_print_io_devices(SpdkPrintCommand):
92
93    def __init__(self):
94        io_devices = IoDevices()
95        name = 'spdk_print_io_devices'
96        super(spdk_print_io_devices, self).__init__(name, io_devices)
97
98
99class Bdev(SpdkObject):
100
101    type_name = 'struct spdk_bdev'
102
103
104class BdevMgrBdevs(SpdkTailqList):
105
106    def __init__(self):
107        tailq_name_list = ['internal', 'link']
108        super(BdevMgrBdevs, self).__init__('g_bdev_mgr->bdevs', Bdev, tailq_name_list)
109
110
111class spdk_print_bdevs(SpdkPrintCommand):
112    name = 'spdk_print_bdevs'
113
114    def __init__(self):
115        bdevs = BdevMgrBdevs()
116        super(spdk_print_bdevs, self).__init__(self.name, bdevs)
117
118
119class spdk_find_bdev(spdk_print_bdevs):
120
121    name = 'spdk_find_bdev'
122
123    def invoke(self, arg, from_tty):
124        print(arg)
125        bdev_query = [bdev for bdev in self.element_list
126                      if str(bdev.get_name()).find(arg) != -1]
127        if bdev_query == []:
128            print("Cannot find bdev with name %s" % arg)
129            return
130
131        self.print_element_list(bdev_query)
132
133
134class NvmfSubsystem(SpdkObject):
135
136    type_name = 'struct spdk_nvmf_subsystem'
137
138    def __init__(self, ptr):
139        self.ptr = ptr
140        gdb_obj = self.ptr.cast(gdb.lookup_type(self.type_name).pointer())
141        super(NvmfSubsystem, self).__init__(gdb_obj)
142
143    def get_name(self):
144        return self.obj['subnqn']
145
146    def get_id(self):
147        return int(self.obj['id'])
148
149    def get_ns_list(self):
150        max_nsid = int(self.obj['max_nsid'])
151        ns_list = []
152        for i in range(0, max_nsid):
153            nsptr = (self.obj['ns'] + i).dereference()
154            if nsptr == 0x0:
155                continue
156            ns = nsptr.cast(gdb.lookup_type('struct spdk_nvmf_ns').pointer())
157            ns_list.append(ns)
158        return ns_list
159
160    def __str__(self):
161        s = super(NvmfSubsystem, self).__str__()
162        s += '\nnqn %s' % self.get_name()
163        s += '\nID %d' % self.get_id()
164        for ns in self.get_ns_list():
165            s + '\t%s' % str(ns)
166        return s
167
168
169class SpdkNvmfTgtSubsystems(SpdkArr):
170
171    def get_num_subsystems(self):
172        try:  # version >= 18.11
173            return int(self.spdk_nvmf_tgt['max_subsystems'])
174        except RuntimeError:  # version < 18.11
175            return int(self.spdk_nvmf_tgt['opts']['max_subsystems'])
176
177    def __init__(self):
178        self.spdk_nvmf_tgt = gdb.parse_and_eval("g_spdk_nvmf_tgt")
179        subsystems = gdb.parse_and_eval("g_spdk_nvmf_tgt->subsystems")
180        super(SpdkNvmfTgtSubsystems, self).__init__(subsystems,
181                                                    self.get_num_subsystems(),
182                                                    NvmfSubsystem)
183
184
185class spdk_print_nvmf_subsystems(SpdkPrintCommand):
186
187    def __init__(self):
188        name = 'spdk_print_nvmf_subsystems'
189        nvmf_tgt_subsystems = SpdkNvmfTgtSubsystems()
190        super(spdk_print_nvmf_subsystems, self).__init__(name, nvmf_tgt_subsystems)
191
192
193class IoChannel(SpdkObject):
194
195    type_name = 'struct spdk_io_channel'
196
197    def get_ref(self):
198
199        return int(self.obj['ref'])
200
201    def get_device(self):
202        return self.obj['dev']
203
204    def get_device_name(self):
205        return self.obj['dev']['name']
206
207    def get_name(self):
208        return ""
209
210    def __str__(self):
211        s = super(IoChannel, self).__str__() + '\n'
212        s += 'ref %d\n' % self.get_ref()
213        s += 'device %s (%s)\n' % (self.get_device(), self.get_device_name())
214        return s
215
216
217# TODO - create TailqList type that gets a gdb object instead of a pointer
218class IoChannels(SpdkTailqList):
219
220    def __init__(self, list_obj):
221        self.tailq_name_list = ['tailq']
222        self.list_member = IoChannel
223        self.list = list_obj
224
225
226class SpdkThread(SpdkObject):
227
228    type_name = 'struct spdk_thread'
229
230    def __init__(self, gdb_obj):
231        super(SpdkThread, self).__init__(gdb_obj)
232        self.io_channels = IoChannels(self.obj['io_channels'])
233
234    def __str__(self):
235        s = super(SpdkThread, self).__str__() + '\n'
236        s += "IO Channels:\n"
237        for io_channel in self.get_io_channels():
238            channel_lines = str(io_channel).split('\n')
239            s += '\n'.join('\t%s' % line for line in channel_lines if line is not '')
240            s += '\n'
241            s += '\t---------------\n'
242            s += '\n'
243        return s
244
245    def get_io_channels(self):
246        return self.io_channels
247
248
249class SpdkThreads(SpdkNormalTailqList):
250
251    def __init__(self):
252        super(SpdkThreads, self).__init__('g_threads', SpdkThread)
253
254
255class spdk_print_threads(SpdkPrintCommand):
256
257    def __init__(self):
258        name = "spdk_print_threads"
259        threads = SpdkThreads()
260        super(spdk_print_threads, self).__init__(name, threads)
261
262
263class spdk_load_macros(gdb.Command):
264
265    def __init__(self):
266        gdb.Command.__init__(self, 'spdk_load_macros',
267                             gdb.COMMAND_DATA,
268                             gdb.COMPLETE_SYMBOL,
269                             True)
270        self.loaded = False
271
272    def invoke(self, arg, from_tty):
273        if arg == '--reload':
274            print('Reloading spdk information')
275            reload = True
276        else:
277            reload = False
278
279        if self.loaded and not reload:
280            return
281
282        spdk_print_threads()
283        spdk_print_bdevs()
284        spdk_print_io_devices()
285        spdk_print_nvmf_subsystems()
286        spdk_find_bdev()
287
288
289spdk_load_macros()
290