summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDhananjay Balan <mb.dhananjay@gmail.com>2013-06-17 22:40:17 +0530
committerChris Johns <chrisj@rtems.org>2014-08-25 09:52:40 +1000
commit56a70aec5536a568fe302a3c84b349fcf17db2fa (patch)
tree0f1043e21f214f7e3b3d1063f446073980859c15
parent911e71038cee3bcf3b9fa60a415dbda824bc3a80 (diff)
Intial commit.
Chris's intial work on the extenstions.
-rw-r--r--tools/gdb/python/__init__.py16
-rw-r--r--tools/gdb/python/chains.py43
-rw-r--r--tools/gdb/python/classic.py216
-rw-r--r--tools/gdb/python/objects.py357
-rw-r--r--tools/gdb/python/rtems.py110
-rw-r--r--tools/gdb/python/threads.py207
-rw-r--r--tools/gdb/python/watchdog.py56
7 files changed, 1005 insertions, 0 deletions
diff --git a/tools/gdb/python/__init__.py b/tools/gdb/python/__init__.py
new file mode 100644
index 0000000..0664d21
--- /dev/null
+++ b/tools/gdb/python/__init__.py
@@ -0,0 +1,16 @@
+
+if __name__ == "__main__":
+ import sys
+ import os.path
+ sys.path.append(os.path.dirname(__file__))
+ import chains
+ import rtems
+ import classic
+ import objects
+ import threads
+ reload(chains)
+ reload(rtems)
+ reload(classic)
+ reload(objects)
+ reload(threads)
+ print 'RTEMS GDB Support loaded'
diff --git a/tools/gdb/python/chains.py b/tools/gdb/python/chains.py
new file mode 100644
index 0000000..961ca2d
--- /dev/null
+++ b/tools/gdb/python/chains.py
@@ -0,0 +1,43 @@
+#
+# RTEMS Chains Support
+# Copyright 2010 Chris Johns (chrisj@rtems.org)
+#
+# $Id$
+#
+
+import gdb
+
+class node:
+ """Manage the Chain_Node."""
+
+ def __init__(self, node_val):
+ self.node_val = node_val
+
+ def null(self):
+ return self.node_val['next'] == 0
+
+ def next(self):
+ if not self.null():
+ self.node_val = self.node_val['next'].dereference()
+
+ def previous(self):
+ if not self.null():
+ self.node_val = self.node_val['previous'].dereference()
+
+ def cast(self, typename):
+ if not self.null():
+ nodetype = gdb.lookup_type(typename)
+ return self.node_val.cast(nodetype)
+ return None
+
+class control:
+ """Manage the Chain_Control."""
+
+ def __init__(self, ctrl):
+ self.ctrl = ctrl
+
+ def first(self):
+ return node(self.ctrl['first'].dereference())
+
+ def last(self):
+ return node(self.ctrl['first'])
diff --git a/tools/gdb/python/classic.py b/tools/gdb/python/classic.py
new file mode 100644
index 0000000..8748bbf
--- /dev/null
+++ b/tools/gdb/python/classic.py
@@ -0,0 +1,216 @@
+#
+# RTEMS Classic API Support
+# Copyright 2010 Chris Johns (chrisj@rtems.org)
+#
+# $Id$
+#
+
+import gdb
+import itertools
+import re
+
+import objects
+import threads
+
+class attribute:
+ """The Classic API attribute."""
+
+ groups = {
+ 'none' : [],
+ 'all' : ['scope',
+ 'priority',
+ 'fpu',
+ 'semaphore-type',
+ 'semaphore-pri',
+ 'semaphore-pri-ceiling',
+ 'barrier',
+ 'task'],
+ 'task' : ['scope',
+ 'priority',
+ 'fpu',
+ 'task'],
+ 'semaphore' : ['scope',
+ 'priority',
+ 'semaphore-type',
+ 'semaphore-pri',
+ 'semaphore-pri-ceiling'],
+ 'barrier' : ['scope',
+ 'priority',
+ 'barrier']
+ }
+
+ masks = {
+ 'scope' : 0x00000002,
+ 'priority' : 0x00000004,
+ 'fpu' : 0x00000001,
+ 'semaphore-type' : 0x00000030,
+ 'semaphore-pri' : 0x00000040,
+ 'semaphore-pri-ceiling' : 0x00000080,
+ 'barrier' : 0x00000010,
+ 'task' : 0x00008000
+ }
+
+ fields = {
+ 'scope' : [(0x00000000, 'local'),
+ (0x00000002, 'global')],
+ 'priority' : [(0x00000000, 'fifo'),
+ (0x00000004, 'pri')],
+ 'fpu' : [(0x00000000, 'no-fpu'),
+ (0x00000001, 'fpu')],
+ 'semaphore-type' : [(0x00000000, 'count-sema'),
+ (0x00000010, 'bin-sema'),
+ (0x00000020, 'simple-bin-sema')],
+ 'semaphore-pri' : [(0x00000000, 'no-inherit-pri'),
+ (0x00000040, 'inherit-pri')],
+ 'semaphore-pri-ceiling' : [(0x00000000, 'no-pri-ceiling'),
+ (0x00000080, 'pri-ceiling')],
+ 'barrier' : [(0x00000010, 'barrier-auto-release'),
+ (0x00000000, 'barrier-manual-release')],
+ 'task' : [(0x00000000, 'app-task'),
+ (0x00008000, 'sys-task')]
+ }
+
+ def __init__(self, attr, attrtype = 'none'):
+ if attrtype not in self.groups:
+ raise 'invalid attribute type'
+ self.attrtype = attrtype
+ self.attr = attr
+
+ def to_string(self):
+ s = '0x%08x,' % (self.attr)
+ if self.attrtype != 'none':
+ for m in self.groups[self.attrtype]:
+ v = self.attr & self.masks[m]
+ for f in self.fields[m]:
+ if f[0] == v:
+ s += f[1] + ','
+ break
+ return s[:-1]
+
+ def test(self, mask, value):
+ if self.attrtype != 'none' and \
+ mask in self.groups[self.attrtype]:
+ v = self.masks[mask] & self.attr
+ for f in self.fields[mask]:
+ if v == f[0] and value == f[1]:
+ return True
+ return False
+
+class attribute_printer:
+
+ def __init__(self, attr):
+ self.attr = attr
+
+ def to_string(self):
+ return gdb.Value(self.attr.to_string())
+
+class semaphore_printer:
+ """Print a Semaphore_Control object. Print using the struct display hint
+ and an iterator."""
+
+ class iterator:
+ """Use an iterator for each field expanded from the id so GDB output
+ is formatted correctly."""
+
+ def __init__(self, semaphore):
+ self.semaphore = semaphore
+ self.count = 0
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ self.count += 1
+ if self.count == 1:
+ return self.semaphore['Object']
+ elif self.count == 2:
+ attr = attribute(self.semaphore['attribute_set'],
+ 'semaphore')
+ return attr.to_string()
+ elif self.count == 3:
+ return self.semaphore['Core_control']
+ raise StopIteration
+
+ def __init__(self, semaphore):
+ self.semaphore = semaphore
+
+ def to_string(self):
+ return ''
+
+ @staticmethod
+ def key(i):
+ if i == 0:
+ return 'Object'
+ elif i == 1:
+ return 'attribute_set'
+ elif i == 2:
+ return 'Core_control'
+ return 'bad'
+
+ def children(self):
+ counter = itertools.imap (self.key, itertools.count())
+ return itertools.izip (counter, self.iterator(self.semaphore))
+
+ def display_hint (self):
+ return 'struct'
+
+class semaphore:
+ "Print a classic semaphore."
+
+ def __init__(self, id):
+ self.id = id;
+ self.object = objects.information.object(self.id).dereference()
+ self.object_control = objects.control(self.object['Object'])
+ self.attr = attribute(self.object['attribute_set'], 'semaphore')
+
+ def show(self, from_tty):
+ print ' Name:', self.object_control.name()
+ print ' Attr:', self.attr.to_string()
+ if self.attr.test('semaphore-type', 'bin-sema') or \
+ self.attr.test('semaphore-type', 'simple-bin-sema'):
+ core_mutex = self.object['Core_control']['mutex']
+ locked = core_mutex['lock'] == 0
+ if locked:
+ s = 'locked'
+ else:
+ s = 'unlocked'
+ print ' Lock:', s
+ print ' Nesting:', core_mutex['nest_count']
+ print ' Blocked:', core_mutex['blocked_count']
+ print ' Holder:',
+ holder = core_mutex['holder']
+ if holder and locked:
+ holder = threads.control(holder.dereference())
+ print holder.brief()
+ elif holder == 0 and locked:
+ print 'locked but no holder'
+ else:
+ print 'unlocked'
+ wait_queue = threads.queue(core_mutex['Wait_queue'])
+ tasks = wait_queue.tasks()
+ print ' Queue: len = %d, state = %s' % (len(tasks),
+ wait_queue.state())
+ for t in range(0, len(tasks)):
+ print ' ', tasks[t].brief(), ' (%08x)' % (tasks[t].id())
+ else:
+ print 'semaphore'
+
+class task:
+ "Print a classic tasks."
+
+ def __init__(self, id):
+ self.id = id;
+ self.task = \
+ threads.control(objects.information.object(self.id).dereference())
+
+ def show(self, from_tty):
+ print ' Name:', self.task.name()
+ print ' State:', self.task.current_state()
+ print ' Current:', self.task.current_priority()
+ print ' Real:', self.task.real_priority()
+ print ' Suspends:', self.task.suspends()
+ print ' Post Ext:', self.task.post_task_switch_ext()
+ print ' Preempt:', self.task.preemptible()
+ print ' T Budget:', self.task.cpu_time_budget()
+ wait_info = self.task.wait_info()
+
diff --git a/tools/gdb/python/objects.py b/tools/gdb/python/objects.py
new file mode 100644
index 0000000..22d2b2c
--- /dev/null
+++ b/tools/gdb/python/objects.py
@@ -0,0 +1,357 @@
+#
+# RTEMS Objects Support
+# Copyright 2010 Chris Johns (chrisj@rtems.org)
+#
+# $Id$
+#
+
+import gdb
+import itertools
+import re
+
+class infotables:
+ """Manage the object information tables."""
+
+ tables_types = {
+ 'classic/tasks' : ('Thread_Control', '_RTEMS_tasks_Information'),
+ 'classic/timers' : ('Timer_Control', '_Timers_Information'),
+ 'classic/semaphores' : ('Semaphore_Control', '_Semaphore_Information'),
+ 'classic/message_queues' : ('Message_queue_Control', '_Message_queue_Information'),
+ 'classic/partitions' : ('Partition_Control', '_Partition_Information'),
+ 'classic/regions' : ('Region_Control', '_Regions_Information'),
+ 'classic/ports' : ('Port_Control', '_Port_Information'),
+ 'classic/periods' : ('Period_Control', '_Period_Information'),
+ 'classic/extensions' : ('Extension_Control', '_Extension_Information'),
+ 'classic/barriers' : ('Barrier_Control', '_Barrier_Information')
+ }
+
+ def __init__(self):
+ self.invalidate()
+
+ def invalidate(self):
+ self.tables = {}
+
+ def name(self, api, _class):
+ return api + '/' + _class
+
+ def load(self, n):
+ if n in self.tables_types:
+ if n not in self.tables:
+ self.tables[n] = gdb.parse_and_eval(self.tables_types[n][1])
+
+ def get(self, api, _class):
+ n = self.name(api, _class)
+ self.load(n)
+ if n in self.tables:
+ return self.tables[n]
+ return None
+
+ def maximum(self, api, _class):
+ n = self.name(api, _class)
+ self.load(n)
+ return int(self.tables[n]['maximum'])
+
+ def object(self, id):
+ if type(id) == gdb.Value:
+ id = ident(id)
+ if type(id) == tuple:
+ api = id[0]
+ _class = id[1]
+ index = id[2]
+ else:
+ api = id.api()
+ _class = id._class()
+ index = id.index()
+ n = self.name(api, _class)
+ self.load(n)
+ max = self.maximum(api, _class)
+ if index >= max:
+ raise IndexError('object index out of range (%d)' % (max))
+ table_type = self.tables_types[n]
+ expr = '(' + table_type[0] + '*)' + \
+ table_type[1] + '.local_table[' + str(index) + ']'
+ return gdb.parse_and_eval(expr)
+
+ def is_string(self, api, _class):
+ n = self.name(api, _class)
+ self.load(n)
+ if n in self.tables:
+ if self.tables[n]['is_string']:
+ return True
+ return False
+
+#
+# Global info tables. These are global in the target.
+#
+information = infotables()
+
+class ident:
+ "An RTEMS object id with support for its bit fields."
+
+ bits = [
+ { 'index': (0, 15),
+ 'node': (0, 0),
+ 'api': (8, 10),
+ 'class': (11, 15) },
+ { 'index': (0, 15),
+ 'node': (16, 23),
+ 'api': (24, 26),
+ 'class': (27, 31) }
+ ]
+
+ OBJECT_16_BITS = 0
+ OBJECT_31_BITS = 1
+
+ api_labels = [
+ 'none',
+ 'internal',
+ 'classic',
+ 'posix',
+ 'itron'
+ ]
+
+ class_labels = {
+ 'internal' : ('threads',
+ 'mutexes'),
+ 'classic' : ('none',
+ 'tasks',
+ 'timers',
+ 'semaphores',
+ 'message_queues',
+ 'partitions',
+ 'regions',
+ 'ports',
+ 'periods',
+ 'extensions',
+ 'barriers'),
+ 'posix' : ('none',
+ 'threads',
+ 'keys',
+ 'interrupts',
+ 'message_queue_fds',
+ 'message_queues',
+ 'mutexes',
+ 'semaphores',
+ 'condition_variables',
+ 'timers',
+ 'barriers',
+ 'spinlocks',
+ 'rwlocks'),
+ 'itron' : ('none',
+ 'tasks',
+ 'eventflags',
+ 'mailboxes',
+ 'message_buffers',
+ 'ports',
+ 'semaphores',
+ 'variable_memory_pools',
+ 'fixed_memory_pools')
+ }
+
+ def __init__(self, id):
+ if type(id) != gdb.Value and type(id) != int and type(id) != unicode:
+ raise TypeError('%s: must be gdb.Value, int, unicoded int' % (type(id)))
+ if type(id) == int:
+ id = gdb.Value(id)
+ self.id = id
+ if self.id.type.sizeof == 2:
+ self.idSize = self.OBJECT_16_BITS
+ else:
+ self.idSize = self.OBJECT_31_BITS
+
+ def get(self, field):
+ if field in self.bits[self.idSize]:
+ bits = self.bits[self.idSize][field]
+ if bits[1] > 0:
+ return (int(self.id) >> bits[0]) & ((1 << (bits[1] - bits[0] + 1)) - 1)
+ return 0
+
+ def value(self):
+ return int(self.id)
+
+ def index(self):
+ return self.get('index')
+
+ def node(self):
+ return self.get('node')
+
+ def api_val(self):
+ return self.get('api')
+
+ def class_val(self):
+ return self.get('class')
+
+ def api(self):
+ api = self.api_val()
+ if api < len(self.api_labels):
+ return self.api_labels[api]
+ return 'none'
+
+ def _class(self):
+ api = self.api()
+ if api == 'none':
+ return 'invalid'
+ _class = self.class_val()
+ if _class < len(self.class_labels[api]):
+ return self.class_labels[api][_class]
+ return 'invalid'
+
+ def valid(self):
+ return self.api() != 'none' and self._class() != 'invalid'
+
+class name:
+ """The Objects_Name can either be told what the name is or can take a
+ guess."""
+
+ def __init__(self, name, is_string = None):
+ self.name = name
+ if is_string == None:
+ self.is_string = 'auto'
+ else:
+ if is_string:
+ self.is_string = 'yes'
+ else:
+ self.is_string = 'no'
+
+ def __str__(self):
+ if self.is_string != 'yes':
+ u32 = int(self.name['name_u32'])
+ s = chr((u32 >> 24) & 0xff) + \
+ chr((u32 >> 16) & 0xff) + chr((u32 >> 8) & 0xff) + \
+ chr(u32 & 0xff)
+ for c in range(0,4):
+ if s[c] < ' ' or s[c] > '~':
+ s = None
+ break
+ if s:
+ return s
+ return str(self.name['name_p'].dereference())
+
+class control:
+ """The Objects_Control structure."""
+
+ def __init__(self, object):
+ self.object = object
+ self._id = ident(self.object['id'])
+
+ def node(self):
+ return self.object['Node']
+
+ def id(self):
+ return self.object['id']
+
+ def name(self):
+ is_string = information.is_string(self._id.api(), self._id._class())
+ return str(name(self.object['name'], is_string))
+
+class id_printer:
+ """Print an object given the ID. Print using the struct display hint and an
+ iterator."""
+
+ class iterator:
+ """Use an iterator for each field expanded from the id so GDB output
+ is formatted correctly."""
+
+ def __init__(self, id):
+ self.id = id
+ self.count = 0
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ self.count += 1
+ if self.count == 1:
+ return int(self.id.value())
+ elif self.count == 2:
+ return self.id.node()
+ elif self.count == 3:
+ return self.id.api()
+ elif self.count == 4:
+ return self.id._class()
+ elif self.count == 5:
+ return self.id.index()
+ raise StopIteration
+
+ def __init__(self, id):
+ self.id = ident(id)
+
+ def to_string(self):
+ return ''
+
+ @staticmethod
+ def key(i):
+ if i == 0:
+ return 'id'
+ elif i == 1:
+ return 'node'
+ elif i == 2:
+ return 'api'
+ elif i == 3:
+ return 'class'
+ elif i == 4:
+ return 'index'
+ return 'bad'
+
+ def children(self):
+ counter = itertools.imap (self.key, itertools.count())
+ return itertools.izip (counter, self.iterator(self.id))
+
+ def display_hint (self):
+ return 'struct'
+
+class name_printer:
+ """Pretty printer for an object's name. It has to guess the type as no
+ information is available to help determine it."""
+
+ def __init__(self, name):
+ self.name = name(name)
+
+ def to_string(self):
+ return gdb.Value(str(self.name))
+
+class control_printer:
+
+ class iterator:
+ """Use an iterator for each field expanded from the id so GDB output
+ is formatted correctly."""
+
+ def __init__(self, object):
+ self.object = object
+ self.count = 0
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ self.count += 1
+ if self.count == 1:
+ return self.object.node()
+ elif self.count == 2:
+ return self.object.id()
+ elif self.count == 3:
+ return self.object.name()
+ raise StopIteration
+
+ def to_string(self):
+ return ''
+
+ def __init__(self, object):
+ self.object = control(object)
+
+ @staticmethod
+ def key(i):
+ if i == 0:
+ return 'Node'
+ elif i == 1:
+ return 'id'
+ elif i == 2:
+ return 'name'
+ return 'bad'
+
+ def children(self):
+ counter = itertools.imap (self.key, itertools.count())
+ return itertools.izip (counter, self.iterator(self.object))
+
+ def display_hint (self):
+ return 'struct'
diff --git a/tools/gdb/python/rtems.py b/tools/gdb/python/rtems.py
new file mode 100644
index 0000000..e227c6f
--- /dev/null
+++ b/tools/gdb/python/rtems.py
@@ -0,0 +1,110 @@
+#
+# RTEMS Pretty Printers
+# Copyright 2010 Chris Johns (chrisj@rtems.org)
+#
+# $Id$
+#
+
+import gdb
+import re
+
+import objects
+import threads
+import classic
+
+nesting = 0
+
+def type_from_value(val):
+ type = val.type;
+ # If it points to a reference, get the reference.
+ if type.code == gdb.TYPE_CODE_REF:
+ type = type.target ()
+ # Get the unqualified type
+ return type.unqualified ()
+
+def register_rtems_printers (obj):
+ "Register RTEMS pretty-printers with objfile Obj."
+
+ if obj == None:
+ obj = gdb
+
+ obj.pretty_printers.append (lookup_function)
+
+def lookup_function (val):
+ "Look-up and return a pretty-printer that can print val."
+
+ global nesting
+
+ typename = str(type_from_value(val))
+
+ for function in pp_dict:
+ if function.search (typename):
+ nesting += 1
+ result = pp_dict[function] (val)
+ nesting -= 1
+ if nesting == 0:
+ objects.information.invalidate()
+ return result
+
+ # Cannot find a pretty printer. Return None.
+ return None
+
+def build_rtems_dict():
+ pp_dict[re.compile('^rtems_id$')] = lambda val: objects.id_printer(val)
+ pp_dict[re.compile('^Objects_Id$')] = lambda val: objects.id_printer(val)
+ pp_dict[re.compile('^Objects_Name$')] = lambda val: objects.name_printer(val)
+ pp_dict[re.compile('^Objects_Control$')] = lambda val: objects.control_printer(val)
+ pp_dict[re.compile('^States_Control$')] = lambda val: threads.state_printer(val)
+ pp_dict[re.compile('^rtems_attribute$')] = lambda val: classic.attribute_printer(val)
+ pp_dict[re.compile('^Semaphore_Control$')] = lambda val: classic.semaphore_printer(val)
+
+class rtems(gdb.Command):
+ """Prefix command for RTEMS."""
+
+ def __init__(self):
+ super(rtems, self).__init__('rtems',
+ gdb.COMMAND_STATUS,
+ gdb.COMPLETE_NONE,
+ True)
+
+class rtems_object(gdb.Command):
+ """Object sub-command for RTEMS"""
+
+ objects = {
+ 'classic/semaphores': lambda id: classic.semaphore(id),
+ 'classic/tasks': lambda id: classic.task(id)
+ }
+
+ def __init__(self):
+ self.__doc__ = 'Display the RTEMS object given a numeric ID.'
+ super(rtems_object, self).__init__('rtems object',
+ gdb.COMMAND_STATUS)
+
+ def invoke(self, arg, from_tty):
+ for num in arg.split():
+ try:
+ val = gdb.parse_and_eval(num)
+ num = int(val)
+ except:
+ print 'error: "%s" is not a number' % (num)
+ return
+ id = objects.ident(num)
+ if not id.valid():
+ print 'Invalid object id'
+ print 'API:%s Class:%s Node:%d Index:%d Id:%08X' % \
+ (id.api(), id._class(), id.node(), id.index(), id.value())
+ objectname = id.api() + '/' + id._class()
+ if objectname in self.objects:
+ object = self.objects[objectname](id)
+ object.show(from_tty)
+ objects.information.invalidate()
+
+#
+# Main
+#
+pp_dict = {}
+build_rtems_dict()
+gdb.pretty_printers = []
+gdb.pretty_printers.append (lookup_function)
+rtems()
+rtems_object()
diff --git a/tools/gdb/python/threads.py b/tools/gdb/python/threads.py
new file mode 100644
index 0000000..906cf5a
--- /dev/null
+++ b/tools/gdb/python/threads.py
@@ -0,0 +1,207 @@
+#
+# RTEMS Threads Support
+# Copyright 2010 Chris Johns (chrisj@rtems.org)
+#
+# $Id$
+#
+
+import gdb
+
+import chains
+import objects
+
+def task_chain(chain):
+ tasks = []
+ node = chain.first()
+ while not node.null():
+ print node.addr
+ tasks.append(control(node.cast('Thread_Control')))
+ node.next()
+ return tasks
+
+class state:
+
+ ALL_SET = 0x000fffff
+ READY = 0x00000000
+ DORMANT = 0x00000001
+ SUSPENDED = 0x00000002
+ TRANSIENT = 0x00000004
+ DELAYING = 0x00000008
+ WAITING_FOR_TIME = 0x00000010
+ WAITING_FOR_BUFFER = 0x00000020
+ WAITING_FOR_SEGMENT = 0x00000040
+ WAITING_FOR_MESSAGE = 0x00000080
+ WAITING_FOR_EVENT = 0x00000100
+ WAITING_FOR_SEMAPHORE = 0x00000200
+ WAITING_FOR_MUTEX = 0x00000400
+ WAITING_FOR_CONDITION_VARIABLE = 0x00000800
+ WAITING_FOR_JOIN_AT_EXIT = 0x00001000
+ WAITING_FOR_RPC_REPLY = 0x00002000
+ WAITING_FOR_PERIOD = 0x00004000
+ WAITING_FOR_SIGNAL = 0x00008000
+ WAITING_FOR_BARRIER = 0x00010000
+ WAITING_FOR_RWLOCK = 0x00020000
+ INTERRUPTIBLE_BY_SIGNAL = 0x10000000
+ LOCALLY_BLOCKED = \
+ WAITING_FOR_BUFFER | \
+ WAITING_FOR_SEGMENT | \
+ WAITING_FOR_MESSAGE | \
+ WAITING_FOR_SEMAPHORE | \
+ WAITING_FOR_MUTEX | \
+ WAITING_FOR_CONDITION_VARIABLE | \
+ WAITING_FOR_JOIN_AT_EXIT | \
+ WAITING_FOR_SIGNAL | \
+ WAITING_FOR_BARRIER | \
+ WAITING_FOR_RWLOCK
+ WAITING_ON_THREAD_QUEUE = \
+ LOCALLY_BLOCKED | WAITING_FOR_RPC_REPLY
+ BLOCKED = \
+ DELAYING | \
+ WAITING_FOR_TIME | \
+ WAITING_FOR_PERIOD | \
+ WAITING_FOR_EVENT | \
+ WAITING_ON_THREAD_QUEUE | \
+ INTERRUPTIBLE_BY_SIGNAL
+
+ masks = {
+ ALL_SET : 'all-set',
+ READY : 'ready',
+ DORMANT : 'dormant',
+ SUSPENDED : 'suspended',
+ TRANSIENT : 'transient',
+ DELAYING : 'delaying',
+ WAITING_FOR_TIME : 'waiting-for-time',
+ WAITING_FOR_BUFFER : 'waiting-for-buffer',
+ WAITING_FOR_SEGMENT : 'waiting-for-segment',
+ WAITING_FOR_MESSAGE : 'waiting-for-message',
+ WAITING_FOR_EVENT : 'waiting-for-event',
+ WAITING_FOR_SEMAPHORE : 'waiting-for-semaphore',
+ WAITING_FOR_MUTEX : 'waiting-for-mutex',
+ WAITING_FOR_CONDITION_VARIABLE : 'waiting-for-condition-variable',
+ WAITING_FOR_JOIN_AT_EXIT : 'waiting-for-join-at-exit',
+ WAITING_FOR_RPC_REPLY : 'waiting-for-rpc-reply',
+ WAITING_FOR_PERIOD : 'waiting-for-period',
+ WAITING_FOR_SIGNAL : 'waiting-for-signal',
+ WAITING_FOR_BARRIER : 'waiting-for-barrier',
+ WAITING_FOR_RWLOCK : 'waiting-for-rwlock'
+ }
+
+ def __init__(self, s):
+ self.s = s
+
+ def to_string(self):
+ if (self.s & self.LOCALLY_BLOCKED) == self.LOCALLY_BLOCKED:
+ return 'locally-blocked'
+ if (self.s & self.WAITING_ON_THREAD_QUEUE) == self.WAITING_ON_THREAD_QUEUE:
+ return 'waiting-on-thread-queue'
+ if (self.s & self.BLOCKED) == self.BLOCKED:
+ return 'blocked'
+ s = ','
+ for m in self.masks:
+ if (self.s & m) == m:
+ s = self.masks[m] + ','
+ return s[:-1]
+
+class wait_info:
+
+ def __init__(self, info):
+ self.info = info
+
+ def id(self):
+ return self.info['id']
+
+ def count(self):
+ return self.info['count']
+
+ def return_arg(self):
+ return self.info['return_argument']
+
+ def option(self):
+ return self.info['option']
+
+ def block2n(self):
+ return task_chain(chains.control(self.info['Block2n']))
+
+ def queue(self):
+ return task_chain(chains.control(self.info['queue']))
+
+class control:
+
+ def __init__(self, ctrl):
+ self.ctrl = ctrl
+ self.object = objects.control(ctrl['Object'])
+
+ def id(self):
+ return self.object.id()
+
+ def name(self):
+ return self.object.name()
+
+ def current_state(self):
+ return state(self.ctrl['current_state']).to_string()
+
+ def current_priority(self):
+ return self.ctrl['current_priority']
+
+ def real_priority(self):
+ return self.ctrl['real_priority']
+
+ def suspends(self):
+ return self.ctrl['suspend_count']
+
+ def post_task_switch_ext(self):
+ return self.ctrl['do_post_task_switch_extension']
+
+ def preemptible(self):
+ return self.ctrl['is_preemptible']
+
+ def cpu_time_budget(self):
+ return self.ctrl['cpu_time_budget']
+
+ def wait_info(self):
+ return wait_info(self.ctrl['Wait'])
+
+ def brief(self):
+ return "'%s' (c:%d, r:%d)" % \
+ (self.name(), self.current_priority(), self.real_priority())
+
+class queue:
+ """Manage the Thread_queue_Control."""
+
+ priority_headers = 4
+
+ def __init__(self, que):
+ self.que = que
+
+ def fifo(self):
+ return str(self.que['discipline']) == 'THREAD_QUEUE_DISCIPLINE_FIFO'
+
+ def priority(self):
+ return str(self.que['discipline']) == 'THREAD_QUEUE_DISCIPLINE_PRIORITY'
+
+ def state(self):
+ return state(self.que['state']).to_string()
+
+ def tasks(self):
+ if self.fifo():
+ t = task_chain(chains.control(self.que['Queues']['Fifo']))
+ else:
+ t = []
+ for ph in range(0, self.priority_headers):
+ t.extend(task_chain(chains.control(self.que['Queues']['Fifo'])))
+ return t
+
+ def to_string(self):
+ if self.fifo():
+ s = 'fifo'
+ else:
+ s = 'priority'
+ return
+
+class state_printer:
+
+ def __init__(self, s):
+ self.s = state(s)
+
+ def to_string(self):
+ return self.s.to_string()
diff --git a/tools/gdb/python/watchdog.py b/tools/gdb/python/watchdog.py
new file mode 100644
index 0000000..0766575
--- /dev/null
+++ b/tools/gdb/python/watchdog.py
@@ -0,0 +1,56 @@
+#
+# RTEMS Watchdog Support
+# Copyright 2010 Chris Johns (chrisj@rtems.org)
+#
+# $Id$
+#
+
+import gdb
+
+import chains
+import objects
+
+class state:
+
+ INACTIVE = 0
+ BEING_INSERTED = 1
+ ACTIVE = 2
+ REMOVE_IT = 3
+
+ states = {
+ 0: 'inactive',
+ 1: 'being-inserted',
+ 2: 'active',
+ 3: 'remove-it'
+ }
+
+ def __init__(self, s):
+ self.s = s
+
+ def to_string(self):
+ return self.states[self.s]
+
+class control:
+
+ def __init__(self, ctrl):
+ self.ctrl = ctrl
+
+ def state(self):
+ return state(self.ctrl['state']).to_string()
+
+ def initial(self):
+ return self.ctrl['initial']
+
+ def delta_interval(self):
+ return self.ctrl['delta_interval']
+
+ def start_time(self):
+ return self.ctrl['start_time']
+
+ def stop_time(self):
+ return self.ctrl['stop_time']
+
+ def routine(self):
+ addr = self.ctrl['routine']
+ sym = gdb.lookup_symbol(addr)
+ print sym