[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 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_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_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_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]*$ 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_ADDRESS_2 = [ \t]*$
MAPFILE_VAR_SIZE_1 = ^ MAPFILE_VAR_SIZE_1 = ^
MAPFILE_VAR_SIZE_2 = [ \t]*(0x[0-9A-Fa-f]*)[ \t]*[^ ]*[ \t]*$ 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$ PARSE_COMMAND=nm -aP $(LIBFILE)
COMMAND_DATA_END = ^([0-9A-Fa-f]*)[ \t]A[ \t]_edata$ COMMAND_VAR_NAME_ADDRESS_SIZE = ^([^.].*?) <SECTION> ([0-9a-fA-F]+) ([0-9a-fA-F])*
COMMAND_BSS_START = ^([0-9A-Fa-f]*)[ \t]A[ \t]__bss_start$ COMMAND_VAR_SEC_DATA = [DdGg]
COMMAND_BSS_END = ^([0-9A-Fa-f]*)[ \t]A[ \t]_end$ 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=\ VISUALIZER_DEFAULT_SKINS=\
org.contikios.cooja.plugins.skins.IDVisualizerSkin;\ 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", "MAPFILE_VAR_SIZE_1", "MAPFILE_VAR_SIZE_2",
"PARSE_COMMAND", "PARSE_COMMAND",
"COMMAND_VAR_NAME_ADDRESS", "COMMAND_VAR_NAME_ADDRESS_SIZE",
"COMMAND_DATA_START", "COMMAND_DATA_END", "COMMAND_DATA_START", "COMMAND_DATA_END",
"COMMAND_BSS_START", "COMMAND_BSS_END", "COMMAND_BSS_START", "COMMAND_BSS_END",
"COMMAND_COMMON_START", "COMMAND_COMMON_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.JComponent;
import javax.swing.JLabel; import javax.swing.JLabel;
import org.apache.log4j.Level;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.jdom.Element; import org.jdom.Element;
@ -426,19 +427,24 @@ public class ContikiMoteType implements MoteType {
dataSecParser = new CommandSectionParser( dataSecParser = new CommandSectionParser(
output, output,
Cooja.getExternalToolsSetting("COMMAND_DATA_START"), Cooja.getExternalToolsSetting("COMMAND_DATA_START"),
Cooja.getExternalToolsSetting("COMMAND_DATA_SIZE")); Cooja.getExternalToolsSetting("COMMAND_DATA_END"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_DATA"));
bssSecParser = new CommandSectionParser( bssSecParser = new CommandSectionParser(
output, output,
Cooja.getExternalToolsSetting("COMMAND_BSS_START"), Cooja.getExternalToolsSetting("COMMAND_BSS_START"),
Cooja.getExternalToolsSetting("COMMAND_BSS_SIZE")); Cooja.getExternalToolsSetting("COMMAND_BSS_END"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_BSS"));
commonSecParser = new CommandSectionParser( commonSecParser = new CommandSectionParser(
output, output,
Cooja.getExternalToolsSetting("COMMAND_COMMON_START"), Cooja.getExternalToolsSetting("COMMAND_COMMON_START"),
Cooja.getExternalToolsSetting("COMMAND_COMMON_SIZE")); Cooja.getExternalToolsSetting("COMMAND_COMMON_END"),
readonlySecParser = new CommandSectionParser( Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_COMMON"));
/* XXX Currently Cooja tries to sync readonly memory */
readonlySecParser = null;/* new CommandSectionParser(
output, output,
Cooja.getExternalToolsSetting("^([0-9A-Fa-f]*)[ \t]t[ \t].text$"), Cooja.getExternalToolsSetting("COMMAND_READONLY_START"),
Cooja.getExternalToolsSetting("")); // XXX Cooja.getExternalToolsSetting("COMMAND_READONLY_END"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_READONLY"));*/
} else { } else {
/* Parse map file */ /* 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 { public static abstract class SectionParser {
private final String[] mapFileData; private final String[] mapFileData;
protected int startAddr;
protected int size;
public SectionParser(String[] mapFileData) { public SectionParser(String[] mapFileData) {
this.mapFileData = mapFileData; this.mapFileData = mapFileData;
@ -540,9 +548,17 @@ public class ContikiMoteType implements MoteType {
return mapFileData; 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(); abstract Map<String, Symbol> parseSymbols();
@ -559,24 +575,33 @@ public class ContikiMoteType implements MoteType {
public MemoryInterface parse() { public MemoryInterface parse() {
/* Parse start address and size of section */ /* Parse start address and size of section */
int mapSectionAddr = parseStartAddr(); parseStartAddr();
int mapSectionSize = parseSize(); parseSize();
if (mapSectionAddr < 0 || mapSectionSize <= 0) { if (getStartAddr() < 0 || getSize() <= 0) {
return null; return null;
} }
Map<String, Symbol> variables = parseSymbols(); Map<String, Symbol> variables = parseSymbols();
logger.info(String.format("Parsed section at 0x%x ( %d == 0x%x bytes)", logger.info(String.format("Parsed section at 0x%x ( %d == 0x%x bytes)",
// getContikiFirmwareFile().getName(), getStartAddr(),
mapSectionAddr, getSize(),
mapSectionSize, getSize()));
mapSectionSize));
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( return new ArrayMemory(
mapSectionAddr, getStartAddr(),
mapSectionSize, getSize(),
MemoryLayout.getNative(), MemoryLayout.getNative(),
variables); variables);
} }
@ -598,19 +623,21 @@ public class ContikiMoteType implements MoteType {
} }
@Override @Override
public int parseStartAddr() { protected void parseStartAddr() {
if (startRegExp == null) { if (startRegExp == null || startRegExp.equals("")) {
return -1; startAddr = -1;
return;
} }
return parseFirstHexInt(startRegExp, getData()); startAddr = parseFirstHexInt(startRegExp, getData());
} }
@Override @Override
public int parseSize() { protected void parseSize() {
if (sizeRegExp == null) { if (sizeRegExp == null || sizeRegExp.equals("")) {
return -1; size = -1;
return;
} }
return parseFirstHexInt(sizeRegExp, getData()); size = parseFirstHexInt(sizeRegExp, getData());
} }
@Override @Override
@ -621,8 +648,8 @@ public class ContikiMoteType implements MoteType {
for (String line : getData()) { for (String line : getData()) {
Matcher matcher = pattern.matcher(line); Matcher matcher = pattern.matcher(line);
if (matcher.find()) { if (matcher.find()) {
if (Integer.decode(matcher.group(1)).intValue() >= parseStartAddr() if (Integer.decode(matcher.group(1)).intValue() >= getStartAddr()
&& Integer.decode(matcher.group(1)).intValue() <= parseStartAddr() + parseSize()) { && Integer.decode(matcher.group(1)).intValue() <= getStartAddr() + getSize()) {
String varName = matcher.group(2); String varName = matcher.group(2);
varNames.put(varName, new Symbol( varNames.put(varName, new Symbol(
Symbol.Type.VARIABLE, Symbol.Type.VARIABLE,
@ -685,59 +712,82 @@ public class ContikiMoteType implements MoteType {
public static class CommandSectionParser extends SectionParser { public static class CommandSectionParser extends SectionParser {
private final String startRegExp; 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); super(mapFileData);
this.startRegExp = startRegExp; this.startRegExp = startRegExp;
this.sizeRegExp = sizeRegExp; this.endRegExp = endRegExp;
this.sectionRegExp = sectionRegExp;
} }
@Override @Override
public int parseStartAddr() { protected void parseStartAddr() {
if (startRegExp == null) { if (startRegExp == null || startRegExp.equals("")) {
return -1; startAddr = -1;
return;
} }
return parseFirstHexInt(startRegExp, getData()); startAddr = parseFirstHexInt(startRegExp, getData());
} }
@Override @Override
public int parseSize() { public void parseSize() {
if (sizeRegExp == null) { if (endRegExp == null || endRegExp.equals("")) {
return -1; size = -1;
return;
} }
int start = parseStartAddr(); if (getStartAddr() < 0) {
if (start < 0) { size = -1;
return -1; return;
} }
int end = parseFirstHexInt(sizeRegExp, getData()); int end = parseFirstHexInt(endRegExp, getData());
if (end < 0) { if (end < 0) {
return -1; size = -1;
return;
} }
return end - start; size = end - getStartAddr();
} }
@Override @Override
public Map<String, Symbol> parseSymbols() { public Map<String, Symbol> parseSymbols() {
HashMap<String, Symbol> addresses = new HashMap<>(); 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()) { for (String line : getData()) {
Matcher matcher = pattern.matcher(line); Matcher matcher = pattern.matcher(line);
if (matcher.find()) { if (matcher.find()) {
/* Line matched variable address */ /* Line matched variable address */
String symbol = matcher.group(2); String symbol = matcher.group(1);
int address = Integer.parseInt(matcher.group(1), 16); 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 */ /* XXX needs to be checked */
if (!addresses.containsKey(symbol)) { 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 { } else {
int oldAddress = (int) addresses.get(symbol).addr; int oldAddress = (int) addresses.get(symbol).addr;
if (oldAddress != address) { if (oldAddress != varAddr) {
/*logger.warn("Warning, command response not matching previous entry of: " /*logger.warn("Warning, command response not matching previous entry of: "
+ varName);*/ + varName);*/
} }

View file

@ -776,10 +776,12 @@ public class ConfigurationWizard extends JDialog {
mapData, mapData,
Cooja.getExternalToolsSetting("MAPFILE_BSS_START"), Cooja.getExternalToolsSetting("MAPFILE_BSS_START"),
Cooja.getExternalToolsSetting("MAPFILE_BSS_SIZE")); Cooja.getExternalToolsSetting("MAPFILE_BSS_SIZE"));
relDataSectionAddr = dataSecParser.parseStartAddr(); dataSecParser.parse();
dataSectionSize = dataSecParser.parseSize(); bssSecParser.parse();
relBssSectionAddr = bssSecParser.parseStartAddr(); relDataSectionAddr = dataSecParser.getStartAddr();
bssSectionSize = bssSecParser.parseSize(); dataSectionSize = dataSecParser.getSize();
relBssSectionAddr = bssSecParser.getStartAddr();
bssSectionSize = bssSecParser.getSize();
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));
@ -859,16 +861,20 @@ public class ConfigurationWizard extends JDialog {
SectionParser dataSecParser = new ContikiMoteType.CommandSectionParser( SectionParser dataSecParser = new ContikiMoteType.CommandSectionParser(
commandData, commandData,
Cooja.getExternalToolsSetting("COMMAND_DATA_START"), 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( SectionParser bssSecParser = new ContikiMoteType.CommandSectionParser(
commandData, commandData,
Cooja.getExternalToolsSetting("COMMAND_BSS_START"), Cooja.getExternalToolsSetting("COMMAND_BSS_START"),
Cooja.getExternalToolsSetting("COMMAND_BSS_SIZE")); Cooja.getExternalToolsSetting("COMMAND_BSS_SIZE"),
Cooja.getExternalToolsSetting("COMMAND_VAR_SEC_BSS"));
relDataSectionAddr = dataSecParser.parseStartAddr(); dataSecParser.parse();
dataSectionSize = dataSecParser.parseSize(); bssSecParser.parse();
relBssSectionAddr = bssSecParser.parseStartAddr(); relDataSectionAddr = dataSecParser.getStartAddr();
bssSectionSize = bssSecParser.parseSize(); dataSectionSize = dataSecParser.getSize();
relBssSectionAddr = bssSecParser.getStartAddr();
bssSectionSize = bssSecParser.getSize();
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));