mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-4709: post-post-post review
GP-4709: post=post review - test logic in error GP-4709: post=post review - test logic in error GP-4709: post-review fixes GP-4709: going for simplicity GP-4709: reverting most stuff GP-4709: fix for replaceValue logic GP-4709: extensions to HexInteger
This commit is contained in:
@@ -87,17 +87,41 @@
|
||||
<p>This view does not support <a href="#EditBytes">editing</a>.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3><a name="Add_Byteviewer_HexInteger_Panel"></a><a name="HexInteger"></a>HexInteger </h3>
|
||||
<h3><a name="Add_Byteviewer_HexShortPanel"></a><a name="HexShort"></a>Hex Short</h3>
|
||||
<blockquote>
|
||||
<p>This format shows four byte numbers represented as an eight digit hex number. </p>
|
||||
<p>This format shows two-byte numbers represented as an four-digit hex number. </p>
|
||||
<p> This view supports <a href="#EditBytes">editing</a>. When a byte
|
||||
is changed, both bytes associated with this address are rendered in
|
||||
<font color="#ff0000"> red</font> to denote the change.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3><a name="Add_Byteviewer_HexInteger_Panel"></a><a name="HexInteger"></a>Hex Integer</h3>
|
||||
<blockquote>
|
||||
<p>This format shows four-byte numbers represented as an eight-digit hex number. </p>
|
||||
<p> This view supports <a href="#EditBytes">editing</a>. When a byte
|
||||
is changed, all four bytes associated with this address are rendered in
|
||||
<font color="#ff0000"> red</font> to denote the change.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3><a name="Add_Byteviewer_HexLong_Panel"></a><a name="HexLongr"></a>Hex Long</h3>
|
||||
<blockquote>
|
||||
<p>This format shows eight-byte numbers represented as an 16-digit hex number. </p>
|
||||
<p> This view supports <a href="#EditBytes">editing</a>. When a byte
|
||||
is changed, all eight bytes associated with this address are rendered in
|
||||
<font color="#ff0000"> red</font> to denote the change.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3><a name="Add_Byteviewer_HexLongLong_Panel"></a><a name="HexLongLong"></a>Hex Long Long</h3>
|
||||
<blockquote>
|
||||
<p>This format shows 16-byte numbers represented as an 32-digit hex number. </p>
|
||||
<p> This view supports <a href="#EditBytes">editing</a>. When a byte
|
||||
is changed, all 16 bytes associated with this address are rendered in
|
||||
<font color="#ff0000"> red</font> to denote the change.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3><a name="Add_Byteviewer_Integer_Panel"></a><a name="Integer"></a>Integer </h3>
|
||||
<blockquote>
|
||||
<p>This view shows four byte numbers represented in decimal format. </p>
|
||||
<p>This view shows four-byte numbers represented in decimal format. </p>
|
||||
<p> This view does not support <a href="#EditBytes">editing</a>.</p>
|
||||
</blockquote>
|
||||
|
||||
|
||||
@@ -912,9 +912,8 @@ public class ByteViewerComponent extends FieldPanel implements FieldMouseListene
|
||||
|
||||
ByteField getField(BigInteger index, int fieldNum) {
|
||||
if (indexMap != null) {
|
||||
int fieldOffset = indexMap.getFieldOffset(index, fieldNum, fieldFactories);
|
||||
if (fieldNum < fieldFactories.length) {
|
||||
return (ByteField) fieldFactories[fieldOffset].getField(index);
|
||||
return (ByteField) fieldFactories[fieldNum].getField(index);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -78,6 +78,19 @@ class FileByteBlock implements ByteBlock {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.core.format.ByteBlock#getShort(int)
|
||||
*/
|
||||
public short getShort(BigInteger bigIndex) throws ByteBlockAccessException {
|
||||
int index = bigIndex.intValue();
|
||||
if (index < buf.length) {
|
||||
byte[] b = new byte[2];
|
||||
System.arraycopy(buf, index, b, 0, b.length);
|
||||
return converter.getShort(b);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.core.format.ByteBlock#getInt(int)
|
||||
*/
|
||||
@@ -114,6 +127,18 @@ class FileByteBlock implements ByteBlock {
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.core.format.ByteBlock#setShort(int, short)
|
||||
*/
|
||||
public void setShort(BigInteger bigIndex, short value) throws ByteBlockAccessException {
|
||||
int index = bigIndex.intValue();
|
||||
if (index < buf.length) {
|
||||
byte[] b = new byte[2];
|
||||
converter.putShort(b, 0, value);
|
||||
System.arraycopy(b, 0, buf, index, b.length);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.core.format.ByteBlock#setInt(int, int)
|
||||
*/
|
||||
|
||||
@@ -225,6 +225,44 @@ public class MemoryByteBlock implements ByteBlock {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the short value at the given index.
|
||||
*
|
||||
* @param index byte index
|
||||
* @throws ByteBlockAccessException if the block cannot be read
|
||||
* @throws IndexOutOfBoundsException if the given index is not in this block.
|
||||
*/
|
||||
@Override
|
||||
public short getShort(BigInteger index) throws ByteBlockAccessException {
|
||||
Address addr = getAddress(index);
|
||||
try {
|
||||
return memory.getShort(addr, bigEndian);
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
throw new ByteBlockAccessException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the short at the given index.
|
||||
*
|
||||
* @param index byte index
|
||||
* @param value value to set
|
||||
* @throws ByteBlockAccessException if the block cannot be updated
|
||||
* @throws IndexOutOfBoundsException if the given index is not in this block.
|
||||
*/
|
||||
@Override
|
||||
public void setShort(BigInteger index, short value) throws ByteBlockAccessException {
|
||||
Address addr = getAddress(index);
|
||||
checkEditsAllowed(addr, 2);
|
||||
try {
|
||||
memory.setShort(addr, value, bigEndian);
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
throw new ByteBlockAccessException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this block can be modified.
|
||||
*/
|
||||
|
||||
@@ -61,6 +61,15 @@ public interface ByteBlock {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the short value at the given index.
|
||||
* @param index byte index
|
||||
* @throws ByteBlockAccessException if the block cannot be read
|
||||
* @throws IndexOutOfBoundsException if the given index is not in this
|
||||
* block.
|
||||
*/
|
||||
public short getShort(BigInteger index) throws ByteBlockAccessException;
|
||||
|
||||
/**
|
||||
* Get the int value at the given index.
|
||||
* @param index byte index
|
||||
@@ -89,6 +98,16 @@ public interface ByteBlock {
|
||||
*/
|
||||
public void setByte(BigInteger index, byte value) throws ByteBlockAccessException;
|
||||
|
||||
/**
|
||||
* Set the short at the given index.
|
||||
* @param index byte index
|
||||
* @param value value to set
|
||||
* @throws ByteBlockAccessException if the block cannot be updated
|
||||
* @throws IndexOutOfBoundsException if the given index is not in this
|
||||
* block.
|
||||
*/
|
||||
public void setShort(BigInteger index, short value) throws ByteBlockAccessException;
|
||||
|
||||
/**
|
||||
* Set the int at the given index.
|
||||
* @param index byte index
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,236 +15,22 @@
|
||||
*/
|
||||
package ghidra.app.plugin.core.format;
|
||||
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Converts byte values to Integer represented as an 8 digit hex number.
|
||||
* Converts byte values to Integer represented as an 4-byte/8-digit hex number.
|
||||
*/
|
||||
public class HexIntegerFormatModel implements UniversalDataFormatModel {
|
||||
|
||||
private int symbolSize;
|
||||
public class HexIntegerFormatModel extends HexValueFormatModel {
|
||||
|
||||
public HexIntegerFormatModel() {
|
||||
|
||||
symbolSize = 8;
|
||||
super("Hex Integer", 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this formatter.
|
||||
*/
|
||||
public String getName() {
|
||||
return "HexInteger";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes to make a unit; in this case,
|
||||
* returns 4.
|
||||
*/
|
||||
public int getUnitByteSize() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the byte used to generate the character at a given
|
||||
* position.
|
||||
* @param position number in the range 0 to 7
|
||||
*/
|
||||
public int getByteOffset(ByteBlock block, int position) {
|
||||
|
||||
int o = position / 2;
|
||||
|
||||
if (block.isBigEndian()) {
|
||||
return o;
|
||||
}
|
||||
return 3 - o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the byte offset into a unit, get the column position.
|
||||
*/
|
||||
public int getColumnPosition(ByteBlock block, int byteOffset) {
|
||||
if (byteOffset > 3) {
|
||||
throw new IllegalArgumentException("invalid byteOffset: " + byteOffset);
|
||||
}
|
||||
if (block.isBigEndian()) {
|
||||
return byteOffset * 2;
|
||||
}
|
||||
return (3 - byteOffset) * 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of characters required to display a
|
||||
* unit.
|
||||
* @return 4 for number of characters in the integer representation.
|
||||
*/
|
||||
public int getDataUnitSymbolSize() {
|
||||
return symbolSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string representation at the given index in the block.
|
||||
* @param block block to change
|
||||
* @param index byte index into the block
|
||||
* @throws ByteBlockAccessException if the block cannot be read
|
||||
* @throws IndexOutOfBoundsException if index is not valid for the
|
||||
* block
|
||||
*/
|
||||
@Override
|
||||
public String getDataRepresentation(ByteBlock block, BigInteger index)
|
||||
throws ByteBlockAccessException {
|
||||
|
||||
int i = block.getInt(index);
|
||||
|
||||
String str = Integer.toHexString(i);
|
||||
|
||||
return pad(str);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true to allow values to be changed.
|
||||
*/
|
||||
public boolean isEditable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite a value in a ByteBlock.
|
||||
* @param block block to change
|
||||
* @param index byte index into the block
|
||||
* @param pos The position within the unit where c will be the
|
||||
* new character.
|
||||
* @param c new character to put at pos param
|
||||
* @return true if the replacement is legal, false if the
|
||||
* replacement value would not make sense for this format, e.g.
|
||||
* attempt to put a 'z' in a hex unit.
|
||||
* @throws ByteBlockAccessException if the block cannot be updated
|
||||
* @throws IndexOutOfBoundsException if index is not valid for the
|
||||
* block
|
||||
*/
|
||||
public boolean replaceValue(ByteBlock block, BigInteger index, int charPosition, char c)
|
||||
throws ByteBlockAccessException {
|
||||
|
||||
if (charPosition < 0 || charPosition > symbolSize - 1) {
|
||||
return false;
|
||||
}
|
||||
char[] charArray = { c };
|
||||
String s = new String(charArray);
|
||||
try {
|
||||
Integer.parseInt(s, 16);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte cb = Byte.parseByte(new String(charArray), 16);
|
||||
// get the correct byte offset based on position
|
||||
int byteOffset = getByteOffset(block, charPosition);
|
||||
BigInteger saveIndex = index;
|
||||
index = index.add(BigInteger.valueOf(byteOffset));
|
||||
byte b = block.getByte(index);
|
||||
b = adjustByte(b, cb, charPosition);
|
||||
int intValue = getInt(block, saveIndex, b, byteOffset);
|
||||
block.setInt(saveIndex, intValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of units in a group. A group may represent
|
||||
* multiple units shown as one entity. This format does not
|
||||
* support groups.
|
||||
*/
|
||||
public int getGroupSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of units in a group. This format does not
|
||||
* support groups.
|
||||
* @throws UnsupportedOperationException
|
||||
*/
|
||||
public void setGroupSize(int groupSize) {
|
||||
throw new UnsupportedOperationException("groups are not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of characters separating units.
|
||||
*/
|
||||
public int getUnitDelimiterSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.plugin.core.format.DataFormatModel#validateBytesPerLine(int)
|
||||
*/
|
||||
public boolean validateBytesPerLine(int bytesPerLine) {
|
||||
return bytesPerLine % 4 == 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// *** private methods ***
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Returns value with leading zeros.
|
||||
*/
|
||||
private String pad(String value) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int len = symbolSize - value.length();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
sb.append("0");
|
||||
}
|
||||
sb.append(value);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* adjust byte b to use either the upper 4 bits or
|
||||
* the lower 4 bits of newb according to charPosition.
|
||||
*/
|
||||
private byte adjustByte(byte b, byte newb, int charPosition) {
|
||||
if (charPosition % 2 == 0) {
|
||||
// its the high order byte
|
||||
b &= 0x0f;
|
||||
newb <<= 4;
|
||||
}
|
||||
else {
|
||||
b &= 0xf0;
|
||||
}
|
||||
b += newb;
|
||||
return b;
|
||||
}
|
||||
|
||||
private int getInt(ByteBlock block, BigInteger offset, byte newb, int byteOffset) {
|
||||
byte[] b = new byte[4];
|
||||
try {
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
b[i] = block.getByte(offset.add(BigInteger.valueOf(i)));
|
||||
}
|
||||
b[byteOffset] = newb;
|
||||
|
||||
if (block.isBigEndian()) {
|
||||
return (b[0] << 24) | ((b[1] << 16) & 0x00FF0000) | ((b[2] << 8) & 0x0000FF00) |
|
||||
(b[3] & 0x000000FF);
|
||||
}
|
||||
return (b[3] << 24) | ((b[2] << 16) & 0x00FF0000) | ((b[1] << 8) & 0x0000FF00) |
|
||||
(b[0] & 0x000000FF);
|
||||
|
||||
}
|
||||
catch (ByteBlockAccessException e) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.app.plugin.format.DataFormatModel#getHelpLocation()
|
||||
*/
|
||||
public HelpLocation getHelpLocation() {
|
||||
return new HelpLocation("ByteViewerPlugin", "HexInteger");
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.format;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Converts byte values to Long represented as an 8-byte/16--digit hex number.
|
||||
*/
|
||||
public class HexLongFormatModel extends HexValueFormatModel {
|
||||
|
||||
public HexLongFormatModel() {
|
||||
super("Hex Long", 8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataRepresentation(ByteBlock block, BigInteger index)
|
||||
throws ByteBlockAccessException {
|
||||
long l = block.getLong(index);
|
||||
String str = Long.toHexString(l);
|
||||
return pad(str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.format;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Converts byte values to LongLong represented as an 16-byte/32-digit hex number.
|
||||
*/
|
||||
public class HexLongLongFormatModel extends HexValueFormatModel {
|
||||
|
||||
public HexLongLongFormatModel() {
|
||||
super("Hex Long Long", 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataRepresentation(ByteBlock block, BigInteger index)
|
||||
throws ByteBlockAccessException {
|
||||
long l0 = block.getLong(index);
|
||||
String str0 = pad(Long.toHexString(l0));
|
||||
long l1 = block.getLong(index.add(BigInteger.valueOf(8)));
|
||||
String str1 = pad(Long.toHexString(l1));
|
||||
String str = str1.substring(16) + str0.substring(16);
|
||||
return pad(str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.format;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Converts byte values to Short represented as an 2-byte/4-digit hex number.
|
||||
*/
|
||||
public class HexShortFormatModel extends HexValueFormatModel {
|
||||
|
||||
public HexShortFormatModel() {
|
||||
super("Hex Short", 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataRepresentation(ByteBlock block, BigInteger index)
|
||||
throws ByteBlockAccessException {
|
||||
short s = block.getShort(index);
|
||||
String str = Integer.toHexString(s & 0xFFFF);
|
||||
return pad(str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.format;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
* Converts byte values to value represented as a 2, 4, 8, or 16-byte hex number.
|
||||
*/
|
||||
public abstract class HexValueFormatModel implements UniversalDataFormatModel {
|
||||
|
||||
protected String name;
|
||||
|
||||
private int symbolSize;
|
||||
protected int nbytes;
|
||||
|
||||
public HexValueFormatModel(String name, int nbytes) {
|
||||
this.name = name;
|
||||
this.nbytes = nbytes;
|
||||
symbolSize = nbytes * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnitByteSize() {
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getByteOffset(ByteBlock block, int position) {
|
||||
|
||||
int o = position / 2;
|
||||
|
||||
if (block.isBigEndian()) {
|
||||
return o;
|
||||
}
|
||||
return nbytes - 1 - o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnPosition(ByteBlock block, int byteOffset) {
|
||||
if (byteOffset > nbytes - 1) {
|
||||
throw new IllegalArgumentException("invalid byteOffset: " + byteOffset);
|
||||
}
|
||||
if (block.isBigEndian()) {
|
||||
return byteOffset * 2;
|
||||
}
|
||||
return (nbytes - 1 - byteOffset) * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDataUnitSymbolSize() {
|
||||
return symbolSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract String getDataRepresentation(ByteBlock block, BigInteger index)
|
||||
throws ByteBlockAccessException;
|
||||
|
||||
@Override
|
||||
public boolean isEditable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceValue(ByteBlock block, BigInteger index, int charPosition, char c)
|
||||
throws ByteBlockAccessException {
|
||||
|
||||
if (charPosition < 0 || charPosition > symbolSize - 1) {
|
||||
// Not sure how this is possible, but...
|
||||
return false;
|
||||
}
|
||||
char[] charArray = { c };
|
||||
byte cb = Byte.parseByte(new String(charArray), 16);
|
||||
// get the correct byte offset based on position
|
||||
int byteOffset = getByteOffset(block, charPosition);
|
||||
index = index.add(BigInteger.valueOf(byteOffset));
|
||||
byte b = block.getByte(index);
|
||||
b = adjustByte(b, cb, charPosition);
|
||||
block.setByte(index, b);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGroupSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of units in a group. This format does not
|
||||
* support groups.
|
||||
*/
|
||||
@Override
|
||||
public void setGroupSize(int groupSize) {
|
||||
throw new UnsupportedOperationException("groups are not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUnitDelimiterSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateBytesPerLine(int bytesPerLine) {
|
||||
return bytesPerLine % nbytes == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns value with leading zeros.
|
||||
*/
|
||||
protected String pad(String value) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
int len = symbolSize - value.length();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
sb.append("0");
|
||||
}
|
||||
sb.append(value);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* adjust byte b to use either the upper 4 bits or
|
||||
* the lower 4 bits of newb according to charPosition.
|
||||
*/
|
||||
private byte adjustByte(byte b, byte newb, int charPosition) {
|
||||
if (charPosition % 2 == 0) {
|
||||
// its the high order byte
|
||||
b &= 0x0f;
|
||||
newb <<= 4;
|
||||
}
|
||||
else {
|
||||
b &= 0xf0;
|
||||
}
|
||||
b += newb;
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpLocation getHelpLocation() {
|
||||
return new HelpLocation("ByteViewerPlugin", "HexValue");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -305,7 +305,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest {
|
||||
field = asciiC.getField(loc.getIndex(), loc.getFieldNum());
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, field.getForeground());
|
||||
|
||||
final ByteViewerComponent hexIntC = findComponent(panel, "HexInteger");
|
||||
final ByteViewerComponent hexIntC = findComponent(panel, "Hex Integer");
|
||||
SwingUtilities.invokeAndWait(() -> panel.setCurrentView(hexIntC));
|
||||
|
||||
loc = getFieldLocation(addr);
|
||||
@@ -456,14 +456,14 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUndoRedoHexInteger() throws Exception {
|
||||
public void testUndoRedoHexShort() throws Exception {
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final Address addr = getAddr(0x01001003);
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
ByteViewerComponent c = findComponent(panel, "HexInteger");
|
||||
ByteViewerComponent c = findComponent(panel, "Hex Short");
|
||||
panel.setCurrentView(c);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
@@ -504,6 +504,228 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUndoRedoHexInteger() throws Exception {
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final Address addr = getAddr(0x01001003);
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
ByteViewerComponent c = findComponent(panel, "Hex Integer");
|
||||
panel.setCurrentView(c);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol());
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
byte value = program.getMemory().getByte(addr);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
KeyEvent ev =
|
||||
new KeyEvent(currentComponent, 0, new Date().getTime(), 0, KeyEvent.VK_A, 'a');
|
||||
currentComponent.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol(), currentComponent.getCurrentField());
|
||||
});
|
||||
program.flushEvents();
|
||||
assertEquals((byte) 0xa0, memory.getByte(addr));
|
||||
|
||||
undo(program);
|
||||
|
||||
assertEquals(value, memory.getByte(addr));
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
ByteField field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
Color fg = field.getForeground();
|
||||
assertTrue(fg == null ||
|
||||
ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR == field.getForeground());
|
||||
|
||||
redo(program);
|
||||
|
||||
// field color should show edit color
|
||||
loc = getFieldLocation(addr);
|
||||
field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, field.getForeground());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUndoRedoHexLong() throws Exception {
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final Address addr = getAddr(0x01001003);
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
ByteViewerComponent c = findComponent(panel, "Hex Long");
|
||||
panel.setCurrentView(c);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol());
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
byte value = program.getMemory().getByte(addr);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
KeyEvent ev =
|
||||
new KeyEvent(currentComponent, 0, new Date().getTime(), 0, KeyEvent.VK_A, 'a');
|
||||
currentComponent.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol(), currentComponent.getCurrentField());
|
||||
});
|
||||
program.flushEvents();
|
||||
assertEquals((byte) 0xa0, memory.getByte(addr));
|
||||
|
||||
undo(program);
|
||||
|
||||
assertEquals(value, memory.getByte(addr));
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
ByteField field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
Color fg = field.getForeground();
|
||||
assertTrue(fg == null ||
|
||||
ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR == field.getForeground());
|
||||
|
||||
redo(program);
|
||||
|
||||
// field color should show edit color
|
||||
loc = getFieldLocation(addr);
|
||||
field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, field.getForeground());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUndoRedoHexLongLong() throws Exception {
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final Address addr = getAddr(0x01001003);
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
ByteViewerComponent c = findComponent(panel, "Hex Long Long");
|
||||
panel.setCurrentView(c);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol());
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
byte value = program.getMemory().getByte(addr);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
KeyEvent ev =
|
||||
new KeyEvent(currentComponent, 0, new Date().getTime(), 0, KeyEvent.VK_A, 'a');
|
||||
currentComponent.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol(), currentComponent.getCurrentField());
|
||||
});
|
||||
program.flushEvents();
|
||||
assertEquals((byte) 0xa0, memory.getByte(addr));
|
||||
|
||||
undo(program);
|
||||
|
||||
assertEquals(value, memory.getByte(addr));
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
ByteField field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
Color fg = field.getForeground();
|
||||
assertTrue(fg == null ||
|
||||
ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR == field.getForeground());
|
||||
|
||||
redo(program);
|
||||
|
||||
// field color should show edit color
|
||||
loc = getFieldLocation(addr);
|
||||
field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, field.getForeground());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUndoRedoHexShort2() throws Exception {
|
||||
// remove code browser plugin so the cursor position does not
|
||||
// get changed because of location events that the code browser
|
||||
// generates.
|
||||
tool.removePlugins(new Plugin[] { cbPlugin });
|
||||
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
ByteViewerComponent c = findComponent(panel, "Hex Short");
|
||||
panel.setCurrentView(c);
|
||||
// make 3 changes
|
||||
// verify that the Undo button is enabled and undo can be done 5 times
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
Address addr = getAddr(0x01001003);
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
char[] values = { 'a', '1', '2' };
|
||||
int[] keyCodes =
|
||||
{ KeyEvent.VK_P, KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_B, KeyEvent.VK_3 };
|
||||
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
FieldLocation loc = currentComponent.getCursorLocation();
|
||||
KeyEvent ev = new KeyEvent(currentComponent, 0, new Date().getTime(), 0,
|
||||
keyCodes[i], values[i]);
|
||||
currentComponent.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol(), currentComponent.getCurrentField());
|
||||
}
|
||||
|
||||
});
|
||||
program.flushEvents();
|
||||
waitForSwing();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
assertTrue(program.canUndo());
|
||||
|
||||
undo(program);
|
||||
|
||||
FieldLocation loc = c.getCursorLocation();
|
||||
ByteField field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
Color fg = field.getForeground();
|
||||
if (i == 2) {
|
||||
assertTrue(fg == null ||
|
||||
ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR == field.getForeground());
|
||||
}
|
||||
else {
|
||||
assertEquals(fg, ByteViewerComponentProvider.CHANGED_VALUE_COLOR);
|
||||
}
|
||||
}
|
||||
assertTrue(!program.canUndo());
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
|
||||
redo(program);
|
||||
|
||||
FieldLocation loc = c.getCursorLocation();
|
||||
ByteField field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
Color fg = field.getForeground();
|
||||
assertEquals(fg, ByteViewerComponentProvider.CHANGED_VALUE_COLOR);
|
||||
}
|
||||
|
||||
assertTrue(program.canUndo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUndoRedoHexInteger2() throws Exception {
|
||||
// remove code browser plugin so the cursor position does not
|
||||
@@ -514,7 +736,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest {
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
ByteViewerComponent c = findComponent(panel, "HexInteger");
|
||||
ByteViewerComponent c = findComponent(panel, "Hex Integer");
|
||||
panel.setCurrentView(c);
|
||||
// make 5 changes
|
||||
// verify that the Undo button is enabled and undo can be done 5 times
|
||||
@@ -579,6 +801,160 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest {
|
||||
assertTrue(program.canUndo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUndoRedoHexLong2() throws Exception {
|
||||
// remove code browser plugin so the cursor position does not
|
||||
// get changed because of location events that the code browser
|
||||
// generates.
|
||||
tool.removePlugins(new Plugin[] { cbPlugin });
|
||||
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
ByteViewerComponent c = findComponent(panel, "Hex Long");
|
||||
panel.setCurrentView(c);
|
||||
// make 9 changes
|
||||
// verify that the Undo button is enabled and undo can be done 5 times
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
Address addr = getAddr(0x01001003);
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
char[] values = { 'a', '1', '2', 'b', '3', 'c', '4', 'd', '5' };
|
||||
int[] keyCodes =
|
||||
{ KeyEvent.VK_P, KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_B, KeyEvent.VK_3,
|
||||
KeyEvent.VK_C, KeyEvent.VK_4, KeyEvent.VK_D, KeyEvent.VK_5 };
|
||||
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
for (int i = 0; i < 9; i++) {
|
||||
FieldLocation loc = currentComponent.getCursorLocation();
|
||||
KeyEvent ev = new KeyEvent(currentComponent, 0, new Date().getTime(), 0,
|
||||
keyCodes[i], values[i]);
|
||||
currentComponent.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol(), currentComponent.getCurrentField());
|
||||
}
|
||||
|
||||
});
|
||||
program.flushEvents();
|
||||
waitForSwing();
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
assertTrue(program.canUndo());
|
||||
|
||||
undo(program);
|
||||
|
||||
FieldLocation loc = c.getCursorLocation();
|
||||
ByteField field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
Color fg = field.getForeground();
|
||||
if (i == 8) {
|
||||
assertTrue(fg == null ||
|
||||
ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR == field.getForeground());
|
||||
}
|
||||
else {
|
||||
assertEquals(fg, ByteViewerComponentProvider.CHANGED_VALUE_COLOR);
|
||||
}
|
||||
}
|
||||
assertTrue(!program.canUndo());
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
|
||||
redo(program);
|
||||
|
||||
FieldLocation loc = c.getCursorLocation();
|
||||
ByteField field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
Color fg = field.getForeground();
|
||||
assertEquals(fg, ByteViewerComponentProvider.CHANGED_VALUE_COLOR);
|
||||
}
|
||||
|
||||
assertTrue(program.canUndo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUndoRedoHexLongLong2() throws Exception {
|
||||
// remove code browser plugin so the cursor position does not
|
||||
// get changed because of location events that the code browser
|
||||
// generates.
|
||||
tool.removePlugins(new Plugin[] { cbPlugin });
|
||||
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
ByteViewerComponent c = findComponent(panel, "Hex Long Long");
|
||||
panel.setCurrentView(c);
|
||||
// make 9 changes
|
||||
// verify that the Undo button is enabled and undo can be done 5 times
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
Address addr = getAddr(0x01001003);
|
||||
FieldLocation loc = getFieldLocation(addr);
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
char[] values = { 'a', '1', '2', 'b', '3', 'c', '4', 'd', '5', 'e', '6', 'f', '7', 'a',
|
||||
'8', 'b', '9' };
|
||||
int[] keyCodes =
|
||||
{ KeyEvent.VK_P, KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_B, KeyEvent.VK_3,
|
||||
KeyEvent.VK_C, KeyEvent.VK_4, KeyEvent.VK_D, KeyEvent.VK_5, KeyEvent.VK_E, KeyEvent.VK_6,
|
||||
KeyEvent.VK_F, KeyEvent.VK_7, KeyEvent.VK_G, KeyEvent.VK_8, KeyEvent.VK_H, KeyEvent.VK_9 };
|
||||
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
for (int i = 0; i < 17; i++) {
|
||||
FieldLocation loc = currentComponent.getCursorLocation();
|
||||
KeyEvent ev = new KeyEvent(currentComponent, 0, new Date().getTime(), 0,
|
||||
keyCodes[i], values[i]);
|
||||
currentComponent.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol(), currentComponent.getCurrentField());
|
||||
}
|
||||
|
||||
});
|
||||
program.flushEvents();
|
||||
waitForSwing();
|
||||
|
||||
for (int i = 0; i < 17; i++) {
|
||||
assertTrue(program.canUndo());
|
||||
|
||||
undo(program);
|
||||
|
||||
FieldLocation loc = c.getCursorLocation();
|
||||
ByteField field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
Color fg = field.getForeground();
|
||||
if (i == 16) {
|
||||
assertTrue(fg == null ||
|
||||
ByteViewerComponentProvider.CURSOR_NON_ACTIVE_COLOR == field.getForeground());
|
||||
}
|
||||
else {
|
||||
assertEquals(fg, ByteViewerComponentProvider.CHANGED_VALUE_COLOR);
|
||||
}
|
||||
}
|
||||
assertTrue(!program.canUndo());
|
||||
|
||||
for (int i = 0; i < 17; i++) {
|
||||
|
||||
redo(program);
|
||||
|
||||
FieldLocation loc = c.getCursorLocation();
|
||||
ByteField field = c.getField(loc.getIndex(), loc.getFieldNum());
|
||||
Color fg = field.getForeground();
|
||||
assertEquals(fg, ByteViewerComponentProvider.CHANGED_VALUE_COLOR);
|
||||
}
|
||||
|
||||
assertTrue(program.canUndo());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditInputHex() throws Exception {
|
||||
env.showTool();
|
||||
@@ -717,12 +1093,129 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest {
|
||||
assertEquals(value, program.getMemory().getByte(getAddr(0x01001000)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditModeHexShort() throws Exception {
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final ByteViewerComponent c = findComponent(panel, "Hex Short");
|
||||
panel.setCurrentView(c);
|
||||
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
final FieldLocation loc = getFieldLocation(getAddr(0x01001003));
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
assertTrue(action.isSelected());
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor());
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1');
|
||||
c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(),
|
||||
c.getCurrentField());
|
||||
});
|
||||
program.flushEvents();
|
||||
assertEquals((byte) 0x10, program.getMemory().getByte(getAddr(0x01001003)));
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR,
|
||||
((ByteField) c.getCurrentField()).getForeground());
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
action.setSelected(false);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
assertTrue(!action.isSelected());
|
||||
assertEquals(ByteViewerComponentProvider.CURSOR_ACTIVE_COLOR,
|
||||
c.getFocusedCursorColor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditModeHexInteger() throws Exception {
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final ByteViewerComponent c = findComponent(panel, "HexInteger");
|
||||
final ByteViewerComponent c = findComponent(panel, "Hex Integer");
|
||||
panel.setCurrentView(c);
|
||||
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
final FieldLocation loc = getFieldLocation(getAddr(0x01001003));
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
assertTrue(action.isSelected());
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor());
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1');
|
||||
c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(),
|
||||
c.getCurrentField());
|
||||
});
|
||||
program.flushEvents();
|
||||
assertEquals((byte) 0x10, program.getMemory().getByte(getAddr(0x01001003)));
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR,
|
||||
((ByteField) c.getCurrentField()).getForeground());
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
action.setSelected(false);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
assertTrue(!action.isSelected());
|
||||
assertEquals(ByteViewerComponentProvider.CURSOR_ACTIVE_COLOR,
|
||||
c.getFocusedCursorColor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditModeHexLong() throws Exception {
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final ByteViewerComponent c = findComponent(panel, "Hex Long");
|
||||
panel.setCurrentView(c);
|
||||
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
final FieldLocation loc = getFieldLocation(getAddr(0x01001003));
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
assertTrue(action.isSelected());
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor());
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1');
|
||||
c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(),
|
||||
c.getCurrentField());
|
||||
});
|
||||
program.flushEvents();
|
||||
assertEquals((byte) 0x10, program.getMemory().getByte(getAddr(0x01001003)));
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR,
|
||||
((ByteField) c.getCurrentField()).getForeground());
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
action.setSelected(false);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
});
|
||||
assertTrue(!action.isSelected());
|
||||
assertEquals(ByteViewerComponentProvider.CURSOR_ACTIVE_COLOR,
|
||||
c.getFocusedCursorColor());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditModeHexLongLong() throws Exception {
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final ByteViewerComponent c = findComponent(panel, "Hex Long Long");
|
||||
panel.setCurrentView(c);
|
||||
|
||||
final ToggleDockingAction action =
|
||||
@@ -1563,7 +2056,10 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest {
|
||||
ByteViewerOptionsDialog dialog = launchByteViewerOptions();
|
||||
setViewSelected(dialog, "Ascii", true);
|
||||
setViewSelected(dialog, "Octal", true);
|
||||
setViewSelected(dialog, "HexInteger", true);
|
||||
setViewSelected(dialog, "Hex Short", true);
|
||||
setViewSelected(dialog, "Hex Integer", true);
|
||||
setViewSelected(dialog, "Hex Long", true);
|
||||
setViewSelected(dialog, "Hex Long Long", true);
|
||||
pressButtonByText(dialog.getComponent(), "OK");
|
||||
}
|
||||
|
||||
|
||||
@@ -237,13 +237,72 @@ public class ByteViewerPluginFormatsTest extends AbstractGhidraHeadedIntegration
|
||||
assertEquals(insertionStr, findLabelStr(panel, "Insertion"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHexShortView() throws Exception {
|
||||
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final ByteViewerComponent c = findComponent(panel, "Hex Short");
|
||||
panel.setCurrentView(c);
|
||||
assertEquals(8, c.getNumberOfFields());
|
||||
assertEquals(2, c.getDataModel().getUnitByteSize());
|
||||
|
||||
final FieldLocation loc = getFieldLocation(getAddr(0x01001000));
|
||||
runSwing(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
});
|
||||
// verify that the 2 bytes are represented as an 4 digit hex number
|
||||
assertEquals(4, c.getCurrentField().getNumCols(loc.getRow()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOtherEditsHexShort() throws Exception {
|
||||
// verify that the 4 byte string is rendered in red when a byte
|
||||
// is changed from another view, e.g. Ascii or Hex
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final ByteViewerComponent c = findComponent(panel, "Ascii");
|
||||
panel.setCurrentView(c);
|
||||
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
final FieldLocation loc = getFieldLocation(getAddr(0x01001000));
|
||||
runSwing(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
KeyEvent ev =
|
||||
new KeyEvent(currentComponent, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1');
|
||||
currentComponent.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol(), currentComponent.getCurrentField());
|
||||
});
|
||||
program.flushEvents();
|
||||
|
||||
final ByteViewerComponent hexComp = findComponent(panel, "Hex Short");
|
||||
|
||||
runSwing(() -> {
|
||||
ProgramByteBlockSet blockset =
|
||||
(ProgramByteBlockSet) plugin.getProvider().getByteBlockSet();
|
||||
ByteBlockInfo bbInfo = blockset.getByteBlockInfo(getAddr(0x01001000));
|
||||
FieldLocation l = hexComp.getFieldLocation(bbInfo.getBlock(), bbInfo.getOffset());
|
||||
hexComp.setCursorPosition(l.getIndex(), l.getFieldNum(), 0, 0);
|
||||
});
|
||||
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR,
|
||||
((ByteField) hexComp.getCurrentField()).getForeground());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHexIntegerView() throws Exception {
|
||||
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final ByteViewerComponent c = findComponent(panel, "HexInteger");
|
||||
final ByteViewerComponent c = findComponent(panel, "Hex Integer");
|
||||
panel.setCurrentView(c);
|
||||
assertEquals(4, c.getNumberOfFields());
|
||||
assertEquals(4, c.getDataModel().getUnitByteSize());
|
||||
@@ -282,7 +341,125 @@ public class ByteViewerPluginFormatsTest extends AbstractGhidraHeadedIntegration
|
||||
});
|
||||
program.flushEvents();
|
||||
|
||||
final ByteViewerComponent hexComp = findComponent(panel, "HexInteger");
|
||||
final ByteViewerComponent hexComp = findComponent(panel, "Hex Integer");
|
||||
|
||||
runSwing(() -> {
|
||||
ProgramByteBlockSet blockset =
|
||||
(ProgramByteBlockSet) plugin.getProvider().getByteBlockSet();
|
||||
ByteBlockInfo bbInfo = blockset.getByteBlockInfo(getAddr(0x01001000));
|
||||
FieldLocation l = hexComp.getFieldLocation(bbInfo.getBlock(), bbInfo.getOffset());
|
||||
hexComp.setCursorPosition(l.getIndex(), l.getFieldNum(), 0, 0);
|
||||
});
|
||||
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR,
|
||||
((ByteField) hexComp.getCurrentField()).getForeground());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHexLongView() throws Exception {
|
||||
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final ByteViewerComponent c = findComponent(panel, "Hex Long");
|
||||
panel.setCurrentView(c);
|
||||
assertEquals(2, c.getNumberOfFields());
|
||||
assertEquals(8, c.getDataModel().getUnitByteSize());
|
||||
|
||||
final FieldLocation loc = getFieldLocation(getAddr(0x01001000));
|
||||
runSwing(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
});
|
||||
// verify that the 8 bytes are represented as an 8 digit hex number
|
||||
assertEquals(16, c.getCurrentField().getNumCols(loc.getRow()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOtherEditsHexLong() throws Exception {
|
||||
// verify that the 4 byte string is rendered in red when a byte
|
||||
// is changed from another view, e.g. Ascii or Hex
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final ByteViewerComponent c = findComponent(panel, "Ascii");
|
||||
panel.setCurrentView(c);
|
||||
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
final FieldLocation loc = getFieldLocation(getAddr(0x01001000));
|
||||
runSwing(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
KeyEvent ev =
|
||||
new KeyEvent(currentComponent, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1');
|
||||
currentComponent.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol(), currentComponent.getCurrentField());
|
||||
});
|
||||
program.flushEvents();
|
||||
|
||||
final ByteViewerComponent hexComp = findComponent(panel, "Hex Long");
|
||||
|
||||
runSwing(() -> {
|
||||
ProgramByteBlockSet blockset =
|
||||
(ProgramByteBlockSet) plugin.getProvider().getByteBlockSet();
|
||||
ByteBlockInfo bbInfo = blockset.getByteBlockInfo(getAddr(0x01001000));
|
||||
FieldLocation l = hexComp.getFieldLocation(bbInfo.getBlock(), bbInfo.getOffset());
|
||||
hexComp.setCursorPosition(l.getIndex(), l.getFieldNum(), 0, 0);
|
||||
});
|
||||
|
||||
assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR,
|
||||
((ByteField) hexComp.getCurrentField()).getForeground());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHexLongLongView() throws Exception {
|
||||
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final ByteViewerComponent c = findComponent(panel, "Hex Long Long");
|
||||
panel.setCurrentView(c);
|
||||
assertEquals(1, c.getNumberOfFields());
|
||||
assertEquals(16, c.getDataModel().getUnitByteSize());
|
||||
|
||||
final FieldLocation loc = getFieldLocation(getAddr(0x01001000));
|
||||
runSwing(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
});
|
||||
// verify that the 16 bytes are represented as an 32 digit hex number
|
||||
assertEquals(32, c.getCurrentField().getNumCols(loc.getRow()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOtherEditsHexLongLong() throws Exception {
|
||||
// verify that the 4 byte string is rendered in red when a byte
|
||||
// is changed from another view, e.g. Ascii or Hex
|
||||
env.showTool();
|
||||
addViews();
|
||||
|
||||
final ByteViewerComponent c = findComponent(panel, "Ascii");
|
||||
panel.setCurrentView(c);
|
||||
|
||||
final ToggleDockingAction action =
|
||||
(ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing");
|
||||
final FieldLocation loc = getFieldLocation(getAddr(0x01001000));
|
||||
runSwing(() -> {
|
||||
ByteViewerComponent currentComponent = panel.getCurrentComponent();
|
||||
currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0);
|
||||
action.setSelected(true);
|
||||
action.actionPerformed(new DefaultActionContext());
|
||||
KeyEvent ev =
|
||||
new KeyEvent(currentComponent, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1');
|
||||
currentComponent.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(),
|
||||
loc.getCol(), currentComponent.getCurrentField());
|
||||
});
|
||||
program.flushEvents();
|
||||
|
||||
final ByteViewerComponent hexComp = findComponent(panel, "Hex Long Long");
|
||||
|
||||
runSwing(() -> {
|
||||
ProgramByteBlockSet blockset =
|
||||
@@ -402,7 +579,7 @@ public class ByteViewerPluginFormatsTest extends AbstractGhidraHeadedIntegration
|
||||
ByteViewerOptionsDialog dialog = launchByteViewerOptions();
|
||||
setViewSelected(dialog, "Ascii", true);
|
||||
setViewSelected(dialog, "Octal", true);
|
||||
setViewSelected(dialog, "HexInteger", true);
|
||||
setViewSelected(dialog, "Hex Integer", true);
|
||||
setViewSelected(dialog, "Integer", true);
|
||||
pressButtonByText(dialog.getComponent(), "OK");
|
||||
waitForSwing();
|
||||
@@ -805,7 +982,10 @@ public class ByteViewerPluginFormatsTest extends AbstractGhidraHeadedIntegration
|
||||
ByteViewerOptionsDialog dialog = launchByteViewerOptions();
|
||||
setViewSelected(dialog, "Ascii", true);
|
||||
setViewSelected(dialog, "Octal", true);
|
||||
setViewSelected(dialog, "HexInteger", true);
|
||||
setViewSelected(dialog, "Hex Short", true);
|
||||
setViewSelected(dialog, "Hex Integer", true);
|
||||
setViewSelected(dialog, "Hex Long", true);
|
||||
setViewSelected(dialog, "Hex Long Long", true);
|
||||
pressButtonByText(dialog.getComponent(), "OK");
|
||||
waitForSwing();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user