[cooja] ContikiMoteType: Fixed Command parsing

- Use `nm -aP` for parsing both addres and size information
- Use symbol section information for parsing
This commit is contained in:
Enrico Joerns 2014-08-06 16:07:52 +02:00
parent d4e36dcd47
commit 3da6c6d55a
4 changed files with 129 additions and 66 deletions

View file

@ -25,7 +25,6 @@ PATH_JAVAC = javac
DEFAULT_PROJECTDIRS = [CONTIKI_DIR]/tools/cooja/apps/mrm;[CONTIKI_DIR]/tools/cooja/apps/mspsim;[CONTIKI_DIR]/tools/cooja/apps/avrora;[CONTIKI_DIR]/tools/cooja/apps/serial_socket;[CONTIKI_DIR]/tools/cooja/apps/collect-view;[CONTIKI_DIR]/tools/cooja/apps/powertracker
PARSE_WITH_COMMAND=false
PARSE_COMMAND=nm -a $(LIBFILE)
MAPFILE_DATA_START = ^.data[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$
MAPFILE_DATA_SIZE = ^.data[ \t]*0x[0-9A-Fa-f]*[ \t]*0x([0-9A-Fa-f]*)[ \t]*$
MAPFILE_BSS_START = ^.bss[ \t]*0x([0-9A-Fa-f]*)[ \t]*0x[0-9A-Fa-f]*[ \t]*$
@ -35,11 +34,19 @@ MAPFILE_VAR_ADDRESS_1 = ^[ \t]*0x([0-9A-Fa-f]*)[ \t]*
MAPFILE_VAR_ADDRESS_2 = [ \t]*$
MAPFILE_VAR_SIZE_1 = ^
MAPFILE_VAR_SIZE_2 = [ \t]*(0x[0-9A-Fa-f]*)[ \t]*[^ ]*[ \t]*$
COMMAND_VAR_NAME_ADDRESS = ^([0-9A-Fa-f][0-9A-Fa-f]*)[ \t][^Tt][ \t]([^ ._][^ ]*)
COMMAND_DATA_START = ^([0-9A-Fa-f]*)[ \t]d[ \t].data$
COMMAND_DATA_END = ^([0-9A-Fa-f]*)[ \t]A[ \t]_edata$
COMMAND_BSS_START = ^([0-9A-Fa-f]*)[ \t]A[ \t]__bss_start$
COMMAND_BSS_END = ^([0-9A-Fa-f]*)[ \t]A[ \t]_end$
PARSE_COMMAND=nm -aP $(LIBFILE)
COMMAND_VAR_NAME_ADDRESS_SIZE = ^([^.].*?) <SECTION> ([0-9a-fA-F]+) ([0-9a-fA-F])*
COMMAND_VAR_SEC_DATA = [DdGg]
COMMAND_VAR_SEC_BSS = [Bb]
COMMAND_VAR_SEC_COMMON = [C]
COMMAND_VAR_SEC_READONLY = [Rr]
COMMAND_DATA_START = ^.data[ \t]d[ \t]([0-9A-Fa-f]*)[ \t]*$
COMMAND_DATA_END = ^_edata[ \t]A[ \t]([0-9A-Fa-f]*)[ \t]*$
COMMAND_BSS_START = ^__bss_start[ \t]A[ \t]([0-9A-Fa-f]*)[ \t]*$
COMMAND_BSS_END = ^_end[ \t]A[ \t]([0-9A-Fa-f]*)[ \t]*$
COMMAND_READONLY_START = ^.rodata[ \t]r[ \t]([0-9A-Fa-f]*)[ \t]*$
COMMAND_READONLY_END = ^.eh_frame_hdr[ \t]r[ \t]([0-9A-Fa-f]*)[ \t]*$
VISUALIZER_DEFAULT_SKINS=\
org.contikios.cooja.plugins.skins.IDVisualizerSkin;\

View file

@ -274,7 +274,7 @@ public class Cooja extends Observable {
"MAPFILE_VAR_SIZE_1", "MAPFILE_VAR_SIZE_2",
"PARSE_COMMAND",
"COMMAND_VAR_NAME_ADDRESS",
"COMMAND_VAR_NAME_ADDRESS_SIZE",
"COMMAND_DATA_START", "COMMAND_DATA_END",
"COMMAND_BSS_START", "COMMAND_BSS_END",
"COMMAND_COMMON_START", "COMMAND_COMMON_END",

View file

@ -51,6 +51,7 @@ import java.util.regex.Pattern;
import javax.swing.JComponent;
import javax.swing.JLabel;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.jdom.Element;
@ -426,19 +427,24 @@ public class ContikiMoteType implements MoteType {
dataSecParser = new CommandSectionParser(
output,
Cooja.getExternalToolsSetting("COMMAND_DATA_START"),
Cooja.getExternalToolsSetting("COMMAND_DATA_SIZE"));
Cooja.getExternalToolsSetting("COMMAND_DATA_END"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_DATA"));
bssSecParser = new CommandSectionParser(
output,
Cooja.getExternalToolsSetting("COMMAND_BSS_START"),
Cooja.getExternalToolsSetting("COMMAND_BSS_SIZE"));
Cooja.getExternalToolsSetting("COMMAND_BSS_END"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_BSS"));
commonSecParser = new CommandSectionParser(
output,
Cooja.getExternalToolsSetting("COMMAND_COMMON_START"),
Cooja.getExternalToolsSetting("COMMAND_COMMON_SIZE"));
readonlySecParser = new CommandSectionParser(
Cooja.getExternalToolsSetting("COMMAND_COMMON_END"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_COMMON"));
/* XXX Currently Cooja tries to sync readonly memory */
readonlySecParser = null;/* new CommandSectionParser(
output,
Cooja.getExternalToolsSetting("^([0-9A-Fa-f]*)[ \t]t[ \t].text$"),
Cooja.getExternalToolsSetting("")); // XXX
Cooja.getExternalToolsSetting("COMMAND_READONLY_START"),
Cooja.getExternalToolsSetting("COMMAND_READONLY_END"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_READONLY"));*/
} else {
/* Parse map file */
@ -526,11 +532,13 @@ public class ContikiMoteType implements MoteType {
}
/**
*
* Abstract base class for concrete section parser class.
*/
public static abstract class SectionParser {
private final String[] mapFileData;
protected int startAddr;
protected int size;
public SectionParser(String[] mapFileData) {
this.mapFileData = mapFileData;
@ -540,9 +548,17 @@ public class ContikiMoteType implements MoteType {
return mapFileData;
}
public abstract int parseStartAddr();
public int getStartAddr() {
return startAddr;
}
public abstract int parseSize();
public int getSize() {
return size;
}
protected abstract void parseStartAddr();
protected abstract void parseSize();
abstract Map<String, Symbol> parseSymbols();
@ -559,24 +575,33 @@ public class ContikiMoteType implements MoteType {
public MemoryInterface parse() {
/* Parse start address and size of section */
int mapSectionAddr = parseStartAddr();
int mapSectionSize = parseSize();
parseStartAddr();
parseSize();
if (mapSectionAddr < 0 || mapSectionSize <= 0) {
if (getStartAddr() < 0 || getSize() <= 0) {
return null;
}
Map<String, Symbol> variables = parseSymbols();
logger.info(String.format("Parsed section at 0x%x ( %d == 0x%x bytes)",
// getContikiFirmwareFile().getName(),
mapSectionAddr,
mapSectionSize,
mapSectionSize));
getStartAddr(),
getSize(),
getSize()));
if (logger.isDebugEnabled()) {
for (String var : variables.keySet()) {
logger.debug(String.format("Found Symbol: %s, 0x%x, %d",
var,
variables.get(var).addr,
variables.get(var).size));
}
}
return new ArrayMemory(
mapSectionAddr,
mapSectionSize,
getStartAddr(),
getSize(),
MemoryLayout.getNative(),
variables);
}
@ -598,19 +623,21 @@ public class ContikiMoteType implements MoteType {
}
@Override
public int parseStartAddr() {
if (startRegExp == null) {
return -1;
protected void parseStartAddr() {
if (startRegExp == null || startRegExp.equals("")) {
startAddr = -1;
return;
}
return parseFirstHexInt(startRegExp, getData());
startAddr = parseFirstHexInt(startRegExp, getData());
}
@Override
public int parseSize() {
if (sizeRegExp == null) {
return -1;
protected void parseSize() {
if (sizeRegExp == null || sizeRegExp.equals("")) {
size = -1;
return;
}
return parseFirstHexInt(sizeRegExp, getData());
size = parseFirstHexInt(sizeRegExp, getData());
}
@Override
@ -621,8 +648,8 @@ public class ContikiMoteType implements MoteType {
for (String line : getData()) {
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
if (Integer.decode(matcher.group(1)).intValue() >= parseStartAddr()
&& Integer.decode(matcher.group(1)).intValue() <= parseStartAddr() + parseSize()) {
if (Integer.decode(matcher.group(1)).intValue() >= getStartAddr()
&& Integer.decode(matcher.group(1)).intValue() <= getStartAddr() + getSize()) {
String varName = matcher.group(2);
varNames.put(varName, new Symbol(
Symbol.Type.VARIABLE,
@ -685,59 +712,82 @@ public class ContikiMoteType implements MoteType {
public static class CommandSectionParser extends SectionParser {
private final String startRegExp;
private final String sizeRegExp;
private final String endRegExp;
private final String sectionRegExp;
public CommandSectionParser(String[] mapFileData, String startRegExp, String sizeRegExp) {
/**
* Creates SectionParser based on output of configurable command.
*
* @param mapFileData Map file lines as array of String
* @param startRegExp Regular expression for parsing start of section
* @param endRegExp Regular expression for parsing end of section
* @param sectionRegExp Reqular expression describing symbol table section identifier (e.g. '[Rr]' for readonly)
* Will be used to replaced '<SECTION>'in 'COMMAND_VAR_NAME_ADDRESS_SIZE'
*/
public CommandSectionParser(String[] mapFileData, String startRegExp, String endRegExp, String sectionRegExp) {
super(mapFileData);
this.startRegExp = startRegExp;
this.sizeRegExp = sizeRegExp;
this.endRegExp = endRegExp;
this.sectionRegExp = sectionRegExp;
}
@Override
public int parseStartAddr() {
if (startRegExp == null) {
return -1;
protected void parseStartAddr() {
if (startRegExp == null || startRegExp.equals("")) {
startAddr = -1;
return;
}
return parseFirstHexInt(startRegExp, getData());
startAddr = parseFirstHexInt(startRegExp, getData());
}
@Override
public int parseSize() {
if (sizeRegExp == null) {
return -1;
public void parseSize() {
if (endRegExp == null || endRegExp.equals("")) {
size = -1;
return;
}
int start = parseStartAddr();
if (start < 0) {
return -1;
if (getStartAddr() < 0) {
size = -1;
return;
}
int end = parseFirstHexInt(sizeRegExp, getData());
int end = parseFirstHexInt(endRegExp, getData());
if (end < 0) {
return -1;
size = -1;
return;
}
return end - start;
size = end - getStartAddr();
}
@Override
public Map<String, Symbol> parseSymbols() {
HashMap<String, Symbol> addresses = new HashMap<>();
Pattern pattern = Pattern.compile(Cooja.getExternalToolsSetting("COMMAND_VAR_NAME_ADDRESS"));
/* Replace "<SECTION>" in regexp by section specific regex */
Pattern pattern = Pattern.compile(
Cooja.getExternalToolsSetting("COMMAND_VAR_NAME_ADDRESS_SIZE")
.replace("<SECTION>", sectionRegExp));
for (String line : getData()) {
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
/* Line matched variable address */
String symbol = matcher.group(2);
int address = Integer.parseInt(matcher.group(1), 16);
String symbol = matcher.group(1);
int varAddr = Integer.parseInt(matcher.group(2), 16);
int varSize;
if (matcher.group(3) != null) {
varSize = Integer.parseInt(matcher.group(3), 16);
} else {
varSize = -1;
}
/* XXX needs to be checked */
if (!addresses.containsKey(symbol)) {
addresses.put(symbol, new Symbol(Symbol.Type.VARIABLE, symbol, address, 1));
addresses.put(symbol, new Symbol(Symbol.Type.VARIABLE, symbol, varAddr, varSize));
} else {
int oldAddress = (int) addresses.get(symbol).addr;
if (oldAddress != address) {
if (oldAddress != varAddr) {
/*logger.warn("Warning, command response not matching previous entry of: "
+ varName);*/
}

View file

@ -776,10 +776,12 @@ public class ConfigurationWizard extends JDialog {
mapData,
Cooja.getExternalToolsSetting("MAPFILE_BSS_START"),
Cooja.getExternalToolsSetting("MAPFILE_BSS_SIZE"));
relDataSectionAddr = dataSecParser.parseStartAddr();
dataSectionSize = dataSecParser.parseSize();
relBssSectionAddr = bssSecParser.parseStartAddr();
bssSectionSize = bssSecParser.parseSize();
dataSecParser.parse();
bssSecParser.parse();
relDataSectionAddr = dataSecParser.getStartAddr();
dataSectionSize = dataSecParser.getSize();
relBssSectionAddr = bssSecParser.getStartAddr();
bssSectionSize = bssSecParser.getSize();
testOutput.addMessage("Data section address: 0x" + Integer.toHexString(relDataSectionAddr));
testOutput.addMessage("Data section size: 0x" + Integer.toHexString(dataSectionSize));
testOutput.addMessage("BSS section address: 0x" + Integer.toHexString(relBssSectionAddr));
@ -859,16 +861,20 @@ public class ConfigurationWizard extends JDialog {
SectionParser dataSecParser = new ContikiMoteType.CommandSectionParser(
commandData,
Cooja.getExternalToolsSetting("COMMAND_DATA_START"),
Cooja.getExternalToolsSetting("COMMAND_DATA_SIZE"));
Cooja.getExternalToolsSetting("COMMAND_DATA_SIZE"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_DATA"));
SectionParser bssSecParser = new ContikiMoteType.CommandSectionParser(
commandData,
Cooja.getExternalToolsSetting("COMMAND_BSS_START"),
Cooja.getExternalToolsSetting("COMMAND_BSS_SIZE"));
Cooja.getExternalToolsSetting("COMMAND_BSS_SIZE"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_BSS"));
relDataSectionAddr = dataSecParser.parseStartAddr();
dataSectionSize = dataSecParser.parseSize();
relBssSectionAddr = bssSecParser.parseStartAddr();
bssSectionSize = bssSecParser.parseSize();
dataSecParser.parse();
bssSecParser.parse();
relDataSectionAddr = dataSecParser.getStartAddr();
dataSectionSize = dataSecParser.getSize();
relBssSectionAddr = bssSecParser.getStartAddr();
bssSectionSize = bssSecParser.getSize();
testOutput.addMessage("Data section address: 0x" + Integer.toHexString(relDataSectionAddr));
testOutput.addMessage("Data section size: 0x" + Integer.toHexString(dataSectionSize));
testOutput.addMessage("BSS section address: 0x" + Integer.toHexString(relBssSectionAddr));