mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
07a35dd91a
15 changed files with 828 additions and 117 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();
|
||||
|
|
|
@ -67,21 +67,31 @@ public class SleighLanguageProvider implements LanguageProvider {
|
|||
public static synchronized SleighLanguageProvider getSleighLanguageProvider() {
|
||||
if (instance == null) {
|
||||
instance = new SleighLanguageProvider();
|
||||
try {
|
||||
instance.createLanguages();
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(SleighLanguageProvider.class,
|
||||
"Sleigh language provider initiailization failed", e);
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct sleigh language provider (singleton)
|
||||
* Construct sleigh language provider (singleton use)
|
||||
*/
|
||||
private SleighLanguageProvider() {
|
||||
try {
|
||||
instance.createLanguages();
|
||||
}
|
||||
catch (Exception e) {
|
||||
Msg.error(SleighLanguageProvider.class,
|
||||
"Sleigh language provider initiailization failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct language provider (intended for test use only)
|
||||
* @param ldefsFile language definitions file
|
||||
* @throws SAXException if parse error occurs
|
||||
* @throws IOException if IO error occurs
|
||||
*/
|
||||
SleighLanguageProvider(ResourceFile ldefsFile) throws SAXException, IOException {
|
||||
createLanguages(ldefsFile);
|
||||
}
|
||||
|
||||
private void createLanguages() throws Exception {
|
||||
|
@ -91,7 +101,7 @@ public class SleighLanguageProvider implements LanguageProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private void createLanguages(ResourceFile file) throws Exception {
|
||||
private void createLanguages(ResourceFile file) throws SAXException, IOException {
|
||||
try {
|
||||
SleighLanguageValidator.validateLdefsFile(file);
|
||||
createLanguageDescriptions(file);
|
||||
|
@ -168,7 +178,8 @@ public class SleighLanguageProvider implements LanguageProvider {
|
|||
return d;
|
||||
}
|
||||
|
||||
private void createLanguageDescriptions(final ResourceFile specFile) throws Exception {
|
||||
private void createLanguageDescriptions(final ResourceFile specFile)
|
||||
throws SAXException, IOException {
|
||||
ErrorHandler errHandler = new ErrorHandler() {
|
||||
@Override
|
||||
public void error(SAXParseException exception) throws SAXException {
|
||||
|
|
|
@ -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,288 @@
|
|||
/* ###
|
||||
* 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.*;
|
||||
|
||||
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.
|
||||
* @throws Exception if unexpected error occurs
|
||||
* @returns 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) {
|
||||
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