Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'python/src/tcf/services')
-rw-r--r--python/src/tcf/services/__init__.py115
-rw-r--r--python/src/tcf/services/breakpoints.py314
-rw-r--r--python/src/tcf/services/locator.py119
-rw-r--r--python/src/tcf/services/remote/BreakpointsProxy.py140
-rw-r--r--python/src/tcf/services/remote/LocatorProxy.py147
-rw-r--r--python/src/tcf/services/remote/RunControlProxy.py152
-rw-r--r--python/src/tcf/services/remote/StackTraceProxy.py52
-rw-r--r--python/src/tcf/services/remote/SymbolsProxy.py115
-rw-r--r--python/src/tcf/services/remote/__init__.py0
-rw-r--r--python/src/tcf/services/runcontrol.py480
-rw-r--r--python/src/tcf/services/stacktrace.py160
-rw-r--r--python/src/tcf/services/symbols.py381
12 files changed, 2175 insertions, 0 deletions
diff --git a/python/src/tcf/services/__init__.py b/python/src/tcf/services/__init__.py
new file mode 100644
index 000000000..349a2b52a
--- /dev/null
+++ b/python/src/tcf/services/__init__.py
@@ -0,0 +1,115 @@
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import threading, exceptions
+from tcf import protocol
+
+_providers = []
+_lock = threading.RLock()
+
+class ServiceProvider(object):
+ """
+ Clients can implement this abstract class if they want to provide implementation of a local service or
+ remote service proxy.
+ """
+ def getLocalService(self, channel):
+ pass
+ def getServiceProxy(self, channel, service_name):
+ pass
+
+def addServiceProvider(provider):
+ with _lock:
+ _providers.append(provider)
+
+def removeServiceProvider(provider):
+ with _lock:
+ _providers.remove(provider)
+
+def onChannelCreated(channel, services_by_name):
+ with _lock:
+ zero_copy = ZeroCopy()
+ services_by_name[zero_copy.getName()] = zero_copy
+ for provider in _providers:
+ try:
+ arr = provider.getLocalService(channel)
+ if not arr: continue
+ for service in arr:
+ if services_by_name.has_key(service.getName()): continue
+ services_by_name[service.getName()] = service
+ except exceptions.Exception as x:
+ protocol.log("Error calling TCF service provider", x);
+
+def onChannelOpened(channel, service_names, services_by_name):
+ with _lock:
+ for name in service_names:
+ for provider in _providers:
+ try:
+ service = provider.getServiceProxy(channel, name)
+ if not service: continue
+ services_by_name[name] = service
+ break
+ except exceptions.Exception as x:
+ protocol.log("Error calling TCF service provider", x)
+ if services_by_name.has_key(name): continue
+ services_by_name[name] = GenericProxy(channel, name)
+
+def getServiceManagerID():
+ # In current implementation ServiceManager is a singleton,
+ # so its ID is same as agent ID.
+ return protocol.getAgentID()
+
+class Service(object):
+ def getName(self):
+ raise exceptions.NotImplementedError("Abstract method")
+ def __str__(self):
+ return self.getName()
+
+class ZeroCopy(Service):
+ def getName(self):
+ return "ZeroCopy"
+
+class GenericProxy(Service):
+ """
+ * Objects of GenericProxy class represent remote services, which don't
+ * have a proxy class defined for them.
+ * Clients still can use such services, but framework will not provide
+ * service specific utility methods for message formatting and parsing.
+ """
+ def __init__(self, channel, name):
+ self.__channel = channel
+ self.name = name
+ def getName(self):
+ return self.name
+ def getChannel(self):
+ return self.__channel
+
+class DefaultServiceProvider(ServiceProvider):
+ package_base = "tcf.services.remote"
+ def getLocalService(self, channel):
+ # TODO DiagnosticsService
+ #return [DiagnosticsService(channel)]
+ return []
+ def getServiceProxy(self, channel, service_name):
+ service = None
+ try:
+ clsName = service_name + "Proxy"
+ package = self.package_base + "." + clsName
+ clsModule = __import__(package, fromlist=[clsName], globals=globals())
+ cls = clsModule.__dict__.get(clsName)
+ service = cls(channel)
+ assert service_name == service.getName()
+ except exceptions.ImportError:
+ pass
+ except exceptions.Exception as x:
+ protocol.log("Cannot instantiate service proxy for "+service_name, x)
+ return service
+
+addServiceProvider(DefaultServiceProvider())
diff --git a/python/src/tcf/services/breakpoints.py b/python/src/tcf/services/breakpoints.py
new file mode 100644
index 000000000..97ee9b2c8
--- /dev/null
+++ b/python/src/tcf/services/breakpoints.py
@@ -0,0 +1,314 @@
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import exceptions
+from tcf import services
+
+"""
+Breakpoint is represented by unique identifier and set of properties.
+Breakpoint identifier (String id) needs to be unique across all hosts and targets.
+
+Breakpoint properties (Map<String,Object>) is extendible collection of named attributes,
+which define breakpoint location and behavior. This module defines some common
+attribute names (see PROP_*), host tools and target agents may support additional attributes.
+
+For each breakpoint a target agent maintains another extendible collection of named attributes:
+breakpoint status (Map<String,Object>, see STATUS_*). While breakpoint properties are
+persistent and represent user input, breakpoint status reflects dynamic target agent reports
+about breakpoint current state, like actual addresses where breakpoint is planted or planting errors.
+"""
+
+# Service name.
+NAME = "Breakpoints"
+
+# Breakpoint property names.
+PROP_ID = "ID" # String
+PROP_ENABLED = "Enabled" # Boolean
+PROP_TYPE = "BreakpointType" # String
+PROP_CONTEXTNAMES = "ContextNames" # Array
+PROP_CONTEXTIDS = "ContextIds" # Array
+PROP_EXECUTABLEPATHS = "ExecPaths" # Array
+PROP_LOCATION = "Location" # String
+PROP_SIZE = "Size" # Number
+PROP_ACCESSMODE = "AccessMode" # Number
+PROP_FILE = "File" # String
+PROP_LINE = "Line" # Number
+PROP_COLUMN = "Column" # Number
+PROP_PATTERN = "MaskValue" # Number
+PROP_MASK = "Mask" # Number
+PROP_STOP_GROUP = "StopGroup" # Array
+PROP_IGNORECOUNT = "IgnoreCount" # Number
+PROP_TIME = "Time" # Number
+PROP_SCALE = "TimeScale" # String
+PROP_UNITS = "TimeUnits" # String
+PROP_CONDITION = "Condition" # String
+PROP_TEMPORARY = "Temporary" # Boolean
+
+# BreakpointType values
+TYPE_SOFTWARE = "Software",
+TYPE_HARDWARE = "Hardware"
+TYPE_AUTO = "Auto"
+
+# AccessMode values
+ACCESSMODE_READ = 0x01
+ACCESSMODE_WRITE = 0x02
+ACCESSMODE_EXECUTE = 0x04
+ACCESSMODE_CHANGE = 0x08
+
+# TimeScale values
+TIMESCALE_RELATIVE = "Relative"
+TIMESCALE_ABSOLUTE = "Absolute"
+
+# TimeUnits values
+TIMEUNIT_NSECS = "Nanoseconds"
+TIMEUNIT_CYCLE_COUNT = "CycleCount"
+TIMEUNIT_INSTRUCTION_COUNT = "InstructionCount"
+
+# Breakpoint status field names.
+STATUS_INSTANCES = "Instances" # Array of Map<String,Object>
+STATUS_ERROR= "Error" # String
+STATUS_FILE = "File" # String
+STATUS_LINE = "Line" # Number
+STATUS_COLUMN = "Column" # Number
+
+# Breakpoint instance field names.
+INSTANCE_ERROR = "Error" # String
+INSTANCE_CONTEXT = "LocationContext" # String
+INSTANCE_ADDRESS = "Address" # Number
+
+# Breakpoint service capabilities.
+CAPABILITY_CONTEXT_ID = "ID" # String
+CAPABILITY_HAS_CHILDREN = "HasChildren" # Boolean
+CAPABILITY_LOCATION = "Location" # Boolean
+CAPABILITY_CONDITION = "Condition" # Boolean
+CAPABILITY_FILE_LINE = "FileLine" # Boolean
+CAPABILITY_CONTEXTIDS = "ContextIds" # Boolean
+CAPABILITY_STOP_GROUP = "StopGroup" # Boolean
+CAPABILITY_IGNORECOUNT = "IgnoreCount" # Boolean
+CAPABILITY_ACCESSMODE = "AccessMode" # Number
+
+class BreakpointsService(services.Service):
+ def getName(self):
+ return NAME
+
+ def set(self, properties, done):
+ """
+ Download breakpoints data to target agent.
+ The command is intended to be used only to initialize target breakpoints table
+ when communication channel is open. After that, host should
+ notify target about (incremental) changes in breakpoint data by sending
+ add, change and remove commands.
+
+ @param properties - array of breakpoints.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def add(self, properties, done):
+ """
+ Called when breakpoint is added into breakpoints table.
+ @param properties - breakpoint properties.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def change(self, properties, done):
+ """
+ Called when breakpoint properties are changed.
+ @param properties - breakpoint properties.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def enable(self, ids, done):
+ """
+ Tell target to change (only) PROP_ENABLED breakpoint property to 'true'.
+ @param ids - array of enabled breakpoint identifiers.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def disable(self, ids, done):
+ """
+ Tell target to change (only) PROP_ENABLED breakpoint property to 'false'.
+ @param ids - array of disabled breakpoint identifiers.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def remove(self, ids, done):
+ """
+ Tell target to remove breakpoints.
+ @param id - unique breakpoint identifier.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def getIDs(self, done):
+ """
+ Upload IDs of breakpoints known to target agent.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneGetIDs
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def getProperties(self, id, done):
+ """
+ Upload properties of given breakpoint from target agent breakpoint table.
+ @param id - unique breakpoint identifier.
+ @param done - command result call back object.
+ @see DoneGetProperties
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def getStatus(self, id, done):
+ """
+ Upload status of given breakpoint from target agent.
+ @param id - unique breakpoint identifier.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneGetStatus
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def getCapabilities(self, id, done):
+ """
+ Report breakpoint service capabilities to clients so they
+ can adjust to different implementations of the service.
+ When called with a None ("") context ID the global capabilities are returned,
+ otherwise context specific capabilities are returned. A special capability
+ property is used to indicate that all child contexts have the same
+ capabilities.
+ @param id - a context ID or None.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneGetCapabilities
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def addListener(self, listener):
+ """
+ Add breakpoints service event listener.
+ @param listener - object that implements BreakpointsListener interface.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def removeListener(self, listener):
+ """
+ Remove breakpoints service event listener.
+ @param listener - object that implements BreakpointsListener interface.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+
+class DoneCommand(object):
+ "Call back interface for breakpoint service commands."
+ def doneCommand(self, token, error):
+ """
+ Called when command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ """
+ pass
+
+class DoneGetIDs(object):
+ "Call back interface for 'getIDs' command."
+ def doneGetIDs(self, token, error, ids):
+ """
+ Called when 'getIDs' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param ids - IDs of breakpoints known to target agent.
+ """
+ pass
+
+class DoneGetProperties(object):
+ "Call back interface for 'getProperties' command."
+ def doneGetProperties(self, token, error, properties):
+ """
+ Called when 'getProperties' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param properties - properties of the breakpoint.
+ """
+ pass
+
+class DoneGetStatus(object):
+ "Call back interface for 'getStatus' command."
+ def doneGetStatus(self, token, error, status):
+ """
+ Called when 'getStatus' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param status - status of the breakpoint.
+ """
+ pass
+
+class DoneGetCapabilities(object):
+ "Call back interface for 'getCapabilities' command."
+ def doneGetCapabilities(self, token, error, capabilities):
+ """
+ Called when 'getCapabilities' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param capabilities - breakpoints service capabilities description.
+ """
+ pass
+
+class BreakpointsListener(object):
+ """
+ Breakpoints service events listener.
+ Note that contextAdded, contextChanged and contextRemoved events carry exactly same set
+ of breakpoint properties that was sent by a client to a target. The purpose of these events is to
+ let all clients know about breakpoints that were created by other clients.
+ """
+
+ def breakpointStatusChanged(self, id, status):
+ """
+ Called when breakpoint status changes.
+ @param id - unique breakpoint identifier.
+ @param status - breakpoint status.
+ """
+ pass
+
+ def contextAdded(self, bps):
+ """
+ Called when a new breakpoints are added.
+ @param bps - array of breakpoints.
+ """
+ pass
+
+ def contextChanged(self, bps):
+ """
+ Called when breakpoint properties change.
+ @param bps - array of breakpoints.
+ """
+ pass
+
+ def contextRemoved(self, ids):
+ """
+ Called when breakpoints are removed .
+ @param ids - array of breakpoint IDs.
+ """
+ pass
diff --git a/python/src/tcf/services/locator.py b/python/src/tcf/services/locator.py
new file mode 100644
index 000000000..5c7f69c65
--- /dev/null
+++ b/python/src/tcf/services/locator.py
@@ -0,0 +1,119 @@
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import exceptions
+from tcf import services, protocol, channel
+
+"""
+Locator service uses transport layer to search for peers and to collect data about
+peer's attributes and capabilities (services). Discovery mechanism depends on transport protocol
+and is part of that protocol handler. Targets, known to other hosts, can be found through
+remote instances of Locator service. Automatically discovered targets require no further
+configuration. Additional targets can be configured manually.
+
+Clients should use protocol.getLocator() to obtain local instance of locator,
+then locator.getPeers() can be used to get list of available peers (hosts and targets).
+"""
+
+# Peer data retention period in milliseconds.
+DATA_RETENTION_PERIOD = 60 * 1000;
+
+# Auto-configuration protocol version.
+CONF_VERSION = '2'
+
+# Auto-configuration command and response codes.
+CONF_REQ_INFO = 1
+CONF_PEER_INFO = 2
+CONF_REQ_SLAVES = 3
+CONF_SLAVES_INFO = 4
+
+NAME = "Locator"
+
+_locator = None
+def getLocator():
+ global _locator
+ if _locator is None:
+ _locator = LocatorService()
+ services.addServiceProvider(LocatorServiceProvider())
+ return _locator
+
+class LocatorService(services.Service):
+ def getName(self):
+ return NAME
+ def getPeers(self):
+ """
+ Get map (ID -> IPeer) of available peers (hosts and targets).
+ The method return cached (currently known to the framework) list of peers.
+ The list is updated according to event received from transport layer
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+ def redirect(self, peer, done):
+ """
+ Redirect this service channel to given peer using this service as a proxy.
+ @param peer - Peer ID or attributes map.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+ def sync(self, done):
+ """
+ Call back after TCF messages sent to this target up to this moment are delivered.
+ This method is intended for synchronization of messages
+ across multiple channels.
+
+ Note: Cross channel synchronization can reduce performance and throughput.
+ Most clients don't need channel synchronization and should not call this method.
+
+ @param done will be executed by dispatch thread after communication
+ messages are delivered to corresponding targets.
+
+ This is internal API, TCF clients should use module 'tcf.protocol'.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+ def addListener(self, listener):
+ "Add a listener for Locator service events."
+ assert listener
+ assert protocol.isDispatchThread()
+ _listeners.append(listener)
+ def removeListener(self, listener):
+ "Remove a listener for Locator service events."
+ assert protocol.isDispatchThread()
+ _listeners.remove(listener)
+
+class LocatorServiceProvider(services.ServiceProvider):
+ def getLocalService(self, _channel):
+ class LocatorCommandServer(channel.CommandServer):
+ def command(self, token, name, data):
+ _locator.command(_channel, token, name, data)
+ _channel.addCommandServer(_locator, LocatorCommandServer())
+ return [_locator]
+ def getServiceProxy(self, channel, service_name):
+ return None
+
+class DoneRedirect(object):
+ def doneRedirect(self, token, error):
+ pass
+
+class DoneSync(object):
+ def doneSync(self, token):
+ pass
+
+class LocatorListener(object):
+ def peerAdded(self, peer):
+ pass
+ def peerChanged(self, peer):
+ pass
+ def peerRemoved(self, id):
+ pass
+ def peerHeartBeat(self, id):
+ pass
+
+_listeners = []
+def getListeners():
+ return _listeners
diff --git a/python/src/tcf/services/remote/BreakpointsProxy.py b/python/src/tcf/services/remote/BreakpointsProxy.py
new file mode 100644
index 000000000..3458e52bd
--- /dev/null
+++ b/python/src/tcf/services/remote/BreakpointsProxy.py
@@ -0,0 +1,140 @@
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import exceptions
+from tcf import channel
+from tcf.services import breakpoints
+from tcf.channel.Command import Command
+
+class BPCommand(Command):
+ def __init__(self, service, cmd, cb, *args):
+ super(BPCommand, self).__init__(service.channel, service, cmd, args)
+ self.__cb = cb
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ self.__cb.doneCommand(self.token, error)
+
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "status":
+ assert len(args) == 2
+ self.listener.breakpointStatusChanged(args[0], args[1])
+ elif name == "contextAdded":
+ assert len(args) == 1
+ self.listener.contextAdded(args[0])
+ elif name == "contextChanged":
+ assert len(args) == 1
+ self.listener.contextChanged(args[0])
+ elif name == "contextRemoved":
+ assert len(args) == 1
+ self.listener.contextRemoved(args[0])
+ else:
+ raise IOError("Breakpoints service: unknown event: " + name);
+ except exceptions.Exception as x:
+ self.service.channel.terminate(x)
+
+class BreakpointsProxy(breakpoints.BreakpointsService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def set(self, properties, done):
+ return BPCommand(self, "set", done, properties).token
+
+ def add(self, properties, done):
+ return BPCommand(self, "add", done, properties).token
+
+ def change(self, properties, done):
+ return BPCommand(self, "change", done, properties).token
+
+ def disable(self, ids, done):
+ return BPCommand(self, "disable", done, ids).token
+
+ def enable(self, ids, done):
+ return BPCommand(self, "enable", done, ids).token
+
+ def remove(self, ids, done):
+ return BPCommand(self, "remove", done, ids).token
+
+ def getIDs(self, done):
+ service = self
+ class GetIDsCommand(Command):
+ def __init__(self):
+ super(GetIDsCommand, self).__init__(service.channel, service, "getIDs", None)
+ def done(self, error, args):
+ ids = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ ids = args[1]
+ done.doneGetIDs(self.token, error, ids)
+ return GetIDsCommand().token
+
+ def getProperties(self, id, done):
+ service = self
+ class GetPropertiesCommand(Command):
+ def __init__(self):
+ super(GetPropertiesCommand, self).__init__(service.channel, service, "getProperties", (id,))
+ def done(self, error, args):
+ map = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ map = args[1]
+ done.doneGetProperties(self.token, error, map)
+ return GetPropertiesCommand().token
+
+ def getStatus(self, id, done):
+ service = self
+ class GetStatusCommand(Command):
+ def __init__(self):
+ super(GetStatusCommand, self).__init__(service.channel, service, "getStatus", (id,))
+ def done(self, error, args):
+ map = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ map = args[1]
+ done.doneGetStatus(self.token, error, map)
+ return GetStatusCommand().token
+
+ def getCapabilities(self, id, done):
+ service = self
+ class GetCapabilitiesCommand(Command):
+ def __init__(self):
+ super(GetCapabilitiesCommand, self).__init__(service.channel, service, "getCapabilities", (id,))
+ def done(self, error, args):
+ map = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ map = args[1]
+ done.doneGetCapabilities(self.token, error, map)
+ return GetCapabilitiesCommand().token
+
+ def addListener(self, listener):
+ l = ChannelEventListener(self, listener)
+ self.channel.addEventListener(self, l)
+ self.listeners[listener] = l
+
+ def removeListener(self, listener):
+ l = self.listeners.get(listener)
+ if l:
+ del self.listeners[listener]
+ self.channel.removeEventListener(self, l)
diff --git a/python/src/tcf/services/remote/LocatorProxy.py b/python/src/tcf/services/remote/LocatorProxy.py
new file mode 100644
index 000000000..f95303bb5
--- /dev/null
+++ b/python/src/tcf/services/remote/LocatorProxy.py
@@ -0,0 +1,147 @@
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import exceptions
+from tcf import protocol, locator, peer, channel
+from tcf.channel.Command import Command
+
+class Peer(peer.TransientPeer):
+ def __init__(self, parent, attrs):
+ super(Peer, self).__init__(attrs)
+ self.parent = parent
+ def openChannel(self):
+ assert protocol.isDispatchThread()
+ c = self.parent.openChannel()
+ c.redirect(self.getID())
+ return c
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, proxy):
+ self.proxy = proxy
+ self.channel = proxy.channel
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "peerAdded":
+ assert len(args) == 1
+ peer = Peer(self.channel.getRemotePeer(), args[0])
+ if self.proxy.peers.get(peer.getID()):
+ protocol.log("Invalid peerAdded event", exceptions.Exception())
+ return
+ self.proxy.peers[peer.getID()] = peer
+ for l in self.proxy.listeners:
+ try:
+ l.peerAdded(peer)
+ except exceptions.Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ elif name == "peerChanged":
+ assert len(args) == 1
+ m = args[0]
+ if not m: raise exceptions.Exception("Locator service: invalid peerChanged event - no peer ID")
+ peer = self.proxy.peers.get(m.get(peer.ATTR_ID))
+ if not peer: return
+ self.proxy.peers[peer.getID()] = peer
+ for l in self.proxy.listeners:
+ try:
+ l.peerChanged(peer)
+ except exceptions.Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ elif name == "peerRemoved":
+ assert len(args) == 1
+ id = args[0]
+ peer = self.proxy.peers.get(id)
+ if not peer: return
+ del self.proxy.peers[id]
+ for l in self.proxy.listeners:
+ try:
+ l.peerRemoved(id)
+ except exceptions.Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ elif name == "peerHeartBeat":
+ assert len(args) == 1
+ id = args[0]
+ peer = self.proxy.peers.get(id)
+ if not peer: return
+ for l in self.proxy.listeners:
+ try:
+ l.peerHeartBeat(id)
+ except exceptions.Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ else:
+ raise exceptions.IOError("Locator service: unknown event: " + name)
+ except exceptions.Exception as x:
+ self.channel.terminate(x)
+
+class LocatorProxy(locator.LocatorService):
+ peers = {}
+ listeners = []
+ get_peers_done = False
+
+ def __init__(self, channel):
+ self.channel = channel;
+ self.event_listener = ChannelEventListener(self)
+ channel.addEventListener(self, self.event_listener)
+
+ def getPeers(self):
+ return self.peers
+
+ def redirect(self, peer, done):
+ service = self
+ class RedirectCommand(Command):
+ def __init__(self):
+ super(RedirectCommand, self).__init__(service.channel, service, "redirect", [peer])
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneRedirect(self.token, error)
+ return RedirectCommand().token
+
+ def sync(self, done):
+ service = self
+ class SyncCommand(Command):
+ def __init__(self):
+ super(SyncCommand, self).__init__(service.channel, service, "sync", None)
+ def done(self, error, args):
+ if error: service.channel.terminate(error)
+ done.doneSync(self.token)
+ return SyncCommand().token
+
+ def addListener(self, listener):
+ self.listeners.add(listener)
+ if not self.get_peers_done:
+ service = self
+ class GetPeersCommand(Command):
+ def __init__(self):
+ super(GetPeersCommand, self).__init__(service.channel, service, "getPeers", None)
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if error:
+ protocol.log("Locator error", error)
+ return
+ c = args[1]
+ if c:
+ for m in c:
+ id = m.get(peer.ATTR_ID)
+ if service.peers.get(id): continue;
+ peer = Peer(service.channel.getRemotePeer(), m)
+ service.peers[id] = peer
+ for l in service.listeners:
+ try:
+ l.peerAdded(peer)
+ except exceptions.Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ self.get_peers_done = True
+
+ def removeListener(self, listener):
+ self.listeners.remove(listener)
diff --git a/python/src/tcf/services/remote/RunControlProxy.py b/python/src/tcf/services/remote/RunControlProxy.py
new file mode 100644
index 000000000..6b1103542
--- /dev/null
+++ b/python/src/tcf/services/remote/RunControlProxy.py
@@ -0,0 +1,152 @@
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import exceptions
+from tcf import channel
+from tcf.services import runcontrol
+from tcf.channel.Command import Command
+
+class RunContext(runcontrol.RunControlContext):
+ def __init__(self, service, props):
+ super(RunContext, self).__init__(props)
+ self.service = service
+
+ def getState(self, done):
+ service = self.service
+ id = self.getID()
+ class GetStateCommand(Command):
+ def __init__(self):
+ super(GetStateCommand, self).__init__(service.channel, service, "getState", (id,))
+ def done(self, error, args):
+ susp = False
+ pc = None
+ reason = None
+ map = None
+ if not error:
+ assert len(args) == 5
+ error = self.toError(args[0])
+ susp = args[1]
+ if args[2]: pc = str(args[2])
+ reason = args[3]
+ map = args[4]
+ done.doneGetState(self.token, error, susp, pc, reason, map)
+ return GetStateCommand().token
+
+# def resume(self, mode, count, done):
+# return self._command("resume", [self.getID(), mode, count], done)
+
+ def resume(self, mode, count, params, done):
+ if not params:
+ return self._command("resume", (self.getID(), mode, count), done)
+ else:
+ return self._command("resume", (self.getID(), mode, count, params), done)
+
+ def suspend(self, done):
+ return self._command("suspend", (self.getID(),), done)
+
+ def terminate(self, done):
+ return self._command("terminate", (self.getID(),), done)
+
+ def _command(self, cmd, args, done):
+ service = self.service
+ class RCCommand(Command):
+ def __init__(self, cmd, args):
+ super(RCCommand, self).__init__(service.channel, service, cmd, args)
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneCommand(self.token, error)
+ return RCCommand(cmd, args).token
+
+ def __str__(self):
+ return "[Run Control Context %s]" % str(self._props)
+
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "contextSuspended":
+ assert len(args) == 4
+ self.listener.contextSuspended(args[0], args[1], args[2], args[3])
+ elif name == "contextResumed":
+ assert len(args) == 1
+ self.listener.contextResumed(args[0])
+ elif name == "contextAdded":
+ assert len(args) == 1
+ self.listener.contextAdded(args[0])
+ elif name == "contextChanged":
+ assert len(args) == 1
+ self.listener.contextChanged(args[0])
+ elif name == "contextRemoved":
+ assert len(args) == 1
+ self.listener.contextRemoved(args[0])
+ elif name == "contextException":
+ assert len(args) == 2
+ self.listener.contextException(args[0], args[1])
+ elif name == "containerSuspended":
+ assert len(args) == 5
+ self.listener.containerSuspended(args[0], args[1], args[2], args[3], args[4])
+ elif name == "containerResumed":
+ assert len(args) == 1
+ self.listener.containerResumed(args[0])
+ else:
+ raise IOError("RunControl service: unknown event: " + name);
+ except exceptions.Exception as x:
+ self.service.channel.terminate(x)
+
+class RunControlProxy(runcontrol.RunControlService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def addListener(self, listener):
+ l = ChannelEventListener(self, listener)
+ self.channel.addEventListener(self, l)
+ self.listeners[listener] = l
+
+ def removeListener(self, listener):
+ l = self.listeners.get(listener)
+ if l:
+ del self.listeners[listener]
+ self.channel.removeEventListener(self, l)
+
+ def getContext(self, context_id, done):
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (context_id,))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = RunContext(service, args[1])
+ done.doneGetContext(self.token, error, ctx)
+ return GetContextCommand().token
+
+ def getChildren(self, parent_context_id, done):
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
diff --git a/python/src/tcf/services/remote/StackTraceProxy.py b/python/src/tcf/services/remote/StackTraceProxy.py
new file mode 100644
index 000000000..350db8295
--- /dev/null
+++ b/python/src/tcf/services/remote/StackTraceProxy.py
@@ -0,0 +1,52 @@
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf.services import stacktrace
+from tcf.channel.Command import Command
+
+class StackTraceProxy(stacktrace.StackTraceService):
+ def __init__(self, channel):
+ self.channel = channel
+
+ def getChildren(self, parent_context_id, done):
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
+
+ def getContext(self, ids, done):
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (ids,))
+ def done(self, error, args):
+ ctxs = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[1])
+ ctxs = service.toContextArray(args[0])
+ done.doneGetContext(self.token, error, ctxs)
+ return GetContextCommand().token
+
+ def toContextArray(self, ctxProps):
+ if ctxProps is None: return None
+ ctxs = []
+ for props in ctxProps:
+ ctxs.append(stacktrace.StackTraceContext(props))
+ return ctxs
diff --git a/python/src/tcf/services/remote/SymbolsProxy.py b/python/src/tcf/services/remote/SymbolsProxy.py
new file mode 100644
index 000000000..7debc1bc7
--- /dev/null
+++ b/python/src/tcf/services/remote/SymbolsProxy.py
@@ -0,0 +1,115 @@
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import channel
+from tcf.services import symbols
+from tcf.channel.Command import Command
+
+
+class Context(symbols.Symbol):
+ def __init__(self, props):
+ super(Context, self).__init__(props)
+ self.value = channel.toByteArray(props.get(symbols.PROP_VALUE))
+
+ def getValue(self):
+ return self.value
+
+
+class SymbolsProxy(symbols.SymbolsService):
+ def __init__(self, channel):
+ self.channel = channel
+
+ def getContext(self, id, done):
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = Context(args[1])
+ done.doneGetContext(self.token, error, ctx)
+ return GetContextCommand().token
+
+ def getChildren(self, parent_context_id, done):
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
+
+ def find(self, context_id, ip, name, done):
+ service = self
+ class FindCommand(Command):
+ def __init__(self):
+ super(FindCommand, self).__init__(service.channel, service, "find", (context_id, ip, name))
+ def done(self, error, args):
+ id = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ id = args[1]
+ done.doneFind(self.token, error, id)
+ return FindCommand().token
+
+ def findByAddr(self, context_id, addr, done):
+ service = self
+ class FindByAddrCommand(Command):
+ def __init__(self):
+ super(FindByAddrCommand, self).__init__(service.channel, service, "findByAddr", (context_id, addr))
+ def done(self, error, args):
+ id = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ id = args[1]
+ done.doneFind(self.token, error, id)
+ return FindByAddrCommand().token
+
+ def list(self, context_id, done):
+ service = self
+ class ListCommand(Command):
+ def __init__(self):
+ super(ListCommand, self).__init__(service.channel, service, "list", (context_id,))
+ def done(self, error, args):
+ lst = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ lst = args[1]
+ done.doneList(self.token, error, lst)
+ return ListCommand().token
+
+ def findFrameInfo(self, context_id, address, done):
+ service = self
+ class FindFrameInfoCommand(Command):
+ def __init__(self):
+ super(FindFrameInfoCommand, self).__init__(service.channel, service, "findFrameInfo", (context_id, address))
+ def done(self, error, args):
+ address = None
+ size = None
+ fp_cmds = None
+ reg_cmds = None
+ if not error:
+ assert len(args) == 5
+ error = self.toError(args[0])
+ address, size, fp_cmds, reg_cmds = args[1:4]
+ done.doneList(self.token, error, address, size, fp_cmds, reg_cmds)
+ return FindFrameInfoCommand().token
diff --git a/python/src/tcf/services/remote/__init__.py b/python/src/tcf/services/remote/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/python/src/tcf/services/remote/__init__.py
diff --git a/python/src/tcf/services/runcontrol.py b/python/src/tcf/services/runcontrol.py
new file mode 100644
index 000000000..085f5e28f
--- /dev/null
+++ b/python/src/tcf/services/runcontrol.py
@@ -0,0 +1,480 @@
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import exceptions
+from tcf import services
+
+NAME = "RunControl"
+
+# Context property names.
+# Run control context ID */
+PROP_ID = "ID"
+
+# Context parent (owner) ID, for a thread it is same as process ID */
+PROP_PARENT_ID = "ParentID"
+
+# Context process (memory space) ID */
+PROP_PROCESS_ID = "ProcessID"
+
+# ID of a context that created this context */
+PROP_CREATOR_ID = "CreatorID"
+
+# Human readable context name */
+PROP_NAME = "Name"
+
+# true if the context is a container. Container can propagate run control commands to his children */
+PROP_IS_CONTAINER = "IsContainer"
+
+# true if context has execution state - can be suspended/resumed */
+PROP_HAS_STATE = "HasState"
+
+# Bit-set of RM_ values that are supported by the context */
+PROP_CAN_RESUME = "CanResume"
+
+# Bit-set of RM_ values that can be used with count > 1 */
+PROP_CAN_COUNT = "CanCount"
+
+# true if suspend command is supported by the context */
+PROP_CAN_SUSPEND = "CanSuspend"
+
+# true if terminate command is supported by the context */
+PROP_CAN_TERMINATE = "CanTerminate"
+
+# Context ID of a run control group that contains the context.
+# Members of same group are always suspended and resumed together:
+# resuming/suspending a context resumes/suspends all members of the group */
+PROP_RC_GROUP = "RCGroup"
+
+# Context resume modes.
+RM_RESUME = 0
+
+# Step over a single instruction.
+# If the instruction is a function call then don't stop until the function returns.
+
+RM_STEP_OVER = 1
+
+# Step a single instruction.
+# If the instruction is a function call then stop at first instruction of the function.
+RM_STEP_INTO = 2
+
+# Step over a single source code line.
+# If the line contains a function call then don't stop until the function returns.
+RM_STEP_OVER_LINE = 3
+
+# Step a single source code line.
+# If the line contains a function call then stop at first line of the function.
+RM_STEP_INTO_LINE = 4
+
+# Run until control returns from current function.
+RM_STEP_OUT = 5
+
+# Start running backwards.
+# Execution will continue until suspended by command or breakpoint.
+RM_REVERSE_RESUME = 6
+
+# Reverse of RM_STEP_OVER - run backwards over a single instruction.
+# If the instruction is a function call then don't stop until get out of the function.
+RM_REVERSE_STEP_OVER = 7
+
+# Reverse of RM_STEP_INTO.
+# This effectively "un-executes" the previous instruction
+RM_REVERSE_STEP_INTO = 8
+
+# Reverse of RM_STEP_OVER_LINE.
+# Resume backward execution of given context until control reaches an instruction that belongs
+# to a different source line.
+# If the line contains a function call then don't stop until get out of the function.
+# Error is returned if line number information not available.
+RM_REVERSE_STEP_OVER_LINE = 9
+
+# Reverse of RM_STEP_INTO_LINE,
+# Resume backward execution of given context until control reaches an instruction that belongs
+# to a different line of source code.
+# If a function is called, stop at the beginning of the last line of the function code.
+# Error is returned if line number information not available.
+RM_REVERSE_STEP_INTO_LINE = 10
+
+# Reverse of RM_STEP_OUT.
+# Resume backward execution of the given context until control reaches the point where the current function was called.
+RM_REVERSE_STEP_OUT = 11
+
+# Step over instructions until PC is outside the specified range.
+# Any function call within the range is considered to be in range.
+RM_STEP_OVER_RANGE = 12
+
+# Step instruction until PC is outside the specified range for any reason.
+RM_STEP_INTO_RANGE = 13
+
+# Reverse of RM_STEP_OVER_RANGE
+RM_REVERSE_STEP_OVER_RANGE = 14
+
+# Reverse of RM_STEP_INTO_RANGE
+RM_REVERSE_STEP_INTO_RANGE = 15
+
+# Run until the context becomes active - scheduled to run on a target CPU
+RM_UNTIL_ACTIVE = 16
+
+# Run reverse until the context becomes active
+RM_REVERSE_UNTIL_ACTIVE = 17
+
+# State change reason of a context.
+# Reason can be any text, but if it is one of predefined strings,
+# a generic client might be able to handle it better.
+REASON_USER_REQUEST = "Suspended"
+REASON_STEP = "Step"
+REASON_BREAKPOINT = "Breakpoint"
+REASON_EXCEPTION = "Exception"
+REASON_CONTAINER = "Container"
+REASON_WATCHPOINT = "Watchpoint"
+REASON_SIGNAL = "Signal"
+REASON_SHAREDLIB = "Shared Library"
+REASON_ERROR = "Error"
+
+# Optional parameters of context state.
+STATE_SIGNAL = "Signal"
+STATE_SIGNAL_NAME = "SignalName"
+STATE_SIGNAL_DESCRIPTION = "SignalDescription"
+STATE_BREAKPOINT_IDS = "BPs"
+STATE_PC_ERROR = "PCError"
+
+# Optional parameters of resume command.
+# Integer - starting address of step range, inclusive */
+RP_RANGE_START = "RangeStart"
+
+# Integer - ending address of step range, exclusive */
+RP_RANGE_END = "RangeEnd"
+
+class RunControlService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, id, done):
+ """
+ Retrieve context properties for given context ID.
+
+ @param id - context ID.
+ @param done - callback interface called when operation is completed.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, done):
+ """
+ Retrieve children of given context.
+
+ @param parent_context_id - parent context ID. Can be null -
+ to retrieve top level of the hierarchy, or one of context IDs retrieved
+ by previous getContext or getChildren commands.
+ @param done - callback interface called when operation is completed.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def addListener(self, listener):
+ """
+ Add run control event listener.
+ @param listener - run control event listener to add.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def removeListener(self, listener):
+ """
+ Remove run control event listener.
+ @param listener - run control event listener to remove.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+
+class RunControlError(exceptions.Exception):
+ pass
+
+class DoneGetState(object):
+ def doneGetState(self, token, error, suspended, pc, reason, params):
+ """
+ Called when getState command execution is complete.
+ @param token - pending command handle.
+ @param error - command execution error or null.
+ @param suspended - true if the context is suspended
+ @param pc - program counter of the context (if suspended).
+ @param reason - suspend reason (if suspended), see REASON_*.
+ @param params - additional target specific data about context state, see STATE_*.
+ """
+ pass
+
+class DoneCommand(object):
+ def doneCommand(self, token, error):
+ """
+ Called when run control command execution is complete.
+ @param token - pending command handle.
+ @param error - command execution error or null.
+ """
+ pass
+
+class DoneGetContext(object):
+ "Client callback interface for getContext()."
+ def doneGetContext(self, token, error, context):
+ """
+ Called when context data retrieval is done.
+ @param error - error description if operation failed, null if succeeded.
+ @param context - context data.
+ """
+ pass
+
+class DoneGetChildren(object):
+ "Client callback interface for getChildren()."
+ def doneGetChildren(self, token, error, context_ids):
+ """
+ Called when context list retrieval is done.
+ @param error - error description if operation failed, null if succeeded.
+ @param context_ids - array of available context IDs.
+ """
+ pass
+
+class RunControlContext(object):
+ """
+ A context corresponds to an execution thread, process, address space, etc.
+ A context can belong to a parent context. Contexts hierarchy can be simple
+ plain list or it can form a tree. It is up to target agent developers to choose
+ layout that is most descriptive for a given target. Context IDs are valid across
+ all services. In other words, all services access same hierarchy of contexts,
+ with same IDs, however, each service accesses its own subset of context's
+ attributes and functionality, which is relevant to that service.
+ """
+ def __init__(self, props):
+ self._props = props or {}
+
+ def getProperties(self):
+ """
+ Get context properties. See PROP_* definitions for property names.
+ Context properties are read only, clients should not try to modify them.
+ @return Map of context properties.
+ """
+ return self._props
+
+ def getID(self):
+ """
+ Retrieve context ID.
+ Same as getProperties().get('ID')
+ """
+ return self._props.get(PROP_ID)
+
+ def getParentID(self):
+ """
+ Retrieve parent context ID.
+ Same as getProperties().get('ParentID')
+ """
+ return self._props.get(PROP_PARENT_ID)
+
+ def getProcessID(self):
+ """
+ Retrieve context process ID.
+ Same as getProperties().get('ProcessID')
+ """
+ return self._props.get(PROP_PROCESS_ID)
+
+ def getCreatorID(self):
+ """
+ Retrieve context creator ID.
+ Same as getProperties().get('CreatorID')
+ """
+ return self._props.get(PROP_CREATOR_ID)
+
+ def getName(self):
+ """
+ Retrieve human readable context name.
+ Same as getProperties().get('Name')
+ """
+ return self._props.get(PROP_NAME)
+
+ def isContainer(self):
+ """
+ Utility method to read context property PROP_IS_CONTAINER.
+ Executing resume or suspend command on a container causes all its children to resume or suspend.
+ @return value of PROP_IS_CONTAINER.
+ """
+ return self._props.get(PROP_IS_CONTAINER)
+
+ def hasState(self):
+ """
+ Utility method to read context property PROP_HAS_STATE.
+ Only context that has a state can be resumed or suspended.
+ @return value of PROP_HAS_STATE.
+ """
+ return self._props.get(PROP_HAS_STATE)
+
+ def canSuspend(self):
+ """
+ Utility method to read context property PROP_CAN_SUSPEND.
+ Value 'true' means suspend command is supported by the context,
+ however the method does not check that the command can be executed successfully in
+ the current state of the context. For example, the command still can fail if context is
+ already suspended.
+ @return value of PROP_CAN_SUSPEND.
+ """
+ return self._props.get(PROP_CAN_SUSPEND)
+
+ def canResume(self, mode):
+ """
+ Utility method to read a 'mode' bit in context property PROP_CAN_RESUME.
+ Value 'true' means resume command is supported by the context,
+ however the method does not check that the command can be executed successfully in
+ the current state of the context. For example, the command still can fail if context is
+ already resumed.
+ @param mode - resume mode, see RM_*.
+ @return value of requested bit of PROP_CAN_RESUME.
+ """
+ b = self._props.get(PROP_CAN_RESUME) or 0
+ return (b & (1 << mode)) != 0
+
+ def canCount(self, mode):
+ """
+ Utility method to read a 'mode' bit in context property PROP_CAN_COUNT.
+ Value 'true' means resume command with count other then 1 is supported by the context,
+ however the method does not check that the command can be executed successfully in
+ the current state of the context. For example, the command still can fail if context is
+ already resumed.
+ @param mode - resume mode, see RM_*.
+ @return value of requested bit of PROP_CAN_COUNT.
+ """
+ b = self._props.get(PROP_CAN_COUNT) or 0
+ return (b & (1 << mode)) != 0
+
+ def canTerminate(self):
+ """
+ Utility method to read context property PROP_CAN_TERMINATE.
+ Value 'true' means terminate command is supported by the context,
+ however the method does not check that the command can be executed successfully in
+ the current state of the context. For example, the command still can fail if context is
+ already exited.
+ @return value of PROP_CAN_SUSPEND.
+ """
+ return self._props.get(PROP_CAN_TERMINATE)
+
+ def getRCGroup(self):
+ """
+ Utility method to read context property PROP_RC_GROUP -
+ context ID of a run control group that contains the context.
+ Members of same group are always suspended and resumed together:
+ resuming/suspending a context resumes/suspends all members of the group.
+ @return value of PROP_RC_GROUP.
+ """
+ return self._props.get(PROP_RC_GROUP)
+
+ def getState(self, done):
+ """
+ Send a command to retrieve current state of a context.
+ @param done - command result call back object.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def suspend(self, done):
+ """
+ Send a command to suspend a context.
+ Also suspends children if context is a container.
+ @param done - command result call back object.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+# def resume(self, mode, count, done):
+# """
+# Send a command to resume a context.
+# Also resumes children if context is a container.
+# @param mode - defines how to resume the context, see RM_*.
+# @param count - if mode implies stepping, defines how many steps to perform.
+# @param done - command result call back object.
+# @return pending command handle, can be used to cancel the command.
+# """
+# raise exceptions.NotImplementedError("Abstract method")
+
+ def resume(self, mode, count, params, done):
+ """
+ Send a command to resume a context.
+ Also resumes children if context is a container.
+ @param mode - defines how to resume the context, see RM_*.
+ @param count - if mode implies stepping, defines how many steps to perform.
+ @param params - resume parameters, for example, step range definition, see RP_*.
+ @param done - command result call back object.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def terminate(self, done):
+ """
+ Send a command to terminate a context.
+ @param done - command result call back object.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+class RunControlListener(object):
+ "Service events listener interface."
+ def contextAdded(self, contexts):
+ """
+ Called when new contexts are created.
+ @param contexts - array of new context properties.
+ """
+ pass
+ def contextChanged(self, contexts):
+ """
+ Called when a context properties changed.
+ @param contexts - array of new context properties.
+ """
+ pass
+ def contextRemoved(self, context_ids):
+ """
+ Called when contexts are removed.
+ @param context_ids - array of removed context IDs.
+ """
+ pass
+ def contextSuspended(self, context, pc, reason, params):
+ """
+ Called when a thread is suspended.
+ @param context - ID of a context that was suspended.
+ @param pc - program counter of the context, can be null.
+ @param reason - human readable description of suspend reason.
+ @param params - additional, target specific data about suspended context.
+ """
+ pass
+ def contextResumed(self, context):
+ """
+ Called when a thread is resumed.
+ @param context - ID of a context that was resumed.
+ """
+ pass
+ def containerSuspended(self, context, pc, reason, params, suspended_ids):
+ """
+ Called when target simultaneously suspends multiple threads in a container
+ (process, core, etc.).
+
+ @param context - ID of a context responsible for the event. It can be container ID or
+ any one of container children, for example, it can be thread that hit "suspend all" breakpoint.
+ Client expected to move focus (selection) to this context.
+ @param pc - program counter of the context.
+ @param reason - suspend reason, see REASON_*.
+ @param params - additional target specific data about context state, see STATE_*.
+ @param suspended_ids - full list of all contexts that were suspended.
+ """
+ pass
+ def containerResumed(self, context_ids):
+ """
+ Called when target simultaneously resumes multiple threads in a container (process,
+ core, etc.).
+
+ @param context_ids - full list of all contexts that were resumed.
+ """
+ pass
+ def contextException(self, context, msg):
+ """
+ Called when an exception is detected in a target thread.
+ @param context - ID of a context that caused an exception.
+ @param msg - human readable description of the exception.
+ """
+ pass
diff --git a/python/src/tcf/services/stacktrace.py b/python/src/tcf/services/stacktrace.py
new file mode 100644
index 000000000..ae8a6d5cf
--- /dev/null
+++ b/python/src/tcf/services/stacktrace.py
@@ -0,0 +1,160 @@
+#******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+#******************************************************************************
+
+import exceptions
+from tcf import services
+
+NAME = "StackTrace"
+
+#
+# Stack frame context property names.
+#
+PROP_ID = "ID" # String, stack frame ID
+PROP_PARENT_ID = "ParentID" # String, stack frame parent ID
+PROP_PROCESS_ID = "ProcessID" # String, stack frame process ID
+PROP_NAME = "Name" # String, human readable name
+PROP_TOP_FRAME = "TopFrame" # Boolean, true if the frame is top frame on a stack
+PROP_LEVEL = "Level" # Integer, stack frame level, starting from stack bottom
+PROP_FRAME_ADDRESS = "FP" # Number, stack frame memory address
+PROP_RETURN_ADDRESS = "RP" # Number, return address
+PROP_INSTRUCTION_ADDRESS = "IP" # Number, instruction pointer
+PROP_ARGUMENTS_COUNT = "ArgsCnt" # Integer, number of function arguments
+PROP_ARGUMENTS_ADDRESS = "ArgsAddr" # Number, memory address of function arguments
+
+class StackTraceService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, ids, done):
+ """
+ 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.
+
+ @param ids - array of context IDs.
+ @param done - call back interface called when operation is completed.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, done):
+ """
+ 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 thread
+ are stacks, and stack frames are deeper in the hierarchy - they can be
+ retrieved with additional getChildren commands.
+
+ The command will fail if parent thread is not suspended.
+ Client can use Run Control service to suspend a thread.
+
+ @param parent_context_id - parent context ID.
+ @param done - call back interface called when operation is completed.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+class DoneGetContext(object):
+ """
+ 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, null if succeeded.
+ @param contexts - array of context data or null if error.
+ """
+ pass
+
+class DoneGetChildren(object):
+ """
+ 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, null if succeeded.
+ @param context_ids - array of available context IDs.
+ Stack frames are ordered from stack bottom to top.
+ """
+ pass
+
+class StackTraceContext(object):
+ """
+ StackTraceContext represents stack trace objects - stacks and stack frames.
+ """
+ def __init__(self, props):
+ self._props = props or {}
+
+ def getID(self):
+ """
+ Get Context ID.
+ @return context ID.
+ """
+ return self._props.get(PROP_ID)
+
+ def getParentID(self):
+ """
+ Get parent context ID.
+ @return parent context ID.
+ """
+ return self._props.get(PROP_PARENT_ID)
+
+ def getName(self):
+ """
+ Get context name - if context represents a stack.
+ @return context name or null.
+ """
+ return self._props.get(PROP_NAME)
+
+ def getFrameAddress(self):
+ """
+ Get memory address of this frame.
+ @return address or None if not a stack frame.
+ """
+ return self._props.get(PROP_FRAME_ADDRESS)
+
+ def getReturnAddress(self):
+ """
+ Get program counter saved in this stack frame -
+ it is address of instruction to be executed when the function returns.
+ @return return address or null if not a stack frame.
+ """
+ return self._props.get(PROP_RETURN_ADDRESS)
+
+ def getInstructionAddress(self):
+ """
+ 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 null if not a stack frame.
+ """
+ return self._props.get(PROP_INSTRUCTION_ADDRESS)
+
+ def getArgumentsCount(self):
+ """
+ Get number of function arguments for this frame.
+ @return function arguments count.
+ """
+ return self._props.get(PROP_ARGUMENTS_COUNT)
+
+ def getArgumentsAddress(self):
+ """
+ Get address of function arguments area in memory.
+ @return function arguments address or null if not available.
+ """
+ return self._props.get(PROP_ARGUMENTS_ADDRESS, 0)
+
+ def getProperties(self):
+ """
+ Get complete map of context properties.
+ @return map of context properties.
+ """
+ return self._props
diff --git a/python/src/tcf/services/symbols.py b/python/src/tcf/services/symbols.py
new file mode 100644
index 000000000..3976956d3
--- /dev/null
+++ b/python/src/tcf/services/symbols.py
@@ -0,0 +1,381 @@
+#******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+#******************************************************************************
+
+import exceptions
+from tcf import services
+
+# Service name.
+NAME = "Symbols"
+
+class SymbolClass:
+ unknown = 0 # unknown symbol class
+ value = 1 # constant value
+ reference = 2 # variable data object
+ function = 3 # function body
+ type = 4 # a type
+
+class TypeClass:
+ unknown = 0 # unknown type class
+ cardinal = 1 # unsigned integer
+ integer = 2 # signed integer
+ real = 3 # float, double
+ pointer = 4 # pointer to anything.
+ array = 5 # array of anything.
+ composite = 6 # struct, union, or class.
+ enumeration = 7 # enumeration type.
+ function = 8 # function type.
+
+#
+# Symbol context property names.
+#
+PROP_ID = "ID"
+PROP_OWNER_ID = "OwnerID"
+PROP_UPDATE_POLICY = "UpdatePolicy"
+PROP_NAME = "Name"
+PROP_SYMBOL_CLASS = "Class"
+PROP_TYPE_CLASS = "TypeClass"
+PROP_TYPE_ID = "TypeID"
+PROP_BASE_TYPE_ID = "BaseTypeID"
+PROP_INDEX_TYPE_ID = "IndexTypeID"
+PROP_SIZE = "Size"
+PROP_LENGTH = "Length"
+PROP_LOWER_BOUND = "LowerBound"
+PROP_UPPER_BOUND = "UpperBound"
+PROP_OFFSET = "Offset"
+PROP_ADDRESS = "Address"
+PROP_VALUE = "Value"
+PROP_BIG_ENDIAN = "BigEndian"
+
+#
+# Symbol context properties update policies.
+#
+
+# Update policy "Memory Map": symbol properties become invalid when
+# memory map changes - when modules are loaded or unloaded.
+# Symbol OwnerID indicates memory space (process) that is invalidation events source.
+# Most static variables and types have this update policy.
+UPDATE_ON_MEMORY_MAP_CHANGES = 0
+
+# Update policy "Execution State": symbol properties become invalid when
+# execution state changes - a thread is suspended, resumed or exited.
+# Symbol OwnerID indicates executable context (thread) that is invalidation events source.
+# Most stack (auto) variables have this update policy.
+UPDATE_ON_EXE_STATE_CHANGES = 1
+
+
+class Symbol(object):
+ """
+ Symbol context interface.
+ """
+ def __init__(self, props):
+ self._props = props or {}
+
+ def getID(self):
+ """
+ Get symbol ID.
+ @return symbol ID.
+ """
+ return self._props.get(PROP_ID)
+
+ def getOwnerID(self):
+ """
+ Get symbol owner ID.
+ The owner can a thread or memory space (process).
+ Certain changes in owner state can invalidate cached symbol properties,
+ see getUpdatePolicy() and UPDATE_*.
+ """
+ return self._props.get(PROP_OWNER_ID)
+
+ def getUpdatePolicy(self):
+ """
+ Get symbol properties update policy ID.
+ Symbol properties can change during program execution.
+ If a client wants to cache symbols, it should invalidate cached data
+ according to update policies of cached symbols.
+ @return symbol update policy ID, see UPDATE_*
+ """
+ return self._props.get(PROP_UPDATE_POLICY)
+
+ def getName(self):
+ """
+ Get symbol name.
+ @return symbol name or null.
+ """
+ return self._props.get(PROP_NAME)
+
+ def getSymbolClass(self):
+ """
+ Get symbol class.
+ @return symbol class.
+ """
+ return self._props.get(PROP_SYMBOL_CLASS)
+
+ def getTypeClass(self):
+ """
+ Get symbol type class.
+ @return type class.
+ """
+ return self._props.get(PROP_TYPE_CLASS)
+
+ def getTypeID(self):
+ """
+ Get type ID.
+ If the symbol is a type and not a 'typedef', return same as getID().
+ @return type ID.
+ """
+ return self._props.get(PROP_TYPE_ID)
+
+ def getBaseTypeID(self):
+ """
+ Get base type ID.
+ If this symbol is a
+ pointer type - return pointed type
+ array type - return element type
+ function type - return function result type
+ class type - return base class
+ otherwise return null.
+ @return type ID.
+ """
+ return self._props.get(PROP_BASE_TYPE_ID)
+
+ def getIndexTypeID(self):
+ """
+ Get index type ID.
+ If this symbol is a
+ array type - return array index type
+ otherwise return null.
+ @return type ID.
+ """
+ return self._props.get(PROP_INDEX_TYPE_ID)
+
+ def getSize(self):
+ """
+ Return value size of the symbol (or type).
+ @return size in bytes.
+ """
+ return self._props.get(PROP_SIZE, 0)
+
+ def getLength(self):
+ """
+ If symbol is an array type - return number of elements.
+ @return number of elements.
+ """
+ return self._props.get(PROP_LENGTH, 0)
+
+ def getLowerBound(self):
+ """
+ If symbol is an array type - return array index lower bound.
+ @return lower bound.
+ """
+ return self._props.get(PROP_LOWER_BOUND)
+
+ def getUpperBound(self):
+ """
+ If symbol is an array type - return array index upper bound.
+ @return upper bound.
+ """
+ return self._props.get(PROP_UPPER_BOUND)
+
+ def getOffset(self):
+ """
+ Return offset from 'this' for member of class, struct or union.
+ @return offset in bytes.
+ """
+ return self._props.get(PROP_OFFSET, 0)
+
+ def getAddress(self):
+ """
+ Return address of the symbol.
+ @return address or null.
+ """
+ return self._props.get(PROP_ADDRESS)
+
+ def getValue(self):
+ """
+ If symbol is a constant object, return its value.
+ @return symbol value as array of bytes.
+ """
+ return self._props.get(PROP_VALUE)
+
+ def isBigEndian(self):
+ """
+ Get symbol values endianness.
+ @return true if symbol is big-endian.
+ """
+ return self._props.get(PROP_BIG_ENDIAN, False)
+
+ def getProperties(self):
+ """
+ Get complete map of context properties.
+ @return map of context properties.
+ """
+ return self._props
+
+class SymbolsService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, id, done):
+ """
+ Retrieve symbol context info for given symbol ID.
+ @see Symbol
+
+ @param id - symbol context ID.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, done):
+ """
+ Retrieve children IDs for given parent ID.
+ Meaning of the operation depends on parent kind:
+ 1. struct, union, or class type - get fields
+ 2. enumeration type - get enumerators
+
+ @param parent_context_id - parent symbol context ID.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def find(self, context_id, ip, name, done):
+ """
+ Search symbol with given name in given context.
+ The context can be memory space, process, thread or stack frame.
+
+ @param context_id - a search scope.
+ @param ip - instruction pointer - ignored if context_id is a stack frame ID
+ @param name - symbol name.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def findByAddr(self, context_id, addr, done):
+ """
+ Search symbol with given address in given context.
+ The context can be memory space, process, thread or stack frame.
+
+ @param context_id - a search scope.
+ @param addr - symbol address.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def list(self, context_id, done):
+ """
+ List all symbols in given context.
+ The context can be a stack frame.
+
+ @param context_id - a scope.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+ def findFrameInfo(self, context_id, address, done):
+ """
+ Retrieve stack tracing commands for given instruction address in a context memory.
+ @param context_id - exacutable context ID.
+ @param address - instruction address.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise exceptions.NotImplementedError("Abstract method")
+
+class DoneGetContext(object):
+ """
+ Client call back interface for getContext().
+ """
+ def doneGetContext(self, token, error, context):
+ """
+ Called when context data retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, null if succeeded.
+ @param context - context properties.
+ """
+ pass
+class DoneGetChildren(object):
+ """
+ Client call back interface for getChildren().
+ """
+ def doneGetChildren(self, token, error, context_ids):
+ """
+ Called when context list retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, null if succeeded.
+ @param context_ids - array of available context IDs.
+ """
+ pass
+
+class DoneFind(object):
+ """
+ Client call back interface for find().
+ """
+ def doneFind(self, token, error, symbol_id):
+ """
+ Called when symbol search is done.
+ @param token - command handle.
+ @param error - error description if operation failed, null if succeeded.
+ @param symbol_id - symbol ID.
+ """
+ pass
+
+class DoneList(object):
+ """
+ Client call back interface for list().
+ """
+ def doneList(self, token, error, symbol_ids):
+ """
+ Called when symbol list retrieval is done.
+ @param token - command handle.
+ @param error - error description if operation failed, null if succeeded.
+ @param symbol_ids - array of symbol IDs.
+ """
+
+
+#
+# Command codes that are used to calculate frame pointer and register values during stack tracing.
+#
+
+# Load a number to the evaluation stack. Command argument is the number.
+CMD_NUMBER = 1
+
+# Load a register value to the evaluation stack. Command argument is the register ID.
+CMD_REGISTER = 2
+
+# Load frame address to the evaluation stack.
+CMD_FP = 3
+
+# Read memory at address on the top of the evaluation stack. Command arguments are
+# the value size (Number) and endianness (Boolean, false - little-endian, true - big-endian).
+CMD_DEREF = 4
+
+# Add two values on top of the evaluation stack
+CMD_ADD = 5
+
+class DoneFindFrameInfo(object):
+ """
+ Client call back interface for findFrameInfo().
+ """
+ def doneFindFrameInfo(self, token, error, address, size, fp_cmds, reg_cmds):
+ """
+ Called when stack tracing information retrieval is done.
+ @param token - command handle.
+ @param error - error description if operation failed, null if succeeded.
+ @param address - start of instruction address range
+ @param size - size of instruction address range
+ @param fp_cmds - commands to calculate stack frame pointer
+ @param reg_cmds - map register IDs -> commands to calculate register values
+ """
+ pass

Back to the top