diff options
author | Dhananjay Balan <mb.dhananjay@gmail.com> | 2013-06-17 22:40:17 +0530 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2014-08-25 09:52:40 +1000 |
commit | 56a70aec5536a568fe302a3c84b349fcf17db2fa (patch) | |
tree | 0f1043e21f214f7e3b3d1063f446073980859c15 | |
parent | 911e71038cee3bcf3b9fa60a415dbda824bc3a80 (diff) |
Intial commit.
Chris's intial work on the extenstions.
-rw-r--r-- | tools/gdb/python/__init__.py | 16 | ||||
-rw-r--r-- | tools/gdb/python/chains.py | 43 | ||||
-rw-r--r-- | tools/gdb/python/classic.py | 216 | ||||
-rw-r--r-- | tools/gdb/python/objects.py | 357 | ||||
-rw-r--r-- | tools/gdb/python/rtems.py | 110 | ||||
-rw-r--r-- | tools/gdb/python/threads.py | 207 | ||||
-rw-r--r-- | tools/gdb/python/watchdog.py | 56 |
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 |