blob: 112757526586438ed1c7e793ddc70b4df67c86f5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 Kichwa Coders Ltd and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.cdt.debug.dap;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import org.eclipse.cdt.debug.dap.CDTDebugProtocol.MemoryContents;
import org.eclipse.cdt.debug.dap.CDTDebugProtocol.MemoryRequestArguments;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IMemoryBlockExtension;
import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
import org.eclipse.debug.core.model.MemoryByte;
public class MemoryBlock extends CDTDebugElement implements IMemoryBlockExtension {
private ArrayList<Object> connections = new ArrayList<>();
@SuppressWarnings("unused")
private boolean isEnabled;
@SuppressWarnings("unused")
private Object context;
private DapDebugTarget debugTarget;
private BigInteger bigBaseAddress;
private String expression;
public MemoryBlock(DapDebugTarget debugTarget, String expression, BigInteger bigBaseAddress, Object context) {
super(debugTarget);
this.debugTarget = debugTarget;
this.expression = expression;
this.bigBaseAddress = bigBaseAddress;
this.context = context;
}
@Override
public long getStartAddress() {
// Not implemented (obsoleted by IMemoryBlockExtension)
return 0;
}
@Override
public long getLength() {
// Not implemented (obsoleted by IMemoryBlockExtension)
return 0;
}
@Override
public byte[] getBytes() throws DebugException {
// Not implemented (obsoleted by IMemoryBlockExtension)
return new byte[0];
}
@Override
public boolean supportsValueModification() {
// TODO
return false;
}
@Override
public void setValue(long offset, byte[] bytes) throws DebugException {
// Not implemented (obsoleted by IMemoryBlockExtension)
}
@Override
public String getExpression() {
return expression;
}
@Override
public BigInteger getBigBaseAddress() throws DebugException {
return bigBaseAddress;
}
@Override
public BigInteger getMemoryBlockStartAddress() throws DebugException {
// Null indicates that memory can be retrieved at addresses lower than the block base address
return null;
}
@Override
public BigInteger getMemoryBlockEndAddress() throws DebugException {
// Null indicates that memory can be retrieved at addresses higher the block base address
return null;
}
@Override
public BigInteger getBigLength() throws DebugException {
// -1 indicates that memory block is unbounded
return BigInteger.valueOf(-1);
}
@Override
public int getAddressSize() throws DebugException {
// TODO Get this from backend
return 8;
}
@Override
public int getAddressableSize() throws DebugException {
// TODO Get this from backend
return 1;
}
@Override
public boolean supportBaseAddressModification() throws DebugException {
return false;
}
@Override
public boolean supportsChangeManagement() {
return false;
}
@Override
public void setBaseAddress(BigInteger address) throws DebugException {
// Not supported
}
@Override
public MemoryByte[] getBytesFromOffset(BigInteger offset, long units) throws DebugException {
return getBytesFromAddress(getBigBaseAddress().add(offset), units);
}
@Override
public MemoryByte[] getBytesFromAddress(BigInteger address, long units) throws DebugException {
MemoryRequestArguments memoryRequestArguments = new MemoryRequestArguments();
memoryRequestArguments.setAddress("0x" + address.toString(16)); //$NON-NLS-1$
memoryRequestArguments.setLength(units);
CompletableFuture<MemoryContents> memory = getDebugProtocolServer().memory(memoryRequestArguments);
MemoryContents body = complete(memory);
String resultAddress = body.getAddress();
String contents = body.getData();
BigInteger bigResultAddress;
BigInteger.valueOf(Long.decode(resultAddress));
try {
bigResultAddress = BigInteger.valueOf(Long.decode(resultAddress));
} catch (NumberFormatException nfexc) {
// TODO
bigResultAddress = address;
}
int numRequestedBytes = (int) (units * getAddressableSize());
MemoryByte[] bytes = new MemoryByte[numRequestedBytes];
int resultOffsetFromRequest = bigResultAddress.subtract(address).intValue();
for (int i = 0; i < resultOffsetFromRequest; i++) {
bytes[i] = new MemoryByte((byte) 0, (byte) (0 & ~MemoryByte.READABLE));
}
for (int i = resultOffsetFromRequest, k = 0; i < resultOffsetFromRequest + (contents.length() / 2)
&& i < numRequestedBytes; i++, k += 2) {
byte b = (byte) Integer.parseInt(contents.substring(k, k + 2), 16);
bytes[i] = new MemoryByte(b);
}
for (int i = resultOffsetFromRequest + (contents.length() / 2); i < numRequestedBytes; i++) {
bytes[i] = new MemoryByte((byte) 0, (byte) (0 & ~MemoryByte.READABLE));
}
return bytes;
}
@Override
public void setValue(BigInteger offset, byte[] bytes) throws DebugException {
// Not supported
}
@Override
public void dispose() throws DebugException {
// nothing to do yet
}
@Override
public IMemoryBlockRetrieval getMemoryBlockRetrieval() {
return debugTarget;
}
@Override
public void connect(Object client) {
if (!connections.contains(client))
connections.add(client);
if (connections.size() == 1)
enable();
}
@Override
public void disconnect(Object client) {
if (connections.contains(client))
connections.remove(client);
if (connections.size() == 0)
disable();
}
@Override
public Object[] getConnections() {
return connections.toArray();
}
private void enable() {
isEnabled = true;
}
private void disable() {
isEnabled = false;
}
}