/*******************************************************************************
* Copyright (c) 2007, 2015 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
*******************************************************************************/
package org.eclipse.tcf.services;
import java.util.Collection;
import java.util.Map;
import org.eclipse.tcf.protocol.IService;
import org.eclipse.tcf.protocol.IToken;
/**
* IMemory service provides basic operations to read/write memory on a target.
*
* The service represents memory addresses in number of bytes, regardless of actual addressable unit size.
* Clients can translate between byte and word addresses using value of "AddressableUnitSize".
* Byte is 8 bits.
*
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface IMemory extends IService {
static final String NAME = "Memory";
/**
* Context property names.
*/
static final String
PROP_ID = "ID", /** String, ID of the context, same as getContext command argument */
PROP_PARENT_ID = "ParentID", /** String, ID of a parent context */
PROP_PROCESS_ID = "ProcessID", /** String, process ID, see Processes service */
PROP_BIG_ENDIAN = "BigEndian", /** Boolean, true if memory is big-endian */
PROP_ADDRESS_SIZE = "AddressSize", /** Number, size of memory address in bytes */
PROP_NAME = "Name", /** String, name of the context, can be used for UI purposes */
PROP_START_BOUND = "StartBound", /** Number, lowest address (inclusive) which is valid for the context */
PROP_END_BOUND = "EndBound", /** Number, highest address (inclusive) which is valid for the context */
PROP_ACCESS_TYPES = "AccessTypes"; /** Array of String, the access types allowed for this context */
/** @since 1.3*/
static final String
PROP_ADDRESSABLE_UNIT_SIZE = "AddressableUnitSize", /** Number, addressable unit size in number of bytes */
PROP_DEFAULT_WORD_SIZE = "DefaultWordSize"; /** Number, default word size in number of bytes */
/**
* Values of "AccessTypes".
* Target system can support multiple different memory access types, like instruction and data access.
* Different access types can use different logic for address translation and memory mapping, so they can
* end up accessing different data bits, even if address is the same.
* Each distinct access type should be represented by separate memory context.
* A memory context can represent multiple access types if they are equivalent - all access same memory bits.
* Same data bits can be exposed through multiple memory contexts.
*/
static final String
ACCESS_INSTRUCTION = "instruction", /** Context represent instructions fetch access */
ACCESS_DATA = "data", /** Context represents data access */
ACCESS_IO = "io", /** Context represents IO peripherals */
ACCESS_USER = "user", /** Context represents a user (e.g. application running in Linux) view to memory */
ACCESS_SUPERVISOR = "supervisor", /** Context represents a supervisor (e.g. Linux kernel) view to memory */
ACCESS_HYPERVISOR = "hypervisor", /** Context represents a hypervisor view to memory */
ACCESS_VIRTUAL = "virtual", /** Context uses virtual addresses */
ACCESS_PHYSICAL = "physical", /** Context uses physical addresses */
ACCESS_CACHE = "cache", /** Context is a cache */
ACCESS_TLB = "tlb"; /** Context is a TLB memory */
/**
* Retrieve context info for given context ID.
*
* @param id - context ID.
* @param done - call back interface called when operation is completed.
* @return - pending command handle.
*/
IToken getContext(String id, DoneGetContext done);
/**
* Client call back interface for getContext().
*/
interface DoneGetContext {
/**
* Called when context data retrieval is done.
* @param error - error description if operation failed, null if succeeded.
* @param context - context data.
*/
void doneGetContext(IToken token, Exception error, MemoryContext context);
}
/**
* Retrieve contexts available for memory commands.
* 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.
*
* @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 getChildren commands.
* @param done - call back interface called when operation is completed.
* @return - pending command handle.
*/
IToken getChildren(String parent_context_id, DoneGetChildren done);
/**
* Client call back interface for getChildren().
*/
interface DoneGetChildren {
/**
* 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.
*/
void doneGetChildren(IToken token, Exception error, String[] context_ids);
}
/**
* Memory access mode:
* Carry on when some of the memory cannot be accessed and
* return MemoryError at the end if any of the bytes
* were not processed correctly.
*/
final static int MODE_CONTINUEONERROR = 0x1;
/**
* Memory access mode:
* Verify result of memory operations (by reading and comparing).
*/
final static int MODE_VERIFY = 0x2;
/**
* @noimplement This interface is not intended to be implemented by clients.
*/
interface MemoryContext {
/**
* Get context ID.
* @return context ID.
*/
String getID();
/**
* Get parent context ID.
* @return parent ID.
*/
String getParentID();
/**
* Get process ID, if applicable.
* @return process ID.
*/
String getProcessID();
/**
* Get memory endianness.
* @return true if memory is big-endian.
*/
boolean isBigEndian();
/**
* Get memory address size.
* @return number of bytes used to store memory address value.
*/
int getAddressSize();
/**
* Get memory context name.
* The name can be used for UI purposes.
* @return context name.
*/
String getName();
/**
* Get lowest address (inclusive) which is valid for the context.
* @return lowest address.
*/
Number getStartBound();
/**
* Get highest address (inclusive) which is valid for the context.
* @return highest address.
*/
Number getEndBound();
/**
* Get the access types allowed for this context.
* @return collection of access type names.
*/
Collection<String> getAccessTypes();
/**
* Get this memory context's addressable unit size in number of bytes.
* The addressable size indicates the minimum number of bytes that
* can be retrieved as a single unit.
* @return addressable unit size in bytes.
* @since 1.3
*/
int getAddressableUnitSize();
/**
* Get default word size in number of bytes.
* The size is supposed to be used as the default memory view word representation.
* Returns zero is word size is unknown.
* @return word size in bytes.
* @since 1.3
*/
int getDefaultWordSize();
/**
* Get context properties.
* @return all available context properties.
*/
Map<String,Object> getProperties();
/**
* Set target memory.
* If 'word_size' is 0 it means client does not care about word size.
*/
IToken set(Number addr, int word_size, byte[] buf,
int offs, int size, int mode, DoneMemory done);
/**
* Read target memory.
*/
IToken get(Number addr, int word_size, byte[] buf,
int offs, int size, int mode, DoneMemory done);
/**
* Fill target memory with given pattern.
* 'size' is number of bytes to fill.
*/
IToken fill(Number addr, int word_size, byte[] value,
int size, int mode, DoneMemory done);
}
/**
* Client call back interface for set(), get() and fill() commands.
*/
interface DoneMemory {
public void doneMemory(IToken token, MemoryError error);
}
class MemoryError extends Exception {
private static final long serialVersionUID = 1L;
public MemoryError(String msg) {
super(msg);
}
}
/**
* ErrorOffset interface can be implemented by MemoryError object,
* which is returned by get, set and fill commands.
*
* get/set/fill () returns this exception when reading failed
* for some but not all bytes, and MODE_CONTINUEONERROR
* has been set in mode. (For example, when only part of the request
* translates to valid memory addresses.)
* Exception.getMessage can be used for generalized message of the
* possible reasons of partial memory operation.
*/
interface ErrorOffset {
// Error may have per byte information
final static int
BYTE_VALID = 0x00,
BYTE_UNKNOWN = 0x01, // e.g. out of range
BYTE_INVALID = 0x02,
BYTE_CANNOT_READ = 0x04,
BYTE_CANNOT_WRITE = 0x08;
final static String
RANGE_KEY_ADDR = "addr",
RANGE_KEY_SIZE = "size",
RANGE_KEY_STAT = "stat",
RANGE_KEY_MSG = "msg";
int getStatus(int offset);
/**
* Returns the detail message string about the
* byte associated with specified location.
* @return the detail error message string.
*/
String getMessage(int offset);
}
/**
* Add memory service event listener.
* @param listener - event listener implementation.
*/
void addListener(MemoryListener listener);
/**
* Remove memory service event listener.
* @param listener - event listener implementation.
*/
void removeListener(MemoryListener listener);
/**
* Memory event listener is notified when memory context hierarchy
* changes, and when memory is modified by memory service commands.
*/
interface MemoryListener {
/**
* Called when a new memory access context(s) is created.
*/
void contextAdded(MemoryContext[] contexts);
/**
* Called when a memory access context(s) properties changed.
*/
void contextChanged(MemoryContext[] contexts);
/**
* Called when memory access context(s) is removed.
*/
void contextRemoved(String[] context_ids);
/**
* Called when target memory content was changed and clients
* need to update themselves. Clients, at least, should invalidate
* corresponding cached memory data.
* Not every change is notified - it is not possible,
* only those, which are not caused by normal execution of the debuggee.
* 'addr' and 'size' can be null if unknown.
*/
void memoryChanged(String context_id, Number[] addr, long[] size);
}
}