mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-10 06:02:09 +00:00
Merge remote-tracking branch 'origin/GP-4928_emteere_PasteHexdump--SQUASHED' into Ghidra_11.2
This commit is contained in:
commit
fd097fb7a6
@ -4,21 +4,26 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
//Useful for getting bytes into a program that have been copied and pasted
|
// Useful for getting bytes into a program that have been copied and pasted
|
||||||
//as text onto a website or other text documents. If there is no program open
|
// as text onto a website or other text documents. The bytes can be from a listing
|
||||||
//when the script is run, you will be prompted to select a processor and a
|
// or from a hexdump.
|
||||||
//new empty program will be created. Text in the copy buffer will be parsed
|
//
|
||||||
//to extract address and bytes, and everything else will be ignored.
|
// If there is no program open when the script is run, you will be prompted
|
||||||
//Example listing text:
|
// to select a processor and a new empty program will be created.
|
||||||
|
//
|
||||||
|
// Text in the clipboard will be parsed
|
||||||
|
// to extract address and bytes, and everything else will be ignored.
|
||||||
|
//
|
||||||
|
// Example listing text:
|
||||||
// LAB_0007aaca XREF[1]:
|
// LAB_0007aaca XREF[1]:
|
||||||
// 0007aac0(j)
|
// 0007aac0(j)
|
||||||
// 0007aaca 01 24
|
// 0007aaca 01 24
|
||||||
@ -30,20 +35,33 @@
|
|||||||
//
|
//
|
||||||
// 0007aad6 1f d0
|
// 0007aad6 1f d0
|
||||||
// beq LAB_0007ab18
|
// beq LAB_0007ab18
|
||||||
|
//
|
||||||
|
// Example hexdump text:
|
||||||
|
// Hex dump of section '.text':
|
||||||
|
// NOTE: This section has relocations against it, but these have NOT been applied to this dump.
|
||||||
|
// 0x00000000 80b487b0 00aff860 c7e90023 3b683b61 .......`...#;h;a
|
||||||
|
// 0x00000010 b7f92030 7b61fb68 1a4607f1 100393e8 .. 0{a.h.F......
|
||||||
|
// ...
|
||||||
|
// 0x00000210 1a443b6a 13441846 1437bd46 5df8047b .D;j.D.F.7.F]..{
|
||||||
|
//
|
||||||
//@category Program
|
//@category Program
|
||||||
//@menupath Edit.Paste Listing Text
|
//@menupath Edit.Paste Listing Text
|
||||||
import java.awt.datatransfer.*;
|
import java.awt.datatransfer.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import docking.dnd.GClipboard;
|
import docking.dnd.GClipboard;
|
||||||
import ghidra.app.script.GhidraScript;
|
import ghidra.app.script.GhidraScript;
|
||||||
import ghidra.app.services.ProgramManager;
|
import ghidra.app.services.ProgramManager;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.mem.*;
|
import ghidra.program.model.mem.*;
|
||||||
|
import ghidra.util.NumericUtilities;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
|
||||||
public class PasteCopiedListingBytesScript extends GhidraScript {
|
public class PasteCopiedListingBytesScript extends GhidraScript {
|
||||||
|
|
||||||
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
int id = 0;
|
int id = 0;
|
||||||
if (currentProgram == null) {
|
if (currentProgram == null) {
|
||||||
@ -57,18 +75,20 @@ public class PasteCopiedListingBytesScript extends GhidraScript {
|
|||||||
Memory memory = currentProgram.getMemory();
|
Memory memory = currentProgram.getMemory();
|
||||||
|
|
||||||
// get data from the clip board and turn it into a string
|
// get data from the clip board and turn it into a string
|
||||||
String ClipboardText = retrieveClipBoardText();
|
String clipBoardText = retrieveClipBoardText();
|
||||||
if (ClipboardText == null) {
|
if (clipBoardText == null) {
|
||||||
println("Nothing is copied to your clip board");
|
println("Nothing is copied to your clip board");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// evaluate the copy buffer and get the byte array
|
// evaluate the copy buffer and get the byte array
|
||||||
Map<Address, byte[]> bytesToAdd = parseListingStringToByte(ClipboardText);
|
Map<Address, byte[]> bytesToAdd = parseListingStringToByte(clipBoardText);
|
||||||
if (bytesToAdd.isEmpty()) {
|
if (bytesToAdd.isEmpty()) {
|
||||||
println("There are no bytes copied to your clip board");
|
println("There are no bytes copied to your clip board");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
coalesceBytes(bytesToAdd);
|
||||||
|
|
||||||
// Check if memory block with the byte+address exists
|
// Check if memory block with the byte+address exists
|
||||||
boolean exists = checkForExistingMemory(memory, bytesToAdd);
|
boolean exists = checkForExistingMemory(memory, bytesToAdd);
|
||||||
@ -97,6 +117,35 @@ public class PasteCopiedListingBytesScript extends GhidraScript {
|
|||||||
println("Created " + getNeededAddressSet(bytesToAdd));
|
println("Created " + getNeededAddressSet(bytesToAdd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void coalesceBytes(Map<Address, byte[]> bytesToAdd) {
|
||||||
|
// Map is assumed to be a sorted Map
|
||||||
|
Set<Entry<Address, byte[]>> entrySet = bytesToAdd.entrySet();
|
||||||
|
Iterator<Entry<Address, byte[]>> iterator = entrySet.iterator();
|
||||||
|
Map.Entry<Address, byte[]> entryA = iterator.next();
|
||||||
|
while (entryA != null && iterator.hasNext()) {
|
||||||
|
Map.Entry<Address, byte[]> entryB = iterator.next();
|
||||||
|
Address addrA = entryA.getKey();
|
||||||
|
Address addrB = entryB.getKey();
|
||||||
|
byte bytesA[] = entryA.getValue();
|
||||||
|
if (addrA.add(bytesA.length).equals(addrB)) {
|
||||||
|
byte bytesB[] = entryB.getValue();
|
||||||
|
// coalesce, and res-start iterator
|
||||||
|
byte concatBytes[] = Arrays.copyOf(bytesA,bytesA.length+bytesB.length);
|
||||||
|
System.arraycopy(bytesB, 0, concatBytes, bytesA.length, bytesB.length);
|
||||||
|
|
||||||
|
bytesToAdd.replace(addrA, concatBytes);
|
||||||
|
bytesToAdd.remove(addrB);
|
||||||
|
iterator = entrySet.iterator();
|
||||||
|
entryA = null;
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
entryA = iterator.next();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entryA = entryB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void createMissingMemory(Map<Address, byte[]> bytesToAdd, Memory memory)
|
private void createMissingMemory(Map<Address, byte[]> bytesToAdd, Memory memory)
|
||||||
throws CancelledException, Exception {
|
throws CancelledException, Exception {
|
||||||
AddressSet neededMem = getNeededAddressSet(bytesToAdd);
|
AddressSet neededMem = getNeededAddressSet(bytesToAdd);
|
||||||
@ -151,44 +200,85 @@ public class PasteCopiedListingBytesScript extends GhidraScript {
|
|||||||
|
|
||||||
private Map<Address, byte[]> parseListingStringToByte(String ClipboardText)
|
private Map<Address, byte[]> parseListingStringToByte(String ClipboardText)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
// TreeMap so the entries will be sorted by Address
|
||||||
|
Map<Address, byte[]> newMap = new TreeMap<Address, byte[]>();
|
||||||
String[] bufferLines = ClipboardText.split("\n");
|
String[] bufferLines = ClipboardText.split("\n");
|
||||||
Map<Address, byte[]> newMap = new HashMap<Address, byte[]>();
|
|
||||||
|
Address firstAddress = null;
|
||||||
|
|
||||||
|
// For each line, look for address and bytes, accumlate address/byteStrings
|
||||||
|
// in a list, throwing out any text that can't be parsed
|
||||||
for (String line : bufferLines) {
|
for (String line : bufferLines) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
|
if (line.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
String[] words = line.split(" ");
|
String[] words = line.split(" ");
|
||||||
|
if (words.length == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
String startOfLine = words[0];
|
String startOfLine = words[0];
|
||||||
Address firstAddress = toAddr(startOfLine);
|
// if start of line word is > 2 assume address
|
||||||
|
// other wise, consider it a continuation of the
|
||||||
|
// previous address
|
||||||
|
// 001325a4 03 00 0b0 sethi %hi(0x1000),g1
|
||||||
|
// 00 04
|
||||||
|
|
||||||
|
boolean skipFirstWord = false;
|
||||||
|
if (startOfLine.length() > 2) {
|
||||||
|
firstAddress = toAddr(startOfLine);
|
||||||
|
skipFirstWord = true;
|
||||||
|
}
|
||||||
if (firstAddress == null) {
|
if (firstAddress == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
List<String> bytesFound = new ArrayList<String>();
|
List<String> bytesStringsList = new ArrayList<String>();
|
||||||
|
int numBytesFound = 0;
|
||||||
for (String word : words) {
|
for (String word : words) {
|
||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
if (word == words[0]) {
|
if (skipFirstWord) {
|
||||||
|
skipFirstWord = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (word.isBlank() || word.length() > 2) {
|
// break if bytes already found and separator more than one " "
|
||||||
|
// 001325a4 03 00 0b0 sethi %hi(0x1000),g1
|
||||||
|
if (numBytesFound > 0 && word.isBlank()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int len = word.length();
|
||||||
|
if (word.isBlank() || len > 8 || (len % 2) != 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Integer.parseInt(word, 16);
|
Long.parseLong(word, 16);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bytesFound.add(word);
|
bytesStringsList.add(word);
|
||||||
|
numBytesFound += len / 2;
|
||||||
}
|
|
||||||
byte[] newBytes = new byte[bytesFound.size()];
|
|
||||||
int i = 0;
|
|
||||||
for (String byteString : bytesFound) {
|
|
||||||
monitor.checkCancelled();
|
|
||||||
byte bVal = (byte) Integer.parseInt(byteString, 16);
|
|
||||||
newBytes[i++] = bVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse found address/byteStrings into byte array
|
||||||
|
byte newBytes[] = parseHexStrings(bytesStringsList,numBytesFound);
|
||||||
newMap.put(firstAddress, newBytes);
|
newMap.put(firstAddress, newBytes);
|
||||||
|
firstAddress = firstAddress.add(newBytes.length);
|
||||||
}
|
}
|
||||||
return newMap;
|
return newMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte[] parseHexStrings(List<String> byteStringsList, int numBytesFound)
|
||||||
|
throws CancelledException {
|
||||||
|
byte[] newBytes = new byte[numBytesFound];
|
||||||
|
int byteArrayIndex = 0;
|
||||||
|
for (String byteString : byteStringsList) {
|
||||||
|
monitor.checkCancelled();
|
||||||
|
int numBytes = byteString.length() / 2;
|
||||||
|
byte[] bytes = NumericUtilities.convertStringToBytes(byteString);
|
||||||
|
System.arraycopy(bytes, 0, newBytes, byteArrayIndex, bytes.length);
|
||||||
|
byteArrayIndex += bytes.length;
|
||||||
|
}
|
||||||
|
return newBytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,332 @@
|
|||||||
|
/* ###
|
||||||
|
* 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.script;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.awt.datatransfer.*;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
import docking.dnd.GClipboard;
|
||||||
|
import ghidra.framework.Application;
|
||||||
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
|
import ghidra.test.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the {@code PasteCopiedListingBytesScript}, which grabs the copy buffer, and
|
||||||
|
* attempts to parse out address/bytes from either listing format or hexdump format.
|
||||||
|
*/
|
||||||
|
public class PasteCopiedListingBytesScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
|
private TestEnv env;
|
||||||
|
private File script;
|
||||||
|
|
||||||
|
private Program program;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
|
||||||
|
program = buildProgram();
|
||||||
|
|
||||||
|
env = new TestEnv();
|
||||||
|
env.launchDefaultTool(program);
|
||||||
|
|
||||||
|
String scriptPath = "ghidra_scripts/PasteCopiedListingBytesScript.java";
|
||||||
|
script = Application.getModuleFile("Base", scriptPath).getFile(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
env.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Program buildProgram() throws Exception {
|
||||||
|
ToyProgramBuilder builder = new ToyProgramBuilder("Test", true, this);
|
||||||
|
|
||||||
|
return builder.getProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetGetClipBoard() throws Exception {
|
||||||
|
|
||||||
|
setClipBoardContents("foo");
|
||||||
|
|
||||||
|
Clipboard systemClipboard = GClipboard.getSystemClipboard();
|
||||||
|
Transferable contents = systemClipboard.getContents(this);
|
||||||
|
assertEquals("foo", contents.getTransferData(DataFlavor.stringFlavor));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoneValid() throws Exception {
|
||||||
|
|
||||||
|
setClipBoardContents("Hex dump of section '.text':\n" +
|
||||||
|
" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n");
|
||||||
|
|
||||||
|
ScriptTaskListener listener = env.runScript(script);
|
||||||
|
|
||||||
|
waitForScriptCompletion(listener, 20000);
|
||||||
|
|
||||||
|
// test that memory blocks created
|
||||||
|
MemoryBlock[] blocks = program.getMemory().getBlocks();
|
||||||
|
assertEquals(0,blocks.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoText() throws Exception {
|
||||||
|
|
||||||
|
// clear clipboard
|
||||||
|
Clipboard systemClipboard = GClipboard.getSystemClipboard();
|
||||||
|
systemClipboard.setContents(new Transferable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||||
|
return flavor.equals(DataFlavor.stringFlavor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataFlavor[] getTransferDataFlavors() {
|
||||||
|
DataFlavor[] df = new DataFlavor[] { DataFlavor.stringFlavor };
|
||||||
|
return df;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getTransferData(DataFlavor flavor)
|
||||||
|
throws UnsupportedFlavorException, IOException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, new ClipboardOwner() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lostOwnership(Clipboard clipboard, Transferable contents) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ScriptTaskListener listener = env.runScript(script);
|
||||||
|
|
||||||
|
waitForScriptCompletion(listener, 20000);
|
||||||
|
|
||||||
|
// test that memory blocks created
|
||||||
|
MemoryBlock[] blocks = program.getMemory().getBlocks();
|
||||||
|
assertEquals(0,blocks.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPasteListing() throws Exception {
|
||||||
|
|
||||||
|
setClipBoardContents(
|
||||||
|
" 00010004 f0 07 a0 40 060 lduw [fp+local_res40],i0\n" +
|
||||||
|
" 00010008 81 c7 e0 0c 060 jmpl i7+0xc\n" +
|
||||||
|
" 0001000c 81 e8 00 00 _restore\n" +
|
||||||
|
" LAB_00010024 XREF[1]: 00010018 \n" +
|
||||||
|
" 00010024 f0 07 bf f8 lduw [fp+-0x8],i0\n" +
|
||||||
|
" 00010028 40 00 03 f6 call EXTERNAL:<EXTERNAL>::r undefined r()\n" +
|
||||||
|
" 0001002c f0 27 bf _stw i0,[fp+-0xc]\n" +
|
||||||
|
"");
|
||||||
|
|
||||||
|
ScriptTaskListener listener = env.runScript(script);
|
||||||
|
|
||||||
|
waitForScriptCompletion(listener, 20000);
|
||||||
|
|
||||||
|
// test that memory blocks created
|
||||||
|
MemoryBlock[] blocks = program.getMemory().getBlocks();
|
||||||
|
assertEquals(2,blocks.length);
|
||||||
|
MemoryBlock block = blocks[0];
|
||||||
|
|
||||||
|
assertEquals(block.getStart().getOffset(), 0x10004L);
|
||||||
|
assertEquals(block.getEnd().getOffset(), 0x1000fL);
|
||||||
|
Address addr = block.getStart();
|
||||||
|
assertEquals(block.getByte(addr),(byte)0xf0);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x1000c")),(byte)0x81);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x1000f")),(byte)0x00);
|
||||||
|
|
||||||
|
block = blocks[1];
|
||||||
|
assertEquals(block.getStart().getOffset(), 0x10024L);
|
||||||
|
assertEquals(block.getEnd().getOffset(), 0x1002eL);
|
||||||
|
addr = block.getStart();
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x10024")),(byte)0xf0);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x1002a")),(byte)0x03);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x1002e")),(byte)0xbf);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPasteListingMultiLine() throws Exception {
|
||||||
|
|
||||||
|
setClipBoardContents(
|
||||||
|
" //\n" +
|
||||||
|
" **************************************************************\n" +
|
||||||
|
" * FUNCTION *\n" +
|
||||||
|
" **************************************************************\n" +
|
||||||
|
" F __stdcall f(F * __return_storage_ptr__)\n" +
|
||||||
|
" F o0:4 (ptr) <RETURN>\n" +
|
||||||
|
" F * Stack[0x40]: __return_storage_ptr__ XREF[1]: 00010004(R) \n" +
|
||||||
|
" undefined4 Stack[0x40]:4 local_res40 XREF[1]: 00010004(R) \n" +
|
||||||
|
" f XREF[3]: Entry Point(*), 00010018(c), \n" +
|
||||||
|
" _elfSectionHeaders::0000005c(*) \n" +
|
||||||
|
" 00010000 9d e3 0 save sp,-0x60,sp\n" +
|
||||||
|
" bf a0\n" +
|
||||||
|
" 00010004 f0 07 060 lduw [fp+local_res40],i0\n" +
|
||||||
|
" a0 40\n" +
|
||||||
|
" 00010008 81 c7 060 jmpl i7+0xc\n" +
|
||||||
|
" e0 0c\n" +
|
||||||
|
" 0001000c 81 e8 _restore\n" +
|
||||||
|
" 00 00\n" +
|
||||||
|
" 00010014 b0 07 add fp,-0x8,i0\n" +
|
||||||
|
" bf f8\n" +
|
||||||
|
" ");
|
||||||
|
|
||||||
|
ScriptTaskListener listener = env.runScript(script);
|
||||||
|
|
||||||
|
waitForScriptCompletion(listener, 20000);
|
||||||
|
|
||||||
|
// test that memory blocks created
|
||||||
|
MemoryBlock[] blocks = program.getMemory().getBlocks();
|
||||||
|
assertEquals(2,blocks.length);
|
||||||
|
MemoryBlock block = blocks[0];
|
||||||
|
|
||||||
|
assertEquals(block.getStart().getOffset(), 0x10000L);
|
||||||
|
assertEquals(block.getEnd().getOffset(), 0x1000fL);
|
||||||
|
Address addr = block.getStart();
|
||||||
|
assertEquals(block.getByte(addr),(byte)0x9d);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x1000c")),(byte)0x81);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x1000f")),(byte)0x00);
|
||||||
|
|
||||||
|
block = blocks[1];
|
||||||
|
assertEquals(block.getStart().getOffset(), 0x10014L);
|
||||||
|
assertEquals(block.getEnd().getOffset(), 0x10017L);
|
||||||
|
addr = block.getStart();
|
||||||
|
assertEquals(block.getByte(addr),(byte)0xb0);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x10016")),(byte)0xbf);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x10017")),(byte)0xf8);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPasteHexDump1Block() throws Exception {
|
||||||
|
|
||||||
|
setClipBoardContents("Hex dump of section '.text':\n" +
|
||||||
|
" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n" +
|
||||||
|
" 0x00000000 80b487b0 00aff860 c7e90023 3b683b61 .......`...#;h;a\n" +
|
||||||
|
" 0x00000010 b7f92030 7b61fb68 1a4607f1 100393e8 .. 0{a.h.F......\n" +
|
||||||
|
" 0x00000020 030082e8 0300f868 1c37bd46 5df8047b .......h.7.F]..{\n" +
|
||||||
|
" 0x00000030 704780b4 83b000af 87ed000b 4ff0ff33 pG..........O..3\n" +
|
||||||
|
" 0x00000040 18460c37 bd465df8 047b7047 80b485b0 .F.7.F]..{pG....");
|
||||||
|
|
||||||
|
ScriptTaskListener listener = env.runScript(script);
|
||||||
|
|
||||||
|
waitForScriptCompletion(listener, 20000);
|
||||||
|
|
||||||
|
// test that memory blocks created
|
||||||
|
MemoryBlock[] blocks = program.getMemory().getBlocks();
|
||||||
|
assertEquals(1,blocks.length);
|
||||||
|
MemoryBlock block = blocks[0];
|
||||||
|
|
||||||
|
assertEquals(block.getStart().getOffset(), 0x0000L);
|
||||||
|
assertEquals(block.getEnd().getOffset(), 0x004fL);
|
||||||
|
Address addr = block.getStart();
|
||||||
|
assertEquals(block.getByte(addr),(byte)0x80);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x0024")),(byte)0x03);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x004f")),(byte)0xb0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPasteHexDump3Blocks() throws Exception {
|
||||||
|
|
||||||
|
setClipBoardContents("Hex dump of section '.text':\n" +
|
||||||
|
" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n" +
|
||||||
|
" 0x00000000 80b487b0 00aff860 c7e90023 3b683b61 .......`...#;h;a\n" +
|
||||||
|
" 0x00000010 b7f92030 7b61fb68 1a4607f1 .. 0{a.h.F......\n" +
|
||||||
|
" 0x00000020 030082e8 0300f868 1c37bd46 5df8047b .......h.7.F]..{\n" +
|
||||||
|
" 0x00000030 704780b4 83b000af 87ed pG..........O..3\n" +
|
||||||
|
" 0x00000040 18460c37 bd465df8 047b7047 80b485b0 .F.7.F]..{pG....");
|
||||||
|
|
||||||
|
ScriptTaskListener listener = env.runScript(script);
|
||||||
|
|
||||||
|
waitForScriptCompletion(listener, 20000);
|
||||||
|
|
||||||
|
// test that memory blocks created
|
||||||
|
MemoryBlock[] blocks = program.getMemory().getBlocks();
|
||||||
|
assertEquals(3,blocks.length);
|
||||||
|
MemoryBlock block = blocks[0];
|
||||||
|
|
||||||
|
assertEquals(28, block.getSize());
|
||||||
|
assertEquals(block.getStart().getOffset(), 0x00000L);
|
||||||
|
|
||||||
|
Address addr = block.getStart();
|
||||||
|
assertEquals((byte)0x80,block.getByte(addr.getAddress("0x00000")));
|
||||||
|
assertEquals((byte)0xb7,block.getByte(addr.getAddress("0x00010")));
|
||||||
|
assertEquals((byte)0xf1,block.getByte(addr.getAddress("0x0001b")));
|
||||||
|
|
||||||
|
block = blocks[1];
|
||||||
|
|
||||||
|
assertEquals(26, block.getSize());
|
||||||
|
assertEquals(block.getStart().getOffset(), 0x00020L);
|
||||||
|
|
||||||
|
addr = block.getStart();
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x00020")),(byte)0x03);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x00030")),(byte)0x70);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x00039")),(byte)0xed);
|
||||||
|
|
||||||
|
block = blocks[2];
|
||||||
|
|
||||||
|
assertEquals(16, block.getSize());
|
||||||
|
assertEquals(block.getStart().getOffset(), 0x00040L);
|
||||||
|
|
||||||
|
addr = block.getStart();
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x00040")),(byte)0x18);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x00048")),(byte)0x04);
|
||||||
|
assertEquals(block.getByte(addr.getAddress("0x0004f")),(byte)0xb0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Clipboard setClipBoardContents(String str) {
|
||||||
|
// put stuff in copy buffer
|
||||||
|
Clipboard systemClipboard = GClipboard.getSystemClipboard();
|
||||||
|
systemClipboard.setContents(new Transferable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||||
|
return flavor.equals(DataFlavor.stringFlavor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataFlavor[] getTransferDataFlavors() {
|
||||||
|
DataFlavor[] df = new DataFlavor[] { DataFlavor.stringFlavor };
|
||||||
|
return df;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getTransferData(DataFlavor flavor)
|
||||||
|
throws UnsupportedFlavorException, IOException {
|
||||||
|
if (!flavor.equals(DataFlavor.stringFlavor)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}, new ClipboardOwner() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lostOwnership(Clipboard clipboard, Transferable contents) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return systemClipboard;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user