cpp-d1064d
[cross.git] / i686-linux-gnu-4.7 / usr / share / gdb / auto-load / lib32 / libpthread-2.28.so-gdb.py
1 # Pretty printers for the NPTL lock types.
2 #
3 # Copyright (C) 2016-2018 Free Software Foundation, Inc.
4 # This file is part of the GNU C Library.
5 #
6 # The GNU C Library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
10 #
11 # The GNU C Library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # Lesser General Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with the GNU C Library; if not, see
18 # <http://www.gnu.org/licenses/>.
19
20 """This file contains the gdb pretty printers for the following types:
21
22     * pthread_mutex_t
23     * pthread_mutexattr_t
24     * pthread_cond_t
25     * pthread_condattr_t
26     * pthread_rwlock_t
27     * pthread_rwlockattr_t
28
29 You can check which printers are registered and enabled by issuing the
30 'info pretty-printer' gdb command.  Printers should trigger automatically when
31 trying to print a variable of one of the types mentioned above.
32 """
33
34 from __future__ import print_function
35
36 import gdb
37 import gdb.printing
38 # GENERATED FILE\n
39 # Constant definitions for pretty printers.
40 # See gen-py-const.awk for details.\n
41 PTHREAD_MUTEX_KIND_MASK = 3
42 PTHREAD_MUTEX_NORMAL = 0
43 PTHREAD_MUTEX_RECURSIVE = 1
44 PTHREAD_MUTEX_ERRORCHECK = 2
45 PTHREAD_MUTEX_ADAPTIVE_NP = 3
46 PTHREAD_MUTEX_DESTROYED = -1
47 PTHREAD_MUTEX_UNLOCKED = 0
48 PTHREAD_MUTEX_LOCKED_NO_WAITERS = 1
49 PTHREAD_MUTEX_INCONSISTENT = 2147483647
50 PTHREAD_MUTEX_NOTRECOVERABLE = 2147483646
51 FUTEX_OWNER_DIED = 1073741824
52 FUTEX_WAITERS = -2147483648
53 FUTEX_TID_MASK = 1073741823
54 PTHREAD_MUTEX_ROBUST_NORMAL_NP = 16
55 PTHREAD_MUTEX_PRIO_INHERIT_NP = 32
56 PTHREAD_MUTEX_PRIO_PROTECT_NP = 64
57 PTHREAD_MUTEX_PSHARED_BIT = 128
58 PTHREAD_MUTEX_PRIO_CEILING_SHIFT = 19
59 PTHREAD_MUTEX_PRIO_CEILING_MASK = -524288
60 PTHREAD_MUTEXATTR_PROTOCOL_SHIFT = 28
61 PTHREAD_MUTEXATTR_PROTOCOL_MASK = 805306368
62 PTHREAD_MUTEXATTR_PRIO_CEILING_MASK = 16773120
63 PTHREAD_MUTEXATTR_FLAG_ROBUST = 1073741824
64 PTHREAD_MUTEXATTR_FLAG_PSHARED = -2147483648
65 PTHREAD_MUTEXATTR_FLAG_BITS = -251662336
66 PTHREAD_MUTEX_NO_ELISION_NP = 512
67 PTHREAD_PRIO_NONE = 0
68 PTHREAD_PRIO_INHERIT = 1
69 PTHREAD_PRIO_PROTECT = 2
70 PTHREAD_COND_SHARED_MASK = 1
71 PTHREAD_COND_CLOCK_MONOTONIC_MASK = 2
72 COND_CLOCK_BITS = 1
73 PTHREAD_COND_WREFS_SHIFT = 3
74 PTHREAD_RWLOCK_PREFER_READER_NP = 0
75 PTHREAD_RWLOCK_PREFER_WRITER_NP = 1
76 PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP = 2
77 PTHREAD_RWLOCK_WRPHASE = 1
78 PTHREAD_RWLOCK_WRLOCKED = 2
79 PTHREAD_RWLOCK_READER_SHIFT = 3
80 PTHREAD_PROCESS_PRIVATE = 0
81 PTHREAD_PROCESS_SHARED = 1
82
83
84 MUTEX_TYPES = {
85     PTHREAD_MUTEX_NORMAL: ('Type', 'Normal'),
86     PTHREAD_MUTEX_RECURSIVE: ('Type', 'Recursive'),
87     PTHREAD_MUTEX_ERRORCHECK: ('Type', 'Error check'),
88     PTHREAD_MUTEX_ADAPTIVE_NP: ('Type', 'Adaptive')
89 }
90
91 class MutexPrinter(object):
92     """Pretty printer for pthread_mutex_t."""
93
94     def __init__(self, mutex):
95         """Initialize the printer's internal data structures.
96
97         Args:
98             mutex: A gdb.value representing a pthread_mutex_t.
99         """
100
101         data = mutex['__data']
102         self.lock = data['__lock']
103         self.count = data['__count']
104         self.owner = data['__owner']
105         self.kind = data['__kind']
106         self.values = []
107         self.read_values()
108
109     def to_string(self):
110         """gdb API function.
111
112         This is called from gdb when we try to print a pthread_mutex_t.
113         """
114
115         return 'pthread_mutex_t'
116
117     def children(self):
118         """gdb API function.
119
120         This is called from gdb when we try to print a pthread_mutex_t.
121         """
122
123         return self.values
124
125     def read_values(self):
126         """Read the mutex's info and store it in self.values.
127
128         The data contained in self.values will be returned by the Iterator
129         created in self.children.
130         """
131
132         self.read_type()
133         self.read_status()
134         self.read_attributes()
135         self.read_misc_info()
136
137     def read_type(self):
138         """Read the mutex's type."""
139
140         mutex_type = self.kind & PTHREAD_MUTEX_KIND_MASK
141
142         # mutex_type must be casted to int because it's a gdb.Value
143         self.values.append(MUTEX_TYPES[int(mutex_type)])
144
145     def read_status(self):
146         """Read the mutex's status.
147
148         Architectures that support lock elision might not record the mutex owner
149         ID in the __owner field.  In that case, the owner will be reported as
150         "Unknown".
151         """
152
153         if self.kind == PTHREAD_MUTEX_DESTROYED:
154             self.values.append(('Status', 'Destroyed'))
155         elif self.kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP:
156             self.read_status_robust()
157         else:
158             self.read_status_no_robust()
159
160     def read_status_robust(self):
161         """Read the status of a robust mutex.
162
163         In glibc robust mutexes are implemented in a very different way than
164         non-robust ones.  This method reads their locking status,
165         whether it may have waiters, their registered owner (if any),
166         whether the owner is alive or not, and the status of the state
167         they're protecting.
168         """
169
170         if self.lock == PTHREAD_MUTEX_UNLOCKED:
171             self.values.append(('Status', 'Not acquired'))
172         else:
173             if self.lock & FUTEX_WAITERS:
174                 self.values.append(('Status',
175                                     'Acquired, possibly with waiters'))
176             else:
177                 self.values.append(('Status',
178                                     'Acquired, possibly with no waiters'))
179
180             if self.lock & FUTEX_OWNER_DIED:
181                 self.values.append(('Owner ID', '%d (dead)' % self.owner))
182             else:
183                 self.values.append(('Owner ID', self.lock & FUTEX_TID_MASK))
184
185         if self.owner == PTHREAD_MUTEX_INCONSISTENT:
186             self.values.append(('State protected by this mutex',
187                                 'Inconsistent'))
188         elif self.owner == PTHREAD_MUTEX_NOTRECOVERABLE:
189             self.values.append(('State protected by this mutex',
190                                 'Not recoverable'))
191
192     def read_status_no_robust(self):
193         """Read the status of a non-robust mutex.
194
195         Read info on whether the mutex is acquired, if it may have waiters
196         and its owner (if any).
197         """
198
199         lock_value = self.lock
200
201         if self.kind & PTHREAD_MUTEX_PRIO_PROTECT_NP:
202             lock_value &= ~(PTHREAD_MUTEX_PRIO_CEILING_MASK)
203
204         if lock_value == PTHREAD_MUTEX_UNLOCKED:
205             self.values.append(('Status', 'Not acquired'))
206         else:
207             if self.kind & PTHREAD_MUTEX_PRIO_INHERIT_NP:
208                 waiters = self.lock & FUTEX_WAITERS
209                 owner = self.lock & FUTEX_TID_MASK
210             else:
211                 # Mutex protocol is PP or none
212                 waiters = (self.lock != PTHREAD_MUTEX_LOCKED_NO_WAITERS)
213                 owner = self.owner
214
215             if waiters:
216                 self.values.append(('Status',
217                                     'Acquired, possibly with waiters'))
218             else:
219                 self.values.append(('Status',
220                                     'Acquired, possibly with no waiters'))
221
222             if self.owner != 0:
223                 self.values.append(('Owner ID', owner))
224             else:
225                 # Owner isn't recorded, probably because lock elision
226                 # is enabled.
227                 self.values.append(('Owner ID', 'Unknown'))
228
229     def read_attributes(self):
230         """Read the mutex's attributes."""
231
232         if self.kind != PTHREAD_MUTEX_DESTROYED:
233             if self.kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP:
234                 self.values.append(('Robust', 'Yes'))
235             else:
236                 self.values.append(('Robust', 'No'))
237
238             # In glibc, robust mutexes always have their pshared flag set to
239             # 'shared' regardless of what the pshared flag of their
240             # mutexattr was.  Therefore a robust mutex will act as shared
241             # even if it was initialized with a 'private' mutexattr.
242             if self.kind & PTHREAD_MUTEX_PSHARED_BIT:
243                 self.values.append(('Shared', 'Yes'))
244             else:
245                 self.values.append(('Shared', 'No'))
246
247             if self.kind & PTHREAD_MUTEX_PRIO_INHERIT_NP:
248                 self.values.append(('Protocol', 'Priority inherit'))
249             elif self.kind & PTHREAD_MUTEX_PRIO_PROTECT_NP:
250                 prio_ceiling = ((self.lock & PTHREAD_MUTEX_PRIO_CEILING_MASK)
251                                 >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT)
252
253                 self.values.append(('Protocol', 'Priority protect'))
254                 self.values.append(('Priority ceiling', prio_ceiling))
255             else:
256                 # PTHREAD_PRIO_NONE
257                 self.values.append(('Protocol', 'None'))
258
259     def read_misc_info(self):
260         """Read miscellaneous info on the mutex.
261
262         For now this reads the number of times a recursive mutex was acquired
263         by the same thread.
264         """
265
266         mutex_type = self.kind & PTHREAD_MUTEX_KIND_MASK
267
268         if mutex_type == PTHREAD_MUTEX_RECURSIVE and self.count > 1:
269             self.values.append(('Times acquired by the owner', self.count))
270
271 class MutexAttributesPrinter(object):
272     """Pretty printer for pthread_mutexattr_t.
273
274     In the NPTL this is a type that's always casted to struct pthread_mutexattr
275     which has a single 'mutexkind' field containing the actual attributes.
276     """
277
278     def __init__(self, mutexattr):
279         """Initialize the printer's internal data structures.
280
281         Args:
282             mutexattr: A gdb.value representing a pthread_mutexattr_t.
283         """
284
285         self.values = []
286
287         try:
288             mutexattr_struct = gdb.lookup_type('struct pthread_mutexattr')
289             self.mutexattr = mutexattr.cast(mutexattr_struct)['mutexkind']
290             self.read_values()
291         except gdb.error:
292             # libpthread doesn't have debug symbols, thus we can't find the
293             # real struct type.  Just print the union members.
294             self.values.append(('__size', mutexattr['__size']))
295             self.values.append(('__align', mutexattr['__align']))
296
297     def to_string(self):
298         """gdb API function.
299
300         This is called from gdb when we try to print a pthread_mutexattr_t.
301         """
302
303         return 'pthread_mutexattr_t'
304
305     def children(self):
306         """gdb API function.
307
308         This is called from gdb when we try to print a pthread_mutexattr_t.
309         """
310
311         return self.values
312
313     def read_values(self):
314         """Read the mutexattr's info and store it in self.values.
315
316         The data contained in self.values will be returned by the Iterator
317         created in self.children.
318         """
319
320         mutexattr_type = (self.mutexattr
321                           & ~PTHREAD_MUTEXATTR_FLAG_BITS
322                           & ~PTHREAD_MUTEX_NO_ELISION_NP)
323
324         # mutexattr_type must be casted to int because it's a gdb.Value
325         self.values.append(MUTEX_TYPES[int(mutexattr_type)])
326
327         if self.mutexattr & PTHREAD_MUTEXATTR_FLAG_ROBUST:
328             self.values.append(('Robust', 'Yes'))
329         else:
330             self.values.append(('Robust', 'No'))
331
332         if self.mutexattr & PTHREAD_MUTEXATTR_FLAG_PSHARED:
333             self.values.append(('Shared', 'Yes'))
334         else:
335             self.values.append(('Shared', 'No'))
336
337         protocol = ((self.mutexattr & PTHREAD_MUTEXATTR_PROTOCOL_MASK) >>
338                     PTHREAD_MUTEXATTR_PROTOCOL_SHIFT)
339
340         if protocol == PTHREAD_PRIO_NONE:
341             self.values.append(('Protocol', 'None'))
342         elif protocol == PTHREAD_PRIO_INHERIT:
343             self.values.append(('Protocol', 'Priority inherit'))
344         elif protocol == PTHREAD_PRIO_PROTECT:
345             self.values.append(('Protocol', 'Priority protect'))
346
347 class ConditionVariablePrinter(object):
348     """Pretty printer for pthread_cond_t."""
349
350     def __init__(self, cond):
351         """Initialize the printer's internal data structures.
352
353         Args:
354             cond: A gdb.value representing a pthread_cond_t.
355         """
356
357         data = cond['__data']
358         self.wrefs = data['__wrefs']
359         self.values = []
360
361         self.read_values()
362
363     def to_string(self):
364         """gdb API function.
365
366         This is called from gdb when we try to print a pthread_cond_t.
367         """
368
369         return 'pthread_cond_t'
370
371     def children(self):
372         """gdb API function.
373
374         This is called from gdb when we try to print a pthread_cond_t.
375         """
376
377         return self.values
378
379     def read_values(self):
380         """Read the condvar's info and store it in self.values.
381
382         The data contained in self.values will be returned by the Iterator
383         created in self.children.
384         """
385
386         self.read_status()
387         self.read_attributes()
388
389     def read_status(self):
390         """Read the status of the condvar.
391
392         This method reads whether the condvar is destroyed and how many threads
393         are waiting for it.
394         """
395
396         self.values.append(('Threads known to still execute a wait function',
397                             self.wrefs >> PTHREAD_COND_WREFS_SHIFT))
398
399     def read_attributes(self):
400         """Read the condvar's attributes."""
401
402         if (self.wrefs & PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0:
403             self.values.append(('Clock ID', 'CLOCK_MONOTONIC'))
404         else:
405             self.values.append(('Clock ID', 'CLOCK_REALTIME'))
406
407         if (self.wrefs & PTHREAD_COND_SHARED_MASK) != 0:
408             self.values.append(('Shared', 'Yes'))
409         else:
410             self.values.append(('Shared', 'No'))
411
412 class ConditionVariableAttributesPrinter(object):
413     """Pretty printer for pthread_condattr_t.
414
415     In the NPTL this is a type that's always casted to struct pthread_condattr,
416     which has a single 'value' field containing the actual attributes.
417     """
418
419     def __init__(self, condattr):
420         """Initialize the printer's internal data structures.
421
422         Args:
423             condattr: A gdb.value representing a pthread_condattr_t.
424         """
425
426         self.values = []
427
428         try:
429             condattr_struct = gdb.lookup_type('struct pthread_condattr')
430             self.condattr = condattr.cast(condattr_struct)['value']
431             self.read_values()
432         except gdb.error:
433             # libpthread doesn't have debug symbols, thus we can't find the
434             # real struct type.  Just print the union members.
435             self.values.append(('__size', condattr['__size']))
436             self.values.append(('__align', condattr['__align']))
437
438     def to_string(self):
439         """gdb API function.
440
441         This is called from gdb when we try to print a pthread_condattr_t.
442         """
443
444         return 'pthread_condattr_t'
445
446     def children(self):
447         """gdb API function.
448
449         This is called from gdb when we try to print a pthread_condattr_t.
450         """
451
452         return self.values
453
454     def read_values(self):
455         """Read the condattr's info and store it in self.values.
456
457         The data contained in self.values will be returned by the Iterator
458         created in self.children.
459         """
460
461         clock_id = (self.condattr >> 1) & ((1 << COND_CLOCK_BITS) - 1)
462
463         if clock_id != 0:
464             self.values.append(('Clock ID', 'CLOCK_MONOTONIC'))
465         else:
466             self.values.append(('Clock ID', 'CLOCK_REALTIME'))
467
468         if self.condattr & 1:
469             self.values.append(('Shared', 'Yes'))
470         else:
471             self.values.append(('Shared', 'No'))
472
473 class RWLockPrinter(object):
474     """Pretty printer for pthread_rwlock_t."""
475
476     def __init__(self, rwlock):
477         """Initialize the printer's internal data structures.
478
479         Args:
480             rwlock: A gdb.value representing a pthread_rwlock_t.
481         """
482
483         data = rwlock['__data']
484         self.readers = data['__readers']
485         self.cur_writer = data['__cur_writer']
486         self.shared = data['__shared']
487         self.flags = data['__flags']
488         self.values = []
489         self.read_values()
490
491     def to_string(self):
492         """gdb API function.
493
494         This is called from gdb when we try to print a pthread_rwlock_t.
495         """
496
497         return 'pthread_rwlock_t'
498
499     def children(self):
500         """gdb API function.
501
502         This is called from gdb when we try to print a pthread_rwlock_t.
503         """
504
505         return self.values
506
507     def read_values(self):
508         """Read the rwlock's info and store it in self.values.
509
510         The data contained in self.values will be returned by the Iterator
511         created in self.children.
512         """
513
514         self.read_status()
515         self.read_attributes()
516
517     def read_status(self):
518         """Read the status of the rwlock."""
519
520         if self.readers & PTHREAD_RWLOCK_WRPHASE:
521             if self.readers & PTHREAD_RWLOCK_WRLOCKED:
522                 self.values.append(('Status', 'Acquired (Write)'))
523                 self.values.append(('Writer ID', self.cur_writer))
524             else:
525                 self.values.append(('Status', 'Not acquired'))
526         else:
527             r = self.readers >> PTHREAD_RWLOCK_READER_SHIFT
528             if r > 0:
529                 self.values.append(('Status', 'Acquired (Read)'))
530                 self.values.append(('Readers', r))
531             else:
532                 self.values.append(('Status', 'Not acquired'))
533
534     def read_attributes(self):
535         """Read the attributes of the rwlock."""
536
537         if self.shared:
538             self.values.append(('Shared', 'Yes'))
539         else:
540             self.values.append(('Shared', 'No'))
541
542         if self.flags == PTHREAD_RWLOCK_PREFER_READER_NP:
543             self.values.append(('Prefers', 'Readers'))
544         elif self.flags == PTHREAD_RWLOCK_PREFER_WRITER_NP:
545             self.values.append(('Prefers', 'Writers'))
546         else:
547             self.values.append(('Prefers', 'Writers no recursive readers'))
548
549 class RWLockAttributesPrinter(object):
550     """Pretty printer for pthread_rwlockattr_t.
551
552     In the NPTL this is a type that's always casted to
553     struct pthread_rwlockattr, which has two fields ('lockkind' and 'pshared')
554     containing the actual attributes.
555     """
556
557     def __init__(self, rwlockattr):
558         """Initialize the printer's internal data structures.
559
560         Args:
561             rwlockattr: A gdb.value representing a pthread_rwlockattr_t.
562         """
563
564         self.values = []
565
566         try:
567             rwlockattr_struct = gdb.lookup_type('struct pthread_rwlockattr')
568             self.rwlockattr = rwlockattr.cast(rwlockattr_struct)
569             self.read_values()
570         except gdb.error:
571             # libpthread doesn't have debug symbols, thus we can't find the
572             # real struct type.  Just print the union members.
573             self.values.append(('__size', rwlockattr['__size']))
574             self.values.append(('__align', rwlockattr['__align']))
575
576     def to_string(self):
577         """gdb API function.
578
579         This is called from gdb when we try to print a pthread_rwlockattr_t.
580         """
581
582         return 'pthread_rwlockattr_t'
583
584     def children(self):
585         """gdb API function.
586
587         This is called from gdb when we try to print a pthread_rwlockattr_t.
588         """
589
590         return self.values
591
592     def read_values(self):
593         """Read the rwlockattr's info and store it in self.values.
594
595         The data contained in self.values will be returned by the Iterator
596         created in self.children.
597         """
598
599         rwlock_type = self.rwlockattr['lockkind']
600         shared = self.rwlockattr['pshared']
601
602         if shared == PTHREAD_PROCESS_SHARED:
603             self.values.append(('Shared', 'Yes'))
604         else:
605             # PTHREAD_PROCESS_PRIVATE
606             self.values.append(('Shared', 'No'))
607
608         if rwlock_type == PTHREAD_RWLOCK_PREFER_READER_NP:
609             self.values.append(('Prefers', 'Readers'))
610         elif rwlock_type == PTHREAD_RWLOCK_PREFER_WRITER_NP:
611             self.values.append(('Prefers', 'Writers'))
612         else:
613             self.values.append(('Prefers', 'Writers no recursive readers'))
614
615 def register(objfile):
616     """Register the pretty printers within the given objfile."""
617
618     printer = gdb.printing.RegexpCollectionPrettyPrinter('glibc-pthread-locks')
619
620     printer.add_printer('pthread_mutex_t', r'^pthread_mutex_t$',
621                         MutexPrinter)
622     printer.add_printer('pthread_mutexattr_t', r'^pthread_mutexattr_t$',
623                         MutexAttributesPrinter)
624     printer.add_printer('pthread_cond_t', r'^pthread_cond_t$',
625                         ConditionVariablePrinter)
626     printer.add_printer('pthread_condattr_t', r'^pthread_condattr_t$',
627                         ConditionVariableAttributesPrinter)
628     printer.add_printer('pthread_rwlock_t', r'^pthread_rwlock_t$',
629                         RWLockPrinter)
630     printer.add_printer('pthread_rwlockattr_t', r'^pthread_rwlockattr_t$',
631                         RWLockAttributesPrinter)
632
633     if objfile == None:
634         objfile = gdb
635
636     gdb.printing.register_pretty_printer(objfile, printer)
637
638 register(gdb.current_objfile())