Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'python/src/tcf/services/stacktrace.py')
-rw-r--r--python/src/tcf/services/stacktrace.py360
1 files changed, 269 insertions, 91 deletions
diff --git a/python/src/tcf/services/stacktrace.py b/python/src/tcf/services/stacktrace.py
index 682a5c51c..0dca56afb 100644
--- a/python/src/tcf/services/stacktrace.py
+++ b/python/src/tcf/services/stacktrace.py
@@ -9,112 +9,188 @@
# * Wind River Systems - initial API and implementation
#******************************************************************************
+"""TCF stacktrace service interface.
+
+.. |getChildren| replace:: :meth:`~StackTraceService.getChildren`
+.. |getContext| replace:: :meth:`~StackTraceService.getContext`
+.. |runcontrol| replace:: :mod:`~tcf.services.runcontrol`
+.. |DoneGetChildren| replace:: :class:`DoneGetChildren`
+.. |DoneGetContext| replace:: :class:`DoneGetContext`
+
+
+The service implements thread stack back tracing.
+
+Properties
+----------
+
++--------------------------+--------------+-----------------------------------+
+| Name | Type | Description |
++==========================+==============+===================================+
+| PROP_ARGUMENTS_ADDRESS | |int| | Memory address of function |
+| | | arguments. |
++--------------------------+--------------+-----------------------------------+
+| PROP_ARGUMENTS_COUNT | |int| | Number of function arguments. |
++--------------------------+--------------+-----------------------------------+
+| PROP_FRAME_ADDRESS | |int| | Stack frame memory address. |
++--------------------------+--------------+-----------------------------------+
+| PROP_ID | |basestring| | String, stack frame ID. |
++--------------------------+--------------+-----------------------------------+
+| PROP_INSTRUCTION_ADDRESS | |int| | Instruction pointer. |
++--------------------------+--------------+-----------------------------------+
+| PROP_LEVEL | |int| | Stack frame level, starting from |
+| | | stack bottom. |
++--------------------------+--------------+-----------------------------------+
+| PROP_NAME | |basestring| | Human readable name. |
++--------------------------+--------------+-----------------------------------+
+| PROP_PARENT_ID | |basestring| | Stack frame parent ID. |
++--------------------------+--------------+-----------------------------------+
+| PROP_PROCESS_ID | |basestring| | Stack frame process ID. |
++--------------------------+--------------+-----------------------------------+
+| PROP_RETURN_ADDRESS | |int| | Return address. |
++--------------------------+--------------+-----------------------------------+
+| PROP_TOP_FRAME | |bool| | **True** if the frame is top frame|
+| | | on a stack. |
++--------------------------+--------------+-----------------------------------+
+
+Service Methods
+---------------
+.. autodata:: NAME
+.. autoclass:: StackTraceService
+
+getName
+^^^^^^^
+.. automethod:: StackTraceService.getName
+
+getContext
+^^^^^^^^^^
+.. automethod:: StackTraceService.getContext
+
+getChildren
+^^^^^^^^^^^
+.. automethod:: StackTraceService.getChildren
+
+Callback Classes
+----------------
+DoneGetContext
+^^^^^^^^^^^^^^^^^
+.. autoclass:: DoneGetContext
+ :members:
+
+DoneGetChildren
+^^^^^^^^^^^^^^^
+.. autoclass:: DoneGetChildren
+ :members:
+
+
+Helper Classes
+--------------
+StackTraceContext
+^^^^^^^^^^^^^^^^^
+.. autoclass:: StackTraceContext
+ :members:
+"""
+
from .. import services
NAME = "StackTrace"
+"""StackTrace service name."""
-#
-# Stack frame context property names.
-#
-# String, stack frame ID
PROP_ID = "ID"
-
-# String, stack frame parent ID
PROP_PARENT_ID = "ParentID"
-
-# String, stack frame process ID
PROP_PROCESS_ID = "ProcessID"
-
-# String, human readable name
PROP_NAME = "Name"
-
-# Boolean, true if the frame is top frame on a stack
PROP_TOP_FRAME = "TopFrame"
-
-# Integer, stack frame level, starting from stack bottom
PROP_LEVEL = "Level"
-
-# Number, stack frame memory address
PROP_FRAME_ADDRESS = "FP"
-
-# Number, return address
PROP_RETURN_ADDRESS = "RP"
-
-# Number, instruction pointer
PROP_INSTRUCTION_ADDRESS = "IP"
-
-# Integer, number of function arguments
PROP_ARGUMENTS_COUNT = "ArgsCnt"
-
-# Number, memory address of function arguments
PROP_ARGUMENTS_ADDRESS = "ArgsAddr"
+PROP_INDEX = "Index"
+PROP_WALK = "Walk"
class StackTraceService(services.Service):
+ """TCF stacktrace service interface."""
+
def getName(self):
+ """Get this service name.
+
+ :returns: This service name, which is the value of :const:`NAME`
+ """
return NAME
def getContext(self, ids, done):
- """
- Retrieve context info for given context IDs.
+ """Retrieve context info for given context IDs.
- The command will fail if parent thread is not suspended.
- Client can use Run Control service to suspend a thread.
+ The command will fail if parent thread is not suspended. Client can use
+ |runcontrol| service to suspend a thread.
- @param ids - array of context IDs.
- @param done - call back interface called when operation is completed.
+ :param ids: List of context IDs.
+ :type ids: |tuple| or |list|
+ :param done: call back interface called when operation is completed
+ :type done: |DoneGetContext|
"""
raise NotImplementedError("Abstract method")
def getChildren(self, parent_context_id, done):
- """
- Retrieve stack trace context list.
+ """Retrieve stack trace context list.
+
Parent context usually corresponds to an execution thread.
- Some targets have more then one stack. In such case children of a
+
+ Some targets have more than one stack. In such case children of a
thread are stacks, and stack frames are deeper in the hierarchy - they
- can be retrieved with additional getChildren commands.
+ can be retrieved with additional :meth:`getChildren` commands.
- The command will fail if parent thread is not suspended.
- Client can use Run Control service to suspend a thread.
+ The command will fail if parent thread is not suspended. Client can use
+ |runcontrol| service to suspend a thread.
- @param parent_context_id - parent context ID.
- @param done - call back interface called when operation is completed.
+ :param parent_context_id: Parent context ID.
+ :type parent_context_id: |basestring|
+ :param done: call back interface called when operation is completed
+ :type done: |DoneGetChildren|
"""
raise NotImplementedError("Abstract method")
class DoneGetContext(object):
- """
- Client call back interface for getContext().
- """
+ """Client call back interface for |getContext|."""
+
def doneGetContext(self, token, error, contexts):
- """
- Called when context data retrieval is done.
- @param error - error description if operation failed, None if
- succeeded.
- @param contexts - array of context data or None if error.
+ """Called when context data retrieval is done.
+
+ :param error: Error description if operation failed, **None** if
+ succeeded.
+ :param contexts: A list of context data or **None** if error.
+ :type contexts: |tuple| or **None**
"""
pass
class DoneGetChildren(object):
- """
- Client call back interface for getChildren().
- """
+ """Client call back interface for |getChildren|."""
+
def doneGetChildren(self, token, error, context_ids):
- """
- Called when context list retrieval is done.
- @param error - error description if operation failed, None if
- succeeded.
- @param context_ids - array of available context IDs.
- Stack frames are ordered from stack bottom to top.
+ """Called when context list retrieval is done.
+
+ .. note:: Stack frames are ordered from stack bottom to top.
+
+ :param error: error description if operation failed, **None** if
+ succeeded
+ :param context_ids: A list of available context IDs.
+ :type context_ids: |tuple|
"""
pass
class StackTraceContext(object):
- """
- StackTraceContext represents stack trace objects - stacks and stack frames.
+ """StackTrace context class.
+
+ *StackTraceContext* represents stack trace objects : stacks and stack
+ frames.
+
+ :param props: The properties to initialise object with. See `Properties`_.
+ :type props: |dict|
"""
def __init__(self, props):
self._props = props or {}
@@ -122,68 +198,170 @@ class StackTraceContext(object):
def __str__(self):
return "[Stack Trace Context %s]" % self._props
+ def __eq__(self, other):
+ # Two frames are considered equal if they have the same properties
+ if other and isinstance(other, StackTraceContext):
+ return self.getProperties() == other.getProperties()
+ return False
+
+ def __getComparable(self, other):
+ assert isinstance(other, StackTraceContext)
+
+ # levels from bottom to top, but we want top first when sorted
+ levels = (other.getLevel(), self.getLevel())
+ # indexes from top to bottom
+ indexes = (self.getIndex(), other.getIndex())
+
+ # By default, use Level as it is more reliable to perform comparison,
+ # even between frames from successive runcontrol (Level is absolute,
+ # Index is function of the top frame which changes).
+ if -1 not in levels:
+ return levels
+ if -1 not in indexes:
+ return indexes
+
+ return None
+
+ def __ge__(self, other):
+ # Compare frames through their index or levels.
+ if other and isinstance(other, StackTraceContext):
+ comp = self.__getComparable(other)
+ return comp and comp[0] >= comp[1]
+ return False
+
+ def __gt__(self, other):
+ # Compare frames through their index or levels.
+ if other and isinstance(other, StackTraceContext):
+ comp = self.__getComparable(other)
+ return comp and comp[0] > comp[1]
+ return True
+
+ def __le__(self, other):
+ # Compare frames through their index or levels.
+ if other and isinstance(other, StackTraceContext):
+ comp = self.__getComparable(other)
+ return comp and comp[0] <= comp[1]
+ return False
+
+ def __lt__(self, other):
+ # Compare frames through their index or levels.
+ if other and isinstance(other, StackTraceContext):
+ comp = self.__getComparable(other)
+ return comp and comp[0] < comp[1]
+ return False
+
+ def __ne__(self, other):
+ # Two frames are considered equal if they have the same properties
+ if other and isinstance(other, StackTraceContext):
+ return self.getProperties() != other.getProperties()
+ return True
+
def getID(self):
+ """Get Context ID.
+
+ :returns: A |basestring| representing this stack context ID. This is
+ the only mandatory field.
+ """
+ return self._props.get(PROP_ID, '')
+
+ def getIndex(self):
+ """Get stack index.
+
+ :returns: An |int| representing this stack index, 0 being the top
+ frame, or **-1** if unknown.
"""
- Get Context ID.
- @return context ID.
+ return self._props.get(PROP_INDEX, -1)
+
+ def getLevel(self):
+ """Get stack level.
+
+ :returns: An |int| representing this context stack level, or **-1** if
+ unknown.
"""
- return self._props.get(PROP_ID)
+ return self._props.get(PROP_LEVEL, -1)
def getParentID(self):
+ """Get parent context ID.
+
+ :returns: A |basestring| representing parent context ID, or an empty
+ |basestring| if unknown.
"""
- Get parent context ID.
- @return parent context ID.
+ return self._props.get(PROP_PARENT_ID, '')
+
+ def getProcessID(self):
+ """Get process context ID.
+
+ :returns: A |basestring| representing process context ID, or an empty
+ |basestring| if unknown.
"""
- return self._props.get(PROP_PARENT_ID)
+ return self._props.get(PROP_PROCESS_ID, '')
def getName(self):
+ """Get context name - if context represents a stack.
+
+ :returns: A |basestring| representing this stack context name or
+ **None**.
"""
- Get context name - if context represents a stack.
- @return context name or None.
- """
- return self._props.get(PROP_NAME)
+ return self._props.get(PROP_NAME, None)
def getFrameAddress(self):
+ """Get memory address of this frame.
+
+ :returns: An |int| representing this frame address or **None** if not a
+ stack frame.
"""
- Get memory address of this frame.
- @return address or None if not a stack frame.
- """
- return self._props.get(PROP_FRAME_ADDRESS)
+ return self._props.get(PROP_FRAME_ADDRESS, None)
def getReturnAddress(self):
+ """Get program counter saved in this stack frame.
+
+ This return address is the address of instruction to be executed when
+ the function returns.
+
+ :returns: An |int| representing the return address or **None** if not a
+ stack frame.
"""
- Get program counter saved in this stack frame -
- it is address of instruction to be executed when the function returns.
- @return return address or None if not a stack frame.
- """
- return self._props.get(PROP_RETURN_ADDRESS)
+ return self._props.get(PROP_RETURN_ADDRESS, None)
def getInstructionAddress(self):
- """
- Get address of the next instruction to be executed in this stack frame.
+ """Get address of the next instruction to be executed in this stack
+ frame.
+
For top frame it is same as PC register value.
+
For other frames it is same as return address of the next frame.
- @return instruction address or None if not a stack frame.
+
+ :returns: An |int| representing this instruction address or **None** if
+ not a stack frame.
"""
- return self._props.get(PROP_INSTRUCTION_ADDRESS)
+ return self._props.get(PROP_INSTRUCTION_ADDRESS, None)
def getArgumentsCount(self):
+ """Get number of function arguments for this frame.
+
+ :returns: An |int| reprsenting this stack function arguments count.
"""
- Get number of function arguments for this frame.
- @return function arguments count.
- """
- return self._props.get(PROP_ARGUMENTS_COUNT)
+ return self._props.get(PROP_ARGUMENTS_COUNT, 0)
def getArgumentsAddress(self):
+ """Get address of function arguments area in memory.
+
+ :returns: An |int| representing this stack function arguments address
+ or **None** if not available.
"""
- Get address of function arguments area in memory.
- @return function arguments address or None if not available.
- """
- return self._props.get(PROP_ARGUMENTS_ADDRESS, 0)
+ return self._props.get(PROP_ARGUMENTS_ADDRESS, None)
def getProperties(self):
- """
- Get complete map of context properties.
- @return map of context properties.
+ """Get complete map of context properties.
+
+ :returns: A |dict| of context properties. See `Properties`_.
"""
return self._props
+
+ def isTopFrame(self):
+ """Check if this stack frame is the top frame.
+
+ :returns: A |bool| set to **True** if this stack is the toplevel
+ stack frame, **False** else.
+ """
+ return self._props.get(PROP_TOP_FRAME, False)

Back to the top