mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 542488: Memory view support
Change-Id: I8c3343f0ead46ab203d58f77370dd2dadda550ff
This commit is contained in:
parent
d7b7f10255
commit
bf327ec364
8 changed files with 667 additions and 2 deletions
|
@ -23,7 +23,11 @@ Require-Bundle: org.apache.commons.io,
|
|||
org.eclipse.lsp4e.debug,
|
||||
org.eclipse.debug.core,
|
||||
org.eclipse.debug.ui,
|
||||
org.eclipse.cdt.debug.core
|
||||
org.eclipse.cdt.debug.core,
|
||||
org.eclipse.lsp4j.debug,
|
||||
org.eclipse.lsp4j.jsonrpc.debug,
|
||||
com.google.guava,
|
||||
org.eclipse.xtext.xbase.lib
|
||||
Bundle-Vendor: %Bundle-Vendor
|
||||
Export-Package: org.eclipse.cdt.debug.dap
|
||||
Bundle-Activator: org.eclipse.cdt.debug.dap.Activator
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2019 Kichwa Coders 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 org.eclipse.lsp4e.debug.debugmodel.DSPDebugElement;
|
||||
import org.eclipse.lsp4e.debug.debugmodel.DSPDebugTarget;
|
||||
|
||||
public class CDTDebugElement extends DSPDebugElement {
|
||||
public CDTDebugElement(DSPDebugTarget target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICDTDebugProtocolServer getDebugProtocolServer() {
|
||||
// TODO Auto-generated method stub
|
||||
return (ICDTDebugProtocolServer) super.getDebugProtocolServer();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2019 Kichwa Coders 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 org.eclipse.lsp4j.jsonrpc.validation.NonNull;
|
||||
import org.eclipse.xtext.xbase.lib.Pure;
|
||||
import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;
|
||||
|
||||
public class CDTDebugProtocol {
|
||||
|
||||
/**
|
||||
* https://github.com/eclipse-cdt/cdt-gdb-adapter/blob/5d788cbbc6ace142b0930375fcd931b4241eddbb/src/GDBDebugSession.ts#L73
|
||||
* export interface MemoryResponse extends Response {
|
||||
* body: MemoryContents;
|
||||
* }
|
||||
*/
|
||||
public static class MemoryRequestResponse {
|
||||
@NonNull
|
||||
private MemoryContents body;
|
||||
|
||||
@Pure
|
||||
@NonNull
|
||||
public MemoryContents getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
public void setBody(@NonNull final MemoryContents address) {
|
||||
if (address == null) {
|
||||
throw new IllegalArgumentException("Property must not be null: body"); //$NON-NLS-1$
|
||||
}
|
||||
this.body = address;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Pure
|
||||
public String toString() {
|
||||
ToStringBuilder b = new ToStringBuilder(this);
|
||||
b.add("body", this.body); //$NON-NLS-1$
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((body == null) ? 0 : body.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
MemoryRequestResponse other = (MemoryRequestResponse) obj;
|
||||
if (body == null) {
|
||||
if (other.body != null)
|
||||
return false;
|
||||
} else if (!body.equals(other.body))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/eclipse-cdt/cdt-gdb-adapter/blob/5d788cbbc6ace142b0930375fcd931b4241eddbb/src/GDBDebugSession.ts#L67
|
||||
* export interface MemoryContents {
|
||||
* /\* Hex-encoded string of bytes. *\/
|
||||
* data: string;
|
||||
* address: string;
|
||||
* }
|
||||
*/
|
||||
public static class MemoryContents {
|
||||
@NonNull
|
||||
private String data;
|
||||
@NonNull
|
||||
private String address;
|
||||
|
||||
@Pure
|
||||
@NonNull
|
||||
public String getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public void setData(@NonNull final String address) {
|
||||
if (address == null) {
|
||||
throw new IllegalArgumentException("Property must not be null: data"); //$NON-NLS-1$
|
||||
}
|
||||
this.data = address;
|
||||
}
|
||||
|
||||
@Pure
|
||||
@NonNull
|
||||
public String getAddress() {
|
||||
return this.address;
|
||||
}
|
||||
|
||||
public void setAddress(@NonNull final String address) {
|
||||
if (address == null) {
|
||||
throw new IllegalArgumentException("Property must not be null: address"); //$NON-NLS-1$
|
||||
}
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Pure
|
||||
public String toString() {
|
||||
ToStringBuilder b = new ToStringBuilder(this);
|
||||
b.add("data", this.data); //$NON-NLS-1$
|
||||
b.add("address", this.address); //$NON-NLS-1$
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((address == null) ? 0 : address.hashCode());
|
||||
result = prime * result + ((data == null) ? 0 : data.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
MemoryContents other = (MemoryContents) obj;
|
||||
if (address == null) {
|
||||
if (other.address != null)
|
||||
return false;
|
||||
} else if (!address.equals(other.address))
|
||||
return false;
|
||||
if (data == null) {
|
||||
if (other.data != null)
|
||||
return false;
|
||||
} else if (!data.equals(other.data))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/eclipse-cdt/cdt-gdb-adapter/blob/5d788cbbc6ace142b0930375fcd931b4241eddbb/src/GDBDebugSession.ts#L58
|
||||
* export interface MemoryRequestArguments {
|
||||
* address: string;
|
||||
* length: number;
|
||||
* offset?: number;
|
||||
* }
|
||||
*
|
||||
*/
|
||||
public static class MemoryRequestArguments {
|
||||
@NonNull
|
||||
private String address;
|
||||
@NonNull
|
||||
private Long length;
|
||||
private Long offset;
|
||||
|
||||
@Pure
|
||||
@NonNull
|
||||
public String getAddress() {
|
||||
return this.address;
|
||||
}
|
||||
|
||||
public void setAddress(@NonNull final String address) {
|
||||
if (address == null) {
|
||||
throw new IllegalArgumentException("Property must not be null: address"); //$NON-NLS-1$
|
||||
}
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
@Pure
|
||||
@NonNull
|
||||
public Long getLength() {
|
||||
return this.length;
|
||||
}
|
||||
|
||||
public void setLength(@NonNull final Long length) {
|
||||
if (length == null) {
|
||||
throw new IllegalArgumentException("Property must not be null: length"); //$NON-NLS-1$
|
||||
}
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@Pure
|
||||
public Long getOffset() {
|
||||
return this.offset;
|
||||
}
|
||||
|
||||
public void setOffset(@NonNull final Long length) {
|
||||
if (length == null) {
|
||||
throw new IllegalArgumentException("Property must not be null: offset"); //$NON-NLS-1$
|
||||
}
|
||||
this.offset = length;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Pure
|
||||
public String toString() {
|
||||
ToStringBuilder b = new ToStringBuilder(this);
|
||||
b.add("address", this.address); //$NON-NLS-1$
|
||||
b.add("length", this.length); //$NON-NLS-1$
|
||||
b.add("offset", this.offset); //$NON-NLS-1$
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Pure
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((address == null) ? 0 : address.hashCode());
|
||||
result = prime * result + ((length == null) ? 0 : length.hashCode());
|
||||
result = prime * result + ((offset == null) ? 0 : offset.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Pure
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
MemoryRequestArguments other = (MemoryRequestArguments) obj;
|
||||
if (address == null) {
|
||||
if (other.address != null)
|
||||
return false;
|
||||
} else if (!address.equals(other.address))
|
||||
return false;
|
||||
if (length == null) {
|
||||
if (other.length != null)
|
||||
return false;
|
||||
} else if (!length.equals(other.length))
|
||||
return false;
|
||||
if (offset == null) {
|
||||
if (other.offset != null)
|
||||
return false;
|
||||
} else if (!offset.equals(other.offset))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2019 Kichwa Coders 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.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import org.eclipse.cdt.debug.dap.CDTDebugProtocol.MemoryContents;
|
||||
import org.eclipse.cdt.debug.dap.CDTDebugProtocol.MemoryRequestArguments;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.model.IMemoryBlock;
|
||||
import org.eclipse.debug.core.model.IMemoryBlockExtension;
|
||||
import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension;
|
||||
import org.eclipse.lsp4e.debug.debugmodel.DSPDebugTarget;
|
||||
import org.eclipse.lsp4j.debug.services.IDebugProtocolServer;
|
||||
import org.eclipse.lsp4j.jsonrpc.Launcher;
|
||||
import org.eclipse.lsp4j.jsonrpc.MessageConsumer;
|
||||
import org.eclipse.lsp4j.jsonrpc.debug.DebugLauncher;
|
||||
|
||||
public class DapDebugTarget extends DSPDebugTarget implements IMemoryBlockRetrievalExtension, ICDTDebugProtocolClient {
|
||||
|
||||
public DapDebugTarget(ILaunch launch, Runnable processCleanup, InputStream in, OutputStream out,
|
||||
Map<String, Object> dspParameters) {
|
||||
super(launch, processCleanup, in, out, dspParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Launcher<? extends IDebugProtocolServer> createLauncher(UnaryOperator<MessageConsumer> wrapper,
|
||||
InputStream in, OutputStream out, ExecutorService threadPool) {
|
||||
Launcher<ICDTDebugProtocolServer> debugProtocolLauncher = DebugLauncher.createLauncher(this,
|
||||
ICDTDebugProtocolServer.class, in, out, threadPool, wrapper);
|
||||
return debugProtocolLauncher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICDTDebugProtocolServer getDebugProtocolServer() {
|
||||
return (ICDTDebugProtocolServer) super.getDebugProtocolServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsStorageRetrieval() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException {
|
||||
throw new DebugException(new Status(IStatus.ERROR, Activator.PLUGIN_ID, DebugException.NOT_SUPPORTED,
|
||||
"getMemoryBlock() not supported, use getExtendedMemoryBlock()", null)); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMemoryBlockExtension getExtendedMemoryBlock(String expression, Object context) throws DebugException {
|
||||
BigInteger bigBaseAddress;
|
||||
/*
|
||||
* See if the expression is a simple numeric value; if it is, we can
|
||||
* avoid some costly processing (calling the back-end to resolve the
|
||||
* expression and obtain an address)
|
||||
*/
|
||||
try {
|
||||
// Now, try to parse the expression. If a NumberFormatException is
|
||||
// thrown, then it wasn't a simple numerical expression and we give
|
||||
// up as debug adapter hasn't provided us what was needed
|
||||
bigBaseAddress = BigInteger.valueOf(Long.decode(expression));
|
||||
|
||||
} catch (NumberFormatException nfexc) {
|
||||
MemoryRequestArguments memoryRequestArguments = new MemoryRequestArguments();
|
||||
memoryRequestArguments.setAddress(expression);
|
||||
memoryRequestArguments.setLength(1L);
|
||||
CompletableFuture<MemoryContents> memory = getDebugProtocolServer().memory(memoryRequestArguments);
|
||||
MemoryContents body = complete(memory);
|
||||
String address = body.getAddress();
|
||||
try {
|
||||
bigBaseAddress = BigInteger.valueOf(Long.decode(address));
|
||||
} catch (NumberFormatException e) {
|
||||
// still no resolvable address
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new MemoryBlock(this, expression, bigBaseAddress, context);
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
package org.eclipse.cdt.debug.dap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -24,10 +25,12 @@ import org.eclipse.core.runtime.FileLocator;
|
|||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.SubMonitor;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||
import org.eclipse.debug.core.Launch;
|
||||
import org.eclipse.debug.core.model.IDebugTarget;
|
||||
import org.eclipse.debug.core.model.IPersistableSourceLocator;
|
||||
import org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2;
|
||||
import org.eclipse.jface.dialogs.ErrorDialog;
|
||||
|
@ -82,7 +85,18 @@ public class DapLaunchDelegate extends AbstractCLaunchDelegate2 {
|
|||
builder.setMonitorDebugAdapter(true);
|
||||
builder.setDspParameters(param);
|
||||
|
||||
new DSPLaunchDelegate().launch(builder);
|
||||
DSPLaunchDelegate dspLaunchDelegate = new DSPLaunchDelegate() {
|
||||
@Override
|
||||
protected IDebugTarget createDebugTarget(SubMonitor subMonitor, Runnable cleanup,
|
||||
InputStream inputStream, java.io.OutputStream outputStream, ILaunch launch,
|
||||
Map<String, Object> dspParameters) throws CoreException {
|
||||
DapDebugTarget target = new DapDebugTarget(launch, cleanup, inputStream, outputStream,
|
||||
dspParameters);
|
||||
target.initialize(subMonitor.split(80));
|
||||
return target;
|
||||
}
|
||||
};
|
||||
dspLaunchDelegate.launch(builder);
|
||||
} catch (IOException e) {
|
||||
IStatus errorStatus = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
|
||||
Activator.getDefault().getLog().log(errorStatus);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2019 Kichwa Coders 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 org.eclipse.lsp4j.debug.services.IDebugProtocolClient;
|
||||
|
||||
public interface ICDTDebugProtocolClient extends IDebugProtocolClient {
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2019 Kichwa Coders 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.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.cdt.debug.dap.CDTDebugProtocol.MemoryContents;
|
||||
import org.eclipse.cdt.debug.dap.CDTDebugProtocol.MemoryRequestArguments;
|
||||
import org.eclipse.lsp4j.debug.services.IDebugProtocolServer;
|
||||
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest;
|
||||
|
||||
public interface ICDTDebugProtocolServer extends IDebugProtocolServer {
|
||||
|
||||
/**
|
||||
* Request a memory block
|
||||
*/
|
||||
@JsonRequest(value = "cdt-gdb-adapter/Memory")
|
||||
default CompletableFuture<MemoryContents> memory(MemoryRequestArguments args) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2019 Kichwa Coders 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));
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue