| /******************************************************************************* |
| * Copyright (c) 2005 The Regents of the University of California. |
| * This material was produced under U.S. Government contract W-7405-ENG-36 |
| * for Los Alamos National Laboratory, which is operated by the University |
| * of California for the U.S. Department of Energy. The U.S. Government has |
| * rights to use, reproduce, and distribute this software. NEITHER THE |
| * GOVERNMENT NOR THE UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR |
| * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified |
| * to produce derivative works, such modified software should be clearly marked, |
| * so as not to confuse it with the version available from LANL. |
| * |
| * Additionally, 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 |
| * |
| * LA-CC 04-115 |
| *******************************************************************************/ |
| package org.eclipse.ptp.debug.internal.core.pdi.model; |
| |
| import java.math.BigInteger; |
| |
| import org.eclipse.ptp.core.util.BitList; |
| import org.eclipse.ptp.debug.core.ExtFormat; |
| import org.eclipse.ptp.debug.core.pdi.IPDISession; |
| import org.eclipse.ptp.debug.core.pdi.PDIException; |
| import org.eclipse.ptp.debug.core.pdi.SessionObject; |
| import org.eclipse.ptp.debug.core.pdi.event.IPDIDataReadMemoryInfo; |
| import org.eclipse.ptp.debug.core.pdi.manager.IPDIExpressionManager; |
| import org.eclipse.ptp.debug.core.pdi.manager.IPDIMemoryManager; |
| import org.eclipse.ptp.debug.core.pdi.manager.IPDIRegisterManager; |
| import org.eclipse.ptp.debug.core.pdi.manager.IPDIVariableManager; |
| import org.eclipse.ptp.debug.core.pdi.model.IPDIMemory; |
| import org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock; |
| import org.eclipse.ptp.debug.core.pdi.request.IPDIDataWriteMemoryRequest; |
| |
| /** |
| * @author Clement chu |
| * |
| */ |
| public class MemoryBlock extends SessionObject implements IPDIMemoryBlock { |
| private IPDIDataReadMemoryInfo mem; |
| private int fWordSize; |
| private BigInteger pStartAddress; //cached start address |
| |
| private byte[] cBytes; //cached bytes |
| private int[] badOffsets; |
| private boolean fIsLittleEndian; |
| String expression; |
| boolean frozen; |
| |
| public MemoryBlock(IPDISession session, BitList tasks, String exp, int wordSize, boolean isLittle, IPDIDataReadMemoryInfo info) { |
| super(session, tasks); |
| expression = exp; |
| fWordSize = wordSize; |
| frozen = true; |
| fIsLittleEndian = isLittle; |
| setDataReadMemoryInfo(info); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#getBytes() |
| */ |
| public byte[] getBytes() throws PDIException { |
| return cBytes; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#getDataReadMemoryInfo() |
| */ |
| public IPDIDataReadMemoryInfo getDataReadMemoryInfo() { |
| return mem; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#getExpression() |
| */ |
| public String getExpression() { |
| return expression; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#getFlags(int) |
| */ |
| public synchronized byte getFlags(int offset) { |
| if (offset < 0 || offset >= getLength()) { |
| throw new IndexOutOfBoundsException(); |
| } |
| if (badOffsets == null) { |
| badOffsets = getBadOffsets(mem); |
| } |
| if (badOffsets != null) { |
| for (int i = 0; i < badOffsets.length; ++i) { |
| if (badOffsets[i] == offset) { |
| return 0; |
| } |
| } |
| } |
| return VALID; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#getLength() |
| */ |
| public long getLength() { |
| try { |
| return getBytes().length; |
| } catch (PDIException e) { |
| // ignore. |
| } |
| return mem.getTotalBytes(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#getStartAddress() |
| */ |
| public BigInteger getStartAddress() { |
| return pStartAddress; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#getWordSize() |
| */ |
| public int getWordSize() { |
| return fWordSize; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#isFrozen() |
| */ |
| public boolean isFrozen() { |
| return frozen; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#refresh() |
| */ |
| public void refresh() throws PDIException { |
| IPDIMemoryManager mgr = session.getMemoryManager(); |
| BigInteger[] addresses = mgr.update(this, null); |
| // Check if this affects other blocks. |
| if (addresses.length > 0) { |
| IPDIMemoryBlock[] blocks = mgr.getMemoryBlocks(getTasks()); |
| for (int i = 0; i < blocks.length; i++) { |
| MemoryBlock block = (MemoryBlock)blocks[i]; |
| if (! block.equals(this) && block.contains(addresses)) { |
| mgr.update(block, null); |
| } |
| } |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#setDataReadMemoryInfo(org.eclipse.ptp.debug.core.pdi.model.IPDIDataReadMemoryInfo) |
| */ |
| public void setDataReadMemoryInfo(IPDIDataReadMemoryInfo m) { |
| pStartAddress = ExtFormat.getBigInteger(m.getAddress()); |
| cBytes = getBytes(m); |
| mem = m; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#setFrozen(boolean) |
| */ |
| public void setFrozen(boolean frozen) { |
| this.frozen = frozen; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ptp.debug.core.pdi.model.IPDIMemoryBlock#setValue(long, byte[]) |
| */ |
| public void setValue(long offset, byte[] bytes) throws PDIException { |
| if (offset >= getLength() || offset + bytes.length > getLength()) { |
| throw new PDIException(getTasks(), "No bad offset found"); |
| } |
| for (int i = 0; i < bytes.length; i++) { |
| long l = new Byte(bytes[i]).longValue() & 0xff; |
| String value = "0x" + Long.toHexString(l); |
| IPDIDataWriteMemoryRequest request = session.getRequestFactory().getDataWriteMemoryRequest(getTasks(), offset + i, expression, ExtFormat.HEXADECIMAL, 1, value); |
| session.getEventRequestManager().addEventRequest(request); |
| request.waitUntilCompleted(getTasks()); |
| } |
| refresh(); |
| |
| IPDIRegisterManager regMgr = session.getRegisterManager(); |
| if (regMgr.isAutoUpdate()) { |
| regMgr.update(getTasks()); |
| } |
| |
| IPDIExpressionManager expMgr = session.getExpressionManager(); |
| if (expMgr.isAutoUpdate()) { |
| expMgr.update(getTasks()); |
| } |
| |
| IPDIVariableManager varMgr = session.getVariableManager(); |
| if (varMgr.isAutoUpdate()) { |
| varMgr.update(getTasks()); |
| } |
| } |
| |
| /** |
| * @param addr |
| * @return |
| */ |
| private boolean contains(BigInteger addr) { |
| BigInteger start = getStartAddress(); |
| long length = getLength(); |
| if ( start.compareTo(addr) <= 0 && addr.compareTo(start.add(BigInteger.valueOf(length))) <= 0 ) { |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * @param adds |
| * @return |
| */ |
| private boolean contains(BigInteger[] adds) { |
| for (int i = 0; i < adds.length; i++) { |
| if (contains(adds[i])) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * @param m |
| * @return |
| */ |
| private int[] getBadOffsets(IPDIDataReadMemoryInfo m) { |
| int[] offsets = new int[0]; |
| if (m == null) { |
| return offsets; |
| } |
| |
| IPDIMemory[] miMem = m.getMemories(); |
| for (int i = 0; i < miMem.length; i++) { |
| int[] data = miMem[i].getBadOffsets(); |
| if (data.length > 0) { |
| int olen = offsets.length; |
| int[] newOffsets = new int[olen + data.length]; |
| System.arraycopy(offsets, 0, newOffsets, 0, olen); |
| System.arraycopy(data, 0, newOffsets, olen, data.length); |
| offsets = newOffsets; |
| } |
| } |
| return offsets; |
| } |
| |
| /** |
| * @param m |
| * @return |
| */ |
| private byte[] getBytes(IPDIDataReadMemoryInfo m) { |
| byte[] bytes = new byte[0]; |
| if (m == null) { |
| return bytes; |
| } |
| |
| IPDIMemory[] miMem = m.getMemories(); |
| for (int i = 0; i < miMem.length; ++i) { |
| long[] data = miMem[i].getData(); |
| if (data != null && data.length > 0) { |
| for (int j = 0; j < data.length; ++j) { |
| byte[] bs = longToBytes(data[j]); |
| // grow the array |
| int blen = bytes.length; |
| byte[] newBytes = new byte[blen + bs.length]; |
| System.arraycopy(bytes, 0, newBytes, 0, blen); |
| System.arraycopy(bs, 0, newBytes, blen, bs.length); |
| bytes = newBytes; |
| } |
| } |
| } |
| return bytes; |
| } |
| |
| /** |
| * @param v |
| * @return |
| */ |
| private byte[] longToBytes(long v) { |
| // Calculate the number of bytes needed |
| int count = 1; |
| long value = v; |
| for (count = 1; (value /= 0x100) > 0; ++count) |
| ; |
| |
| // Reset the wordSize if incorrect. |
| if (fWordSize != count) { |
| fWordSize = count; |
| } |
| |
| byte[] bytes = new byte[count]; |
| if (fIsLittleEndian) { |
| for (int i = count - 1; i >= 0; --i) { |
| int shift = i * count; |
| bytes[i] = (byte)((v >>> shift) & 0xFF); |
| } |
| // bytes[7] = (byte)((v >>> 56) & 0xFF); |
| // bytes[6] = (byte)((v >>> 48) & 0xFF); |
| // bytes[5] = (byte)((v >>> 40) & 0xFF); |
| // bytes[4] = (byte)((v >>> 32) & 0xFF); |
| // bytes[3] = (byte)((v >>> 24) & 0xFF); |
| // bytes[2] = (byte)((v >>> 16) & 0xFF); |
| // bytes[1] = (byte)((v >>> 8) & 0xFF); |
| // bytes[0] = (byte)((v >>> 0) & 0xFF); |
| } else { |
| for (int i = 0; i < count; ++i) { |
| int shift = (count - i - 1) * count; |
| bytes[i] = (byte)((v >>> shift) & 0xFF); |
| } |
| // bytes[0] = (byte)((v >>> 56) & 0xFF); |
| // bytes[1] = (byte)((v >>> 48) & 0xFF); |
| // bytes[2] = (byte)((v >>> 40) & 0xFF); |
| // bytes[3] = (byte)((v >>> 32) & 0xFF); |
| // bytes[4] = (byte)((v >>> 24) & 0xFF); |
| // bytes[5] = (byte)((v >>> 16) & 0xFF); |
| // bytes[6] = (byte)((v >>> 8) & 0xFF); |
| // bytes[7] = (byte)((v >>> 0) & 0xFF); |
| } |
| return bytes; |
| } |
| } |