From e2a14c751ff9bd6957d10de479c76147966fc6a3 Mon Sep 17 00:00:00 2001 From: Randy Rohrbach Date: Tue, 27 Oct 2009 18:29:04 +0000 Subject: [PATCH] Bugzilla 293480. --- .../cdt/dsf/debug/model/DsfMemoryBlock.java | 329 ++++++++++++------ 1 file changed, 217 insertions(+), 112 deletions(-) diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/model/DsfMemoryBlock.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/model/DsfMemoryBlock.java index 3f8873794db..d329e9027c0 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/model/DsfMemoryBlock.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/model/DsfMemoryBlock.java @@ -297,120 +297,230 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens return false; } - /* (non-Javadoc) - * @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBytesFromAddress(java.math.BigInteger, long) - */ - public MemoryByte[] getBytesFromAddress(BigInteger address, long units) throws DebugException { + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IMemoryBlockExtension#getBytesFromAddress(java.math.BigInteger, long) + */ + @SuppressWarnings("null") + public MemoryByte[] getBytesFromAddress(BigInteger address, long units) throws DebugException { - if (isUseCacheData() && fBlockAddress.compareTo(address) == 0 && units * getAddressableSize() <= fBlock.length) - return fBlock; - - MemoryByte[] newBlock = fetchMemoryBlock(address, units); - int newLength = (newBlock != null) ? newBlock.length : 0; + if (isUseCacheData() && fBlockAddress.compareTo(address) == 0 && units * getAddressableSize() <= fBlock.length) + return fBlock; + + MemoryByte[] newBlock = fetchMemoryBlock(address, units); + int newLength = (newBlock != null) ? newBlock.length : 0; - // If the retrieved block overlaps with the cached block, flag the changed bytes - // so they can be properly highlighted in the platform Memory view. - // Note: In the standard Memory view, the values are displayed in cells of 4 bytes - // (on 4-bytes address boundaries) and all 4 bytes have to be flagged so the - // cell is highlighted (and the delta sigh is shown). - if (fBlock != null && newLength > 0) { - switch (fBlockAddress.compareTo(address)) { - // Cached block begins before the retrieved block location - // If there is no overlap, there are no bytes to flag - case -1: - { - // Determine the distance between the cached and the - // requested block addresses - BigInteger bigDistance = address.subtract(fBlockAddress); + // If the retrieved block overlaps with the cached block, flag the changed bytes + // so they can be properly highlighted in the platform Memory view. + // Note: In the standard Memory view, the values are displayed in cells of 4 bytes + // (on 4-bytes address boundaries) and all 4 bytes have to be flagged so the + // cell is highlighted (and the delta sigh is shown). + if (fBlock != null && newLength > 0) { + switch (fBlockAddress.compareTo(address)) { + // Cached block begins before the retrieved block location + // + // <--- fLength --------------------------------------------------> + // +--------------------------------------------------------------+ + // | Cached data from previous retrieve | + // | | + // | <------------------ length ----------------------------->| + // | <------------------ newLength --------------------> | + // | +-------------------------------------------------+ | + // | | | | + // | | Newly retrieved data | | + // |<-+->+-------------------------------------------------+ | + // | | address | + // | | | + // | +--- bigDistance/distance | + // | | + // | <------------------ length ----------------------------->| + // | <------------------ newLength -------------------------->| + // | +--------------------------------------------------------+ + // | | | + // | | Newly retrieved data | + // |<-+->+--------------------------------------------------------+ + // | | address | + // | | | + // | +--- bigDistance/distance | + // | | + // | <------------------ length ----------------------------->| + // | <------------------ newLength ----------------------------------> + // | +---------------------------------------------------------------+ + // | | | + // | | Newly retrieved data | + // |<-+->+---------------------------------------------------------------+ + // | | address | + // | | | + // | +--- bigDistance/distance | + // | | + // +--------------------------------------------------------------+ + // fBlockAddress + case -1: + { + // Determine the distance between the cached and the + // requested block addresses + BigInteger bigDistance = address.subtract(fBlockAddress); - // If the distance does not exceed the length of the cached block, - // then there is some overlap between the blocks and we have to - // mark the changed bytes (if applicable) - if (bigDistance.compareTo(BigInteger.valueOf(fLength)) == -1) { - // Here we can reasonably assume that java integers are OK - int distance = bigDistance.intValue(); - int length = fLength - distance; + // If the distance does not exceed the length of the cached block, + // then there is some overlap between the blocks and we have to + // mark the changed bytes (if applicable) + if (bigDistance.compareTo(BigInteger.valueOf(fLength)) == -1) { + // Here we can reasonably assume that java integers are OK + int distance = bigDistance.intValue(); + int length = fLength - distance; + if ( length > newLength ) { + length = newLength; + } - // Work by cells of 4 bytes - for (int i = 0; i < length; i += 4) { - // Determine if any byte within the cell was modified - boolean changed = false; - for (int j = i; j < (i + 4) && j < length; j++) { - if ( j < fBlock.length ) { - newBlock[j].setFlags(fBlock[distance + j].getFlags()); - if (newBlock[j].getValue() != fBlock[distance + j].getValue()) - changed = true; - } - } - // If so, flag the whole cell as modified - if (changed) - for (int j = i; j < (i + 4) && j < length; j++) { - newBlock[j].setHistoryKnown(true); - newBlock[j].setChanged(true); - } - } - - } - break; - } + // Work by cells of 4 bytes + for (int i = 0; i < length && i + 4 < newLength; i += 4) { + // Determine if any byte within the cell was modified + boolean changed = false; + for (int j = i; j < (i + 4) && j < length; j++) { + if ( j < newLength ) { + newBlock[j].setFlags(fBlock[distance + j].getFlags()); + if (newBlock[j].getValue() != fBlock[distance + j].getValue()) { + changed = true; + } + } + } + // If so, flag the whole cell as modified + if (changed) { + for (int j = i; j < (i + 4) && j < length; j++) { + if ( j < newLength ) { + newBlock[j].setHistoryKnown(true); + newBlock[j].setChanged(true); + } + } + } + } + + } + break; + } - // Cached block begins before the retrieved block location - // If there is no overlap, there are no bytes to flag - // (this block of code is symmetric with the previous one) - case 0: - case 1: - { - // Determine the distance between the cached and the - // requested block addresses - BigInteger bigDistance = fBlockAddress.subtract(address); + // The cached block starts at the same address as the retrieved data + // or it starts after the retrieved block and the retrieved block runs + // in to it. + // + // Case 0: + // + // <--- fLength --------------------------------------------------> + // +--------------------------------------------------------------+ + // | Cached data from previous retrieve | + // | | + // |<-- length ----------------> | + // |<-- newLength -------------> | + // +---------------------------+ | + // | | | + // | Newly retrieve data | | + // +---------------------------+ | + // |address | + // | | + // |<--------------------- length ------------------------------->| + // |<--------------------- newLength ---------------------------->| + // +--------------------------------------------------------------+ + // | | + // | Newly retrieve data | + // +--------------------------------------------------------------+ + // |address | + // | | + // +--------------------------------------------------------------+ + // fBlockAddress + // bigDistance/distance = 0 + // + // Case 1: + // <--- fLength --------------------------------------------------> + // +--------------------------------------------------------------+ + // | Cached data from previous retrieve | + // | | + // |<-- length -----> | + // <-- newLength ----------> | + // +-----------------------+ | + // | | | + // | Newly retrieved data | | + // +-----------------------+ | + // address| | + // | | + // |<----------------------- length ----------------------------->| + // <------------------------------- newLength -------------------------->| + // +---------------------------------------------------------------------+ + // | | + // | Newly retrieved data | + // +---------------------------------------------------------------------+ + // address| | + // | | + // |<----------------------- length ----------------------------->| + // <------------------------------- newLength ---------------------------------> + // +---------------------------------------------------------------------------+ + // | | + // | Newly retrieved data | + // +---------------------------------------------------------------------------+ + // address| | + // <--+-->| | + // | +--------------------------------------------------------------+ + // | fBlockAddress + // +---bigDistance/distance + case 0: + case 1: + { + // Determine the distance between the cached and the + // requested block addresses + BigInteger bigDistance = fBlockAddress.subtract(address); - // If the distance does not exceed the length of the new block, - // then there is some overlap between the blocks and we have to - // mark the changed bytes (if applicable) - if (bigDistance.compareTo(BigInteger.valueOf(newLength)) == -1) { - // Here we can reasonably assume that java integers are OK - int distance = bigDistance.intValue(); - int length = newLength - distance; - - // Work by cells of 4 bytes - for (int i = 0; i < length; i += 4) { - // Determine if any byte within the cell was modified - boolean changed = false; - for (int j = i; j < (i + 4) && j < length; j++) { - if ( j < fBlock.length ) { - newBlock[distance + j].setFlags(fBlock[j].getFlags()); - if (newBlock[distance + j].getValue() != fBlock[j].getValue()) - changed = true; - } - } - // If so, flag the whole cell as modified - if (changed) - for (int j = i; j < (i + 4) && j < length; j++) { - newBlock[distance + j].setHistoryKnown(true); - newBlock[distance + j].setChanged(true); - } - } - } - break; - } + // If the distance does not exceed the length of the new block, + // then there is some overlap between the blocks and we have to + // mark the changed bytes (if applicable) + if (bigDistance.compareTo(BigInteger.valueOf(newLength)) == -1) { + // Here we can reasonably assume that java integers are OK + int distance = bigDistance.intValue(); + int length = newLength - distance; + if ( length > fBlock.length ) { + length = fBlock.length; + } + + // Work by cells of 4 bytes + for (int i = 0; i < length && distance + i + 4 < newLength; i += 4) { + // Determine if any byte within the cell was modified + boolean changed = false; + for (int j = i; j < (i + 4) && j < length; j++) { + if ( ( distance + j ) < newLength ) { + newBlock[distance + j].setFlags(fBlock[j].getFlags()); + if (newBlock[distance + j].getValue() != fBlock[j].getValue()) { + changed = true; + } + } + } + // If so, flag the whole cell as modified + if (changed) { + for (int j = i; j < (i + 4) && j < length; j++) { + if ( ( distance + j ) < newLength ) { + newBlock[distance + j].setHistoryKnown(true); + newBlock[distance + j].setChanged(true); + } + } + } + } + } + break; + } - default: - break; - } - } + default: + break; + } + } - // Update the internal state - fBlock = newBlock; - fBlockAddress = address; - fLength = newLength; - - if (fUpdatePolicy.equals(DsfMemoryBlock.UPDATE_POLICY_BREAKPOINT)) - fUseCachedData = true; - else if (fUpdatePolicy.equals(DsfMemoryBlock.UPDATE_POLICY_MANUAL)) - fUseCachedData = true; + // Update the internal state + fBlock = newBlock; + fBlockAddress = address; + fLength = newLength; + + if (fUpdatePolicy.equals(DsfMemoryBlock.UPDATE_POLICY_BREAKPOINT)) + fUseCachedData = true; + else if (fUpdatePolicy.equals(DsfMemoryBlock.UPDATE_POLICY_MANUAL)) + fUseCachedData = true; - return fBlock; - } + return fBlock; + } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IMemoryBlockExtension#setValue(java.math.BigInteger, byte[]) @@ -522,7 +632,6 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens else { drm.done(); } - } }; fRetrieval.getExecutor().execute(query); @@ -530,13 +639,9 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens try { return query.get(); } catch (InterruptedException e) { - throw new DebugException(new Status(IStatus.ERROR, - DsfPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, - "Error reading memory block (InterruptedException)", e)); //$NON-NLS-1$ + throw new DebugException(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Error reading memory block (InterruptedException)", e)); //$NON-NLS-1$ } catch (ExecutionException e) { - throw new DebugException(new Status(IStatus.ERROR, - DsfPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, - "Error reading memory block (ExecutionException)", e)); //$NON-NLS-1$ + throw new DebugException(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Error reading memory block (ExecutionException)", e)); //$NON-NLS-1$ } }