blob: 11ac2b15a8b9940adb641da2186c31733f6e1b8e [file] [log] [blame]
/*
*(c) Copyright QNX Software Systems Ltd. 2002.
* All Rights Reserved.
*
*/
package org.eclipse.cdt.debug.mi.core.cdi;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.debug.core.cdi.CDIException;
import org.eclipse.cdt.debug.core.cdi.ICDIMemoryManager;
import org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlock;
import org.eclipse.cdt.debug.mi.core.MIException;
import org.eclipse.cdt.debug.mi.core.MIFormat;
import org.eclipse.cdt.debug.mi.core.MISession;
import org.eclipse.cdt.debug.mi.core.cdi.model.MemoryBlock;
import org.eclipse.cdt.debug.mi.core.command.CommandFactory;
import org.eclipse.cdt.debug.mi.core.command.MIDataReadMemory;
import org.eclipse.cdt.debug.mi.core.event.MIEvent;
import org.eclipse.cdt.debug.mi.core.event.MIMemoryChangedEvent;
import org.eclipse.cdt.debug.mi.core.event.MIMemoryCreatedEvent;
import org.eclipse.cdt.debug.mi.core.output.MIDataReadMemoryInfo;
/**
*/
public class MemoryManager extends SessionObject implements ICDIMemoryManager {
List blockList;
boolean autoupdate;
public MemoryManager(Session session) {
super(session);
blockList = new ArrayList();
autoupdate = true;
}
/**
* This method will be call by the eventManager.processSuspended() every time the
* inferior comes to a Stop/Suspended. It will allow to look at the blocks that
* are registered and fired any event if changed.
* Note: Frozen blocks are not updated.
*
* @see org.eclipse.cdt.debug.core.cdi.ICDIMemoryManager#createMemoryBlock(long, int)
*/
public void update() {
Session session = (Session)getSession();
MISession mi = session.getMISession();
MemoryBlock[] blocks = listMemoryBlocks();
List eventList = new ArrayList(blocks.length);
for (int i = 0; i < blocks.length; i++) {
if (! blocks[i].isFrozen()) {
try {
update(blocks[i], eventList);
} catch (CDIException e) {
}
}
}
MIEvent[] events = (MIEvent[])eventList.toArray(new MIEvent[0]);
mi.fireEvents(events);
}
/**
* update one Block.
*/
public Long[] update(MemoryBlock block, List aList) throws CDIException {
MemoryBlock newBlock = cloneBlock(block);
boolean newAddress = ( newBlock.getStartAddress() != block.getStartAddress() );
Long[] array = compareBlocks(block, newBlock);
// Update the block MIDataReadMemoryInfo.
block.setMIDataReadMemoryInfo(newBlock.getMIDataReadMemoryInfo());
if (array.length > 0 || newAddress) {
if (aList != null) {
aList.add(new MIMemoryChangedEvent(array));
} else {
Session session = (Session)getSession();
MISession mi = session.getMISession();
mi.fireEvent(new MIMemoryChangedEvent(array));
}
}
return array;
}
/**
* @return the registers MemoryBlock.
*/
public MemoryBlock[] listMemoryBlocks() {
return (MemoryBlock[])blockList.toArray(new MemoryBlock[0]);
}
/**
* Compare two blocks and return an array of all _addresses_ that are different.
* This method is not smart it always assume that:
* oldBlock.getStartAddress() == newBlock.getStartAddress;
* oldBlock.getLength() == newBlock.getLength();
* @return Long[] array of modified addresses.
*/
Long[] compareBlocks (MemoryBlock oldBlock, MemoryBlock newBlock) throws CDIException {
byte[] oldBytes = oldBlock.getBytes();
byte[] newBytes = newBlock.getBytes();
List aList = new ArrayList(newBytes.length);
long diff = newBlock.getStartAddress() - oldBlock.getStartAddress();
if ( Math.abs( diff ) < newBytes.length ) {
for (int i = 0; i < newBytes.length; i++) {
if (i + (int)diff < oldBytes.length && i + (int)diff >= 0) {
if (oldBytes[i + (int)diff] != newBytes[i]) {
aList.add(new Long(newBlock.getStartAddress() + i));
}
}
}
}
return (Long[])aList.toArray(new Long[0]);
}
/**
* Use the same expression and length of the original block
* to create a new MemoryBlock. The new block is not register
* with the MemoryManager.
*/
MemoryBlock cloneBlock(MemoryBlock block) throws CDIException {
Session session = (Session)getSession();
String exp = block.getExpression();
MIDataReadMemoryInfo info = createMIDataReadMemoryInfo(exp, (int)block.getLength());
return new MemoryBlock(session.getCurrentTarget(), exp, info);
}
/**
* Post a -data-read-memory to gdb/mi.
*/
MIDataReadMemoryInfo createMIDataReadMemoryInfo(String exp, int length) throws CDIException {
Session session = (Session)getSession();
MISession mi = session.getMISession();
CommandFactory factory = mi.getCommandFactory();
MIDataReadMemory mem = factory.createMIDataReadMemory(0, exp, MIFormat.HEXADECIMAL, 1, 1, length, null);
try {
mi.postCommand(mem);
MIDataReadMemoryInfo info = mem.getMIDataReadMemoryInfo();
if (info == null) {
throw new CDIException("No answer");
}
return info;
} catch (MIException e) {
throw new MI2CDIException(e);
}
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIMemoryManager#createMemoryBlock(long, int)
*/
public ICDIMemoryBlock createMemoryBlock(long address, int length)
throws CDIException {
String addr = "0x" + Long.toHexString(address);
return createMemoryBlock(addr, length);
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIMemoryManager#createMemoryBlock(string, int)
*/
public ICDIMemoryBlock createMemoryBlock(String address, int length) throws CDIException {
Session session = (Session)getSession();
MIDataReadMemoryInfo info = createMIDataReadMemoryInfo(address, length);
ICDIMemoryBlock block = new MemoryBlock(session.getCurrentTarget(), address, info);
blockList.add(block);
MISession mi = session.getMISession();
mi.fireEvent(new MIMemoryCreatedEvent(block.getStartAddress(), block.getLength()));
return block;
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIMemoryManager#getBlocks()
*/
public ICDIMemoryBlock[] getMemoryBlocks() throws CDIException {
return (ICDIMemoryBlock[])listMemoryBlocks();
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIMemoryManager#removeAllBlocks()
*/
public void removeAllBlocks() throws CDIException {
blockList.clear();
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIMemoryManager#removeBlock(ICDIMemoryBlock)
*/
public void removeBlock(ICDIMemoryBlock memoryBlock) throws CDIException {
blockList.remove(memoryBlock);
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIMemoryManager#removeBlocks(ICDIMemoryBlock[])
*/
public void removeBlocks(ICDIMemoryBlock[] memoryBlocks)
throws CDIException {
for (int i = 0; i < memoryBlocks.length; i++) {
removeBlock(memoryBlocks[i]);
}
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIMemoryManager#isAutoUpdate()
*/
public boolean isAutoUpdate() {
return autoupdate;
}
/**
* @see org.eclipse.cdt.debug.core.cdi.ICDIMemoryManager#setAutoUpdate(boolean)
*/
public void setAutoUpdate(boolean update) {
autoupdate = update;
}
}