mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-2606
Fixed typo in AddressLabelInfo. Improved implementation and error handling of AddressLabelInfo. GP-2606 Refactored the package of 'AddressLabelInfo' to beghidra.program.model.lang. Removed the source and namespace variablesfrom AddressLabelInfo since they would always be global and IMPORTED.Removed a number of constructors to simplify AddressLabelInfo. Improvederror handing in SleighLanguage class. GP-2606 Added javadocs to and throw exceptions from AddressLabelInfo constructors and removed extra constructors that were no longer needed. Added exception handling to AbsractProgramLoader and SleighLanguage for thrown exceptions. Made some variables in SleighLanguage private and removed an unnecessary null check. GP-2606 Prepared test to help investigate volatility interplay settings. GP-2606 Updated per review comments. SleighLanguage will parse pspec files andthen apply symbol element settings for volatility afterward. Simplifiedtests for SleighLanguage and the Decompiler. GP-2606 Made updates based on review feedback. Address label info holds the endaddress of the label. Sleigh language will resolve symbol mutabilityafter parsing the pspec file such that the order of elements in the filewill not be a factor. Rearranged tests in preparation for improvement.Added a constructor to the ProgramBuilder class so that custom definedpspec files may be used in the tests. GP-2606 Updated SpecXmlUtils decodeBoolean method to call decodeNullableBooleanfirst, however if the result is null, to return false instead of null. GP-2606 Changed size of addressLabelInfo to sizeInBytes and added comment toisVolatile that specifies what null, false, or true mean in context.Incorporated improvements per review comments to SleighLanguage. GP-2606 Added tests for the sleigh language volatility changes and thedecompiler itself. GP-2606: Updated SleighLanguage to alter 'volatileAddresses' based on the symbolelements and their attributes in pspec files. Added size and volatilevariables to AddressLabelInfo class. Added Boolean parser method to theSpecXmlUtils.java file. GP-2606: Added optional volatile boolean and optional size integer attributes to the symbol element of processor specification (pspec) files.
This commit is contained in:
parent
480f1e3a8b
commit
dce57a7bf7
13 changed files with 801 additions and 102 deletions
|
@ -45,8 +45,6 @@ import ghidra.program.model.mem.MemBuffer;
|
|||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.pcode.ElementId;
|
||||
import ghidra.program.model.pcode.Encoder;
|
||||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.program.model.util.AddressLabelInfo;
|
||||
import ghidra.program.model.util.ProcessorSymbolType;
|
||||
import ghidra.sleigh.grammar.SleighPreprocessor;
|
||||
import ghidra.sleigh.grammar.SourceFileIndexer;
|
||||
|
@ -93,9 +91,11 @@ public class SleighLanguage implements Language {
|
|||
/**
|
||||
* Non-null if a space should yes segmented addressing
|
||||
*/
|
||||
String segmentedspace = "";
|
||||
String segmentType = "";
|
||||
AddressSet volatileAddresses;
|
||||
private String segmentedspace = "";
|
||||
private String segmentType = "";
|
||||
private AddressSet volatileAddresses;
|
||||
private AddressSet volatileSymbolAddresses;
|
||||
private AddressSet nonVolatileSymbolAddresses;
|
||||
private ContextCache contextcache = null;
|
||||
/**
|
||||
* Cached instruction prototypes
|
||||
|
@ -156,7 +156,7 @@ public class SleighLanguage implements Language {
|
|||
registerBuilder = new RegisterBuilder();
|
||||
loadRegisters(registerBuilder);
|
||||
readRemainingSpecification();
|
||||
|
||||
buildVolatileSymbolAddresses();
|
||||
xrefRegisters();
|
||||
|
||||
instructProtoMap = new LinkedHashMap<>();
|
||||
|
@ -164,6 +164,18 @@ public class SleighLanguage implements Language {
|
|||
initParallelHelper();
|
||||
}
|
||||
|
||||
private void buildVolatileSymbolAddresses() {
|
||||
if (volatileAddresses == null) {
|
||||
volatileAddresses = new AddressSet();
|
||||
}
|
||||
if (volatileSymbolAddresses != null) {
|
||||
volatileAddresses.add(volatileSymbolAddresses);
|
||||
}
|
||||
if (nonVolatileSymbolAddresses != null) {
|
||||
volatileAddresses.delete(nonVolatileSymbolAddresses);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSLAWrongVersion(ResourceFile slaFile) {
|
||||
XmlPullParser parser = null;
|
||||
try {
|
||||
|
@ -383,10 +395,7 @@ public class SleighLanguage implements Language {
|
|||
|
||||
@Override
|
||||
public boolean isVolatile(Address addr) {
|
||||
if (volatileAddresses != null) {
|
||||
return volatileAddresses.contains(addr);
|
||||
}
|
||||
return false;
|
||||
return volatileAddresses.contains(addr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -798,15 +807,38 @@ public class SleighLanguage implements Language {
|
|||
String typeString = symbol.getAttribute("type");
|
||||
ProcessorSymbolType type = ProcessorSymbolType.getType(typeString);
|
||||
boolean isEntry = SpecXmlUtils.decodeBoolean(symbol.getAttribute("entry"));
|
||||
Address address = addressFactory.getAddress(addressString);
|
||||
if (address == null) {
|
||||
Address startAddress = addressFactory.getAddress(addressString);
|
||||
int rangeSize = SpecXmlUtils.decodeInt(symbol.getAttribute("size"));
|
||||
Boolean isVolatile = SpecXmlUtils.decodeNullableBoolean(
|
||||
symbol.getAttribute("volatile"));
|
||||
if (startAddress == null) {
|
||||
Msg.error(this, "invalid symbol address \"" + addressString + "\": " +
|
||||
description.getSpecFile());
|
||||
}
|
||||
else {
|
||||
AddressLabelInfo info = new AddressLabelInfo(address, labelName, false,
|
||||
null, SourceType.IMPORTED, isEntry, type);
|
||||
AddressLabelInfo info;
|
||||
try {
|
||||
info = new AddressLabelInfo(startAddress, rangeSize, labelName, false,
|
||||
isEntry, type, isVolatile);
|
||||
} catch (AddressOverflowException e) {
|
||||
throw new XmlParseException("invalid symbol definition: " + labelName, e);
|
||||
}
|
||||
defaultSymbols.add(info);
|
||||
if (isVolatile != null) {
|
||||
Address endAddress = info.getEndAddress();
|
||||
if (isVolatile) {
|
||||
if (volatileSymbolAddresses == null) {
|
||||
volatileSymbolAddresses = new AddressSet();
|
||||
}
|
||||
volatileSymbolAddresses.addRange(startAddress, endAddress);
|
||||
} else {
|
||||
if (nonVolatileSymbolAddresses == null) {
|
||||
nonVolatileSymbolAddresses = new AddressSet();
|
||||
}
|
||||
// punch a hole in the volatile address space.
|
||||
nonVolatileSymbolAddresses.addRange(startAddress, endAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
// skip the end tag
|
||||
parser.end(symbol);
|
||||
|
@ -864,7 +896,7 @@ public class SleighLanguage implements Language {
|
|||
read(parser);
|
||||
}
|
||||
catch (XmlParseException e) {
|
||||
Msg.error(this, e.getMessage());
|
||||
Msg.error(this, "Failed to parse Sleigh Specification ("+ specFile.getName() + "): " + e.getMessage());
|
||||
}
|
||||
finally {
|
||||
parser.dispose();
|
||||
|
|
|
@ -13,63 +13,54 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.program.model.util;
|
||||
package ghidra.program.model.lang;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.model.address.AddressOverflowException;
|
||||
import ghidra.program.model.util.ProcessorSymbolType;
|
||||
|
||||
/**
|
||||
* <CODE>AddressLabelInfo</CODE> is a utility class for storing
|
||||
* an <CODE>Address</CODE> and a corresponding label or alias together.
|
||||
* an <CODE>Address</CODE> together with a corresponding language-defined
|
||||
* label or alias that is within the global namespace which is
|
||||
* established with a SourceType of IMPORTED within a program.
|
||||
*/
|
||||
public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
||||
private Address addr;
|
||||
private Address endAddr;
|
||||
private String label;
|
||||
private boolean isPrimary;
|
||||
private Namespace scope;
|
||||
private SourceType symbolSource;
|
||||
private boolean isEntry;
|
||||
private ProcessorSymbolType processorSymbolType;
|
||||
|
||||
private int sizeInBytes;
|
||||
private Boolean isVolatile;
|
||||
|
||||
/**
|
||||
* Constructs a new AddressLabelInfo object
|
||||
* @param s symbol to initialize info from.
|
||||
* Constructor for class AddressLabelInfo
|
||||
*
|
||||
* @param addr Address object that describes the memory address
|
||||
* @param sizeInBytes Integer describing the Size in bytes that the label applies to.
|
||||
* @param label String label or alias for the Address
|
||||
* @param isPrimary boolean describes if this object is the primary label for the Address 'addr'
|
||||
* @param isEntry boolean describes if this object is an entry label for the Address 'addr'
|
||||
* @param type ProcessorSymbolType the type of symbol
|
||||
* @param isVolatile Boolean describes if the memory at this address is volatile
|
||||
*/
|
||||
public AddressLabelInfo(Symbol s) {
|
||||
this.addr = s.getAddress();
|
||||
this.label = s.getName();
|
||||
this.isPrimary = s.isPrimary();
|
||||
scope = s.getParentNamespace();
|
||||
symbolSource = s.getSource();
|
||||
isEntry = s.isExternalEntryPoint();
|
||||
}
|
||||
|
||||
public AddressLabelInfo(Address addr, String label, boolean isPrimary, Namespace scope,
|
||||
SourceType symbolSource, boolean isEntry) {
|
||||
this(addr, label, isPrimary, scope, symbolSource, isEntry, null);
|
||||
}
|
||||
|
||||
public AddressLabelInfo(Address addr, String label, boolean isPrimary, Namespace scope,
|
||||
SourceType symbolSource, boolean isEntry, ProcessorSymbolType type) {
|
||||
public AddressLabelInfo(Address addr, Integer sizeInBytes, String label, boolean isPrimary,
|
||||
boolean isEntry, ProcessorSymbolType type, Boolean isVolatile) throws AddressOverflowException {
|
||||
this.addr = addr;
|
||||
if ( sizeInBytes == null || sizeInBytes <= 0 ) {
|
||||
// Default size in addressable units
|
||||
this.sizeInBytes = addr.getAddressSpace().getAddressableUnitSize();
|
||||
} else {
|
||||
this.sizeInBytes = sizeInBytes;
|
||||
}
|
||||
this.endAddr = this.addr.addNoWrap(this.sizeInBytes-1);
|
||||
this.label = label;
|
||||
this.isPrimary = isPrimary;
|
||||
this.scope = scope;
|
||||
this.symbolSource = symbolSource;
|
||||
this.isEntry = isEntry;
|
||||
this.processorSymbolType = type;
|
||||
}
|
||||
|
||||
public AddressLabelInfo(Address addr, String label, boolean isPrimary, SourceType symbolSource) {
|
||||
this(addr, label, isPrimary, null, symbolSource, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new AddressLabelInfo object with only address information
|
||||
* @param addr the address to store in this object
|
||||
*/
|
||||
public AddressLabelInfo(Address addr) {
|
||||
this(addr, null, false, null, SourceType.DEFAULT, false);
|
||||
this.isVolatile = isVolatile;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,7 +69,14 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
|||
public final Address getAddress() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the object's end address.
|
||||
*/
|
||||
public final Address getEndAddress() {
|
||||
return endAddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object's label or alias.
|
||||
*/
|
||||
|
@ -86,18 +84,29 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
|||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object's size in bytes. Always non-zero positive value and defaults to
|
||||
* addressable unit size of associated address space.
|
||||
*/
|
||||
public final int getByteSize() {
|
||||
return sizeInBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the object is the primary label at the address.
|
||||
*/
|
||||
public final boolean isPrimary() {
|
||||
return isPrimary;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the scope for the symbol.
|
||||
* Returns whether the object is volatile.
|
||||
* Boolean.False when the address is explicitly not volatile.
|
||||
* Boolean.True when the address is volatile.
|
||||
* NULL when the volatility is not defined at this address.
|
||||
*/
|
||||
public Namespace getScope() {
|
||||
return scope;
|
||||
public final Boolean isVolatile() {
|
||||
return isVolatile;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -140,10 +149,6 @@ public class AddressLabelInfo implements Comparable<AddressLabelInfo> {
|
|||
return thisLabel.compareTo(addrLabel);
|
||||
}
|
||||
|
||||
public SourceType getSource() {
|
||||
return symbolSource;
|
||||
}
|
||||
|
||||
public boolean isEntry() {
|
||||
return isEntry;
|
||||
}
|
|
@ -24,7 +24,6 @@ import ghidra.program.model.address.*;
|
|||
import ghidra.program.model.listing.DefaultProgramContext;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.util.AddressLabelInfo;
|
||||
import ghidra.util.ManualEntry;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ import ghidra.program.model.address.*;
|
|||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.DefaultProgramContext;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.util.AddressLabelInfo;
|
||||
import ghidra.util.ManualEntry;
|
||||
import ghidra.util.XmlProgramUtilities;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
/* ###
|
||||
* 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.processors.sleigh;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.LanguageID;
|
||||
|
||||
public class SleighLanguageVolatilityTest extends AbstractGenericTest{
|
||||
protected SleighLanguage lang;
|
||||
protected String PORTFAddressString = "mem:0x31";
|
||||
protected String PORTGAddressString = "mem:0x34";
|
||||
protected boolean isPORTFVolatile;
|
||||
protected boolean isPORTGVolatile;
|
||||
/**
|
||||
* Constructs a string based on parameters, and uses that as the content of a custom pspec file.
|
||||
* Parameters effect the volatility of the symbol "PORTF".
|
||||
* The pspec file is read by the SleighLanguage object which tracks volatile addresses.
|
||||
* @param symbolVolatile Nullable boolean value that specifies the symbol PORTF volatility setting.
|
||||
* @param symbolSize Nullable integer value specifying the symbol PORTF size in bytes.
|
||||
* @param memoryVolatile Nullable boolean value that specifies the volatility setting of the
|
||||
* memory location that includes PORTF.
|
||||
* @param reverseOrder boolean, reverseOrder refers to the order that 'volatile' and
|
||||
* 'default_symbols' elements appear in the pspec file.
|
||||
* @return the data
|
||||
*/
|
||||
public void setUp(Boolean symbolVolatile, Integer symbolSize, Boolean memoryVolatile, boolean reverseOrder) throws Exception {
|
||||
//symbolVolatile and symbolSize are in reference to the symbol PORTF. However, setting a
|
||||
//size that is too large will overwrite other symbols such as PING, DDRG or PORTG.
|
||||
String defaultSymbolsElement =
|
||||
" <default_symbols>\r\n"
|
||||
+ " <symbol name=\"RESET\" address=\"code:0x0000\" entry=\"true\"/>\r\n"
|
||||
+ " <symbol name=\"INT0\" address=\"code:0x0002\" entry=\"true\"/>\r\n"
|
||||
+ " <symbol name=\"INT1\" address=\"code:0x0004\" entry=\"true\"/>\r\n"
|
||||
+ " <symbol name=\"PORTE\" address=\"mem:0x2e\"/>\r\n"
|
||||
+ " <symbol name=\"PINF\" address=\"mem:0x2f\"/>\r\n"
|
||||
+ " <symbol name=\"DDRF\" address=\"mem:0x30\"/>\r\n"
|
||||
+ " <symbol name=\"PORTF\" address=\"mem:0x31\"";
|
||||
defaultSymbolsElement += symbolVolatile==null ? "" : " volatile=\"" + symbolVolatile.toString() + "\"";
|
||||
defaultSymbolsElement += symbolSize==null ? "" : " size=\"" + symbolSize.toString() + "\"";
|
||||
defaultSymbolsElement += " />\r\n"
|
||||
+ " <symbol name=\"PING\" address=\"mem:0x32\"/>\r\n"
|
||||
+ " <symbol name=\"DDRG\" address=\"mem:0x33\"/>\r\n"
|
||||
+ " <symbol name=\"PORTG\" address=\"mem:0x34\"/>\r\n"
|
||||
+ " <symbol name=\"TIFR0\" address=\"mem:0x35\"/>\r\n"
|
||||
+ " </default_symbols>\r\n";
|
||||
|
||||
//memoryVolatile null will not set the memory range 0x20 to 0x57 as volatile.
|
||||
//memoryVolatile true will set the memory range 0x20 to 0x57 to volatile.
|
||||
//memoryVolatile false will exclude the address of PORTF (0x31) from the volatility setting.
|
||||
//Example:
|
||||
// "<range space=\"mem\" first=\"0x20\" last=\"0x30\"/>"
|
||||
// "<range space=\"mem\" first=\"0x32\" last=\"0x57\"/>"
|
||||
String volatileElement =
|
||||
" <volatile outputop=\"write_volatile\" inputop=\"read_volatile\">\r\n";
|
||||
volatileElement += memoryVolatile == null ? "" :
|
||||
memoryVolatile ?
|
||||
"<range space=\"mem\" first=\"0x20\" last=\"0x57\"/>\r\n"
|
||||
:
|
||||
"<range space=\"mem\" first=\"0x20\" last=\"0x30\"/>\r\n"
|
||||
+ "<range space=\"mem\" first=\"0x32\" last=\"0x57\"/>\r\n";
|
||||
|
||||
volatileElement += " <range space=\"mem\" first=\"0x60\" last=\"0xff\"/>\r\n"
|
||||
+ " </volatile>\r\n";
|
||||
|
||||
//This variable represents the content of a pspec file.
|
||||
//The original pspec file this is based on is the avr8 atmega256.pspec.
|
||||
String pspecContentString =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
|
||||
+ "\r\n"
|
||||
+ "<processor_spec>\r\n"
|
||||
+ "\r\n"
|
||||
+ " <programcounter register=\"PC\"/> \r\n"
|
||||
+ " <data_space space=\"mem\"/>\r\n";
|
||||
pspecContentString += reverseOrder ? volatileElement : defaultSymbolsElement;
|
||||
pspecContentString += " \r\n"
|
||||
+ " <context_data>\r\n"
|
||||
+ " <tracked_set space=\"code\">\r\n"
|
||||
+ " <set name=\"R1\" val=\"0\"/>\r\n"
|
||||
+ " </tracked_set>\r\n"
|
||||
+ " </context_data>\r\n"
|
||||
+ " \r\n";
|
||||
pspecContentString += reverseOrder ? defaultSymbolsElement : volatileElement;
|
||||
pspecContentString += "\r\n"
|
||||
+ " <default_memory_blocks>\r\n"
|
||||
+ " <memory_block name=\"regalias\" start_address=\"mem:0x00\" length=\"0x20\" initialized=\"false\"/>\r\n"
|
||||
+ " <memory_block name=\"iospace\" start_address=\"mem:0x20\" length=\"0x1e0\" initialized=\"false\"/>\r\n"
|
||||
+ " <memory_block name=\"sram\" start_address=\"mem:0x200\" length=\"0x4000\" initialized=\"false\"/>\r\n"
|
||||
+ " <memory_block name=\"codebyte\" start_address=\"codebyte:0x0\" length=\"0x40000\" byte_mapped_address=\"code:0x0\"/>\r\n"
|
||||
+ " </default_memory_blocks>\r\n"
|
||||
+ "\r\n"
|
||||
+ "\r\n"
|
||||
+ "</processor_spec>\r\n"
|
||||
+ "";
|
||||
|
||||
String languageIDString = "avr8:LE:16:atmega256Test";
|
||||
LanguageID langId = new LanguageID(languageIDString);
|
||||
|
||||
ResourceFile pspecFile = createCustomPspecFile("atmega256", pspecContentString);
|
||||
ResourceFile ldefFile = createTempLdefsFile("avr8", pspecFile);
|
||||
SleighLanguageProvider provider = new SleighLanguageProvider(ldefFile);
|
||||
lang = (SleighLanguage) provider.getLanguage(langId);
|
||||
|
||||
Address PORTFAddress = lang.getAddressFactory().getAddress(PORTFAddressString);
|
||||
Address PORTGAddress = lang.getAddressFactory().getAddress(PORTGAddressString);
|
||||
|
||||
isPORTFVolatile = lang.isVolatile(PORTFAddress);
|
||||
isPORTGVolatile = lang.isVolatile(PORTGAddress);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPORTFWithSymbolVolatility() throws Exception {
|
||||
setUp(null, null, null, false);
|
||||
|
||||
Assert.assertFalse(isPORTFVolatile);
|
||||
|
||||
setUp(false, null, null, false);
|
||||
|
||||
Assert.assertFalse(isPORTFVolatile);
|
||||
|
||||
setUp(true, null, null, false);
|
||||
|
||||
Assert.assertTrue(isPORTFVolatile);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPORTFWithSize() throws Exception {
|
||||
setUp(null, 1, null, false);
|
||||
|
||||
Assert.assertFalse(isPORTFVolatile);
|
||||
Assert.assertFalse(isPORTGVolatile);
|
||||
|
||||
setUp(false, 1, null, false);
|
||||
|
||||
Assert.assertFalse(isPORTFVolatile);
|
||||
Assert.assertFalse(isPORTGVolatile);
|
||||
|
||||
setUp(true, 1, null, false);
|
||||
|
||||
Assert.assertTrue(isPORTFVolatile);
|
||||
Assert.assertFalse(isPORTGVolatile);
|
||||
|
||||
setUp(null, 4, null, false);
|
||||
|
||||
Assert.assertFalse(isPORTFVolatile);
|
||||
Assert.assertFalse(isPORTGVolatile);
|
||||
|
||||
setUp(false, 4, null, false);
|
||||
|
||||
Assert.assertFalse(isPORTFVolatile);
|
||||
Assert.assertFalse(isPORTGVolatile);
|
||||
|
||||
setUp(true, 4, null, false); // setting portf to size 4 overwrites portg as well
|
||||
|
||||
Assert.assertTrue(isPORTFVolatile);
|
||||
Assert.assertTrue(isPORTGVolatile);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPORTFNoSizeOrSymbolVolatility() throws Exception {
|
||||
setUp(null, null, null, false);
|
||||
|
||||
Assert.assertFalse(isPORTFVolatile);
|
||||
|
||||
setUp(null, null, false, false);
|
||||
|
||||
Assert.assertFalse(isPORTFVolatile);
|
||||
|
||||
setUp(null, null, true, false);
|
||||
|
||||
Assert.assertTrue(isPORTFVolatile);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPORTFNoSize() throws Exception {
|
||||
setUp(true, null, true, false);
|
||||
|
||||
Assert.assertTrue(isPORTFVolatile);
|
||||
|
||||
setUp(false, null, true, false);
|
||||
|
||||
Assert.assertFalse(isPORTFVolatile);
|
||||
|
||||
setUp(true, null, false, false);
|
||||
|
||||
Assert.assertTrue(isPORTFVolatile);
|
||||
|
||||
setUp(false, null, false, false);
|
||||
|
||||
Assert.assertFalse(isPORTFVolatile);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReverseSettingPORTFVolatile() throws Exception {
|
||||
setUp(false, null, null, true);
|
||||
Assert.assertFalse(isPORTFVolatile);
|
||||
setUp(true, null, null, true);
|
||||
Assert.assertTrue(isPORTFVolatile);
|
||||
}
|
||||
|
||||
private ResourceFile createTempLdefsFile(String name, ResourceFile pspecFile) throws IOException {
|
||||
String pspecFilename = pspecFile.getName();
|
||||
return createCustomLdefFile("avr8", pspecFilename);
|
||||
}
|
||||
|
||||
public ResourceFile createCustomPspecFile(String name, String content) {
|
||||
File newPspecFile = null;
|
||||
try {
|
||||
newPspecFile = File.createTempFile(name, ".pspec");
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(newPspecFile));
|
||||
bw.write(content);
|
||||
bw.close();
|
||||
|
||||
}
|
||||
catch(IOException e){
|
||||
System.err.println("Error creating test pspec file.");
|
||||
}
|
||||
newPspecFile.deleteOnExit();
|
||||
return new ResourceFile(newPspecFile);
|
||||
}
|
||||
|
||||
public ResourceFile createCustomLdefFile(String name, String pspecFilename) {
|
||||
Iterable<ResourceFile> files = Application.findFilesByExtensionInApplication(".ldefs");
|
||||
ResourceFile originalLdefFile = null;
|
||||
for (ResourceFile file : files) {
|
||||
if (file.getName().equals(name + ".ldefs"))
|
||||
{
|
||||
originalLdefFile = file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
File editedPspecFile = File.createTempFile(name, ".ldefs");
|
||||
BufferedReader br = new BufferedReader(new FileReader(originalLdefFile.getFile(false)));
|
||||
BufferedWriter bw = new BufferedWriter(new FileWriter(editedPspecFile));
|
||||
String s;
|
||||
while ((s = br.readLine()) != null) {
|
||||
//if the string is defining a filename, edit that line
|
||||
String originalPspecFilename = "atmega256.pspec";
|
||||
|
||||
if ( s.contains(originalPspecFilename) )
|
||||
{
|
||||
s = s.replace(originalPspecFilename, pspecFilename);
|
||||
}
|
||||
|
||||
if (s.contains("avr8:LE:16:atmega256"))
|
||||
{
|
||||
s = s.replace("avr8:LE:16:atmega256", "avr8:LE:16:atmega256Test");
|
||||
}
|
||||
bw.write(s);
|
||||
bw.newLine();
|
||||
}
|
||||
bw.close();
|
||||
br.close();
|
||||
editedPspecFile.deleteOnExit();
|
||||
return new ResourceFile(editedPspecFile);
|
||||
}
|
||||
catch(IOException e) {
|
||||
System.err.println("Error creating test pspec file.");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue