[cooja] ContikiMoteType: Introduce abstract SectionParser
Should encapsulate and decrease both redundancy and code duplication
This commit is contained in:
parent
f4979ffeeb
commit
c5ff3555a0
|
@ -43,6 +43,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
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;
|
||||||
|
@ -72,6 +73,7 @@ import org.contikios.cooja.mote.memory.ArrayMemory;
|
||||||
import org.contikios.cooja.mote.memory.MemoryInterface;
|
import org.contikios.cooja.mote.memory.MemoryInterface;
|
||||||
import org.contikios.cooja.mote.memory.MemoryInterface.Symbol;
|
import org.contikios.cooja.mote.memory.MemoryInterface.Symbol;
|
||||||
import org.contikios.cooja.mote.memory.MemoryLayout;
|
import org.contikios.cooja.mote.memory.MemoryLayout;
|
||||||
|
import org.contikios.cooja.mote.memory.UnknownVariableException;
|
||||||
import org.contikios.cooja.mote.memory.VarMemory;
|
import org.contikios.cooja.mote.memory.VarMemory;
|
||||||
import org.contikios.cooja.util.StringUtils;
|
import org.contikios.cooja.util.StringUtils;
|
||||||
|
|
||||||
|
@ -405,38 +407,35 @@ public class ContikiMoteType implements MoteType {
|
||||||
*/
|
*/
|
||||||
boolean useCommand = Boolean.parseBoolean(Cooja.getExternalToolsSetting("PARSE_WITH_COMMAND", "false"));
|
boolean useCommand = Boolean.parseBoolean(Cooja.getExternalToolsSetting("PARSE_WITH_COMMAND", "false"));
|
||||||
|
|
||||||
int dataSectionRelAddr = -1, dataSectionSize = -1;
|
SectionParser dataSecParser;
|
||||||
int bssSectionRelAddr = -1, bssSectionSize = -1;
|
SectionParser bssSecParser;
|
||||||
int commonSectionRelAddr = -1, commonSectionSize = -1;
|
SectionParser commonSecParser;
|
||||||
int readonlySectionRelAddr = -1, readonlySectionSize = -1;
|
SectionParser readonlySecParser = null;
|
||||||
|
|
||||||
HashMap<String, Symbol> addresses = new HashMap<String, Symbol>();
|
HashMap<String, Symbol> variables = new HashMap<>();
|
||||||
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, addresses);
|
|
||||||
if (!parseOK) {
|
|
||||||
logger.fatal("Command output parsing failed");
|
|
||||||
throw new MoteTypeCreationException("Command output parsing failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
dataSectionRelAddr = parseCommandDataSectionAddr(output);
|
dataSecParser = new CommandSectionParser(
|
||||||
dataSectionSize = parseCommandDataSectionSize(output);
|
output,
|
||||||
bssSectionRelAddr = parseCommandBssSectionAddr(output);
|
Cooja.getExternalToolsSetting("COMMAND_DATA_START"),
|
||||||
bssSectionSize = parseCommandBssSectionSize(output);
|
Cooja.getExternalToolsSetting("COMMAND_DATA_SIZE"));
|
||||||
commonSectionRelAddr = parseCommandCommonSectionAddr(output);
|
bssSecParser = new CommandSectionParser(
|
||||||
commonSectionSize = parseCommandCommonSectionSize(output);
|
output,
|
||||||
|
Cooja.getExternalToolsSetting("COMMAND_BSS_START"),
|
||||||
try {
|
Cooja.getExternalToolsSetting("COMMAND_BSS_SIZE"));
|
||||||
readonlySectionRelAddr = parseCommandReadonlySectionAddr(output);
|
commonSecParser = new CommandSectionParser(
|
||||||
readonlySectionSize = parseCommandReadonlySectionSize(output);
|
output,
|
||||||
} catch (Exception e) {
|
Cooja.getExternalToolsSetting("COMMAND_COMMON_START"),
|
||||||
readonlySectionRelAddr = -1;
|
Cooja.getExternalToolsSetting("COMMAND_COMMON_SIZE"));
|
||||||
readonlySectionSize = -1;
|
readonlySecParser = new CommandSectionParser(
|
||||||
}
|
output,
|
||||||
|
Cooja.getExternalToolsSetting("^([0-9A-Fa-f]*)[ \t]t[ \t].text$"),
|
||||||
|
Cooja.getExternalToolsSetting("")); // XXX
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Parse map file */
|
/* Parse map file */
|
||||||
|
@ -449,63 +448,32 @@ 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, addresses);
|
|
||||||
if (!parseOK) {
|
|
||||||
logger.fatal("Map data parsing failed");
|
|
||||||
throw new MoteTypeCreationException("Map data parsing failed: " + mapFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
dataSectionRelAddr = parseMapDataSectionAddr(mapData);
|
dataSecParser = new MapSectionParser(
|
||||||
dataSectionSize = parseMapDataSectionSize(mapData);
|
mapData,
|
||||||
bssSectionRelAddr = parseMapBssSectionAddr(mapData);
|
Cooja.getExternalToolsSetting("MAPFILE_DATA_START"),
|
||||||
bssSectionSize = parseMapBssSectionSize(mapData);
|
Cooja.getExternalToolsSetting("MAPFILE_DATA_SIZE"));
|
||||||
commonSectionRelAddr = parseMapCommonSectionAddr(mapData);
|
bssSecParser = new MapSectionParser(
|
||||||
commonSectionSize = parseMapCommonSectionSize(mapData);
|
mapData,
|
||||||
readonlySectionRelAddr = -1;
|
Cooja.getExternalToolsSetting("MAPFILE_BSS_START"),
|
||||||
readonlySectionSize = -1;
|
Cooja.getExternalToolsSetting("MAPFILE_BSS_SIZE"));
|
||||||
|
commonSecParser = new MapSectionParser(
|
||||||
|
mapData,
|
||||||
|
Cooja.getExternalToolsSetting("MAPFILE_COMMON_START"),
|
||||||
|
Cooja.getExternalToolsSetting("MAPFILE_COMMON_SIZE"));
|
||||||
|
readonlySecParser = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataSectionRelAddr >= 0) {
|
|
||||||
logger.info(getContikiFirmwareFile().getName()
|
|
||||||
+ ": data section at 0x" + Integer.toHexString(dataSectionRelAddr)
|
|
||||||
+ " (" + dataSectionSize + " == 0x" + Integer.toHexString(dataSectionSize) + " bytes)");
|
|
||||||
} else {
|
|
||||||
logger.fatal(getContikiFirmwareFile().getName() + ": no data section found");
|
|
||||||
}
|
|
||||||
if (bssSectionRelAddr >= 0) {
|
|
||||||
logger.info(getContikiFirmwareFile().getName()
|
|
||||||
+ ": BSS section at 0x" + Integer.toHexString(bssSectionRelAddr)
|
|
||||||
+ " (" + bssSectionSize + " == 0x" + Integer.toHexString(bssSectionSize) + " bytes)");
|
|
||||||
} else {
|
|
||||||
logger.fatal(getContikiFirmwareFile().getName() + ": no BSS section found");
|
|
||||||
}
|
|
||||||
if (commonSectionRelAddr >= 0) {
|
|
||||||
logger.info(getContikiFirmwareFile().getName()
|
|
||||||
+ ": common section at 0x" + Integer.toHexString(commonSectionRelAddr)
|
|
||||||
+ " (" + commonSectionSize + " == 0x" + Integer.toHexString(commonSectionSize) + " bytes)");
|
|
||||||
} else {
|
|
||||||
logger.info(getContikiFirmwareFile().getName() + ": no common section found");
|
|
||||||
}
|
|
||||||
if (readonlySectionRelAddr >= 0) {
|
|
||||||
logger.info(getContikiFirmwareFile().getName()
|
|
||||||
+ ": readonly section at 0x" + Integer.toHexString(readonlySectionRelAddr)
|
|
||||||
+ " (" + readonlySectionSize + " == 0x" + Integer.toHexString(readonlySectionSize) + " bytes)");
|
|
||||||
} else {
|
|
||||||
logger.warn(getContikiFirmwareFile().getName() + ": no readonly section found");
|
|
||||||
}
|
|
||||||
if (addresses.isEmpty()) {
|
|
||||||
throw new MoteTypeCreationException("Library variables parsing failed");
|
|
||||||
}
|
|
||||||
if (dataSectionRelAddr <= 0 || dataSectionSize <= 0
|
|
||||||
|| bssSectionRelAddr <= 0 || bssSectionSize <= 0) {
|
|
||||||
throw new MoteTypeCreationException("Library section addresses parsing failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/* Relative <-> absolute addresses offset */
|
Map<String, Symbol> vars = bssSecParser.getSymbols();
|
||||||
int referenceVar = (int) addresses.get("referenceVar").addr;
|
for (Symbol s : vars.values()) {
|
||||||
myCoreComm.setReferenceAddress(referenceVar);
|
if (s.name.equals("referenceVar")) {
|
||||||
|
/* Relative <-> absolute addresses offset */
|
||||||
|
int referenceVar = (int) s.addr;
|
||||||
|
myCoreComm.setReferenceAddress(referenceVar);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new MoteTypeCreationException("JNI call error: " + e.getMessage(), e);
|
throw new MoteTypeCreationException("JNI call error: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
@ -518,42 +486,185 @@ public class ContikiMoteType implements MoteType {
|
||||||
* Contiki's and Cooja's address spaces */
|
* Contiki's and Cooja's address spaces */
|
||||||
int offset;
|
int offset;
|
||||||
{
|
{
|
||||||
SectionMoteMemory tmp = new SectionMoteMemory(addresses, 0);
|
SectionMoteMemory tmp = new SectionMoteMemory(variables, 0);
|
||||||
VarMemory varMem = new VarMemory(tmp);
|
VarMemory varMem = new VarMemory(tmp);
|
||||||
byte[] data = new byte[dataSectionSize];
|
tmp.addMemorySection("tmp.data", dataSecParser.parse());
|
||||||
getCoreMemory(dataSectionRelAddr, dataSectionSize, data);
|
|
||||||
tmp.addMemorySection("data", new ArrayMemory(dataSectionRelAddr, MemoryLayout.getNative(), data, null));
|
tmp.addMemorySection("tmp.bss", bssSecParser.parse());
|
||||||
byte[] bss = new byte[bssSectionSize];
|
|
||||||
getCoreMemory(bssSectionRelAddr, bssSectionSize, bss);
|
try {
|
||||||
tmp.addMemorySection("bss", new ArrayMemory(bssSectionRelAddr, MemoryLayout.getNative(), bss, null));
|
int referenceVar = (int) varMem.getVariable("referenceVar").addr;
|
||||||
|
myCoreComm.setReferenceAddress(referenceVar);
|
||||||
|
} catch (UnknownVariableException e) {
|
||||||
|
throw new MoteTypeCreationException("JNI call error: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getCoreMemory(tmp);
|
||||||
|
|
||||||
offset = varMem.getIntValueOf("referenceVar");
|
offset = varMem.getIntValueOf("referenceVar");
|
||||||
logger.info(getContikiFirmwareFile().getName()
|
logger.info(getContikiFirmwareFile().getName()
|
||||||
+ ": offsetting Cooja mote address space: " + offset);
|
+ ": offsetting Cooja mote address space: " + Long.toHexString(offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create initial memory: data+bss+optional common */
|
/* Create initial memory: data+bss+optional common */
|
||||||
initialMemory = new SectionMoteMemory(addresses, offset);
|
initialMemory = new SectionMoteMemory(variables, offset);
|
||||||
|
|
||||||
byte[] initialDataSection = new byte[dataSectionSize];
|
initialMemory.addMemorySection("data", dataSecParser.parse());
|
||||||
getCoreMemory(dataSectionRelAddr, dataSectionSize, initialDataSection);
|
|
||||||
initialMemory.addMemorySection("data", new ArrayMemory(dataSectionRelAddr, MemoryLayout.getNative(), initialDataSection, null));
|
|
||||||
|
|
||||||
byte[] initialBssSection = new byte[bssSectionSize];
|
initialMemory.addMemorySection("bss", bssSecParser.parse());
|
||||||
getCoreMemory(bssSectionRelAddr, bssSectionSize, initialBssSection);
|
|
||||||
initialMemory.addMemorySection("bss", new ArrayMemory(bssSectionRelAddr, MemoryLayout.getNative(), initialBssSection, null));
|
|
||||||
|
|
||||||
if (commonSectionRelAddr >= 0 && commonSectionSize > 0) {
|
initialMemory.addMemorySection("common", commonSecParser.parse());
|
||||||
byte[] initialCommonSection = new byte[commonSectionSize];
|
|
||||||
getCoreMemory(commonSectionRelAddr, commonSectionSize, initialCommonSection);
|
if (readonlySecParser != null) {
|
||||||
initialMemory.addMemorySection("common", new ArrayMemory(commonSectionRelAddr, MemoryLayout.getNative(), initialCommonSection, null));
|
initialMemory.addMemorySection("readonly", readonlySecParser.parse());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read "read-only" memory */
|
getCoreMemory(initialMemory);
|
||||||
if (readonlySectionRelAddr >= 0 && readonlySectionSize > 0) {
|
}
|
||||||
byte[] readonlySection = new byte[readonlySectionSize];
|
|
||||||
getCoreMemory(readonlySectionRelAddr, readonlySectionSize, readonlySection);
|
public static abstract class SectionParser {
|
||||||
initialMemory.addMemorySection("readonly", new ArrayMemory(readonlySectionRelAddr, MemoryLayout.getNative(), readonlySection, true, null));
|
|
||||||
|
private final String[] mapFileData;
|
||||||
|
|
||||||
|
public SectionParser(String[] mapFileData) {
|
||||||
|
this.mapFileData = mapFileData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getData() {
|
||||||
|
return mapFileData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract int parseAddr();
|
||||||
|
|
||||||
|
public abstract int parseSize();
|
||||||
|
|
||||||
|
abstract Map<String, Symbol> getSymbols();
|
||||||
|
|
||||||
|
protected int parseFirstHexInt(String regexp, String[] data) {
|
||||||
|
String retString = getFirstMatchGroup(data, regexp, 1);
|
||||||
|
|
||||||
|
if (retString == null || retString.equals("")) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Integer.parseInt(retString.trim(), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemoryInterface parse() {
|
||||||
|
|
||||||
|
int mapSectionAddr = parseAddr();
|
||||||
|
int mapSectionSize = parseSize();
|
||||||
|
|
||||||
|
if (mapSectionAddr < 0 || mapSectionSize <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Symbol> variables = getMapFileVarsInRange(
|
||||||
|
getData(),
|
||||||
|
mapSectionAddr,
|
||||||
|
mapSectionAddr + mapSectionSize);
|
||||||
|
if (variables == null || variables.isEmpty()) {
|
||||||
|
logger.warn("Map data symbol parsing failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(String.format("Parsed section at 0x%x ( %d == 0x%x bytes)",
|
||||||
|
// getContikiFirmwareFile().getName(),
|
||||||
|
mapSectionAddr,
|
||||||
|
mapSectionSize,
|
||||||
|
mapSectionSize));
|
||||||
|
|
||||||
|
return new ArrayMemory(
|
||||||
|
mapSectionAddr,
|
||||||
|
mapSectionSize,
|
||||||
|
MemoryLayout.getNative(),
|
||||||
|
variables);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses Map file for seciton data.
|
||||||
|
*/
|
||||||
|
public static class MapSectionParser extends SectionParser {
|
||||||
|
|
||||||
|
private final String startRegExp;
|
||||||
|
private final String sizeRegExp;
|
||||||
|
|
||||||
|
public MapSectionParser(String[] mapFileData, String startRegExp, String sizeRegExp) {
|
||||||
|
super(mapFileData);
|
||||||
|
this.startRegExp = startRegExp;
|
||||||
|
this.sizeRegExp = sizeRegExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int parseAddr() {
|
||||||
|
if (startRegExp == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return parseFirstHexInt(startRegExp, getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int parseSize() {
|
||||||
|
if (sizeRegExp == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return parseFirstHexInt(sizeRegExp, getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Symbol> getSymbols() {
|
||||||
|
return getMapFileVarsInRange(
|
||||||
|
getData(),
|
||||||
|
parseAddr(),
|
||||||
|
parseAddr() + parseSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses command output for section data.
|
||||||
|
*/
|
||||||
|
public static class CommandSectionParser extends SectionParser {
|
||||||
|
|
||||||
|
private final String startRegExp;
|
||||||
|
private final String sizeRegExp;
|
||||||
|
|
||||||
|
public CommandSectionParser(String[] mapFileData, String startRegExp, String sizeRegExp) {
|
||||||
|
super(mapFileData);
|
||||||
|
this.startRegExp = startRegExp;
|
||||||
|
this.sizeRegExp = sizeRegExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int parseAddr() {
|
||||||
|
if (startRegExp == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return parseFirstHexInt(startRegExp, getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int parseSize() {
|
||||||
|
if (sizeRegExp == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int start = parseAddr();
|
||||||
|
if (start < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int end = parseFirstHexInt(sizeRegExp, getData());
|
||||||
|
if (end < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return end - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Symbol> getSymbols() {
|
||||||
|
return parseCommandVariables(getData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,46 +721,19 @@ public class ContikiMoteType implements MoteType {
|
||||||
myCoreComm.setMemory(relAddr, length, mem);
|
myCoreComm.setMemory(relAddr, length, mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses specified map file data for variable name to addresses mappings. The
|
|
||||||
* mappings are added to the given properties object.
|
|
||||||
*
|
|
||||||
* @param mapFileData
|
|
||||||
* Contents of entire map file
|
|
||||||
* @param varAddresses
|
|
||||||
* Properties that should contain the name to addresses mappings.
|
|
||||||
*/
|
|
||||||
public static boolean parseMapFileData(String[] mapFileData, HashMap<String, Symbol> varAddresses) {
|
|
||||||
String[] varNames = getMapFileVarNames(mapFileData);
|
|
||||||
if (varNames == null || varNames.length == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String varName : varNames) {
|
|
||||||
int varAddress = getMapFileVarAddress(mapFileData, varName);
|
|
||||||
if (varAddress > 0) {
|
|
||||||
varAddresses.put(varName, new Symbol(Symbol.Type.VARIABLE, varName, varAddress, 1));
|
|
||||||
} else {
|
|
||||||
logger.warn("Parsed Contiki variable '" + varName
|
|
||||||
+ "' but could not find address");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses parse command output for variable name to addresses mappings.
|
* Parses parse command output for variable name to addresses mappings.
|
||||||
* The mappings are written to the given properties object.
|
* The mappings are written to the given properties object.
|
||||||
|
*
|
||||||
|
* TODO: need InRange version!
|
||||||
*
|
*
|
||||||
* @param output Command output
|
* @param output Command output
|
||||||
* @param addresses Variable addresses mappings
|
* @return
|
||||||
*/
|
*/
|
||||||
public static boolean parseCommandData(String[] output, HashMap<String, Symbol> addresses) {
|
public static Map<String, Symbol> parseCommandVariables(String[] output) {
|
||||||
int nrNew = 0, nrOld = 0, nrMismatch = 0;
|
int nrNew = 0, nrOld = 0, nrMismatch = 0;
|
||||||
|
HashMap<String, Symbol> addresses = new HashMap<>();
|
||||||
Pattern pattern
|
Pattern pattern = Pattern.compile(Cooja.getExternalToolsSetting("COMMAND_VAR_NAME_ADDRESS"));
|
||||||
= Pattern.compile(Cooja.getExternalToolsSetting("COMMAND_VAR_NAME_ADDRESS"));
|
|
||||||
|
|
||||||
for (String line : output) {
|
for (String line : output) {
|
||||||
Matcher matcher = pattern.matcher(line);
|
Matcher matcher = pattern.matcher(line);
|
||||||
|
@ -659,6 +743,7 @@ public class ContikiMoteType implements MoteType {
|
||||||
String symbol = matcher.group(2);
|
String symbol = matcher.group(2);
|
||||||
int address = Integer.parseInt(matcher.group(1), 16);
|
int address = Integer.parseInt(matcher.group(1), 16);
|
||||||
|
|
||||||
|
/* XXX needs to be checked */
|
||||||
if (!addresses.containsKey(symbol)) {
|
if (!addresses.containsKey(symbol)) {
|
||||||
nrNew++;
|
nrNew++;
|
||||||
addresses.put(symbol, new Symbol(Symbol.Type.VARIABLE, symbol, address, 1));
|
addresses.put(symbol, new Symbol(Symbol.Type.VARIABLE, symbol, address, 1));
|
||||||
|
@ -682,7 +767,7 @@ public class ContikiMoteType implements MoteType {
|
||||||
logger.debug("Command response parsing summary: Added " + nrNew
|
logger.debug("Command response parsing summary: Added " + nrNew
|
||||||
+ " variables. Found " + nrOld + " old variables");
|
+ " variables. Found " + nrOld + " old variables");
|
||||||
}*/
|
}*/
|
||||||
return (nrNew + nrOld) > 0;
|
return addresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -754,6 +839,9 @@ public class ContikiMoteType implements MoteType {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getFirstMatchGroup(String[] lines, String regexp, int groupNr) {
|
private static String getFirstMatchGroup(String[] lines, String regexp, int groupNr) {
|
||||||
|
if (regexp == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Pattern pattern = Pattern.compile(regexp);
|
Pattern pattern = Pattern.compile(regexp);
|
||||||
for (String line : lines) {
|
for (String line : lines) {
|
||||||
Matcher matcher = pattern.matcher(line);
|
Matcher matcher = pattern.matcher(line);
|
||||||
|
@ -764,34 +852,11 @@ public class ContikiMoteType implements MoteType {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static Map<String, Symbol> getMapFileVarsInRange(
|
||||||
* Returns all variable names in both data and BSS section by parsing the map
|
String[] lines,
|
||||||
* file. These values should not be trusted completely as the parsing may
|
int startAddress,
|
||||||
* fail.
|
int endAddress) {
|
||||||
*
|
Map<String, Symbol> varNames = new HashMap<>();
|
||||||
* @return Variable names found in the data and bss section
|
|
||||||
*/
|
|
||||||
public static String[] getMapFileVarNames(String[] mapFileData) {
|
|
||||||
ArrayList<String> varNames = new ArrayList<>();
|
|
||||||
|
|
||||||
String[] dataVariables = getAllVariableNames(
|
|
||||||
mapFileData,
|
|
||||||
parseMapDataSectionAddr(mapFileData),
|
|
||||||
parseMapDataSectionAddr(mapFileData) + parseMapDataSectionSize(mapFileData));
|
|
||||||
varNames.addAll(Arrays.asList(dataVariables));
|
|
||||||
|
|
||||||
String[] bssVariables = getAllVariableNames(
|
|
||||||
mapFileData,
|
|
||||||
parseMapBssSectionAddr(mapFileData),
|
|
||||||
parseMapBssSectionAddr(mapFileData) + parseMapBssSectionSize(mapFileData));
|
|
||||||
varNames.addAll(Arrays.asList(bssVariables));
|
|
||||||
|
|
||||||
return varNames.toArray(new String[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String[] getAllVariableNames(String[] lines,
|
|
||||||
int startAddress, int endAddress) {
|
|
||||||
ArrayList<String> varNames = new ArrayList<>();
|
|
||||||
|
|
||||||
Pattern pattern = Pattern.compile(Cooja.getExternalToolsSetting("MAPFILE_VAR_NAME"));
|
Pattern pattern = Pattern.compile(Cooja.getExternalToolsSetting("MAPFILE_VAR_NAME"));
|
||||||
for (String line : lines) {
|
for (String line : lines) {
|
||||||
|
@ -799,11 +864,16 @@ public class ContikiMoteType implements MoteType {
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
if (Integer.decode(matcher.group(1)).intValue() >= startAddress
|
if (Integer.decode(matcher.group(1)).intValue() >= startAddress
|
||||||
&& Integer.decode(matcher.group(1)).intValue() <= endAddress) {
|
&& Integer.decode(matcher.group(1)).intValue() <= endAddress) {
|
||||||
varNames.add(matcher.group(2));
|
String varName = matcher.group(2);
|
||||||
|
varNames.put(varName, new Symbol(
|
||||||
|
Symbol.Type.VARIABLE,
|
||||||
|
varName,
|
||||||
|
getMapFileVarAddress(lines, varName),
|
||||||
|
getMapFileVarSize(lines, varName)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return varNames.toArray(new String[0]);
|
return varNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -841,156 +911,6 @@ public class ContikiMoteType implements MoteType {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int parseFirstHexInt(String regexp, String[] data) {
|
|
||||||
String retString
|
|
||||||
= getFirstMatchGroup(data, regexp, 1);
|
|
||||||
|
|
||||||
if (retString != null) {
|
|
||||||
return Integer.parseInt(retString.trim(), 16);
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseMapDataSectionAddr(String[] mapFileData) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("MAPFILE_DATA_START", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return parseFirstHexInt(regexp, mapFileData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseMapDataSectionSize(String[] mapFileData) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("MAPFILE_DATA_SIZE", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return parseFirstHexInt(regexp, mapFileData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseMapBssSectionAddr(String[] mapFileData) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("MAPFILE_BSS_START", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return parseFirstHexInt(regexp, mapFileData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseMapBssSectionSize(String[] mapFileData) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("MAPFILE_BSS_SIZE", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return parseFirstHexInt(regexp, mapFileData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseMapCommonSectionAddr(String[] mapFileData) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("MAPFILE_COMMON_START", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return parseFirstHexInt(regexp, mapFileData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseMapCommonSectionSize(String[] mapFileData) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("MAPFILE_COMMON_SIZE", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return parseFirstHexInt(regexp, mapFileData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseCommandDataSectionAddr(String[] output) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("COMMAND_DATA_START", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return parseFirstHexInt(regexp, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseCommandDataSectionSize(String[] output) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("COMMAND_DATA_END", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int start = parseCommandDataSectionAddr(output);
|
|
||||||
if (start < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int end = parseFirstHexInt(regexp, output);
|
|
||||||
if (end < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return end - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseCommandBssSectionAddr(String[] output) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("COMMAND_BSS_START", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return parseFirstHexInt(regexp, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseCommandBssSectionSize(String[] output) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("COMMAND_BSS_END", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int start = parseCommandBssSectionAddr(output);
|
|
||||||
if (start < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int end = parseFirstHexInt(regexp, output);
|
|
||||||
if (end < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return end - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseCommandCommonSectionAddr(String[] output) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("COMMAND_COMMON_START", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return parseFirstHexInt(regexp, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int parseCommandCommonSectionSize(String[] output) {
|
|
||||||
String regexp = Cooja.getExternalToolsSetting("COMMAND_COMMON_END", "");
|
|
||||||
if (regexp.equals("")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int start = parseCommandCommonSectionAddr(output);
|
|
||||||
if (start < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int end = parseFirstHexInt(regexp, output);
|
|
||||||
if (end < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
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
|
||||||
= Cooja.getExternalToolsSetting("MAPFILE_VAR_ADDRESS_1")
|
= Cooja.getExternalToolsSetting("MAPFILE_VAR_ADDRESS_1")
|
||||||
|
|
|
@ -68,6 +68,7 @@ import org.contikios.cooja.Cooja;
|
||||||
import org.contikios.cooja.MoteType.MoteTypeCreationException;
|
import org.contikios.cooja.MoteType.MoteTypeCreationException;
|
||||||
import org.contikios.cooja.mote.memory.SectionMoteMemory;
|
import org.contikios.cooja.mote.memory.SectionMoteMemory;
|
||||||
import org.contikios.cooja.contikimote.ContikiMoteType;
|
import org.contikios.cooja.contikimote.ContikiMoteType;
|
||||||
|
import org.contikios.cooja.contikimote.ContikiMoteType.SectionParser;
|
||||||
import org.contikios.cooja.mote.memory.MemoryInterface.Symbol;
|
import org.contikios.cooja.mote.memory.MemoryInterface.Symbol;
|
||||||
import org.contikios.cooja.mote.memory.VarMemory;
|
import org.contikios.cooja.mote.memory.VarMemory;
|
||||||
|
|
||||||
|
@ -760,17 +761,25 @@ public class ConfigurationWizard extends JDialog {
|
||||||
|
|
||||||
testOutput.addMessage("### Parsing map file data for addresses");
|
testOutput.addMessage("### Parsing map file data for addresses");
|
||||||
addresses = new HashMap<String, Symbol>();
|
addresses = new HashMap<String, Symbol>();
|
||||||
boolean parseOK = ContikiMoteType.parseMapFileData(mapData, addresses);
|
// boolean parseOK = ContikiMoteType.parseMapFileData(mapData, addresses);
|
||||||
if (!parseOK) {
|
// if (!parseOK) {
|
||||||
testOutput.addMessage("### Error: Failed parsing map file data", MessageList.ERROR);
|
// testOutput.addMessage("### Error: Failed parsing map file data", MessageList.ERROR);
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
testOutput.addMessage("### Validating section addresses");
|
testOutput.addMessage("### Validating section addresses");
|
||||||
relDataSectionAddr = ContikiMoteType.parseMapDataSectionAddr(mapData);
|
SectionParser dataSecParser = new ContikiMoteType.MapSectionParser(
|
||||||
dataSectionSize = ContikiMoteType.parseMapDataSectionSize(mapData);
|
mapData,
|
||||||
relBssSectionAddr = ContikiMoteType.parseMapBssSectionAddr(mapData);
|
Cooja.getExternalToolsSetting("MAPFILE_DATA_START"),
|
||||||
bssSectionSize = ContikiMoteType.parseMapBssSectionSize(mapData);
|
Cooja.getExternalToolsSetting("MAPFILE_DATA_SIZE"));
|
||||||
|
SectionParser bssSecParser = new ContikiMoteType.MapSectionParser(
|
||||||
|
mapData,
|
||||||
|
Cooja.getExternalToolsSetting("MAPFILE_BSS_START"),
|
||||||
|
Cooja.getExternalToolsSetting("MAPFILE_BSS_SIZE"));
|
||||||
|
relDataSectionAddr = dataSecParser.parseAddr();
|
||||||
|
dataSectionSize = dataSecParser.parseSize();
|
||||||
|
relBssSectionAddr = bssSecParser.parseAddr();
|
||||||
|
bssSectionSize = bssSecParser.parseSize();
|
||||||
testOutput.addMessage("Data section address: 0x" + Integer.toHexString(relDataSectionAddr));
|
testOutput.addMessage("Data section address: 0x" + Integer.toHexString(relDataSectionAddr));
|
||||||
testOutput.addMessage("Data section size: 0x" + Integer.toHexString(dataSectionSize));
|
testOutput.addMessage("Data section size: 0x" + Integer.toHexString(dataSectionSize));
|
||||||
testOutput.addMessage("BSS section address: 0x" + Integer.toHexString(relBssSectionAddr));
|
testOutput.addMessage("BSS section address: 0x" + Integer.toHexString(relBssSectionAddr));
|
||||||
|
@ -840,17 +849,26 @@ public class ConfigurationWizard extends JDialog {
|
||||||
|
|
||||||
testOutput.addMessage("### Parsing command output for addresses");
|
testOutput.addMessage("### Parsing command output for addresses");
|
||||||
addresses = new HashMap<String, Symbol>();
|
addresses = new HashMap<String, Symbol>();
|
||||||
boolean parseOK = ContikiMoteType.parseCommandData(commandData, addresses);
|
// boolean parseOK = ContikiMoteType.parseCommandData(commandData, addresses);
|
||||||
if (!parseOK) {
|
// if (!parseOK) {
|
||||||
testOutput.addMessage("### Error: Failed parsing command output", MessageList.ERROR);
|
// testOutput.addMessage("### Error: Failed parsing command output", MessageList.ERROR);
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
testOutput.addMessage("### Validating section addresses");
|
testOutput.addMessage("### Validating section addresses");
|
||||||
relDataSectionAddr = ContikiMoteType.parseCommandDataSectionAddr(commandData);
|
SectionParser dataSecParser = new ContikiMoteType.CommandSectionParser(
|
||||||
dataSectionSize = ContikiMoteType.parseCommandDataSectionSize(commandData);
|
commandData,
|
||||||
relBssSectionAddr = ContikiMoteType.parseCommandBssSectionAddr(commandData);
|
Cooja.getExternalToolsSetting("COMMAND_DATA_START"),
|
||||||
bssSectionSize = ContikiMoteType.parseCommandBssSectionSize(commandData);
|
Cooja.getExternalToolsSetting("COMMAND_DATA_SIZE"));
|
||||||
|
SectionParser bssSecParser = new ContikiMoteType.CommandSectionParser(
|
||||||
|
commandData,
|
||||||
|
Cooja.getExternalToolsSetting("COMMAND_BSS_START"),
|
||||||
|
Cooja.getExternalToolsSetting("COMMAND_BSS_SIZE"));
|
||||||
|
|
||||||
|
relDataSectionAddr = dataSecParser.parseAddr();
|
||||||
|
dataSectionSize = dataSecParser.parseSize();
|
||||||
|
relBssSectionAddr = bssSecParser.parseAddr();
|
||||||
|
bssSectionSize = bssSecParser.parseSize();
|
||||||
testOutput.addMessage("Data section address: 0x" + Integer.toHexString(relDataSectionAddr));
|
testOutput.addMessage("Data section address: 0x" + Integer.toHexString(relDataSectionAddr));
|
||||||
testOutput.addMessage("Data section size: 0x" + Integer.toHexString(dataSectionSize));
|
testOutput.addMessage("Data section size: 0x" + Integer.toHexString(dataSectionSize));
|
||||||
testOutput.addMessage("BSS section address: 0x" + Integer.toHexString(relBssSectionAddr));
|
testOutput.addMessage("BSS section address: 0x" + Integer.toHexString(relBssSectionAddr));
|
||||||
|
|
Loading…
Reference in a new issue