mirror of
https://git.rtems.org/rtems-tools/
synced 2025-05-14 01:19:19 +08:00
Intial commit.
Chris's intial work on the extenstions.
This commit is contained in:
parent
911e71038c
commit
56a70aec55
16
tools/gdb/python/__init__.py
Normal file
16
tools/gdb/python/__init__.py
Normal file
@ -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'
|
43
tools/gdb/python/chains.py
Normal file
43
tools/gdb/python/chains.py
Normal file
@ -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'])
|
216
tools/gdb/python/classic.py
Normal file
216
tools/gdb/python/classic.py
Normal file
@ -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()
|
||||
|
357
tools/gdb/python/objects.py
Normal file
357
tools/gdb/python/objects.py
Normal file
@ -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'
|
110
tools/gdb/python/rtems.py
Normal file
110
tools/gdb/python/rtems.py
Normal file
@ -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()
|
207
tools/gdb/python/threads.py
Normal file
207
tools/gdb/python/threads.py
Normal file
@ -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()
|
56
tools/gdb/python/watchdog.py
Normal file
56
tools/gdb/python/watchdog.py
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user