mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-233 Added sleigh source file names to constructor info
This commit is contained in:
parent
9dd458e9e1
commit
ec5009f613
14 changed files with 415 additions and 76 deletions
|
@ -26,6 +26,7 @@ import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
|
|||
import ghidra.app.plugin.processors.sleigh.template.HandleTpl;
|
||||
import ghidra.program.model.lang.UnknownInstructionException;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.xml.SpecXmlUtils;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
@ -55,6 +56,7 @@ public class Constructor implements Comparable<Constructor> {
|
|||
in original (uncompiled) specfile */
|
||||
|
||||
private int flowthruindex;
|
||||
private String sourceFile;
|
||||
|
||||
public Constructor() {
|
||||
parent = null;
|
||||
|
@ -115,14 +117,14 @@ public class Constructor implements Comparable<Constructor> {
|
|||
|
||||
public String print(ParserWalker walker) throws MemoryAccessException {
|
||||
String res = "";
|
||||
for (int i = 0; i < printpiece.length; ++i) {
|
||||
if (printpiece[i].length() != 0) {
|
||||
if (printpiece[i].charAt(0) == '\n') {
|
||||
int index = printpiece[i].charAt(1) - 'A';
|
||||
for (String element : printpiece) {
|
||||
if (element.length() != 0) {
|
||||
if (element.charAt(0) == '\n') {
|
||||
int index = element.charAt(1) - 'A';
|
||||
res += operands[index].print(walker);
|
||||
}
|
||||
else {
|
||||
res += printpiece[i];
|
||||
res += element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +132,7 @@ public class Constructor implements Comparable<Constructor> {
|
|||
}
|
||||
|
||||
public String printSeparator(int separatorIndex) {
|
||||
|
||||
|
||||
// Separator is all chars to the left of the corresponding operand
|
||||
// The mnemonic (first sequence of contiguous non-space print-pieces)
|
||||
// is ignored when identifying the first separator (index 0) and the
|
||||
|
@ -140,7 +142,7 @@ public class Constructor implements Comparable<Constructor> {
|
|||
if (separatorIndex < 0 || separatorIndex > operands.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
String cachedSeparator = separators[separatorIndex];
|
||||
if (cachedSeparator != null) {
|
||||
if (cachedSeparator.length() == 0) {
|
||||
|
@ -188,11 +190,11 @@ public class Constructor implements Comparable<Constructor> {
|
|||
FixedHandle lastHandle = null;
|
||||
int lastHandleIndex = -1;
|
||||
|
||||
for (int i = 0; i < printpiece.length; ++i) {
|
||||
for (String element : printpiece) {
|
||||
int prevSize = list.size();
|
||||
if (printpiece[i].length() != 0) {
|
||||
if (printpiece[i].charAt(0) == '\n') {
|
||||
int index = printpiece[i].charAt(1) - 'A';
|
||||
if (element.length() != 0) {
|
||||
if (element.charAt(0) == '\n') {
|
||||
int index = element.charAt(1) - 'A';
|
||||
operands[index].printList(walker, list);
|
||||
if (prevSize != list.size() && ++opSymbolCnt == 1) {
|
||||
// Identify sole handle which can be fixed
|
||||
|
@ -212,8 +214,9 @@ public class Constructor implements Comparable<Constructor> {
|
|||
}
|
||||
}
|
||||
else {
|
||||
for (int j = 0; j < printpiece[i].length(); ++j)
|
||||
list.add(new Character(printpiece[i].charAt(j)));
|
||||
for (int j = 0; j < element.length(); ++j) {
|
||||
list.add(new Character(element.charAt(j)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -264,8 +267,9 @@ public class Constructor implements Comparable<Constructor> {
|
|||
return res;
|
||||
}
|
||||
}
|
||||
if (firstwhitespace == -1)
|
||||
if (firstwhitespace == -1) {
|
||||
return res; // Nothing to print
|
||||
}
|
||||
for (int i = firstwhitespace + 1; i < printpiece.length; ++i) {
|
||||
if (printpiece[i].length() != 0) {
|
||||
if (printpiece[i].charAt(0) == '\n') {
|
||||
|
@ -289,8 +293,8 @@ public class Constructor implements Comparable<Constructor> {
|
|||
*/
|
||||
public void applyContext(ParserWalker walker, SleighDebugLogger debug)
|
||||
throws MemoryAccessException {
|
||||
for (int i = 0; i < context.length; ++i) {
|
||||
context[i].apply(walker, debug);
|
||||
for (ContextChange element : context) {
|
||||
element.apply(walker, debug);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,10 +304,12 @@ public class Constructor implements Comparable<Constructor> {
|
|||
* @return the named section (or null)
|
||||
*/
|
||||
public ConstructTpl getNamedTempl(int secnum) {
|
||||
if (namedtempl == null)
|
||||
if (namedtempl == null) {
|
||||
return null;
|
||||
if (secnum < namedtempl.size())
|
||||
}
|
||||
if (secnum < namedtempl.size()) {
|
||||
return namedtempl.get(secnum);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -316,7 +322,17 @@ public class Constructor implements Comparable<Constructor> {
|
|||
parent = (SubtableSymbol) symtab.findSymbol(myId);
|
||||
firstwhitespace = SpecXmlUtils.decodeInt(el.getAttribute("first"));
|
||||
minimumlength = SpecXmlUtils.decodeInt(el.getAttribute("length"));
|
||||
lineno = SpecXmlUtils.decodeInt(el.getAttribute("line"));
|
||||
String sourceAndLine = el.getAttribute("line");
|
||||
String[] parts = sourceAndLine.split(":");
|
||||
if (parts.length != 2) {
|
||||
Msg.error(this, "Bad line attribute in .sla file");
|
||||
lineno = -1;
|
||||
sourceFile = "UNKNOWN";
|
||||
}
|
||||
else {
|
||||
lineno = Integer.parseInt(parts[1].trim());
|
||||
sourceFile = sleigh.getSourceFileIndexer().getFileName(Integer.parseInt(parts[0].trim()));
|
||||
}
|
||||
|
||||
ArrayList<Object> oplist = new ArrayList<>();
|
||||
ArrayList<Object> piecelist = new ArrayList<>();
|
||||
|
@ -354,17 +370,21 @@ public class Constructor implements Comparable<Constructor> {
|
|||
ConstructTpl curtempl = new ConstructTpl();
|
||||
int sectionid = curtempl.restoreXml(parser, sleigh.getAddressFactory());
|
||||
if (sectionid < 0) {
|
||||
if (templ != null)
|
||||
if (templ != null) {
|
||||
throw new UnknownInstructionException("Duplicate main template section");
|
||||
}
|
||||
templ = curtempl;
|
||||
}
|
||||
else {
|
||||
if (namedtempl == null)
|
||||
if (namedtempl == null) {
|
||||
namedtempl = new ArrayList<>();
|
||||
while (namedtempl.size() <= sectionid)
|
||||
}
|
||||
while (namedtempl.size() <= sectionid) {
|
||||
namedtempl.add(null);
|
||||
if (namedtempl.get(sectionid) != null)
|
||||
}
|
||||
if (namedtempl.get(sectionid) != null) {
|
||||
throw new UnknownInstructionException("Duplicate named template section");
|
||||
}
|
||||
namedtempl.set(sectionid, curtempl);
|
||||
}
|
||||
}
|
||||
|
@ -378,10 +398,12 @@ public class Constructor implements Comparable<Constructor> {
|
|||
context = new ContextChange[coplist.size()];
|
||||
coplist.toArray(context);
|
||||
if ((printpiece.length == 1) && (printpiece[0].length() >= 2) &&
|
||||
(printpiece[0].charAt(0) == '\n'))
|
||||
(printpiece[0].charAt(0) == '\n')) {
|
||||
flowthruindex = printpiece[0].charAt(1) - 'A';
|
||||
else
|
||||
}
|
||||
else {
|
||||
flowthruindex = -1;
|
||||
}
|
||||
parser.end(el);
|
||||
}
|
||||
|
||||
|
@ -391,18 +413,21 @@ public class Constructor implements Comparable<Constructor> {
|
|||
* @return array of operand indices
|
||||
*/
|
||||
public int[] getOpsPrintOrder() {
|
||||
if (firstwhitespace == -1)
|
||||
if (firstwhitespace == -1) {
|
||||
return new int[0];
|
||||
}
|
||||
int count = 0;
|
||||
for (int i = firstwhitespace + 1; i < printpiece.length; ++i) {
|
||||
if (printpiece[i].length() != 0 && printpiece[i].charAt(0) == '\n')
|
||||
if (printpiece[i].length() != 0 && printpiece[i].charAt(0) == '\n') {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
int[] res = new int[count];
|
||||
count = 0;
|
||||
for (int i = firstwhitespace + 1; i < printpiece.length; ++i) {
|
||||
if (printpiece[i].length() != 0 && printpiece[i].charAt(0) == '\n')
|
||||
if (printpiece[i].length() != 0 && printpiece[i].charAt(0) == '\n') {
|
||||
res[count++] = printpiece[i].charAt(1) - 'A';
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -444,4 +469,12 @@ public class Constructor implements Comparable<Constructor> {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the source file
|
||||
* @return source file
|
||||
*/
|
||||
public String getSourceFile() {
|
||||
return sourceFile;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,8 +84,8 @@ public class SleighDebugLogger {
|
|||
}
|
||||
|
||||
if (!(language instanceof SleighLanguage)) {
|
||||
throw new IllegalArgumentException("unsupport language provider: " +
|
||||
language.getClass().getSimpleName());
|
||||
throw new IllegalArgumentException(
|
||||
"unsupport language provider: " + language.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
ContextCache contextCache = new ContextCache();
|
||||
|
@ -112,9 +112,8 @@ public class SleighDebugLogger {
|
|||
}
|
||||
|
||||
try {
|
||||
prototype =
|
||||
new SleighInstructionPrototype((SleighLanguage) language, buf, context,
|
||||
contextCache, false, this);
|
||||
prototype = new SleighInstructionPrototype((SleighLanguage) language, buf, context,
|
||||
contextCache, false, this);
|
||||
|
||||
prototype.cacheInfo(buf, context, false);
|
||||
|
||||
|
@ -148,8 +147,9 @@ public class SleighDebugLogger {
|
|||
* @throws IllegalArgumentException if program language provider is not Sleigh
|
||||
*/
|
||||
public SleighDebugLogger(Program program, Address start, SleighDebugMode mode) {
|
||||
this(new MemoryBufferImpl(program.getMemory(), start), new MyProcessorContextView(
|
||||
program.getProgramContext(), start), program.getLanguage(), mode);
|
||||
this(new MemoryBufferImpl(program.getMemory(), start),
|
||||
new MyProcessorContextView(program.getProgramContext(), start), program.getLanguage(),
|
||||
mode);
|
||||
}
|
||||
|
||||
private class DebugInstructionContext implements InstructionContext {
|
||||
|
@ -240,7 +240,8 @@ public class SleighDebugLogger {
|
|||
if (!"instruction".equals(tableName) || name.startsWith("\n")) {
|
||||
name = tableName;
|
||||
}
|
||||
list.add(name + "(" + Integer.toString(ct.getLineno()) + ")");
|
||||
|
||||
list.add(name + "(" + ct.getSourceFile() + ":" + Integer.toString(ct.getLineno()) + ")");
|
||||
|
||||
int flowthruindex = ct.getFlowthruIndex();
|
||||
if (flowthruindex != -1) {
|
||||
|
@ -338,8 +339,7 @@ public class SleighDebugLogger {
|
|||
endbit = endbit % 8;
|
||||
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
String byteStr =
|
||||
StringUtilities.pad(Integer.toBinaryString(value[i] & 0xff), '0', 8);
|
||||
String byteStr = StringUtilities.pad(Integer.toBinaryString(value[i] & 0xff), '0', 8);
|
||||
if (startbit >= 0) {
|
||||
if (endByte == i) {
|
||||
byteStr =
|
||||
|
@ -621,8 +621,8 @@ public class SleighDebugLogger {
|
|||
Math.min(contextBaseRegister.getMinimumByteSize() - byteOffset, maskvec.length * 4);
|
||||
|
||||
byte[] maskPatternValue = new byte[2 * contextBaseRegister.getMinimumByteSize()];
|
||||
System.arraycopy(getBytes(valvec), 0, maskPatternValue, (maskPatternValue.length / 2) +
|
||||
byteOffset, vecByteCnt);
|
||||
System.arraycopy(getBytes(valvec), 0, maskPatternValue,
|
||||
(maskPatternValue.length / 2) + byteOffset, vecByteCnt);
|
||||
|
||||
byte[] mask = getBytes(maskvec);
|
||||
System.arraycopy(mask, 0, maskActualValue, byteOffset, vecByteCnt);
|
||||
|
@ -640,9 +640,8 @@ public class SleighDebugLogger {
|
|||
BigInteger actual = childActualValue.getUnsignedValueIgnoreMask();
|
||||
BigInteger match = childMatchValue.getUnsignedValueIgnoreMask();
|
||||
String partialMatch = childMatchValue.hasValue() ? "" : "*";
|
||||
String matchStr =
|
||||
match.equals(actual) ? " Match" : (" Failed (=0x" +
|
||||
Long.toHexString(actual.longValue()) + ")");
|
||||
String matchStr = match.equals(actual) ? " Match"
|
||||
: (" Failed (=0x" + Long.toHexString(actual.longValue()) + ")");
|
||||
int msb = baseRegSize - reg.getLeastSignificatBitInBaseRegister() - 1;
|
||||
int lsb = msb - reg.getBitLength() + 1;
|
||||
append(partialMatch + reg.getName() + "(" + lsb + "," + msb + ") == 0x" +
|
||||
|
@ -719,7 +718,8 @@ public class SleighDebugLogger {
|
|||
dumpGlobalSet(state, num, mask, value, null);
|
||||
}
|
||||
|
||||
private void dumpGlobalSet(ConstructState state, int num, int mask, int value, Address setAddr) {
|
||||
private void dumpGlobalSet(ConstructState state, int num, int mask, int value,
|
||||
Address setAddr) {
|
||||
|
||||
byte[] maskActualValue = new byte[contextBaseRegister.getMinimumByteSize() * 2];
|
||||
int byteOffset = num * 4;
|
||||
|
@ -951,8 +951,7 @@ public class SleighDebugLogger {
|
|||
public static String getFormattedBytes(byte[] value) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
String byteStr =
|
||||
StringUtilities.pad(Integer.toBinaryString(value[i] & 0xff), '0', 8);
|
||||
String byteStr = StringUtilities.pad(Integer.toBinaryString(value[i] & 0xff), '0', 8);
|
||||
buf.append(byteStr);
|
||||
if (i < (value.length - 1)) {
|
||||
buf.append(" ");
|
||||
|
|
|
@ -42,6 +42,7 @@ import ghidra.program.model.mem.MemoryAccessException;
|
|||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.program.model.util.AddressLabelInfo;
|
||||
import ghidra.program.model.util.ProcessorSymbolType;
|
||||
import ghidra.sleigh.grammar.SourceFileIndexer;
|
||||
import ghidra.sleigh.grammar.SleighPreprocessor;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -52,8 +53,18 @@ import utilities.util.FileUtilities;
|
|||
|
||||
public class SleighLanguage implements Language {
|
||||
|
||||
public static final int SLA_FORMAT_VERSION = 2; // What format of the .sla file this expects
|
||||
// This value should always match SleighBase.SLA_FORMAT_VERSION
|
||||
/**
|
||||
* NOTE: The value of {@link SleighLanguage#SLA_FORMAT_VERSION} must match that of
|
||||
* {@link ghidra.pcodeCPort.sleighbase.SleighBase#SLA_FORMAT_VERSION}!.
|
||||
* <p>
|
||||
* SLA_FORMAT_VERSION should be incremented whenever the format of the .sla
|
||||
* files change.
|
||||
* <p>
|
||||
* Version 3: October 2020: added source file information for each constructor. <br>
|
||||
* Version 2: April 2019: Changed numbering of Overlay spaces.<br>
|
||||
* Version 1: Initial version.<br>
|
||||
*/
|
||||
public static final int SLA_FORMAT_VERSION = 3;
|
||||
private Map<CompilerSpecID, SleighCompilerSpecDescription> compilerSpecDescriptions;
|
||||
private HashMap<CompilerSpecID, BasicCompilerSpec> compilerSpecs;
|
||||
private List<InjectPayloadSleigh> additionalInject = null;
|
||||
|
@ -70,6 +81,7 @@ public class SleighLanguage implements Language {
|
|||
private int defaultPointerWordSize = 1; // Default wordsize to send down with pointer data-types
|
||||
private SleighLanguageDescription description;
|
||||
private ParallelInstructionLanguageHelper parallelHelper;
|
||||
private SourceFileIndexer indexer; //used to provide source file info for constructors
|
||||
|
||||
/**
|
||||
* Symbols used by sleigh
|
||||
|
@ -427,6 +439,14 @@ public class SleighLanguage implements Language {
|
|||
return symtab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the source file indexer
|
||||
* @return indexer
|
||||
*/
|
||||
public SourceFileIndexer getSourceFileIndexer() {
|
||||
return indexer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadLanguage(TaskMonitor monitor) throws IOException {
|
||||
reloadLanguage(monitor, false);
|
||||
|
@ -663,8 +683,7 @@ public class SleighLanguage implements Language {
|
|||
while (!parser.peek().isEnd()) {
|
||||
element = parser.start("properties", "segmented_address", "segmentop", "programcounter",
|
||||
"data_space", "inferptrbounds", "context_data", "volatile", "jumpassist",
|
||||
"incidentalcopy",
|
||||
"register_data", "default_symbols", "default_memory_blocks");
|
||||
"incidentalcopy", "register_data", "default_symbols", "default_memory_blocks");
|
||||
if (element.getName().equals("properties")) {
|
||||
while (!parser.peek().isEnd()) {
|
||||
XmlElement next = parser.start("property");
|
||||
|
@ -905,6 +924,8 @@ public class SleighLanguage implements Language {
|
|||
if (numsecstr != null) {
|
||||
numSections = SpecXmlUtils.decodeInt(numsecstr);
|
||||
}
|
||||
indexer = new SourceFileIndexer();
|
||||
indexer.restoreXml(parser);
|
||||
parseSpaces(parser);
|
||||
symtab = new SymbolTable();
|
||||
symtab.restoreXml(parser, this);
|
||||
|
|
|
@ -27,14 +27,18 @@ import ghidra.pcodeCPort.space.AddrSpace;
|
|||
import ghidra.pcodeCPort.space.spacetype;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.sleigh.grammar.SourceFileIndexer;
|
||||
|
||||
public abstract class SleighBase extends Translate implements NamedSymbolProvider {
|
||||
|
||||
// NOTE: restoreXml method removed as it is only used by the decompiler's
|
||||
// implementation
|
||||
|
||||
public static final int SLA_FORMAT_VERSION = 2; // What format of the .sla file this produces
|
||||
// This value should always match SleighLanguage.SLA_FORMAT_VERSION
|
||||
/**
|
||||
* Note: The value of {@link SleighBase#SLA_FORMAT_VERSION} must match
|
||||
* {@link ghidra.app.plugin.processors.sleigh.SleighLanguage#SLA_FORMAT_VERSION}.
|
||||
*/
|
||||
public static final int SLA_FORMAT_VERSION = 3;
|
||||
private VectorSTL<String> userop = new VectorSTL<>();
|
||||
private address_set varnode_xref = new address_set(); // Cross-reference registers by address
|
||||
protected SubtableSymbol root;
|
||||
|
@ -42,6 +46,8 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
|
|||
protected int maxdelayslotbytes; // Maximum number of bytes in a delayslot directive
|
||||
protected int unique_allocatemask; // Bits that are guaranteed to be zero in the unique allocation scheme
|
||||
protected int numSections; // Number of named sections
|
||||
protected SourceFileIndexer indexer; //indexer for source files
|
||||
//used to provide source file info for constructors
|
||||
|
||||
@Override
|
||||
public SleighSymbol findSymbol(String nm) {
|
||||
|
@ -61,6 +67,7 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
|
|||
maxdelayslotbytes = 0;
|
||||
unique_allocatemask = 0;
|
||||
numSections = 0;
|
||||
indexer = new SourceFileIndexer();
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
|
@ -74,18 +81,21 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
|
|||
for (iter = glb.begin(); !iter.isEnd(); iter.increment()) {
|
||||
SleighSymbol sym = iter.get();
|
||||
if (sym.getType() == symbol_type.varnode_symbol) {
|
||||
Pair<IteratorSTL<VarnodeSymbol>, Boolean> res = varnode_xref.insert((VarnodeSymbol) sym);
|
||||
Pair<IteratorSTL<VarnodeSymbol>, Boolean> res =
|
||||
varnode_xref.insert((VarnodeSymbol) sym);
|
||||
if (!res.second) {
|
||||
errorPairs.add(sym);
|
||||
errorPairs.add(res.first.get());
|
||||
}
|
||||
} else if (sym.getType() == symbol_type.userop_symbol) {
|
||||
}
|
||||
else if (sym.getType() == symbol_type.userop_symbol) {
|
||||
int index = ((UserOpSymbol) sym).getIndex();
|
||||
while (userop.size() <= index) {
|
||||
userop.push_back("");
|
||||
}
|
||||
userop.set(index, sym.getName());
|
||||
} else if (sym.getType() == symbol_type.context_symbol) {
|
||||
}
|
||||
else if (sym.getType() == symbol_type.context_symbol) {
|
||||
ContextSymbol csym = (ContextSymbol) sym;
|
||||
ContextField field = (ContextField) csym.getPatternValue();
|
||||
int startbit = field.getStartBit();
|
||||
|
@ -189,13 +199,14 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
|
|||
XmlUtils.a_v_u(s, "numsections", numSections);
|
||||
}
|
||||
s.append(">\n");
|
||||
indexer.saveXml(s);
|
||||
s.append("<spaces");
|
||||
XmlUtils.a_v(s, "defaultspace", getDefaultSpace().getName());
|
||||
s.append(">\n");
|
||||
for (int i = 0; i < numSpaces(); ++i) {
|
||||
AddrSpace spc = getSpace(i);
|
||||
if ((spc.getType() == spacetype.IPTR_CONSTANT) || (spc.getType() == spacetype.IPTR_FSPEC)
|
||||
|| (spc.getType() == spacetype.IPTR_IOP)) {
|
||||
if ((spc.getType() == spacetype.IPTR_CONSTANT) ||
|
||||
(spc.getType() == spacetype.IPTR_FSPEC) || (spc.getType() == spacetype.IPTR_IOP)) {
|
||||
continue;
|
||||
}
|
||||
spc.saveXml(s);
|
||||
|
|
|
@ -381,8 +381,7 @@ public class SleighCompile extends SleighBase {
|
|||
final int symSize = sym.getSize();
|
||||
if (symSize % 4 != 0) {
|
||||
reportError(sym.location,
|
||||
String.format(
|
||||
"Invalid size of context register '%s' (%d); must be a multiple of 4",
|
||||
String.format("Invalid size of context register '%s' (%d); must be a multiple of 4",
|
||||
sym.getName(), symSize));
|
||||
}
|
||||
final int maxBits = symSize * 8 - 1;
|
||||
|
@ -563,8 +562,7 @@ public class SleighCompile extends SleighBase {
|
|||
noCollisions = false;
|
||||
if (warnalllocalcollisions) {
|
||||
reportWarning(ct.location,
|
||||
String.format(
|
||||
"Possible operand collision between symbols '%s' and '%s'",
|
||||
String.format("Possible operand collision between symbols '%s' and '%s'",
|
||||
ct.getOperand(collideOperand).getName(), ct.getOperand(i).getName()));
|
||||
|
||||
}
|
||||
|
@ -649,7 +647,6 @@ public class SleighCompile extends SleighBase {
|
|||
pcode.resetLabelCount();
|
||||
}
|
||||
|
||||
|
||||
public void reportError(Location location, String msg) {
|
||||
entry("reportError", location, msg);
|
||||
Msg.error(this, MessageFormattingUtils.format(location, msg));
|
||||
|
@ -915,9 +912,8 @@ public class SleighCompile extends SleighBase {
|
|||
insertSpace(spc);
|
||||
if (qual.isdefault) {
|
||||
if (getDefaultSpace() != null) {
|
||||
reportError(location,
|
||||
"Multiple default spaces -- '" + getDefaultSpace().getName() + "', '" +
|
||||
qual.name + "'");
|
||||
reportError(location, "Multiple default spaces -- '" + getDefaultSpace().getName() +
|
||||
"', '" + qual.name + "'");
|
||||
}
|
||||
else {
|
||||
setDefaultSpace(spc.getIndex()); // Make the flagged space
|
||||
|
@ -1324,6 +1320,10 @@ public class SleighCompile extends SleighBase {
|
|||
sym.addConstructor(curct);
|
||||
symtab.addScope(); // Make a new symbol scope for our constructor
|
||||
pcode.resetLabelCount();
|
||||
Integer index = indexer.index(location);
|
||||
if (index != null) {
|
||||
curct.setSourceFileIndex(index);
|
||||
}
|
||||
return curct;
|
||||
}
|
||||
|
||||
|
@ -1445,8 +1445,7 @@ public class SleighCompile extends SleighBase {
|
|||
big.markSubtableOperands(check);
|
||||
Pair<Integer, Location> res = cur.section.fillinBuild(check, getConstantSpace());
|
||||
if (res.first == 1) {
|
||||
myErrors.push_back(
|
||||
scopeString + "Duplicate BUILD statements at " + res.second);
|
||||
myErrors.push_back(scopeString + "Duplicate BUILD statements at " + res.second);
|
||||
}
|
||||
if (res.first == 2) {
|
||||
myErrors.push_back(
|
||||
|
@ -1454,8 +1453,7 @@ public class SleighCompile extends SleighBase {
|
|||
}
|
||||
|
||||
if (!pcode.propagateSize(cur.section)) {
|
||||
myErrors.push_back(
|
||||
scopeString + "Could not resolve at least 1 variable size");
|
||||
myErrors.push_back(scopeString + "Could not resolve at least 1 variable size");
|
||||
}
|
||||
}
|
||||
if (i < 0) { // These potential errors only apply to main section
|
||||
|
|
|
@ -48,6 +48,7 @@ public class Constructor {
|
|||
private int firstwhitespace; // Index of first whitespace piece in -printpiece-
|
||||
private int flowthruindex; // if >=0 then print only a single operand no markup
|
||||
private boolean inerror;
|
||||
private int sourceFileIndex = -1; //source file index
|
||||
|
||||
public TokenPattern getPattern() {
|
||||
return pattern;
|
||||
|
@ -77,6 +78,22 @@ public class Constructor {
|
|||
return location == null ? 0 : location.lineno;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the source file index
|
||||
* @param index index
|
||||
*/
|
||||
public void setSourceFileIndex(int index) {
|
||||
sourceFileIndex = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the source file index
|
||||
* @return index
|
||||
*/
|
||||
public int getIndex() {
|
||||
return sourceFileIndex;
|
||||
}
|
||||
|
||||
public void addContext(VectorSTL<ContextChange> vec) {
|
||||
context = vec;
|
||||
}
|
||||
|
@ -359,6 +376,8 @@ public class Constructor {
|
|||
s.print(minimumlength);
|
||||
s.append("\"");
|
||||
s.append(" line=\"");
|
||||
s.print(sourceFileIndex);
|
||||
s.append(":");
|
||||
s.print(getLineno());
|
||||
s.append("\">\n");
|
||||
for (int i = 0; i < operands.size(); ++i) {
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.sleigh.grammar;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
|
||||
import ghidra.pcodeCPort.utils.XmlUtils;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.xml.XmlElement;
|
||||
import ghidra.xml.XmlPullParser;
|
||||
|
||||
/**
|
||||
* This class is used to index source files in a SLEIGH language module.
|
||||
* The SLEIGH compiler records the index of the source file for a constructor rather
|
||||
* than the file name. This is an optimization to avoid repeating the file name in
|
||||
* the .sla files.
|
||||
*/
|
||||
public class SourceFileIndexer {
|
||||
|
||||
private BiMap<String, Integer> filenameToIndex;
|
||||
private int leastUnusedIndex;
|
||||
|
||||
/**
|
||||
* Creates a {code SourceFileIndexer} object with an empty index.
|
||||
*/
|
||||
public SourceFileIndexer() {
|
||||
filenameToIndex = HashBiMap.create();
|
||||
leastUnusedIndex = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the filename of a location to the index if it is not already present.
|
||||
* @param loc location containing filename to add
|
||||
* @return index associated with filename, or {@code null} if a {@code null} {@link Location}
|
||||
* or a {@link Location} with a {@code null} filename was provided as input.
|
||||
*/
|
||||
public Integer index(Location loc) {
|
||||
if (loc == null) {
|
||||
Msg.info(this, "null Location");
|
||||
return null;
|
||||
}
|
||||
String filename = loc.filename;
|
||||
if (filename == null) {
|
||||
Msg.info(this, "null filename");
|
||||
return null;
|
||||
}
|
||||
Integer res = filenameToIndex.putIfAbsent(filename, leastUnusedIndex);
|
||||
if (res == null) {
|
||||
return leastUnusedIndex++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index for a filename
|
||||
* @param filename file
|
||||
* @return index or {@code null} if {@code filename} is not in the index.
|
||||
*/
|
||||
public Integer getIndex(String filename) {
|
||||
return filenameToIndex.get(filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file name at a given index
|
||||
* @param index index
|
||||
* @return file name or {@code null} if there is no file with that index
|
||||
*/
|
||||
public String getFileName(Integer index) {
|
||||
return filenameToIndex.inverse().get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the index as XML
|
||||
* @param s stream to write to
|
||||
*/
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<sourcefiles>\n");
|
||||
for (int i = 0; i < leastUnusedIndex; ++i) {
|
||||
s.append("<sourcefile name=\"");
|
||||
XmlUtils.xml_escape(s, filenameToIndex.inverse().get(i));
|
||||
s.append("\" index=\"" + i + "\"/>\n");
|
||||
}
|
||||
s.append("</sourcefiles>\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore an index saved as to XML
|
||||
* @param parser xml parser
|
||||
*/
|
||||
public void restoreXml(XmlPullParser parser) {
|
||||
XmlElement elem = parser.start("sourcefiles");
|
||||
XmlElement subElem = null;
|
||||
while ((subElem = parser.softStart("sourcefile")) != null) {
|
||||
String filename = subElem.getAttribute("name");
|
||||
Integer index = Integer.parseInt(subElem.getAttribute("index"));
|
||||
filenameToIndex.put(filename, index);
|
||||
parser.end(subElem);
|
||||
}
|
||||
parser.end(elem);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.sleigh.grammar;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
|
||||
public class SourceFileIndexerTest extends AbstractGenericTest {
|
||||
|
||||
@Test
|
||||
public void basicTest() {
|
||||
Location loc1_1 = new Location("file1", 1);
|
||||
Location loc1_2 = new Location("file1", 2);
|
||||
Location loc2_1 = new Location("file2", 11);
|
||||
Location loc2_2 = new Location("file2", 22);
|
||||
Location loc3_1 = new Location("file3", 111);
|
||||
Location loc3_2 = new Location("file3", 222);
|
||||
Location nullLocation = null;
|
||||
Location nullFilename = new Location(null, 1000);
|
||||
|
||||
SourceFileIndexer indexer = new SourceFileIndexer();
|
||||
indexer.index(loc1_1);
|
||||
indexer.index(loc1_2);
|
||||
indexer.index(loc3_2);
|
||||
int ret2_1 = indexer.index(loc2_1);
|
||||
indexer.index(nullLocation);
|
||||
indexer.index(loc3_1);
|
||||
indexer.index(nullFilename);
|
||||
int ret2_2 = indexer.index(loc2_2);
|
||||
|
||||
assertEquals(ret2_1, ret2_2);
|
||||
|
||||
int file1_index = indexer.getIndex(loc1_1.filename);
|
||||
assertEquals(file1_index, indexer.getIndex(loc1_2.filename).intValue());
|
||||
|
||||
int file2_index = indexer.getIndex(loc2_1.filename);
|
||||
assertEquals(file2_index, indexer.getIndex(loc2_2.filename).intValue());
|
||||
|
||||
int file3_index = indexer.getIndex(loc3_1.filename);
|
||||
assertEquals(file3_index, indexer.getIndex(loc3_2.filename).intValue());
|
||||
|
||||
assertNotEquals(file1_index, file2_index);
|
||||
assertNotEquals(file1_index, file3_index);
|
||||
assertNotEquals(file2_index, file3_index);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue