mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +02:00
GT-3079 Added checking to binary loader to check for memory conflicts
before loading in the "add to program" case.
This commit is contained in:
parent
6da0d9340d
commit
ae5662a50f
19 changed files with 132 additions and 99 deletions
|
@ -225,14 +225,13 @@ public class MemoryBlockUtils {
|
|||
block = program.getMemory().createInitializedBlock(name, start, fileBytes, offset,
|
||||
length, isOverlay);
|
||||
}
|
||||
catch (MemoryConflictException e) {
|
||||
block = program.getMemory().createInitializedBlock(name, start, fileBytes, offset,
|
||||
length, true);
|
||||
catch (MemoryConflictException | DuplicateNameException e) {
|
||||
block = createBlockNoDuplicateName(program, name, start, fileBytes, offset, length);
|
||||
log.appendMsg("Conflict attempting to create memory block: " + name +
|
||||
" at address " + start.toString() + " Created block in new overlay instead");
|
||||
}
|
||||
}
|
||||
catch (LockException | DuplicateNameException | MemoryConflictException e) {
|
||||
catch (LockException | MemoryConflictException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
@ -241,6 +240,22 @@ public class MemoryBlockUtils {
|
|||
return block;
|
||||
}
|
||||
|
||||
private static MemoryBlock createBlockNoDuplicateName(Program program, String blockName,
|
||||
Address start, FileBytes fileBytes, long offset, long length)
|
||||
throws LockException, MemoryConflictException, AddressOverflowException {
|
||||
int count = 1;
|
||||
String name = blockName;
|
||||
while (true) {
|
||||
try {
|
||||
return program.getMemory().createInitializedBlock(name, start, fileBytes, offset,
|
||||
length, true);
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
name = blockName + "_" + count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new initialized block in memory using the bytes from the given input stream.
|
||||
* If there is a conflict when creating this block (some other block occupies at least some
|
||||
|
|
|
@ -139,7 +139,7 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program) {
|
||||
|
||||
if (options != null) {
|
||||
for (Option option : options) {
|
||||
|
@ -151,7 +151,7 @@ public abstract class AbstractLibrarySupportLoader extends AbstractProgramLoader
|
|||
}
|
||||
}
|
||||
}
|
||||
return super.validateOptions(provider, loadSpec, options);
|
||||
return super.validateOptions(provider, loadSpec, options, program);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -188,7 +188,7 @@ public abstract class AbstractProgramLoader implements Loader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program) {
|
||||
if (options != null) {
|
||||
for (Option option : options) {
|
||||
String name = option.getName();
|
||||
|
|
|
@ -23,16 +23,14 @@ import ghidra.app.util.bin.ByteProvider;
|
|||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.framework.model.DomainFolder;
|
||||
import ghidra.framework.model.DomainObject;
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.database.mem.FileBytes;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.*;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.NumericUtilities;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class BinaryLoader extends AbstractProgramLoader {
|
||||
|
@ -91,7 +89,8 @@ public class BinaryLoader extends AbstractProgramLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options,
|
||||
Program program) {
|
||||
Address baseAddr = null;
|
||||
long length = 0;
|
||||
long fileOffset = 0;
|
||||
|
@ -194,7 +193,12 @@ public class BinaryLoader extends AbstractProgramLoader {
|
|||
if (length == -1) {
|
||||
return "Invalid length specified";
|
||||
}
|
||||
return super.validateOptions(provider, loadSpec, options);
|
||||
if (program != null) {
|
||||
if (program.getMemory().intersects(baseAddr, baseAddr.add(length - 1))) {
|
||||
return "Memory Conflict: Use <Options...> to change the base address!";
|
||||
}
|
||||
}
|
||||
return super.validateOptions(provider, loadSpec, options, program);
|
||||
}
|
||||
|
||||
private Address getBaseAddr(List<Option> options) {
|
||||
|
@ -322,27 +326,27 @@ public class BinaryLoader extends AbstractProgramLoader {
|
|||
if (blockName == null || blockName.length() == 0) {
|
||||
blockName = generateBlockName(prog, isOverlay, baseAddr.getAddressSpace());
|
||||
}
|
||||
try {
|
||||
MemoryBlock block = prog.getMemory().createInitializedBlock(blockName, baseAddr,
|
||||
fileBytes, 0, length, isOverlay);
|
||||
block.setRead(true);
|
||||
block.setWrite(isOverlay ? false : true);
|
||||
block.setExecute(isOverlay ? false : true);
|
||||
block.setSourceName("Binary Loader");
|
||||
MemoryBlockUtils.adjustFragment(prog, block.getStart(), blockName);
|
||||
}
|
||||
catch (LockException | MemoryConflictException e) {
|
||||
Msg.error(this, "Unexpected exception creating memory block", e);
|
||||
}
|
||||
createBlock(prog, isOverlay, blockName, baseAddr, fileBytes, length, log);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (AddressOverflowException e) {
|
||||
throw new IllegalArgumentException("Invalid address range specified: start:" +
|
||||
baseAddr + ", length:" + length + " - end address exceeds address space boundary!");
|
||||
}
|
||||
catch (DuplicateNameException e) {
|
||||
throw new IllegalArgumentException("Duplicate block name specified: " + blockName);
|
||||
}
|
||||
|
||||
private void createBlock(Program prog, boolean isOverlay, String blockName, Address baseAddr,
|
||||
FileBytes fileBytes, long length, MessageLog log)
|
||||
throws AddressOverflowException, IOException {
|
||||
|
||||
if (prog.getMemory().intersects(baseAddr, baseAddr.add(length - 1))) {
|
||||
throw new IOException("Can't load " + length + " bytes at address " + baseAddr +
|
||||
" since it conflicts with existing memory blocks!");
|
||||
}
|
||||
MemoryBlockUtils.createInitializedBlock(prog, isOverlay, blockName, baseAddr, fileBytes, 0,
|
||||
length, null, "Binary Loader", true, !isOverlay, !isOverlay, log);
|
||||
|
||||
}
|
||||
|
||||
private long clipToMemorySpace(long length, MessageLog log, Program program) {
|
||||
|
|
|
@ -153,7 +153,7 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program) {
|
||||
if (options != null) {
|
||||
for (Option option : options) {
|
||||
String name = option.getName();
|
||||
|
@ -164,7 +164,7 @@ public class CoffLoader extends AbstractLibrarySupportLoader {
|
|||
}
|
||||
}
|
||||
}
|
||||
return super.validateOptions(provider, loadSpec, options);
|
||||
return super.validateOptions(provider, loadSpec, options, program);
|
||||
}
|
||||
|
||||
private boolean performFakeLinking(List<Option> options) {
|
||||
|
|
|
@ -90,14 +90,14 @@ public class ElfLoader extends AbstractLibrarySupportLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program) {
|
||||
if (options != null) {
|
||||
String validationErrorStr = ElfLoaderOptionsFactory.validateOptions(loadSpec, options);
|
||||
if (validationErrorStr != null) {
|
||||
return validationErrorStr;
|
||||
}
|
||||
}
|
||||
return super.validateOptions(provider, loadSpec, options);
|
||||
return super.validateOptions(provider, loadSpec, options, program);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -89,7 +89,7 @@ public class GdtLoader implements Loader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program) {
|
||||
if (options != null && options.size() > 0) {
|
||||
return "GDTLoader takes no options";
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public class GzfLoader implements Loader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program) {
|
||||
if (options != null && options.size() > 0) {
|
||||
return "GzfLoader takes no options";
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ public class IntelHexLoader extends AbstractProgramLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program) {
|
||||
Address baseAddr = null;
|
||||
|
||||
for (Option option : options) {
|
||||
|
|
|
@ -23,7 +23,6 @@ import ghidra.app.util.importer.MessageLog;
|
|||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
class IntelHexMemImage {
|
||||
|
@ -212,23 +211,9 @@ class IntelHexMemImage {
|
|||
}
|
||||
|
||||
String name = blockName == null ? base.getAddressSpace().getName() : blockName;
|
||||
while (true) {
|
||||
try {
|
||||
MemoryBlockUtils.createInitializedBlock(program, isOverlay, name,
|
||||
blockRange.getMinAddress(), new ByteArrayInputStream(data), data.length,
|
||||
"Generated by " + creator, progFile, true, !isOverlay, !isOverlay, log,
|
||||
monitor);
|
||||
break;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (!(cause instanceof DuplicateNameException)) {
|
||||
throw e;
|
||||
}
|
||||
++count;
|
||||
name = blockName + "_" + count;
|
||||
}
|
||||
}
|
||||
"Generated by " + creator, progFile, true, !isOverlay, !isOverlay, log, monitor);
|
||||
}
|
||||
return log.toString();
|
||||
}
|
||||
|
|
|
@ -124,10 +124,13 @@ public interface Loader extends ExtensionPoint, Comparable<Loader> {
|
|||
* @param provider The bytes of the thing being loaded.
|
||||
* @param loadSpec The proposed {@link LoadSpec}.
|
||||
* @param options The list of {@link Option}s to validate.
|
||||
* @param program existing program if the loader is adding to an existing program. If it is
|
||||
* a fresh import, then this will be null.
|
||||
* @return null if all {@link Option}s are valid; otherwise, an error message describing the
|
||||
* problem is returned.
|
||||
*/
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options);
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options,
|
||||
Program program);
|
||||
|
||||
/**
|
||||
* Gets the {@link Loader}'s name, which is used both for display purposes, and to identify the
|
||||
|
|
|
@ -92,7 +92,8 @@ public class MotorolaHexLoader extends AbstractProgramLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options,
|
||||
Program program) {
|
||||
Address baseAddr = null;
|
||||
|
||||
for (Option option : options) {
|
||||
|
@ -335,23 +336,9 @@ public class MotorolaHexLoader extends AbstractProgramLoader {
|
|||
|
||||
String name =
|
||||
blockName == null ? baseAddr.getAddressSpace().getName() : blockName;
|
||||
int count = 0;
|
||||
while (true) {
|
||||
try {
|
||||
MemoryBlockUtils.createInitializedBlock(program, isOverlay, name,
|
||||
start, new ByteArrayInputStream(data), data.length, "",
|
||||
provider.getName(), true, isOverlay, isOverlay, log, monitor);
|
||||
break;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (!(cause instanceof DuplicateNameException)) {
|
||||
throw e;
|
||||
}
|
||||
++count;
|
||||
name = blockName + "_" + count;
|
||||
}
|
||||
}
|
||||
MemoryBlockUtils.createInitializedBlock(program, isOverlay, name, start,
|
||||
new ByteArrayInputStream(data), data.length, "", provider.getName(),
|
||||
true, isOverlay, isOverlay, log, monitor);
|
||||
}
|
||||
offset = 0;
|
||||
// set up new start address of new block we are starting
|
||||
|
|
|
@ -177,7 +177,7 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program) {
|
||||
if (options != null) {
|
||||
for (Option option : options) {
|
||||
String name = option.getName();
|
||||
|
@ -188,7 +188,7 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
}
|
||||
}
|
||||
}
|
||||
return super.validateOptions(provider, loadSpec, options);
|
||||
return super.validateOptions(provider, loadSpec, options, program);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -335,7 +335,7 @@ public class XmlLoader extends AbstractProgramLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program) {
|
||||
// XXX will this work? is there other state that xmlOptions needs to
|
||||
// know?
|
||||
try {
|
||||
|
|
|
@ -60,10 +60,12 @@ public class AddToProgramDialog extends ImporterDialog {
|
|||
folderButton.setEnabled(false);
|
||||
languageButton.setEnabled(false);
|
||||
filenameTextField.setEnabled(false);
|
||||
validateFormInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean validateFormInput() {
|
||||
|
||||
setOkEnabled(false);
|
||||
optionsButton.setEnabled(false);
|
||||
Loader loader = getSelectedLoader();
|
||||
|
@ -75,10 +77,20 @@ public class AddToProgramDialog extends ImporterDialog {
|
|||
setStatusText(loader.getName() + " does not support add to program.");
|
||||
return false;
|
||||
}
|
||||
optionsButton.setEnabled(true);
|
||||
|
||||
LoadSpec loadSpec = getSelectedLoadSpec(loader);
|
||||
|
||||
String result =
|
||||
loader.validateOptions(byteProvider, loadSpec, getOptions(loadSpec), addToProgram);
|
||||
|
||||
if (result != null) {
|
||||
setStatusText(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
setStatusText("");
|
||||
setOkEnabled(true);
|
||||
optionsButton.setEnabled(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -102,19 +114,19 @@ public class AddToProgramDialog extends ImporterDialog {
|
|||
options = selectedLoader.getDefaultOptions(byteProvider, selectedLoadSpec, null, true);
|
||||
}
|
||||
TaskLauncher.launchNonModal("Import File", monitor -> {
|
||||
ImporterUtilities.addContentToProgram(tool, addToProgram, fsrl, selectedLoadSpec, options,
|
||||
monitor);
|
||||
ImporterUtilities.addContentToProgram(tool, addToProgram, fsrl, selectedLoadSpec,
|
||||
options, monitor);
|
||||
});
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Option> getOptions(LoadSpec loadSpec) {
|
||||
if (options == null) {
|
||||
options = loadSpec.getLoader().getDefaultOptions(byteProvider, loadSpec, null, true);
|
||||
}
|
||||
if (options != null) {
|
||||
return options;
|
||||
}
|
||||
return loadSpec.getLoader().getDefaultOptions(byteProvider, loadSpec, addToProgram, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current language/compiler spec from the program that will be added to.
|
||||
|
|
|
@ -346,10 +346,9 @@ public class ImporterDialog extends DialogComponentProvider {
|
|||
String programPath = removeTrailingSlashes(getName());
|
||||
DomainFolder importFolder = getOrCreateImportFolder(destinationFolder, programPath);
|
||||
String programName = FilenameUtils.getName(programPath);
|
||||
List<Option> localOptions = getOptions(loadSpec);
|
||||
TaskLauncher.launchNonModal("Import File", monitor -> {
|
||||
ImporterUtilities.importSingleFile(tool, programManager, fsrl, importFolder,
|
||||
loadSpec, programName, localOptions, monitor);
|
||||
loadSpec, programName, getOptions(loadSpec), monitor);
|
||||
});
|
||||
close();
|
||||
}
|
||||
|
@ -404,24 +403,24 @@ public class ImporterDialog extends DialogComponentProvider {
|
|||
AddressFactory addressFactory = selectedLanguage.getLanguage().getAddressFactory();
|
||||
LoadSpec loadSpec = getSelectedLoadSpec(loader);
|
||||
OptionValidator validator =
|
||||
optionList -> loader.validateOptions(byteProvider, loadSpec, optionList);
|
||||
optionList -> loader.validateOptions(byteProvider, loadSpec, optionList, null);
|
||||
|
||||
AddressFactoryService service = () -> addressFactory;
|
||||
|
||||
List<Option> defaultOptions = getOptions(loadSpec);
|
||||
if (defaultOptions.isEmpty()) {
|
||||
List<Option> currentOptions = getOptions(loadSpec);
|
||||
if (currentOptions.isEmpty()) {
|
||||
Msg.showInfo(this, null, "Options", "There are no options for this importer!");
|
||||
return;
|
||||
}
|
||||
|
||||
OptionsDialog optionsDialog = new OptionsDialog(defaultOptions, validator, service);
|
||||
OptionsDialog optionsDialog = new OptionsDialog(currentOptions, validator, service);
|
||||
optionsDialog.setHelpLocation(
|
||||
new HelpLocation("ImporterPlugin", getAnchorForSelectedLoader(loader)));
|
||||
tool.showDialog(optionsDialog);
|
||||
if (!optionsDialog.wasCancelled()) {
|
||||
options = optionsDialog.getOptions();
|
||||
}
|
||||
|
||||
validateFormInput();
|
||||
}
|
||||
catch (LanguageNotFoundException e) {
|
||||
Msg.showError(this, null, "Language Error",
|
||||
|
|
|
@ -23,8 +23,12 @@ import java.util.Arrays;
|
|||
|
||||
import org.junit.*;
|
||||
|
||||
import ghidra.app.util.bin.ByteArrayProvider;
|
||||
import ghidra.app.util.bin.ByteProvider;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.database.mem.FileBytes;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
|
@ -72,8 +76,7 @@ public class MemoryBlockUtilTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
Arrays.fill(data, (byte) 0xb);
|
||||
is = new ByteArrayInputStream(data);
|
||||
MemoryBlockUtils.createInitializedBlock(prog, false, "b", space.getAddress(3500), is, 1000,
|
||||
"bbbb", "b b b", false,
|
||||
false, false, log, TaskMonitor.DUMMY);
|
||||
"bbbb", "b b b", false, false, false, log, TaskMonitor.DUMMY);
|
||||
|
||||
MemoryBlock[] blocks = prog.getMemory().getBlocks();
|
||||
assertEquals(2, blocks.length);
|
||||
|
@ -111,8 +114,8 @@ public class MemoryBlockUtilTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
byte[] cdata = new byte[1000];
|
||||
Arrays.fill(cdata, (byte) 0xc);
|
||||
MemoryBlockUtils.createInitializedBlock(prog, false, "c", space.getAddress(4000),
|
||||
new ByteArrayInputStream(cdata),
|
||||
1000, "Ccomment", "Csource", false, false, false, log, TaskMonitor.DUMMY);
|
||||
new ByteArrayInputStream(cdata), 1000, "Ccomment", "Csource", false, false, false, log,
|
||||
TaskMonitor.DUMMY);
|
||||
|
||||
MemoryBlock[] blocks = prog.getMemory().getBlocks();
|
||||
assertEquals(2, blocks.length);
|
||||
|
@ -127,5 +130,30 @@ public class MemoryBlockUtilTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
assertTrue(blocks[1].isInitialized());
|
||||
}
|
||||
|
||||
//TODO test bit blocks and code unit clearing...
|
||||
private Address addr(long offset) {
|
||||
return space.getAddress(offset);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicateExceptionHandling() throws Exception {
|
||||
ByteProvider byteProvider = new ByteArrayProvider(new byte[1000]);
|
||||
FileBytes fileBytes =
|
||||
MemoryBlockUtils.createFileBytes(prog, byteProvider, TaskMonitor.DUMMY);
|
||||
|
||||
MemoryBlockUtils.createInitializedBlock(prog, true, "test", addr(0), fileBytes, 0, 10, "",
|
||||
"", true, true, true, new MessageLog());
|
||||
MemoryBlockUtils.createInitializedBlock(prog, true, "test", addr(0), fileBytes, 0, 10, "",
|
||||
"", true, true, true, new MessageLog());
|
||||
MemoryBlockUtils.createInitializedBlock(prog, true, "test", addr(0), fileBytes, 0, 10, "",
|
||||
"", true, true, true, new MessageLog());
|
||||
|
||||
MemoryBlock[] blocks = prog.getMemory().getBlocks();
|
||||
assertEquals(3, blocks.length);
|
||||
|
||||
assertEquals("test", blocks[0].getName());
|
||||
assertEquals("test_1", blocks[1].getName());
|
||||
assertEquals("test_2", blocks[2].getName());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package generic.test;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
@ -661,10 +661,10 @@ public abstract class AbstractGenericTest extends AbstractGTest {
|
|||
if (button == null) {
|
||||
throw new AssertionError("Couldn't find button " + buttonText + ".");
|
||||
}
|
||||
if (!button.isShowing()) {
|
||||
if (!runSwing(() -> button.isShowing())) {
|
||||
throw new AssertionError("Button " + buttonText + " is not showing.");
|
||||
}
|
||||
if (!button.isEnabled()) {
|
||||
if (!runSwing(() -> button.isEnabled())) {
|
||||
throw new AssertionError("Button " + buttonText + " is not enabled.");
|
||||
}
|
||||
pressButton(button, waitForCompletion);
|
||||
|
@ -700,10 +700,10 @@ public abstract class AbstractGenericTest extends AbstractGTest {
|
|||
if (button == null) {
|
||||
throw new AssertionError("Couldn't find button " + buttonName + ".");
|
||||
}
|
||||
if (!button.isVisible()) {
|
||||
if (!runSwing(() -> button.isShowing())) {
|
||||
throw new AssertionError("Button " + buttonName + " is not showing.");
|
||||
}
|
||||
if (!button.isEnabled()) {
|
||||
if (!runSwing(() -> button.isEnabled())) {
|
||||
throw new AssertionError("Button " + buttonName + " is not enabled.");
|
||||
}
|
||||
pressButton(button, waitForCompletion);
|
||||
|
|
|
@ -73,11 +73,11 @@ public class SkeletonLoader extends AbstractLibrarySupportLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program) {
|
||||
|
||||
// TODO: If this loader has custom options, validate them here. Not all options require
|
||||
// validation.
|
||||
|
||||
return super.validateOptions(provider, loadSpec, options);
|
||||
return super.validateOptions(provider, loadSpec, options, program);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue