diff options
Diffstat (limited to 'nptl/nptl-printers.py')
-rw-r--r-- | nptl/nptl-printers.py | 594 |
1 files changed, 0 insertions, 594 deletions
diff --git a/nptl/nptl-printers.py b/nptl/nptl-printers.py deleted file mode 100644 index 572a25c32e..0000000000 --- a/nptl/nptl-printers.py +++ /dev/null @@ -1,594 +0,0 @@ -# Pretty printers for the NPTL lock types. -# -# Copyright (C) 2016-2017 Free Software Foundation, Inc. -# This file is part of the GNU C Library. -# -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# The GNU C Library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with the GNU C Library; if not, see -# <http://www.gnu.org/licenses/>. - -"""This file contains the gdb pretty printers for the following types: - - * pthread_mutex_t - * pthread_mutexattr_t - * pthread_cond_t - * pthread_condattr_t - * pthread_rwlock_t - * pthread_rwlockattr_t - -You can check which printers are registered and enabled by issuing the -'info pretty-printer' gdb command. Printers should trigger automatically when -trying to print a variable of one of the types mentioned above. -""" - -from __future__ import print_function - -import gdb -import gdb.printing -from nptl_lock_constants import * - -MUTEX_TYPES = { - PTHREAD_MUTEX_NORMAL: ('Type', 'Normal'), - PTHREAD_MUTEX_RECURSIVE: ('Type', 'Recursive'), - PTHREAD_MUTEX_ERRORCHECK: ('Type', 'Error check'), - PTHREAD_MUTEX_ADAPTIVE_NP: ('Type', 'Adaptive') -} - -class MutexPrinter(object): - """Pretty printer for pthread_mutex_t.""" - - def __init__(self, mutex): - """Initialize the printer's internal data structures. - - Args: - mutex: A gdb.value representing a pthread_mutex_t. - """ - - data = mutex['__data'] - self.lock = data['__lock'] - self.count = data['__count'] - self.owner = data['__owner'] - self.kind = data['__kind'] - self.values = [] - self.read_values() - - def to_string(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_mutex_t. - """ - - return 'pthread_mutex_t' - - def children(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_mutex_t. - """ - - return self.values - - def read_values(self): - """Read the mutex's info and store it in self.values. - - The data contained in self.values will be returned by the Iterator - created in self.children. - """ - - self.read_type() - self.read_status() - self.read_attributes() - self.read_misc_info() - - def read_type(self): - """Read the mutex's type.""" - - mutex_type = self.kind & PTHREAD_MUTEX_KIND_MASK - - # mutex_type must be casted to int because it's a gdb.Value - self.values.append(MUTEX_TYPES[int(mutex_type)]) - - def read_status(self): - """Read the mutex's status. - - Architectures that support lock elision might not record the mutex owner - ID in the __owner field. In that case, the owner will be reported as - "Unknown". - """ - - if self.kind == PTHREAD_MUTEX_DESTROYED: - self.values.append(('Status', 'Destroyed')) - elif self.kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP: - self.read_status_robust() - else: - self.read_status_no_robust() - - def read_status_robust(self): - """Read the status of a robust mutex. - - In glibc robust mutexes are implemented in a very different way than - non-robust ones. This method reads their locking status, - whether it may have waiters, their registered owner (if any), - whether the owner is alive or not, and the status of the state - they're protecting. - """ - - if self.lock == PTHREAD_MUTEX_UNLOCKED: - self.values.append(('Status', 'Not acquired')) - else: - if self.lock & FUTEX_WAITERS: - self.values.append(('Status', - 'Acquired, possibly with waiters')) - else: - self.values.append(('Status', - 'Acquired, possibly with no waiters')) - - if self.lock & FUTEX_OWNER_DIED: - self.values.append(('Owner ID', '%d (dead)' % self.owner)) - else: - self.values.append(('Owner ID', self.lock & FUTEX_TID_MASK)) - - if self.owner == PTHREAD_MUTEX_INCONSISTENT: - self.values.append(('State protected by this mutex', - 'Inconsistent')) - elif self.owner == PTHREAD_MUTEX_NOTRECOVERABLE: - self.values.append(('State protected by this mutex', - 'Not recoverable')) - - def read_status_no_robust(self): - """Read the status of a non-robust mutex. - - Read info on whether the mutex is acquired, if it may have waiters - and its owner (if any). - """ - - lock_value = self.lock - - if self.kind & PTHREAD_MUTEX_PRIO_PROTECT_NP: - lock_value &= ~(PTHREAD_MUTEX_PRIO_CEILING_MASK) - - if lock_value == PTHREAD_MUTEX_UNLOCKED: - self.values.append(('Status', 'Not acquired')) - else: - if self.kind & PTHREAD_MUTEX_PRIO_INHERIT_NP: - waiters = self.lock & FUTEX_WAITERS - owner = self.lock & FUTEX_TID_MASK - else: - # Mutex protocol is PP or none - waiters = (self.lock != PTHREAD_MUTEX_LOCKED_NO_WAITERS) - owner = self.owner - - if waiters: - self.values.append(('Status', - 'Acquired, possibly with waiters')) - else: - self.values.append(('Status', - 'Acquired, possibly with no waiters')) - - if self.owner != 0: - self.values.append(('Owner ID', owner)) - else: - # Owner isn't recorded, probably because lock elision - # is enabled. - self.values.append(('Owner ID', 'Unknown')) - - def read_attributes(self): - """Read the mutex's attributes.""" - - if self.kind != PTHREAD_MUTEX_DESTROYED: - if self.kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP: - self.values.append(('Robust', 'Yes')) - else: - self.values.append(('Robust', 'No')) - - # In glibc, robust mutexes always have their pshared flag set to - # 'shared' regardless of what the pshared flag of their - # mutexattr was. Therefore a robust mutex will act as shared - # even if it was initialized with a 'private' mutexattr. - if self.kind & PTHREAD_MUTEX_PSHARED_BIT: - self.values.append(('Shared', 'Yes')) - else: - self.values.append(('Shared', 'No')) - - if self.kind & PTHREAD_MUTEX_PRIO_INHERIT_NP: - self.values.append(('Protocol', 'Priority inherit')) - elif self.kind & PTHREAD_MUTEX_PRIO_PROTECT_NP: - prio_ceiling = ((self.lock & PTHREAD_MUTEX_PRIO_CEILING_MASK) - >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT) - - self.values.append(('Protocol', 'Priority protect')) - self.values.append(('Priority ceiling', prio_ceiling)) - else: - # PTHREAD_PRIO_NONE - self.values.append(('Protocol', 'None')) - - def read_misc_info(self): - """Read miscellaneous info on the mutex. - - For now this reads the number of times a recursive mutex was acquired - by the same thread. - """ - - mutex_type = self.kind & PTHREAD_MUTEX_KIND_MASK - - if mutex_type == PTHREAD_MUTEX_RECURSIVE and self.count > 1: - self.values.append(('Times acquired by the owner', self.count)) - -class MutexAttributesPrinter(object): - """Pretty printer for pthread_mutexattr_t. - - In the NPTL this is a type that's always casted to struct pthread_mutexattr - which has a single 'mutexkind' field containing the actual attributes. - """ - - def __init__(self, mutexattr): - """Initialize the printer's internal data structures. - - Args: - mutexattr: A gdb.value representing a pthread_mutexattr_t. - """ - - self.values = [] - - try: - mutexattr_struct = gdb.lookup_type('struct pthread_mutexattr') - self.mutexattr = mutexattr.cast(mutexattr_struct)['mutexkind'] - self.read_values() - except gdb.error: - # libpthread doesn't have debug symbols, thus we can't find the - # real struct type. Just print the union members. - self.values.append(('__size', mutexattr['__size'])) - self.values.append(('__align', mutexattr['__align'])) - - def to_string(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_mutexattr_t. - """ - - return 'pthread_mutexattr_t' - - def children(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_mutexattr_t. - """ - - return self.values - - def read_values(self): - """Read the mutexattr's info and store it in self.values. - - The data contained in self.values will be returned by the Iterator - created in self.children. - """ - - mutexattr_type = (self.mutexattr - & ~PTHREAD_MUTEXATTR_FLAG_BITS - & ~PTHREAD_MUTEX_NO_ELISION_NP) - - # mutexattr_type must be casted to int because it's a gdb.Value - self.values.append(MUTEX_TYPES[int(mutexattr_type)]) - - if self.mutexattr & PTHREAD_MUTEXATTR_FLAG_ROBUST: - self.values.append(('Robust', 'Yes')) - else: - self.values.append(('Robust', 'No')) - - if self.mutexattr & PTHREAD_MUTEXATTR_FLAG_PSHARED: - self.values.append(('Shared', 'Yes')) - else: - self.values.append(('Shared', 'No')) - - protocol = ((self.mutexattr & PTHREAD_MUTEXATTR_PROTOCOL_MASK) >> - PTHREAD_MUTEXATTR_PROTOCOL_SHIFT) - - if protocol == PTHREAD_PRIO_NONE: - self.values.append(('Protocol', 'None')) - elif protocol == PTHREAD_PRIO_INHERIT: - self.values.append(('Protocol', 'Priority inherit')) - elif protocol == PTHREAD_PRIO_PROTECT: - self.values.append(('Protocol', 'Priority protect')) - -class ConditionVariablePrinter(object): - """Pretty printer for pthread_cond_t.""" - - def __init__(self, cond): - """Initialize the printer's internal data structures. - - Args: - cond: A gdb.value representing a pthread_cond_t. - """ - - data = cond['__data'] - self.wrefs = data['__wrefs'] - self.values = [] - - self.read_values() - - def to_string(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_cond_t. - """ - - return 'pthread_cond_t' - - def children(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_cond_t. - """ - - return self.values - - def read_values(self): - """Read the condvar's info and store it in self.values. - - The data contained in self.values will be returned by the Iterator - created in self.children. - """ - - self.read_status() - self.read_attributes() - - def read_status(self): - """Read the status of the condvar. - - This method reads whether the condvar is destroyed and how many threads - are waiting for it. - """ - - self.values.append(('Threads known to still execute a wait function', - self.wrefs >> PTHREAD_COND_WREFS_SHIFT)) - - def read_attributes(self): - """Read the condvar's attributes.""" - - if (self.wrefs & PTHREAD_COND_CLOCK_MONOTONIC_MASK) != 0: - self.values.append(('Clock ID', 'CLOCK_MONOTONIC')) - else: - self.values.append(('Clock ID', 'CLOCK_REALTIME')) - - if (self.wrefs & PTHREAD_COND_SHARED_MASK) != 0: - self.values.append(('Shared', 'Yes')) - else: - self.values.append(('Shared', 'No')) - -class ConditionVariableAttributesPrinter(object): - """Pretty printer for pthread_condattr_t. - - In the NPTL this is a type that's always casted to struct pthread_condattr, - which has a single 'value' field containing the actual attributes. - """ - - def __init__(self, condattr): - """Initialize the printer's internal data structures. - - Args: - condattr: A gdb.value representing a pthread_condattr_t. - """ - - self.values = [] - - try: - condattr_struct = gdb.lookup_type('struct pthread_condattr') - self.condattr = condattr.cast(condattr_struct)['value'] - self.read_values() - except gdb.error: - # libpthread doesn't have debug symbols, thus we can't find the - # real struct type. Just print the union members. - self.values.append(('__size', condattr['__size'])) - self.values.append(('__align', condattr['__align'])) - - def to_string(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_condattr_t. - """ - - return 'pthread_condattr_t' - - def children(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_condattr_t. - """ - - return self.values - - def read_values(self): - """Read the condattr's info and store it in self.values. - - The data contained in self.values will be returned by the Iterator - created in self.children. - """ - - clock_id = (self.condattr >> 1) & ((1 << COND_CLOCK_BITS) - 1) - - if clock_id != 0: - self.values.append(('Clock ID', 'CLOCK_MONOTONIC')) - else: - self.values.append(('Clock ID', 'CLOCK_REALTIME')) - - if self.condattr & 1: - self.values.append(('Shared', 'Yes')) - else: - self.values.append(('Shared', 'No')) - -class RWLockPrinter(object): - """Pretty printer for pthread_rwlock_t.""" - - def __init__(self, rwlock): - """Initialize the printer's internal data structures. - - Args: - rwlock: A gdb.value representing a pthread_rwlock_t. - """ - - data = rwlock['__data'] - self.readers = data['__readers'] - self.cur_writer = data['__cur_writer'] - self.shared = data['__shared'] - self.flags = data['__flags'] - self.values = [] - self.read_values() - - def to_string(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_rwlock_t. - """ - - return 'pthread_rwlock_t' - - def children(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_rwlock_t. - """ - - return self.values - - def read_values(self): - """Read the rwlock's info and store it in self.values. - - The data contained in self.values will be returned by the Iterator - created in self.children. - """ - - self.read_status() - self.read_attributes() - - def read_status(self): - """Read the status of the rwlock.""" - - if self.readers & PTHREAD_RWLOCK_WRPHASE: - if self.readers & PTHREAD_RWLOCK_WRLOCKED: - self.values.append(('Status', 'Acquired (Write)')) - self.values.append(('Writer ID', self.cur_writer)) - else: - self.values.append(('Status', 'Not acquired')) - else: - r = self.readers >> PTHREAD_RWLOCK_READER_SHIFT - if r > 0: - self.values.append(('Status', 'Acquired (Read)')) - self.values.append(('Readers', r)) - else: - self.values.append(('Status', 'Not acquired')) - - def read_attributes(self): - """Read the attributes of the rwlock.""" - - if self.shared: - self.values.append(('Shared', 'Yes')) - else: - self.values.append(('Shared', 'No')) - - if self.flags == PTHREAD_RWLOCK_PREFER_READER_NP: - self.values.append(('Prefers', 'Readers')) - elif self.flags == PTHREAD_RWLOCK_PREFER_WRITER_NP: - self.values.append(('Prefers', 'Writers')) - else: - self.values.append(('Prefers', 'Writers no recursive readers')) - -class RWLockAttributesPrinter(object): - """Pretty printer for pthread_rwlockattr_t. - - In the NPTL this is a type that's always casted to - struct pthread_rwlockattr, which has two fields ('lockkind' and 'pshared') - containing the actual attributes. - """ - - def __init__(self, rwlockattr): - """Initialize the printer's internal data structures. - - Args: - rwlockattr: A gdb.value representing a pthread_rwlockattr_t. - """ - - self.values = [] - - try: - rwlockattr_struct = gdb.lookup_type('struct pthread_rwlockattr') - self.rwlockattr = rwlockattr.cast(rwlockattr_struct) - self.read_values() - except gdb.error: - # libpthread doesn't have debug symbols, thus we can't find the - # real struct type. Just print the union members. - self.values.append(('__size', rwlockattr['__size'])) - self.values.append(('__align', rwlockattr['__align'])) - - def to_string(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_rwlockattr_t. - """ - - return 'pthread_rwlockattr_t' - - def children(self): - """gdb API function. - - This is called from gdb when we try to print a pthread_rwlockattr_t. - """ - - return self.values - - def read_values(self): - """Read the rwlockattr's info and store it in self.values. - - The data contained in self.values will be returned by the Iterator - created in self.children. - """ - - rwlock_type = self.rwlockattr['lockkind'] - shared = self.rwlockattr['pshared'] - - if shared == PTHREAD_PROCESS_SHARED: - self.values.append(('Shared', 'Yes')) - else: - # PTHREAD_PROCESS_PRIVATE - self.values.append(('Shared', 'No')) - - if rwlock_type == PTHREAD_RWLOCK_PREFER_READER_NP: - self.values.append(('Prefers', 'Readers')) - elif rwlock_type == PTHREAD_RWLOCK_PREFER_WRITER_NP: - self.values.append(('Prefers', 'Writers')) - else: - self.values.append(('Prefers', 'Writers no recursive readers')) - -def register(objfile): - """Register the pretty printers within the given objfile.""" - - printer = gdb.printing.RegexpCollectionPrettyPrinter('glibc-pthread-locks') - - printer.add_printer('pthread_mutex_t', r'^pthread_mutex_t$', - MutexPrinter) - printer.add_printer('pthread_mutexattr_t', r'^pthread_mutexattr_t$', - MutexAttributesPrinter) - printer.add_printer('pthread_cond_t', r'^pthread_cond_t$', - ConditionVariablePrinter) - printer.add_printer('pthread_condattr_t', r'^pthread_condattr_t$', - ConditionVariableAttributesPrinter) - printer.add_printer('pthread_rwlock_t', r'^pthread_rwlock_t$', - RWLockPrinter) - printer.add_printer('pthread_rwlockattr_t', r'^pthread_rwlockattr_t$', - RWLockAttributesPrinter) - - if objfile == None: - objfile = gdb - - gdb.printing.register_pretty_printer(objfile, printer) - -register(gdb.current_objfile()) |