1
/*******************************************************************************
2
* Copyright (c) 2002, 2005 QNX Software Systems and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* QNX Software Systems - Initial API and implementation
10
*******************************************************************************/
12
package org.eclipse.cdt.debug.mi.core.cdi.model;
14
import java.math.BigInteger;
16
import org.eclipse.cdt.debug.core.cdi.CDIException;
17
import org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlock;
18
import org.eclipse.cdt.debug.mi.core.MIException;
19
import org.eclipse.cdt.debug.mi.core.MIFormat;
20
import org.eclipse.cdt.debug.mi.core.MISession;
21
import org.eclipse.cdt.debug.mi.core.cdi.CdiResources;
22
import org.eclipse.cdt.debug.mi.core.cdi.ExpressionManager;
23
import org.eclipse.cdt.debug.mi.core.cdi.MI2CDIException;
24
import org.eclipse.cdt.debug.mi.core.cdi.MemoryManager;
25
import org.eclipse.cdt.debug.mi.core.cdi.RegisterManager;
26
import org.eclipse.cdt.debug.mi.core.cdi.Session;
27
import org.eclipse.cdt.debug.mi.core.cdi.VariableManager;
28
import org.eclipse.cdt.debug.mi.core.command.CommandFactory;
29
import org.eclipse.cdt.debug.mi.core.command.MIDataWriteMemory;
30
import org.eclipse.cdt.debug.mi.core.output.MIDataReadMemoryInfo;
31
import org.eclipse.cdt.debug.mi.core.output.MIInfo;
32
import org.eclipse.cdt.debug.mi.core.output.MIMemory;
36
public class MemoryBlock extends CObject implements ICDIMemoryBlock {
42
private MIDataReadMemoryInfo mem;
43
private int fWordSize;
44
private BigInteger cStartAddress; //cached start address
45
private byte[] cBytes; //cached bytes
46
private int[] badOffsets;
47
private boolean fIsLittleEndian;
49
public MemoryBlock(Target target, String exp, int wordSize, boolean isLittle, MIDataReadMemoryInfo info) {
54
fIsLittleEndian = isLittle;
55
setMIDataReadMemoryInfo(info);
59
* @return the expression use to create the block.
61
public String getExpression() {
66
* @return the size of each memory word in bytes.
68
public int getWordSize() {
73
* Reset the internal MIDataReadMemoryInfo. All modifications into mem info should be done
76
public void setMIDataReadMemoryInfo(MIDataReadMemoryInfo m) {
77
cStartAddress = MIFormat.getBigInteger(m.getAddress());
83
* @return the internal MIDataReadMemoryInfo.
85
public MIDataReadMemoryInfo getMIDataReadMemoryInfo() {
90
* @return true if any address in the array is within the block.
92
public boolean contains(BigInteger[] adds) {
93
for (int i = 0; i < adds.length; i++) {
94
if (contains(adds[i])) {
102
* @return true if the address is within the block.
104
public boolean contains(BigInteger addr) {
105
BigInteger start = getStartAddress();
106
long length = getLength();
107
if ( start.compareTo(addr) <= 0 &&
108
addr.compareTo(start.add(BigInteger.valueOf(length))) <= 0 )
116
* Use by the EventManager to check fire events when doing refresh().
118
public boolean isDirty() {
123
* Use by the EventManager to check fire events when doing refresh().
125
public void setDirty(boolean d) {
132
private byte[] getBytes(MIDataReadMemoryInfo m) {
133
byte[] bytes = new byte[0];
141
MIMemory[] miMem = m.getMemories();
142
for (int i = 0; i < miMem.length; ++i) {
143
long[] data = miMem[i].getData();
144
if (data != null && data.length > 0) {
145
// int blen = bytes.length;
146
// byte[] newBytes = new byte[blen + data.length];
147
// System.arraycopy(bytes, 0, newBytes, 0, blen);
148
// for (int j = 0; j < data.length; ++j, ++blen) {
149
// newBytes[blen] = (byte)data[j];
152
for (int j = 0; j < data.length; ++j) {
153
byte[] bs = longToBytes(data[j]);
155
int blen = bytes.length;
156
byte[] newBytes = new byte[blen + bs.length];
157
System.arraycopy(bytes, 0, newBytes, 0, blen);
158
System.arraycopy(bs, 0, newBytes, blen, bs.length);
166
private int[] getBadOffsets(MIDataReadMemoryInfo m) {
167
int[] offsets = new int[0];
175
MIMemory[] miMem = m.getMemories();
176
for (int i = 0; i < miMem.length; i++) {
177
int[] data = miMem[i].getBadOffsets();
178
if (data.length > 0) {
179
int olen = offsets.length;
180
int[] newOffsets = new int[olen + data.length];
181
System.arraycopy(offsets, 0, newOffsets, 0, olen);
182
System.arraycopy(data, 0, newOffsets, olen, data.length);
183
offsets = newOffsets;
189
public byte[] getBytes() throws CDIException {
194
* @see org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlock#refresh()
196
public void refresh() throws CDIException {
197
Target target = (Target)getTarget();
198
MemoryManager mgr = ((Session)target.getSession()).getMemoryManager();
200
BigInteger[] addresses = mgr.update(this, null);
201
// Check if this affects other blocks.
202
if (addresses.length > 0) {
203
MemoryBlock[] blocks = mgr.getMemoryBlocks(target.getMISession());
204
for (int i = 0; i < blocks.length; i++) {
205
MemoryBlock block = blocks[i];
206
if (! block.equals(this) && block.contains(addresses)) {
207
block.setDirty(true);
208
mgr.update(block, null);
215
* @see org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlock#getLength()
217
public long getLength() {
219
// use this instead. If the wordSize
220
// given does not match the hardware,
221
// counting the bytes will be correct.
222
return getBytes().length;
223
} catch (CDIException e) {
226
return mem.getTotalBytes();
230
* @see org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlock#getStartAddress()
232
public BigInteger getStartAddress() {
233
return cStartAddress;
237
* @see org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlock#isFrozen()
239
public boolean isFrozen() {
244
* @see org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlock#setFrozen(boolean)
246
public void setFrozen(boolean frozen) {
247
this.frozen = frozen;
251
* @see org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlock#setValue(long, byte[])
253
public void setValue(long offset, byte[] bytes) throws CDIException {
254
if (offset >= getLength() || offset + bytes.length > getLength()) {
255
throw new CDIException(CdiResources.getString("cdi.model.MemoryBlock.Bad_Offset")); //$NON-NLS-1$
257
MISession miSession = ((Target)getTarget()).getMISession();
258
CommandFactory factory = miSession.getCommandFactory();
259
for (int i = 0; i < bytes.length; i++) {
260
long l = new Byte(bytes[i]).longValue() & 0xff;
261
String value = "0x" + Long.toHexString(l); //$NON-NLS-1$
262
MIDataWriteMemory mw = factory.createMIDataWriteMemory(offset + i,
263
expression, MIFormat.HEXADECIMAL, 1, value);
265
miSession.postCommand(mw);
266
MIInfo info = mw.getMIInfo();
268
throw new CDIException(CdiResources.getString("cdi.Common.No_answer")); //$NON-NLS-1$
270
} catch (MIException e) {
271
throw new MI2CDIException(e);
274
// If the assign was succesfull fire a MIChangedEvent() via refresh.
277
Target target = (Target)getTarget();
279
// If register manager is on autoupdate, update all registers
280
RegisterManager regMgr = ((Session)target.getSession()).getRegisterManager();
281
if (regMgr.isAutoUpdate()) {
282
regMgr.update(target);
285
// If expression manager is on autoupdate, update all expressions
286
ExpressionManager expMgr = ((Session)target.getSession()).getExpressionManager();
287
if (expMgr.isAutoUpdate()) {
288
expMgr.update(target);
291
// If variable manager is on autoupdate, update all variables.
292
VariableManager varMgr = ((Session)target.getSession()).getVariableManager();
293
if (varMgr.isAutoUpdate()) {
294
varMgr.update(target);
299
* @see org.eclipse.cdt.debug.core.cdi.model.ICDIMemoryBlock#getFlags(int)
301
public synchronized byte getFlags(int offset) {
302
if (offset < 0 || offset >= getLength()) {
303
throw new IndexOutOfBoundsException();
305
if (badOffsets == null) {
306
badOffsets = getBadOffsets(mem);
308
if (badOffsets != null) {
309
for (int i = 0; i < badOffsets.length; ++i) {
310
if (badOffsets[i] == offset) {
320
* We should use the wordSize ... but ...
321
* The problem: the user may not have the right wordsize
322
* For example on some DSP the user set the wordSize to be 1 byte
323
* but in fact GDB is reading 2 bytes.
324
* So let do some guessing since the data(long) may have a bigger value then one byte.
326
private byte[] longToBytes(long v) {
327
// Calculate the number of bytes needed
330
for (count = 1; (value /= 0x100) > 0; ++count)
333
// Reset the wordSize if incorrect.
334
if (fWordSize != count) {
338
byte[] bytes = new byte[count];
339
if (fIsLittleEndian) {
340
for (int i = count - 1; i >= 0; --i) {
341
int shift = i * count;
342
bytes[i] = (byte)((v >>> shift) & 0xFF);
344
// bytes[7] = (byte)((v >>> 56) & 0xFF);
345
// bytes[6] = (byte)((v >>> 48) & 0xFF);
346
// bytes[5] = (byte)((v >>> 40) & 0xFF);
347
// bytes[4] = (byte)((v >>> 32) & 0xFF);
348
// bytes[3] = (byte)((v >>> 24) & 0xFF);
349
// bytes[2] = (byte)((v >>> 16) & 0xFF);
350
// bytes[1] = (byte)((v >>> 8) & 0xFF);
351
// bytes[0] = (byte)((v >>> 0) & 0xFF);
353
for (int i = 0; i < count; ++i) {
354
int shift = (count - i - 1) * count;
355
bytes[i] = (byte)((v >>> shift) & 0xFF);
357
// bytes[0] = (byte)((v >>> 56) & 0xFF);
358
// bytes[1] = (byte)((v >>> 48) & 0xFF);
359
// bytes[2] = (byte)((v >>> 40) & 0xFF);
360
// bytes[3] = (byte)((v >>> 32) & 0xFF);
361
// bytes[4] = (byte)((v >>> 24) & 0xFF);
362
// bytes[5] = (byte)((v >>> 16) & 0xFF);
363
// bytes[6] = (byte)((v >>> 8) & 0xFF);
364
// bytes[7] = (byte)((v >>> 0) & 0xFF);