From fe13a037b7bdf789d570fc19a8ff6175442a6656 Mon Sep 17 00:00:00 2001 From: Jonah Graham Date: Thu, 31 Oct 2019 15:31:03 -0400 Subject: Bug 542488: Disassembly support Change-Id: I8a280fba5147ed3ebd8ecace8b943d3e5350dacf --- .../org.eclipse.cdt.debug.dap/META-INF/MANIFEST.MF | 7 +- debug/org.eclipse.cdt.debug.dap/pom.xml | 2 +- .../src/org/eclipse/cdt/debug/dap/Activator.java | 4 + .../eclipse/cdt/debug/dap/CDTDebugProtocol.java | 97 ++++-- .../org/eclipse/cdt/debug/dap/DapDebugTarget.java | 1 - .../cdt/debug/dap/DapDisassemblyBackend.java | 382 +++++++++++++++++++++ .../debug/dap/DapDisassemblyBackendFactory.java | 29 ++ .../cdt/debug/dap/ICDTDebugProtocolServer.java | 1 - .../org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF | 2 +- .../ui/disassembly/dsf/DisassemblyUtils.java | 13 + releng/org.eclipse.cdt.target/cdt.target | 2 +- 11 files changed, 504 insertions(+), 36 deletions(-) create mode 100644 debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDisassemblyBackend.java create mode 100644 debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDisassemblyBackendFactory.java diff --git a/debug/org.eclipse.cdt.debug.dap/META-INF/MANIFEST.MF b/debug/org.eclipse.cdt.debug.dap/META-INF/MANIFEST.MF index 78fb69d4190..771ad41fb65 100644 --- a/debug/org.eclipse.cdt.debug.dap/META-INF/MANIFEST.MF +++ b/debug/org.eclipse.cdt.debug.dap/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: org.eclipse.cdt.debug.dap;singleton:=true -Bundle-Version: 1.0.100.qualifier +Bundle-Version: 1.1.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.apache.commons.io, org.eclipse.core.runtime, @@ -20,7 +20,7 @@ Require-Bundle: org.apache.commons.io, com.google.gson;bundle-version="2.8.2", org.eclipse.lsp4j.jsonrpc, org.eclipse.cdt.launch, - org.eclipse.lsp4e.debug, + org.eclipse.lsp4e.debug;bundle-version="0.11.0", org.eclipse.debug.core, org.eclipse.debug.ui, org.eclipse.cdt.debug.core, @@ -28,7 +28,8 @@ Require-Bundle: org.apache.commons.io, org.eclipse.lsp4j.jsonrpc.debug, com.google.guava, org.eclipse.xtext.xbase.lib, - org.eclipse.cdt.dsf.gdb;bundle-version="5.7.200" + org.eclipse.cdt.dsf.gdb;bundle-version="5.7.200", + org.eclipse.cdt.debug.ui Bundle-Vendor: %Bundle-Vendor Export-Package: org.eclipse.cdt.debug.dap Bundle-Activator: org.eclipse.cdt.debug.dap.Activator diff --git a/debug/org.eclipse.cdt.debug.dap/pom.xml b/debug/org.eclipse.cdt.debug.dap/pom.xml index 01aa6cac231..7cbc92dbf66 100644 --- a/debug/org.eclipse.cdt.debug.dap/pom.xml +++ b/debug/org.eclipse.cdt.debug.dap/pom.xml @@ -12,7 +12,7 @@ ../../pom.xml - 1.0.100-SNAPSHOT + 1.1.0-SNAPSHOT org.eclipse.cdt.debug.dap eclipse-plugin diff --git a/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/Activator.java b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/Activator.java index b5823b45e96..983d5ec779c 100644 --- a/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/Activator.java +++ b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/Activator.java @@ -12,7 +12,9 @@ package org.eclipse.cdt.debug.dap; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; +import org.eclipse.lsp4e.debug.debugmodel.DSPDebugElement; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; @@ -29,6 +31,8 @@ public class Activator extends AbstractUIPlugin { public void start(BundleContext context) throws Exception { super.start(context); plugin = this; + + Platform.getAdapterManager().registerAdapters(new DapDisassemblyBackendFactory(), DSPDebugElement.class); } @Override diff --git a/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/CDTDebugProtocol.java b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/CDTDebugProtocol.java index 1d65e233653..40a74f73af1 100644 --- a/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/CDTDebugProtocol.java +++ b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/CDTDebugProtocol.java @@ -10,6 +10,11 @@ *******************************************************************************/ package org.eclipse.cdt.debug.dap; +import java.util.Objects; + +import org.eclipse.lsp4j.debug.DisassembleArguments; +import org.eclipse.lsp4j.debug.services.IDebugProtocolServer; +import org.eclipse.lsp4j.debug.util.Preconditions; import org.eclipse.lsp4j.jsonrpc.validation.NonNull; import org.eclipse.xtext.xbase.lib.Pure; import org.eclipse.xtext.xbase.lib.util.ToStringBuilder; @@ -32,11 +37,8 @@ public class CDTDebugProtocol { 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; + public void setBody(@NonNull final MemoryContents body) { + this.body = Preconditions.checkNotNull(body, "body"); //$NON-NLS-1$ } @Override @@ -93,11 +95,8 @@ public class CDTDebugProtocol { 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; + public void setData(@NonNull final String data) { + this.data = Preconditions.checkNotNull(data, "data"); //$NON-NLS-1$ } @Pure @@ -107,10 +106,7 @@ public class CDTDebugProtocol { } 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; + this.address = Preconditions.checkNotNull(address, "address"); //$NON-NLS-1$ } @Override @@ -177,10 +173,7 @@ public class CDTDebugProtocol { } 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; + this.address = Preconditions.checkNotNull(address, "address"); //$NON-NLS-1$ } @Pure @@ -190,10 +183,7 @@ public class CDTDebugProtocol { } 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; + this.length = Preconditions.checkNotNull(length, "length"); //$NON-NLS-1$ } @Pure @@ -201,11 +191,8 @@ public class CDTDebugProtocol { 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; + public void setOffset(final Long offset) { + this.offset = offset; } @Override @@ -256,6 +243,60 @@ public class CDTDebugProtocol { return false; return true; } + } + + /** + * An extension to standard {@link DisassembleArguments} that can + * be passed to {@link IDebugProtocolServer#disassemble(DisassembleArguments)} + * + * When endMemoryReference is provided, the disassemble command will return + * the minimum number of instructions to get to the end address or number + * of lines (instructionCount), whichever is smaller. + */ + public static class CDTDisassembleArguments extends DisassembleArguments { + + private String endMemoryReference; + + @Pure + public String getEndMemoryReference() { + return this.endMemoryReference; + } + + public void setEndMemoryReference(final String endMemoryReference) { + this.endMemoryReference = endMemoryReference; + } + @Override + @Pure + public String toString() { + ToStringBuilder b = new ToStringBuilder(this); + b.add("memoryReference", this.getMemoryReference()); //$NON-NLS-1$ + b.add("offset", this.getOffset()); //$NON-NLS-1$ + b.add("instructionOffset", this.getInstructionOffset()); //$NON-NLS-1$ + b.add("instructionCount", this.getInstructionCount()); //$NON-NLS-1$ + b.add("resolveSymbols", this.getResolveSymbols()); //$NON-NLS-1$ + b.add("endMemoryReference", this.endMemoryReference); //$NON-NLS-1$ + return b.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + Objects.hash(endMemoryReference); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + CDTDisassembleArguments other = (CDTDisassembleArguments) obj; + return Objects.equals(endMemoryReference, other.endMemoryReference); + } } -} \ No newline at end of file +} diff --git a/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDebugTarget.java b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDebugTarget.java index 419e125d3e8..fe00ba2d9c3 100644 --- a/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDebugTarget.java +++ b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDebugTarget.java @@ -94,5 +94,4 @@ public class DapDebugTarget extends DSPDebugTarget implements IMemoryBlockRetrie } return new MemoryBlock(this, expression, bigBaseAddress, context); } - } diff --git a/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDisassemblyBackend.java b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDisassemblyBackend.java new file mode 100644 index 00000000000..1ee81839428 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDisassemblyBackend.java @@ -0,0 +1,382 @@ +package org.eclipse.cdt.debug.dap; + +import static org.eclipse.cdt.debug.internal.ui.disassembly.dsf.DisassemblyUtils.DEBUG; + +import java.math.BigInteger; +import java.text.MessageFormat; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import org.eclipse.cdt.debug.dap.CDTDebugProtocol.CDTDisassembleArguments; +import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.AbstractDisassemblyBackend; +import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.AddressRangePosition; +import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.DisassemblyUtils; +import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.ErrorPosition; +import org.eclipse.core.runtime.IAdaptable; +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.ISourceLocator; +import org.eclipse.debug.core.model.IVariable; +import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Position; +import org.eclipse.lsp4e.debug.debugmodel.DSPDebugTarget; +import org.eclipse.lsp4e.debug.debugmodel.DSPStackFrame; +import org.eclipse.lsp4j.debug.DisassembleResponse; +import org.eclipse.lsp4j.debug.DisassembledInstruction; +import org.eclipse.lsp4j.debug.Source; + +@SuppressWarnings("restriction") +public class DapDisassemblyBackend extends AbstractDisassemblyBackend { + + private DSPStackFrame dspStackFrame; + + @Override + public boolean supportsDebugContext(IAdaptable context) { + return context instanceof DSPStackFrame; + } + + @Override + public boolean hasDebugContext() { + return dspStackFrame != null; + } + + @Override + public SetDebugContextResult setDebugContext(IAdaptable context) { + assert context instanceof DSPStackFrame; + SetDebugContextResult setDebugContextResult = new SetDebugContextResult(); + if (context instanceof DSPStackFrame) { + + DSPStackFrame newDspStackFrame = (DSPStackFrame) context; + setDebugContextResult.contextChanged = !newDspStackFrame.equals(dspStackFrame); + dspStackFrame = newDspStackFrame; + // sessionId should have been boolean and been hasSessionId, only null/non-null is relevant + setDebugContextResult.sessionId = ""; //$NON-NLS-1$ + if (!setDebugContextResult.contextChanged) { + fCallback.gotoFrameIfActive(dspStackFrame.getDepth()); + } + } else { + setDebugContextResult.contextChanged = true; + setDebugContextResult.sessionId = null; + } + + return setDebugContextResult; + } + + @Override + public void clearDebugContext() { + dspStackFrame = null; + } + + @Override + public void retrieveFrameAddress(int frame) { + fCallback.setUpdatePending(false); + fCallback.asyncExec(() -> { + int addressBits = dspStackFrame.getFrameInstructionAddressBits(); + BigInteger address = dspStackFrame.getFrameInstructionAddress(); + if (addressBits != fCallback.getAddressSize()) { + fCallback.addressSizeChanged(addressBits); + } + if (frame == 0) { + fCallback.updatePC(address); + } else { + fCallback.gotoFrame(frame, address); + } + }); + } + + @Override + public int getFrameLevel() { + return dspStackFrame.getDepth(); + } + + @Override + public boolean isSuspended() { + return dspStackFrame.getDebugTarget().isSuspended(); + } + + @Override + public boolean hasFrameContext() { + + return false; + } + + @Override + public String getFrameFile() { + + return null; + } + + @Override + public int getFrameLine() { + + return 0; + } + + /** + * Retrieves disassembly based on either (a) start and end address range, or + * (b) file, line number, and line count. If the caller specifies both sets + * of information, the implementation should honor (b) and ignore (a). + */ + @Override + public void retrieveDisassembly(BigInteger startAddress, BigInteger endAddress, String file, int lineNumber, + int lines, boolean mixed, boolean showSymbols, boolean showDisassembly, int linesHint) { + CDTDisassembleArguments args = new CDTDisassembleArguments(); + args.setMemoryReference("0x" + startAddress.toString(16)); //$NON-NLS-1$ + args.setInstructionCount((long) lines); + args.setEndMemoryReference("1+0x" + endAddress.toString(16)); //$NON-NLS-1$ + CompletableFuture future = dspStackFrame.getDebugProtocolServer().disassemble(args); + future.thenAcceptAsync(res -> { + fCallback.asyncExec(() -> insertDisassembly(startAddress, endAddress, res, showSymbols, showDisassembly)); + }); + } + + /** + * @param startAddress + * an address the caller is hoping will be covered by this + * insertion. I.e., [mixedInstructions] may or may not contain + * that address; the caller wants to know if it does, and so we + * indicate that via our return value. Can be null to indicate n/a, + * in which case we return true as long as any instruction was inserted + * as long as any instruction was inserted + * @param endAddress + * cut-off address. Any elements in [mixedInstructions] that + * extend beyond this address are ignored. + * @param mixedInstructions + * @param showSymbols + * @param showDisassembly + * @return whether [startAddress] was inserted + */ + private void insertDisassembly(BigInteger startAddress, BigInteger endAddress, DisassembleResponse response, + boolean showSymbols, boolean showDisassembly) { + if (!fCallback.hasViewer() || dspStackFrame == null) { + if (DEBUG) { + System.out.println( + MessageFormat.format("insertDisassembly ignored at {0} : missing context: [dspStackFrame={1}]", //$NON-NLS-1$ + DisassemblyUtils.getAddressText(startAddress), dspStackFrame)); + } + if (dspStackFrame == null) { + fCallback.setUpdatePending(false); + } + return; + } + if (DEBUG) + System.out.println("insertDisassembly " + DisassemblyUtils.getAddressText(startAddress)); //$NON-NLS-1$ + boolean updatePending = fCallback.getUpdatePending(); + assert updatePending; + if (!updatePending) { + // safe-guard in case something weird is going on + return; + } + + boolean insertedAnyAddress = false; + try { + fCallback.lockScroller(); + + AddressRangePosition p = null; + Source location = null; + DisassembledInstruction[] instructions = response.getInstructions(); + for (int i = 0; i < instructions.length; ++i) { + DisassembledInstruction instruction = instructions[i]; + if (instruction.getLocation() != null) { + location = instruction.getLocation(); + } + assert location != null; + String file = null; + if (location != null) { + file = location.getPath(); + } + Long line = instruction.getLine(); + int lineNumber = (line == null ? 0 : line.intValue()) - 1; + BigInteger address = getAddress(instruction); + if (startAddress == null) { + startAddress = address; + fCallback.setGotoAddressPending(address); + } + if (p == null || !p.containsAddress(address)) { + p = fCallback.getPositionOfAddress(address); + } + if (p instanceof ErrorPosition && p.fValid) { + p.fValid = false; + fCallback.getDocument().addInvalidAddressRange(p); + } else if (p == null || address.compareTo(endAddress) > 0) { + if (DEBUG) + System.out.println("Excess disassembly lines at " + DisassemblyUtils.getAddressText(address)); //$NON-NLS-1$ + return; + } else if (p.fValid) { + if (DEBUG) + System.out.println("Excess disassembly lines at " + DisassemblyUtils.getAddressText(address)); //$NON-NLS-1$ + if (!p.fAddressOffset.equals(address)) { + // override probably unaligned disassembly + p.fValid = false; + fCallback.getDocument().addInvalidAddressRange(p); + } else { + continue; + } + } + boolean hasSource = false; + if (file != null && lineNumber >= 0) { + p = fCallback.insertSource(p, address, file, lineNumber); + hasSource = fCallback.getStorageForFile(file) != null; + } + // insert symbol label + String functionName; + int offset; + String symbol = instruction.getSymbol(); + if (symbol != null) { + String[] split = symbol.split("\\+", 2); //$NON-NLS-1$ + functionName = split[0]; + if (split.length > 1) { + try { + offset = Integer.parseInt(split[1]); + } catch (NumberFormatException e) { + offset = 0; + } + } else { + offset = 0; + } + } else { + functionName = null; + offset = 0; + } + if (functionName != null && !functionName.isEmpty() && offset == 0) { + p = fCallback.getDocument().insertLabel(p, address, functionName, + showSymbols && (!hasSource || showDisassembly)); + } + // determine instruction byte length + BigInteger instrLength = null; + if (i < instructions.length - 1) { + instrLength = getAddress(instructions[i + 1]).subtract(address).abs(); + } else { + // cannot determine length of last instruction + break; + } + String funcOffset = instruction.getSymbol(); + if (funcOffset == null) { + funcOffset = ""; //$NON-NLS-1$ + } + + BigInteger opCodes = null; + if (instruction.getInstructionBytes() != null) { + opCodes = new BigInteger(instruction.getInstructionBytes().replace(" ", ""), 16); //$NON-NLS-1$//$NON-NLS-2$ + } + + p = fCallback.getDocument().insertDisassemblyLine(p, address, instrLength.intValue(), funcOffset, + opCodes, instruction.getInstruction(), file, lineNumber); + if (p == null) { + break; + } + insertedAnyAddress = true; + + } + + } catch (BadLocationException e) { + // should not happen + DisassemblyUtils.internalError(e); + } finally { + fCallback.setUpdatePending(false); + if (insertedAnyAddress) { + fCallback.updateInvalidSource(); + fCallback.unlockScroller(); + fCallback.doPending(); + fCallback.updateVisibleArea(); + } else { + fCallback.unlockScroller(); + } + } + } + + private BigInteger getAddress(DisassembledInstruction instruction) { + if (instruction.getAddress().startsWith("0x")) { //$NON-NLS-1$ + return new BigInteger(instruction.getAddress().substring(2), 16); + } else { + return new BigInteger(instruction.getAddress(), 10); + } + } + + @Override + public Object insertSource(Position pos, BigInteger address, String file, int lineNumber) { + ISourceLookupDirector lookupDirector = getSourceLookupDirector(); + return lookupDirector.getSourceElement(file); + } + + private ISourceLookupDirector getSourceLookupDirector() { + if (dspStackFrame == null) { + return null; + } + DSPDebugTarget debugTarget = dspStackFrame.getDebugTarget(); + if (debugTarget == null) { + return null; + } + ILaunch launch = debugTarget.getLaunch(); + if (launch == null) { + return null; + } + ISourceLocator sourceLocator = launch.getSourceLocator(); + if (sourceLocator instanceof ISourceLookupDirector) { + ISourceLookupDirector lookupDirector = (ISourceLookupDirector) sourceLocator; + return lookupDirector; + } + return null; + } + + @Override + public void gotoSymbol(String symbol) { + String.class.getClass(); + + } + + @Override + public void retrieveDisassembly(String file, int lines, BigInteger endAddress, boolean mixed, boolean showSymbols, + boolean showDisassembly) { + String.class.getClass(); + + } + + @Override + public String evaluateExpression(String expression) { + CompletableFuture evaluate = dspStackFrame.evaluate(expression); + try { + IVariable iVariable = evaluate.get(); + return iVariable.getValue().getValueString(); + } catch (InterruptedException e) { + return null; + } catch (ExecutionException | DebugException | NumberFormatException e) { + return null; + } + } + + @Override + public void dispose() { + String.class.getClass(); + + } + + @Override + protected void handleError(IStatus status) { + Activator.log(status); + } + + @Override + public BigInteger evaluateAddressExpression(String expression, boolean suppressError) { + CompletableFuture evaluate = dspStackFrame.evaluate(expression); + try { + IVariable variable = evaluate.get(); + return DisassemblyUtils.decodeAddress(variable.getValue().getValueString()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return null; + } catch (ExecutionException | DebugException | NumberFormatException e) { + if (!suppressError) { + DapDisassemblyBackend.this.handleError(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, + "Expression does not evaluate to an address (" //$NON-NLS-1$ + + e.getMessage() + ")", //$NON-NLS-1$ + null)); + } + return null; + } + + } +} diff --git a/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDisassemblyBackendFactory.java b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDisassemblyBackendFactory.java new file mode 100644 index 00000000000..18f268c30fc --- /dev/null +++ b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/DapDisassemblyBackendFactory.java @@ -0,0 +1,29 @@ +package org.eclipse.cdt.debug.dap; + +import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.IDisassemblyBackend; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.lsp4e.debug.debugmodel.DSPStackFrame; + +public class DapDisassemblyBackendFactory implements IAdapterFactory { + + private static final Class[] ADAPTERS = { IDisassemblyBackend.class }; + + @Override + @SuppressWarnings("unchecked") + public T getAdapter(Object adaptableObject, Class adapterType) { + if (IDisassemblyBackend.class.equals(adapterType)) { + if (adaptableObject instanceof DSPStackFrame) { + DSPStackFrame dspDebugElement = (DSPStackFrame) adaptableObject; + if (dspDebugElement.getDebugTarget() instanceof DapDebugTarget) { + return (T) new DapDisassemblyBackend(); + } + } + } + return null; + } + + @Override + public Class[] getAdapterList() { + return ADAPTERS; + } +} diff --git a/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/ICDTDebugProtocolServer.java b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/ICDTDebugProtocolServer.java index 11c7593cb6a..27a34f7b320 100644 --- a/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/ICDTDebugProtocolServer.java +++ b/debug/org.eclipse.cdt.debug.dap/src/org/eclipse/cdt/debug/dap/ICDTDebugProtocolServer.java @@ -26,5 +26,4 @@ public interface ICDTDebugProtocolServer extends IDebugProtocolServer { default CompletableFuture memory(MemoryRequestArguments args) { throw new UnsupportedOperationException(); } - } diff --git a/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF b/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF index 84e9d379c73..69cff113b32 100644 --- a/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF +++ b/debug/org.eclipse.cdt.debug.ui/META-INF/MANIFEST.MF @@ -14,7 +14,7 @@ Export-Package: org.eclipse.cdt.debug.internal.ui;x-friends:="org.eclipse.cdt.ds org.eclipse.cdt.debug.internal.ui.dialogfields;x-friends:="org.eclipse.cdt.dsf.gdb.ui", org.eclipse.cdt.debug.internal.ui.dialogs;x-internal:=true, org.eclipse.cdt.debug.internal.ui.disassembly.commands;x-internal:=true, - org.eclipse.cdt.debug.internal.ui.disassembly.dsf;x-friends:="org.eclipse.cdt.dsf.ui", + org.eclipse.cdt.debug.internal.ui.disassembly.dsf;x-friends:="org.eclipse.cdt.dsf.ui,org.eclipse.cdt.debug.dap", org.eclipse.cdt.debug.internal.ui.disassembly.editor;x-internal:=true, org.eclipse.cdt.debug.internal.ui.disassembly.viewer;x-internal:=true, org.eclipse.cdt.debug.internal.ui.editors;x-internal:=true, diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/DisassemblyUtils.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/DisassemblyUtils.java index 5dde9afa17a..bf1f3dd53db 100644 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/DisassemblyUtils.java +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/disassembly/dsf/DisassemblyUtils.java @@ -50,6 +50,19 @@ public class DisassemblyUtils { } public static BigInteger decodeAddress(String string) { + // Handle case where address has type info, such as: + // {int (const char *, ...)} 0x7ffff7a48e80 <__printf> + if (string.startsWith("{")) { //$NON-NLS-1$ + int indexOf = string.indexOf('}'); + if (indexOf >= 0 && indexOf < string.length()) { + string = string.substring(indexOf + 1); + } + indexOf = string.indexOf('<'); + if (indexOf >= 0) { + string = string.substring(0, indexOf); + } + string = string.trim(); + } if (string.startsWith("0x")) { //$NON-NLS-1$ return new BigInteger(string.substring(2), 16); } diff --git a/releng/org.eclipse.cdt.target/cdt.target b/releng/org.eclipse.cdt.target/cdt.target index c644ae01289..c81a6916415 100644 --- a/releng/org.eclipse.cdt.target/cdt.target +++ b/releng/org.eclipse.cdt.target/cdt.target @@ -92,7 +92,7 @@ - + -- cgit v1.2.3