added support for readonly memory sections

updated to use new SectionMoteMemory with address space offset
code cleanup
This commit is contained in:
Fredrik Osterlind 2012-03-09 14:58:43 +01:00
parent b49d1892f2
commit bf39b411c9

View File

@ -45,7 +45,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
import java.util.HashMap;
import java.util.Random;
import java.util.Vector;
import java.util.regex.Matcher;
@ -199,13 +199,8 @@ public class ContikiMoteType implements MoteType {
// Type specific class configuration
private ProjectConfig myConfig = null;
private int relAddressOfReferenceVariable = 0;
private CoreComm myCoreComm = null;
// Variable name to address mappings
private Properties varAddresses = new Properties();
// Initial memory for all motes of this type
private SectionMoteMemory initialMemory = null;
@ -403,14 +398,16 @@ public class ContikiMoteType implements MoteType {
int dataSectionAddr = -1, dataSectionSize = -1;
int bssSectionAddr = -1, bssSectionSize = -1;
int commonSectionAddr = -1, commonSectionSize = -1;
int readonlySectionAddr = -1, readonlySectionSize = -1;
HashMap<String, Integer> addresses = new HashMap<String, Integer>();
if (useCommand) {
/* Parse command output */
String[] output = loadCommandData(getContikiFirmwareFile());
if (output == null) {
throw new MoteTypeCreationException("No parse command output loaded");
}
boolean parseOK = parseCommandData(output, varAddresses);
boolean parseOK = parseCommandData(output, addresses);
if (!parseOK) {
logger.fatal("Command output parsing failed");
throw new MoteTypeCreationException("Command output parsing failed");
@ -422,6 +419,14 @@ public class ContikiMoteType implements MoteType {
bssSectionSize = parseCommandBssSectionSize(output);
commonSectionAddr = parseCommandCommonSectionAddr(output);
commonSectionSize = parseCommandCommonSectionSize(output);
try {
readonlySectionAddr = parseCommandReadonlySectionAddr(output);
readonlySectionSize = parseCommandReadonlySectionSize(output);
} catch (Exception e) {
readonlySectionAddr = -1;
readonlySectionSize = -1;
}
} else {
/* Parse command output */
@ -434,7 +439,7 @@ public class ContikiMoteType implements MoteType {
logger.fatal("No map data could be loaded");
throw new MoteTypeCreationException("No map data could be loaded: " + mapFile);
}
boolean parseOK = parseMapFileData(mapData, varAddresses);
boolean parseOK = parseMapFileData(mapData, addresses);
if (!parseOK) {
logger.fatal("Map data parsing failed");
throw new MoteTypeCreationException("Map data parsing failed: " + mapFile);
@ -446,52 +451,99 @@ public class ContikiMoteType implements MoteType {
bssSectionSize = parseMapBssSectionSize(mapData);
commonSectionAddr = parseMapCommonSectionAddr(mapData);
commonSectionSize = parseMapCommonSectionSize(mapData);
readonlySectionAddr = -1;
readonlySectionSize = -1;
}
if (varAddresses.size() == 0) {
if (dataSectionAddr >= 0) {
logger.info(getContikiFirmwareFile().getName() +
": data section at 0x" + Integer.toHexString(dataSectionAddr) +
" (" + dataSectionSize + " bytes)");
} else {
logger.fatal(getContikiFirmwareFile().getName() + ": no data section found");
}
if (bssSectionAddr >= 0) {
logger.info(getContikiFirmwareFile().getName() +
": BSS section at 0x" + Integer.toHexString(bssSectionAddr) +
" (" + bssSectionSize + " bytes)");
} else {
logger.fatal(getContikiFirmwareFile().getName() + ": no BSS section found");
}
if (commonSectionAddr >= 0) {
logger.info(getContikiFirmwareFile().getName() +
": common section at 0x" + Integer.toHexString(commonSectionAddr) +
" (" + commonSectionSize + " bytes)");
} else {
logger.info(getContikiFirmwareFile().getName() + ": no common section found");
}
if (readonlySectionAddr >= 0) {
logger.info(getContikiFirmwareFile().getName() +
": readonly section at 0x" + Integer.toHexString(readonlySectionAddr) +
" (" + readonlySectionSize + " bytes)");
} else {
logger.warn(getContikiFirmwareFile().getName() + ": no readonly section found");
}
if (addresses.size() == 0) {
throw new MoteTypeCreationException("Library variables parsing failed");
}
try {
/* Relative <-> absolute addresses offset */
relAddressOfReferenceVariable = (Integer) varAddresses.get("referenceVar");
} catch (Exception e) {
throw (MoteTypeCreationException) new MoteTypeCreationException(
"JNI call error: " + e.getMessage()).initCause(e);
}
if (dataSectionAddr <= 0 || dataSectionSize <= 0
|| bssSectionAddr <= 0 || bssSectionSize <= 0) {
throw new MoteTypeCreationException("Library section addresses parsing failed");
}
myCoreComm.setReferenceAddress(relAddressOfReferenceVariable);
try {
/* Relative <-> absolute addresses offset */
int referenceVar = (Integer) addresses.get("referenceVar");
myCoreComm.setReferenceAddress(referenceVar);
} catch (Exception e) {
throw (MoteTypeCreationException) new MoteTypeCreationException(
"JNI call error: " + e.getMessage()).initCause(e);
}
/* We first need the value of Contiki's referenceVar, which tells us the
* memory offset between Contiki's variable and the relative addresses that
* were calculated directly from the library file.
*
* This offset will be used in Cooja in the memory abstraction to match
* Contiki's and Cooja's address spaces */
int offset;
{
SectionMoteMemory tmp = new SectionMoteMemory(addresses, 0);
byte[] data = new byte[dataSectionSize];
getCoreMemory(dataSectionAddr, dataSectionSize, data);
tmp.setMemorySegment(dataSectionAddr, data);
byte[] bss = new byte[bssSectionSize];
getCoreMemory(bssSectionAddr, bssSectionSize, bss);
tmp.setMemorySegment(bssSectionAddr, bss);
offset = tmp.getIntValueOf("referenceVar");
logger.info(getContikiFirmwareFile().getName() +
": offsetting Contiki mote address space: " + offset);
}
/* Create initial memory: data+bss+optional common */
initialMemory = new SectionMoteMemory(varAddresses);
initialMemory = new SectionMoteMemory(addresses, offset);
byte[] initialDataSection = new byte[dataSectionSize];
getCoreMemory(dataSectionAddr, dataSectionSize, initialDataSection);
initialMemory.setMemorySegment(dataSectionAddr, initialDataSection);
logger.info(getContikiFirmwareFile().getName() +
": data section at 0x" + Integer.toHexString(dataSectionAddr) +
" (" + dataSectionSize + " bytes)");
initialMemory.setMemorySegmentNative(dataSectionAddr, initialDataSection);
byte[] initialBssSection = new byte[bssSectionSize];
getCoreMemory(bssSectionAddr, bssSectionSize, initialBssSection);
initialMemory.setMemorySegment(bssSectionAddr, initialBssSection);
logger.info(getContikiFirmwareFile().getName() +
": BSS section at 0x" + Integer.toHexString(bssSectionAddr) +
" (" + bssSectionSize + " bytes)");
initialMemory.setMemorySegmentNative(bssSectionAddr, initialBssSection);
if (commonSectionAddr > 0 && commonSectionSize > 0) {
if (commonSectionAddr >= 0 && commonSectionSize > 0) {
byte[] initialCommonSection = new byte[commonSectionSize];
getCoreMemory(commonSectionAddr, commonSectionSize, initialCommonSection);
initialMemory.setMemorySegment(commonSectionAddr, initialCommonSection);
logger.info(getContikiFirmwareFile().getName() +
": common section at 0x" + Integer.toHexString(commonSectionAddr) +
" (" + commonSectionSize + " bytes)");
initialMemory.setMemorySegmentNative(commonSectionAddr, initialCommonSection);
}
/* Read "read-only" memory */
if (readonlySectionAddr >= 0 && readonlySectionSize > 0) {
byte[] readonlySection = new byte[readonlySectionSize];
getCoreMemory(readonlySectionAddr, readonlySectionSize, readonlySection);
initialMemory.setReadonlyMemorySegment(readonlySectionAddr+offset, readonlySection);
}
}
@ -524,7 +576,7 @@ public class ContikiMoteType implements MoteType {
public void setCoreMemory(SectionMoteMemory mem) {
for (int i = 0; i < mem.getNumberOfSections(); i++) {
setCoreMemory(
mem.getStartAddrOfSection(i),
mem.getSectionNativeAddress(i) /* native address space */,
mem.getSizeOfSection(i), mem.getDataOfSection(i));
}
}
@ -538,8 +590,7 @@ public class ContikiMoteType implements MoteType {
* @param varAddresses
* Properties that should contain the name to addresses mappings.
*/
public static boolean parseMapFileData(String[] mapFileData,
Properties varAddresses) {
public static boolean parseMapFileData(String[] mapFileData, HashMap<String, Integer> varAddresses) {
String[] varNames = getMapFileVarNames(mapFileData);
if (varNames == null || varNames.length == 0) {
return false;
@ -565,7 +616,7 @@ public class ContikiMoteType implements MoteType {
* @param output Command output
* @param addresses Variable addresses mappings
*/
public static boolean parseCommandData(String[] output, Properties addresses) {
public static boolean parseCommandData(String[] output, HashMap<String, Integer> addresses) {
int nrNew = 0, nrOld = 0, nrMismatch = 0;
Pattern pattern =
@ -615,10 +666,9 @@ public class ContikiMoteType implements MoteType {
*/
public void getCoreMemory(SectionMoteMemory mem) {
for (int i = 0; i < mem.getNumberOfSections(); i++) {
int startAddr = mem.getStartAddrOfSection(i);
int startAddr = mem.getSectionNativeAddress(i); /* native address space */
int size = mem.getSizeOfSection(i);
byte[] data = mem.getDataOfSection(i);
getCoreMemory(startAddr, size, data);
}
}
@ -689,12 +739,10 @@ public class ContikiMoteType implements MoteType {
* @param varName Name of variable
* @return Relative memory address of variable or -1 if not found
*/
public static int getMapFileVarAddress(String[] mapFileData, String varName, Properties varAddresses) {
int varAddr;
String varAddrString;
if ((varAddrString = varAddresses.getProperty(varName)) != null) {
varAddr = Integer.parseInt(varAddrString);
return varAddr;
private static int getMapFileVarAddress(String[] mapFileData, String varName, HashMap<String, Integer> varAddresses) {
Integer varAddrInteger;
if ((varAddrInteger = varAddresses.get(varName)) != null) {
return varAddrInteger.intValue();
}
String regExp =
@ -704,9 +752,9 @@ public class ContikiMoteType implements MoteType {
String retString = getFirstMatchGroup(mapFileData, regExp, 1);
if (retString != null) {
varAddresses.setProperty(varName, Integer.toString(Integer.parseInt(
retString.trim(), 16)));
return Integer.parseInt(retString.trim(), 16);
varAddrInteger = Integer.parseInt(retString.trim(), 16);
varAddresses.put(varName, varAddrInteger);
return varAddrInteger.intValue();
} else {
return -1;
}
@ -760,7 +808,7 @@ public class ContikiMoteType implements MoteType {
return varNames.toArray(new String[0]);
}
public static String[] getAllVariableNames(String[] lines,
private static String[] getAllVariableNames(String[] lines,
int startAddress, int endAddress) {
ArrayList<String> varNames = new ArrayList<String>();
@ -914,6 +962,21 @@ public class ContikiMoteType implements MoteType {
}
return end - start;
}
private static int parseCommandReadonlySectionAddr(String[] output) {
return parseFirstHexInt("^([0-9A-Fa-f]*)[ \t]t[ \t].text$", output);
}
private static int parseCommandReadonlySectionSize(String[] output) {
int start = parseCommandReadonlySectionAddr(output);
if (start < 0) {
return -1;
}
/* Extract the last specified address, assuming that the interval covers all the memory */
String last = output[output.length-1];
int lastAddress = Integer.parseInt(last.split("[ \t]")[0],16);
return lastAddress - start;
}
private static int getRelVarAddr(String mapFileData[], String varName) {
String regExp =