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.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Properties; import java.util.HashMap;
import java.util.Random; import java.util.Random;
import java.util.Vector; import java.util.Vector;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -199,13 +199,8 @@ public class ContikiMoteType implements MoteType {
// Type specific class configuration // Type specific class configuration
private ProjectConfig myConfig = null; private ProjectConfig myConfig = null;
private int relAddressOfReferenceVariable = 0;
private CoreComm myCoreComm = null; private CoreComm myCoreComm = null;
// Variable name to address mappings
private Properties varAddresses = new Properties();
// Initial memory for all motes of this type // Initial memory for all motes of this type
private SectionMoteMemory initialMemory = null; private SectionMoteMemory initialMemory = null;
@ -403,14 +398,16 @@ public class ContikiMoteType implements MoteType {
int dataSectionAddr = -1, dataSectionSize = -1; int dataSectionAddr = -1, dataSectionSize = -1;
int bssSectionAddr = -1, bssSectionSize = -1; int bssSectionAddr = -1, bssSectionSize = -1;
int commonSectionAddr = -1, commonSectionSize = -1; int commonSectionAddr = -1, commonSectionSize = -1;
int readonlySectionAddr = -1, readonlySectionSize = -1;
HashMap<String, Integer> addresses = new HashMap<String, Integer>();
if (useCommand) { if (useCommand) {
/* Parse command output */ /* Parse command output */
String[] output = loadCommandData(getContikiFirmwareFile()); String[] output = loadCommandData(getContikiFirmwareFile());
if (output == null) { if (output == null) {
throw new MoteTypeCreationException("No parse command output loaded"); throw new MoteTypeCreationException("No parse command output loaded");
} }
boolean parseOK = parseCommandData(output, varAddresses); boolean parseOK = parseCommandData(output, addresses);
if (!parseOK) { if (!parseOK) {
logger.fatal("Command output parsing failed"); logger.fatal("Command output parsing failed");
throw new MoteTypeCreationException("Command output parsing failed"); throw new MoteTypeCreationException("Command output parsing failed");
@ -422,6 +419,14 @@ public class ContikiMoteType implements MoteType {
bssSectionSize = parseCommandBssSectionSize(output); bssSectionSize = parseCommandBssSectionSize(output);
commonSectionAddr = parseCommandCommonSectionAddr(output); commonSectionAddr = parseCommandCommonSectionAddr(output);
commonSectionSize = parseCommandCommonSectionSize(output); commonSectionSize = parseCommandCommonSectionSize(output);
try {
readonlySectionAddr = parseCommandReadonlySectionAddr(output);
readonlySectionSize = parseCommandReadonlySectionSize(output);
} catch (Exception e) {
readonlySectionAddr = -1;
readonlySectionSize = -1;
}
} else { } else {
/* Parse command output */ /* Parse command output */
@ -434,7 +439,7 @@ public class ContikiMoteType implements MoteType {
logger.fatal("No map data could be loaded"); logger.fatal("No map data could be loaded");
throw new MoteTypeCreationException("No map data could be loaded: " + mapFile); throw new MoteTypeCreationException("No map data could be loaded: " + mapFile);
} }
boolean parseOK = parseMapFileData(mapData, varAddresses); boolean parseOK = parseMapFileData(mapData, addresses);
if (!parseOK) { if (!parseOK) {
logger.fatal("Map data parsing failed"); logger.fatal("Map data parsing failed");
throw new MoteTypeCreationException("Map data parsing failed: " + mapFile); throw new MoteTypeCreationException("Map data parsing failed: " + mapFile);
@ -446,52 +451,99 @@ public class ContikiMoteType implements MoteType {
bssSectionSize = parseMapBssSectionSize(mapData); bssSectionSize = parseMapBssSectionSize(mapData);
commonSectionAddr = parseMapCommonSectionAddr(mapData); commonSectionAddr = parseMapCommonSectionAddr(mapData);
commonSectionSize = parseMapCommonSectionSize(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"); 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 if (dataSectionAddr <= 0 || dataSectionSize <= 0
|| bssSectionAddr <= 0 || bssSectionSize <= 0) { || bssSectionAddr <= 0 || bssSectionSize <= 0) {
throw new MoteTypeCreationException("Library section addresses parsing failed"); 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 */ /* Create initial memory: data+bss+optional common */
initialMemory = new SectionMoteMemory(varAddresses); initialMemory = new SectionMoteMemory(addresses, offset);
byte[] initialDataSection = new byte[dataSectionSize]; byte[] initialDataSection = new byte[dataSectionSize];
getCoreMemory(dataSectionAddr, dataSectionSize, initialDataSection); getCoreMemory(dataSectionAddr, dataSectionSize, initialDataSection);
initialMemory.setMemorySegment(dataSectionAddr, initialDataSection); initialMemory.setMemorySegmentNative(dataSectionAddr, initialDataSection);
logger.info(getContikiFirmwareFile().getName() +
": data section at 0x" + Integer.toHexString(dataSectionAddr) +
" (" + dataSectionSize + " bytes)");
byte[] initialBssSection = new byte[bssSectionSize]; byte[] initialBssSection = new byte[bssSectionSize];
getCoreMemory(bssSectionAddr, bssSectionSize, initialBssSection); getCoreMemory(bssSectionAddr, bssSectionSize, initialBssSection);
initialMemory.setMemorySegment(bssSectionAddr, initialBssSection); initialMemory.setMemorySegmentNative(bssSectionAddr, initialBssSection);
logger.info(getContikiFirmwareFile().getName() +
": BSS section at 0x" + Integer.toHexString(bssSectionAddr) +
" (" + bssSectionSize + " bytes)");
if (commonSectionAddr > 0 && commonSectionSize > 0) { if (commonSectionAddr >= 0 && commonSectionSize > 0) {
byte[] initialCommonSection = new byte[commonSectionSize]; byte[] initialCommonSection = new byte[commonSectionSize];
getCoreMemory(commonSectionAddr, commonSectionSize, initialCommonSection); getCoreMemory(commonSectionAddr, commonSectionSize, initialCommonSection);
initialMemory.setMemorySegment(commonSectionAddr, initialCommonSection); initialMemory.setMemorySegmentNative(commonSectionAddr, initialCommonSection);
logger.info(getContikiFirmwareFile().getName() + }
": common section at 0x" + Integer.toHexString(commonSectionAddr) +
" (" + commonSectionSize + " bytes)"); /* 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) { public void setCoreMemory(SectionMoteMemory mem) {
for (int i = 0; i < mem.getNumberOfSections(); i++) { for (int i = 0; i < mem.getNumberOfSections(); i++) {
setCoreMemory( setCoreMemory(
mem.getStartAddrOfSection(i), mem.getSectionNativeAddress(i) /* native address space */,
mem.getSizeOfSection(i), mem.getDataOfSection(i)); mem.getSizeOfSection(i), mem.getDataOfSection(i));
} }
} }
@ -538,8 +590,7 @@ public class ContikiMoteType implements MoteType {
* @param varAddresses * @param varAddresses
* Properties that should contain the name to addresses mappings. * Properties that should contain the name to addresses mappings.
*/ */
public static boolean parseMapFileData(String[] mapFileData, public static boolean parseMapFileData(String[] mapFileData, HashMap<String, Integer> varAddresses) {
Properties varAddresses) {
String[] varNames = getMapFileVarNames(mapFileData); String[] varNames = getMapFileVarNames(mapFileData);
if (varNames == null || varNames.length == 0) { if (varNames == null || varNames.length == 0) {
return false; return false;
@ -565,7 +616,7 @@ public class ContikiMoteType implements MoteType {
* @param output Command output * @param output Command output
* @param addresses Variable addresses mappings * @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; int nrNew = 0, nrOld = 0, nrMismatch = 0;
Pattern pattern = Pattern pattern =
@ -615,10 +666,9 @@ public class ContikiMoteType implements MoteType {
*/ */
public void getCoreMemory(SectionMoteMemory mem) { public void getCoreMemory(SectionMoteMemory mem) {
for (int i = 0; i < mem.getNumberOfSections(); i++) { 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); int size = mem.getSizeOfSection(i);
byte[] data = mem.getDataOfSection(i); byte[] data = mem.getDataOfSection(i);
getCoreMemory(startAddr, size, data); getCoreMemory(startAddr, size, data);
} }
} }
@ -689,12 +739,10 @@ public class ContikiMoteType implements MoteType {
* @param varName Name of variable * @param varName Name of variable
* @return Relative memory address of variable or -1 if not found * @return Relative memory address of variable or -1 if not found
*/ */
public static int getMapFileVarAddress(String[] mapFileData, String varName, Properties varAddresses) { private static int getMapFileVarAddress(String[] mapFileData, String varName, HashMap<String, Integer> varAddresses) {
int varAddr; Integer varAddrInteger;
String varAddrString; if ((varAddrInteger = varAddresses.get(varName)) != null) {
if ((varAddrString = varAddresses.getProperty(varName)) != null) { return varAddrInteger.intValue();
varAddr = Integer.parseInt(varAddrString);
return varAddr;
} }
String regExp = String regExp =
@ -704,9 +752,9 @@ public class ContikiMoteType implements MoteType {
String retString = getFirstMatchGroup(mapFileData, regExp, 1); String retString = getFirstMatchGroup(mapFileData, regExp, 1);
if (retString != null) { if (retString != null) {
varAddresses.setProperty(varName, Integer.toString(Integer.parseInt( varAddrInteger = Integer.parseInt(retString.trim(), 16);
retString.trim(), 16))); varAddresses.put(varName, varAddrInteger);
return Integer.parseInt(retString.trim(), 16); return varAddrInteger.intValue();
} else { } else {
return -1; return -1;
} }
@ -760,7 +808,7 @@ public class ContikiMoteType implements MoteType {
return varNames.toArray(new String[0]); return varNames.toArray(new String[0]);
} }
public static String[] getAllVariableNames(String[] lines, private static String[] getAllVariableNames(String[] lines,
int startAddress, int endAddress) { int startAddress, int endAddress) {
ArrayList<String> varNames = new ArrayList<String>(); ArrayList<String> varNames = new ArrayList<String>();
@ -914,6 +962,21 @@ public class ContikiMoteType implements MoteType {
} }
return end - start; 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) { private static int getRelVarAddr(String mapFileData[], String varName) {
String regExp = String regExp =