1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 572880: show opcodes in disassembly view as byte sequence

Change-Id: Ib7ad37968ab23ff22cbb1fc110e85b47ffc37ab8
This commit is contained in:
Marc Ernst 2021-04-20 09:34:23 +02:00 committed by Jonah Graham
parent 6386faff0d
commit 766d6fec6a
18 changed files with 158 additions and 96 deletions

View file

@ -258,13 +258,13 @@ public class DapDisassemblyBackend extends AbstractDisassemblyBackend {
funcOffset = ""; //$NON-NLS-1$
}
BigInteger opCodes = null;
Byte[] opcode = null;
if (instruction.getInstructionBytes() != null) {
opCodes = new BigInteger(instruction.getInstructionBytes().replace(" ", ""), 16); //$NON-NLS-1$//$NON-NLS-2$
opcode = DisassemblyUtils.decodeOpcode(instruction.getInstructionBytes());
}
p = fCallback.getDocument().insertDisassemblyLine(p, address, instrLength.intValue(), funcOffset,
opCodes, instruction.getInstruction(), file, lineNumber);
opcode, instruction.getInstruction(), file, lineNumber);
if (p == null) {
break;
}

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.debug.ui; singleton:=true
Bundle-Version: 8.4.100.qualifier
Bundle-Version: 8.4.200.qualifier
Bundle-Activator: org.eclipse.cdt.debug.ui.CDebugUIPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin

View file

@ -21,7 +21,7 @@ import java.math.BigInteger;
public class DisassemblyPosition extends AddressRangePosition {
public char[] fFunction;
public BigInteger fOpcodes;
public Byte[] fOpcode;
/**
* @param offset
@ -29,12 +29,12 @@ public class DisassemblyPosition extends AddressRangePosition {
* @param addressOffset
* @param addressLength
* @param functionOffset
* @param opcodes
* @param opcode
*/
public DisassemblyPosition(int offset, int length, BigInteger addressOffset, BigInteger addressLength,
String functionOffset, BigInteger opcodes) {
String functionOffset, Byte[] opcode) {
super(offset, length, addressOffset, addressLength);
fOpcodes = opcodes;
fOpcode = opcode;
fFunction = functionOffset.toCharArray();
}

View file

@ -15,6 +15,8 @@
package org.eclipse.cdt.debug.internal.ui.disassembly.dsf;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
import org.eclipse.core.runtime.Platform;
@ -68,4 +70,41 @@ public class DisassemblyUtils {
}
return new BigInteger(string);
}
/**
* Decode given string representation of a space separated hex encoded byte
* array
*
* @param value
* space separated hexadecimal byte array
* @return opcode bytes as <code>Byte</code> array, an empty array if the decoding failed
*/
public static Byte[] decodeOpcode(String value) {
List<Byte> opcodeBytesList = new ArrayList<>();
if (value == null || value.isBlank()) {
return new Byte[0];
}
// Removing space separation and parse as bytes
for (String opcodeStringValue : value.split("\\s+")) { //$NON-NLS-1$
if (opcodeStringValue.length() > 0) {
// Check that the opcode does not contain some invalid byte sequence
if (opcodeStringValue.length() > 2) {
return new Byte[0];
}
byte byteValue = 0;
char charAtIndexZero = opcodeStringValue.charAt(0);
char charAtIndexOne = opcodeStringValue.length() > 1 ? opcodeStringValue.charAt(1) : 0;
int digitZero = Character.digit(charAtIndexZero, 16);
int digitOne = Character.digit(charAtIndexOne, 16);
// Check if characters are valid hex numbers
if (digitZero == -1 || digitOne == -1) {
return new Byte[0];
}
byteValue = (byte) ((digitZero << 4) + digitOne);
opcodeBytesList.add(Byte.valueOf(byteValue));
}
}
return opcodeBytesList.toArray(new Byte[0]);
}
}

View file

@ -35,7 +35,7 @@ public interface IDisassemblyDocument {
throws BadLocationException;
AddressRangePosition insertDisassemblyLine(AddressRangePosition p, BigInteger address, int length,
String functionOffset, BigInteger opcode, String instruction, String compilationPath, int lineNumber)
String functionOffset, Byte[] opcode, String instruction, String compilationPath, int lineNumber)
throws BadLocationException;
AddressRangePosition getDisassemblyPosition(BigInteger address);

View file

@ -28,6 +28,7 @@ public class MIInstruction extends AbstractInstruction {
String function = ""; //$NON-NLS-1$
long offset;
String opcode = ""; //$NON-NLS-1$
String rawOpcodeString = null;
String args = ""; //$NON-NLS-1$
BigInteger rawOpcodes = null;
Integer opcodeSize = null;
@ -71,6 +72,11 @@ public class MIInstruction extends AbstractInstruction {
return rawOpcodes;
}
@Override
public String getRawOpcode() {
return rawOpcodeString;
}
/**
* Parse the assembly instruction result. Each instruction has the following
* fields:
@ -157,6 +163,7 @@ public class MIInstruction extends AbstractInstruction {
if (var.equals("opcodes")) { //$NON-NLS-1$
try {
rawOpcodeString = str;
rawOpcodes = decodeOpcodes(str);
opcodeSize = Integer.valueOf(str.replace(" ", "").length() / 2); //$NON-NLS-1$//$NON-NLS-2$
} catch (NumberFormatException e) {

View file

@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-SymbolicName: org.eclipse.cdt.dsf.ui;singleton:=true
Bundle-Version: 2.6.100.qualifier
Bundle-Version: 2.6.200.qualifier
Bundle-Activator: org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui;bundle-version="3.5.0",

View file

@ -56,7 +56,7 @@ import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData;
import org.eclipse.cdt.dsf.debug.service.IInstruction;
import org.eclipse.cdt.dsf.debug.service.IInstructionWithRawOpcodes;
import org.eclipse.cdt.dsf.debug.service.IInstructionWithRawOpcode;
import org.eclipse.cdt.dsf.debug.service.IInstructionWithSize;
import org.eclipse.cdt.dsf.debug.service.IMixedInstruction;
import org.eclipse.cdt.dsf.debug.service.IRegisters;
@ -739,14 +739,14 @@ public class DisassemblyBackendDsf extends AbstractDisassemblyBackend implements
functionOffset = ""; //$NON-NLS-1$
}
BigInteger opCodes = null;
Byte[] opcode = {};
// Get raw Opcodes if available
if (instruction instanceof IInstructionWithRawOpcodes) {
opCodes = ((IInstructionWithRawOpcodes) instruction).getRawOpcodes();
if (instruction instanceof IInstructionWithRawOpcode) {
opcode = DisassemblyUtils.decodeOpcode(((IInstructionWithRawOpcode) instruction).getRawOpcode());
}
p = fCallback.getDocument().insertDisassemblyLine(p, address, instrLength.intValue(), functionOffset,
opCodes, instruction.getInstruction(), compilationPath, -1);
opcode, instruction.getInstruction(), compilationPath, -1);
if (p == null) {
break;
}
@ -895,13 +895,14 @@ public class DisassemblyBackendDsf extends AbstractDisassemblyBackend implements
funcOffset = ""; //$NON-NLS-1$
}
BigInteger opCodes = null;
if (instruction instanceof IInstructionWithRawOpcodes) {
opCodes = ((IInstructionWithRawOpcodes) instruction).getRawOpcodes();
Byte[] opcode = {};
if (instruction instanceof IInstructionWithRawOpcode) {
opcode = DisassemblyUtils
.decodeOpcode(((IInstructionWithRawOpcode) instruction).getRawOpcode());
}
p = fCallback.getDocument().insertDisassemblyLine(p, address, instrLength.intValue(), funcOffset,
opCodes, instruction.getInstruction(), file, lineNumber);
opcode, instruction.getInstruction(), file, lineNumber);
if (p == null) {
break;
}

View file

@ -13,12 +13,13 @@
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.internal.ui.disassembly;
import java.util.StringJoiner;
import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.AddressRangePosition;
import org.eclipse.cdt.debug.internal.ui.disassembly.dsf.DisassemblyPosition;
import org.eclipse.cdt.dsf.debug.internal.ui.disassembly.model.DisassemblyDocument;
import org.eclipse.cdt.dsf.debug.internal.ui.disassembly.preferences.DisassemblyPreferenceConstants;
import org.eclipse.cdt.dsf.debug.internal.ui.disassembly.provisional.DisassemblyRulerColumn;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.util.PropertyChangeEvent;
@ -30,10 +31,8 @@ public class OpcodeRulerColumn extends DisassemblyRulerColumn {
public static final String ID = "org.eclipse.cdt.dsf.ui.disassemblyColumn.opcode"; //$NON-NLS-1$
/** Maximum width of column (in characters) */
private static final int MAXWIDTH = 20;
private int fRadix;
private String fRadixPrefix;
/** 15 bytes plus separator */
private static final int MAXWIDTH = 44;
/**
* Default constructor.
@ -42,22 +41,6 @@ public class OpcodeRulerColumn extends DisassemblyRulerColumn {
super();
setBackground(getColor(DisassemblyPreferenceConstants.RULER_BACKGROUND_COLOR));
setForeground(getColor(DisassemblyPreferenceConstants.CODE_BYTES_COLOR));
setRadix(getPreferenceStore().getInt(DisassemblyPreferenceConstants.OPCODE_RADIX));
}
public void setRadix(int radix) {
fRadix = radix;
setShowRadixPrefix();
}
public void setShowRadixPrefix() {
if (fRadix == 16) {
fRadixPrefix = "0x"; //$NON-NLS-1$
} else if (fRadix == 8) {
fRadixPrefix = "0"; //$NON-NLS-1$
} else {
fRadixPrefix = null;
}
}
/*
@ -73,25 +56,9 @@ public class OpcodeRulerColumn extends DisassemblyRulerColumn {
AddressRangePosition pos = doc.getDisassemblyPosition(offset);
if (pos instanceof DisassemblyPosition && pos.length > 0 && pos.offset == offset && pos.fValid) {
DisassemblyPosition disassPos = (DisassemblyPosition) pos;
if (disassPos.fOpcodes != null) {
if (disassPos.fOpcode != null) {
// Format the output.
String str = disassPos.fOpcodes.toString(fRadix);
int prefixLength = 0;
if (fRadixPrefix != null)
prefixLength = fRadixPrefix.length();
StringBuilder buf = new StringBuilder(nChars);
if (prefixLength != 0)
buf.append(fRadixPrefix);
for (int i = str.length() + prefixLength; i < nChars; ++i)
buf.append('0');
buf.append(str);
if (buf.length() > nChars)
buf.delete(nChars, buf.length());
return buf.toString();
return getOpcodeString(disassPos.fOpcode);
}
} else if (pos != null && !pos.fValid) {
return DOTS.substring(0, nChars);
@ -103,24 +70,31 @@ public class OpcodeRulerColumn extends DisassemblyRulerColumn {
return ""; //$NON-NLS-1$
}
protected String getOpcodeString(Byte[] opcode) {
if (opcode.length == 0) {
return "??"; //$NON-NLS-1$
}
StringJoiner opcodeStringJoiner = new StringJoiner(" "); //$NON-NLS-1$
for (int i = 0; i < opcode.length; i++) {
opcodeStringJoiner.add(String.format("%02x", //$NON-NLS-1$
opcode[i].intValue() & 0xff));
}
return opcodeStringJoiner.toString();
}
@Override
protected int computeNumberOfCharacters() {
DisassemblyDocument doc = (DisassemblyDocument) getParentRuler().getTextViewer().getDocument();
return Math.min(MAXWIDTH, doc.getMaxOpcodeLength(fRadix));
return Math.min(MAXWIDTH, doc.getMaxOpcodeLength());
}
@Override
public void propertyChange(PropertyChangeEvent event) {
String property = event.getProperty();
IPreferenceStore store = getPreferenceStore();
boolean needRedraw = false;
if (DisassemblyPreferenceConstants.CODE_BYTES_COLOR.equals(property)) {
setForeground(getColor(property));
needRedraw = true;
} else if (DisassemblyPreferenceConstants.OPCODE_RADIX.equals(property)) {
setRadix(store.getInt(property));
layout(false);
needRedraw = true;
} else if (DisassemblyPreferenceConstants.RULER_BACKGROUND_COLOR.equals(property)) {
setBackground(getColor(property));
needRedraw = true;

View file

@ -73,7 +73,8 @@ public class DisassemblyDocument extends REDDocument implements IDisassemblyDocu
private final Map<IStorage, SourceFileInfo> fFileInfoMap = new HashMap<>();
private int fMaxFunctionLength = 0;
private BigInteger fMaxOpcodeLength = null;
/** Max opcode length is equal to the single bytes shown */
private int fMaxOpcodeLength = 0;
private boolean fShowAddresses = false;
private int fRadix = 16;
@ -150,25 +151,22 @@ public class DisassemblyDocument extends REDDocument implements IDisassemblyDocu
return fMaxFunctionLength;
}
public void setMaxOpcodeLength(BigInteger longOpcode) {
fMaxOpcodeLength = longOpcode;
public void setMaxOpcodeLength(int opcodeLength) {
fMaxOpcodeLength = opcodeLength;
}
public int getMaxOpcodeLength(int radix) {
int retVal = 0;
if (fMaxOpcodeLength != null) {
String str = fMaxOpcodeLength.toString(radix);
retVal = str.length();
switch (radix) {
case 8:
retVal += 1; // Padded for 0 prefix
break;
case 16:
retVal += 2; // Padded for 0x prefix
break;
default:
break;
public int getMaxOpcodeLength() {
// Check if an error on opcode decode occurred, in
// this case we show ??
if (fMaxOpcodeLength == 0) {
return 2;
}
int retVal = fMaxOpcodeLength;
// We show the bytes in hex, therefore it needs to be multiplied by 2
retVal *= 2;
// add bytes separator length
if (retVal > 0) {
retVal += fMaxOpcodeLength - 1;
}
return retVal;
}
@ -706,9 +704,10 @@ public class DisassemblyDocument extends REDDocument implements IDisassemblyDocu
if (functionLength > fMaxFunctionLength) {
fMaxFunctionLength = functionLength;
}
if (disassPos.fOpcodes != null) {
if (fMaxOpcodeLength == null || fMaxOpcodeLength.compareTo(disassPos.fOpcodes) == -1) {
fMaxOpcodeLength = disassPos.fOpcodes;
if (disassPos.fOpcode != null) {
int opcodeLength = disassPos.fOpcode.length;
if (opcodeLength > fMaxOpcodeLength) {
fMaxOpcodeLength = opcodeLength;
}
}
if (fNumberOfInstructions < 100 && fMeanSizeOfInstructions < 16.0) {
@ -1023,7 +1022,7 @@ public class DisassemblyDocument extends REDDocument implements IDisassemblyDocu
*/
@Override
public AddressRangePosition insertDisassemblyLine(AddressRangePosition pos, BigInteger address, int length,
String functionOffset, BigInteger opcode, String instruction, String file, int lineNr)
String functionOffset, Byte[] opcode, String instruction, String file, int lineNr)
throws BadLocationException {
assert isGuiThread();
String disassLine = null;

View file

@ -34,7 +34,7 @@ public class DisassemblyWithSourcePosition extends DisassemblyPosition {
* @param opcode
*/
public DisassemblyWithSourcePosition(int offset, int length, BigInteger addressOffset, BigInteger addressLength,
String functionOffset, BigInteger opcode, String file, int lineNr) {
String functionOffset, Byte[] opcode, String file, int lineNr) {
super(offset, length, addressOffset, addressLength, functionOffset, opcode);
fFile = file;
fLine = lineNr;

View file

@ -33,7 +33,6 @@ public class DisassemblyPreferenceConstants {
public static final String SHOW_SOURCE = "disassembly.showSource"; //$NON-NLS-1$
public static final String SHOW_SYMBOLS = "disassembly.showSymbols"; //$NON-NLS-1$
public static final String ADDRESS_RADIX = "disassembly.addressRadix"; //$NON-NLS-1$
public static final String OPCODE_RADIX = "disassembly.opcodeRadix"; //$NON-NLS-1$
public static final String SHOW_ADDRESS_RADIX = "disassembly.showAddressRadix"; //$NON-NLS-1$
public static final String ADDRESS_COLOR = "disassembly.addressColor"; //$NON-NLS-1$
public static final String FUNCTION_OFFSETS_COLOR = "disassembly.functionOffsetsColor"; //$NON-NLS-1$
@ -65,7 +64,6 @@ public class DisassemblyPreferenceConstants {
store.setDefault(SHOW_SOURCE, true);
store.setDefault(SHOW_SYMBOLS, true);
store.setDefault(ADDRESS_RADIX, 16);
store.setDefault(OPCODE_RADIX, 16);
store.setDefault(SHOW_ADDRESS_RADIX, false);
store.setDefault(AVOID_READ_BEFORE_PC, false);
PreferenceConverter.setDefault(store, ADDRESS_COLOR, new RGB(0, 96, 0));

View file

@ -57,7 +57,6 @@ public class DisassemblyPreferencePage extends PreferencePage implements IWorkbe
}
};
private Combo fAddressFormatCombo;
private Combo fOpcodeFormatCombo;
private final static String[] fcRadixItems = { DisassemblyMessages.DisassemblyPreferencePage_radix_octal,
DisassemblyMessages.DisassemblyPreferencePage_radix_decimal,
DisassemblyMessages.DisassemblyPreferencePage_radix_hexadecimal, };
@ -104,10 +103,6 @@ public class DisassemblyPreferencePage extends PreferencePage implements IWorkbe
Button showRadixCB = addCheckBox(composite, label, DisassemblyPreferenceConstants.SHOW_ADDRESS_RADIX, 0);
showRadixCB.setToolTipText(DisassemblyMessages.DisassemblyPreferencePage_showRadixTooltip);
label = DisassemblyMessages.DisassemblyPreferencePage_OpcodeFormat;
fOpcodeFormatCombo = addComboBox(composite, label, DisassemblyPreferenceConstants.OPCODE_RADIX, fcRadixItems);
fOpcodeFormatCombo.setToolTipText(DisassemblyMessages.DisassemblyPreferencePage_OpcodeFormatTooltip);
label = DisassemblyMessages.DisassemblyPreferencePage_showSource;
Button showSourceCB = addCheckBox(composite, label, DisassemblyPreferenceConstants.SHOW_SOURCE, 0);
showSourceCB.setToolTipText(DisassemblyMessages.DisassemblyPreferencePage_showSourceTooltip);

View file

@ -9,6 +9,12 @@
</filter>
</resource>
<resource path="src/org/eclipse/cdt/dsf/debug/service/AbstractInstruction.java" type="org.eclipse.cdt.dsf.debug.service.AbstractInstruction">
<filter comment="Squash over zealous warning from PDE. See Bug 558477" id="576725006">
<message_arguments>
<message_argument value="IInstructionWithRawOpcode"/>
<message_argument value="AbstractInstruction"/>
</message_arguments>
</filter>
<filter comment="Squash over zealous warning from PDE. See Bug 558477" id="576725006">
<message_arguments>
<message_argument value="IInstructionWithRawOpcodes"/>

View file

@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-SymbolicName: org.eclipse.cdt.dsf;singleton:=true
Bundle-Version: 2.10.100.qualifier
Bundle-Version: 2.11.0.qualifier
Bundle-Activator: org.eclipse.cdt.dsf.internal.DsfPlugin
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.runtime,

View file

@ -22,7 +22,8 @@ import java.math.BigInteger;
*
* @since 2.2
*/
public abstract class AbstractInstruction implements IInstructionWithSize, IInstructionWithRawOpcodes {
public abstract class AbstractInstruction
implements IInstructionWithSize, IInstructionWithRawOpcodes, IInstructionWithRawOpcode {
/*
* @see org.eclipse.cdt.dsf.debug.service.IInstructionWithSize#getSize()
*/
@ -40,4 +41,11 @@ public abstract class AbstractInstruction implements IInstructionWithSize, IInst
return null;
}
/**
* @since 2.10
*/
@Override
public String getRawOpcode() {
return null;
}
}

View file

@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2021 Intel Corporation.
*
* 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
* Contributors:
* Intel Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.service;
/**
* Extension interface for instructions with raw Opcodes
* <p>
* Implementers must extend {@link AbstractInstruction} instead of implementing
* this interface directly.
* </p>
*
* @since 2.11
* @noimplement This interface is not intended to be implemented by clients.
* @noextend This interface is not intended to be extended by clients.
*/
public interface IInstructionWithRawOpcode extends IInstruction {
/**
* @return The raw opcode of the instruction as <code>String</code>, the instruction
* bytes are separated by space. If there is no opcode, <code>null</code> is returned.
*/
String getRawOpcode();
}

View file

@ -25,7 +25,9 @@ import java.math.BigInteger;
* @since 2.5
* @noimplement This interface is not intended to be implemented by clients.
* @noextend This interface is not intended to be extended by clients.
* @deprecated use {@link IInstructionWithRawOpcode} instead.
*/
@Deprecated
public interface IInstructionWithRawOpcodes extends IInstruction {
/**