GP-233 Added sleigh source file names to constructor info

This commit is contained in:
ghidra1 2021-01-26 10:53:18 -05:00
parent 9dd458e9e1
commit ec5009f613
14 changed files with 415 additions and 76 deletions

View file

@ -279,7 +279,6 @@ libdecomp.a: $(LIBDECOMP_OPT_OBJS)
ranlib libdecomp.a
sleighexamp_dir:
rm -rf $(SLEIGHVERSION)
mkdir $(SLEIGHVERSION)
mkdir $(SLEIGHVERSION)/src $(SLEIGHVERSION)/specfiles
cp ../../../../../Processors/x86/data/languages/x86.sla \

View file

@ -15,7 +15,48 @@
*/
#include "sleighbase.hh"
const int4 SleighBase::SLA_FORMAT_VERSION = 2;
const int4 SleighBase::SLA_FORMAT_VERSION = 3;
int4 SourceFileIndexer::index(const string filename){
auto it = fileToIndex.find(filename);
if (fileToIndex.end() != it){
return it->second;
}
fileToIndex[filename] = leastUnusedIndex;
indexToFile[leastUnusedIndex] = filename;
return leastUnusedIndex++;
}
int4 SourceFileIndexer::getIndex(string filename){
return fileToIndex[filename];
}
string SourceFileIndexer::getFilename(int4 index){
return indexToFile[index];
}
void SourceFileIndexer::restoreXml(const Element *el){
const List &sourceFiles(el->getChildren());
List::const_iterator iter = sourceFiles.begin();
for (; iter != sourceFiles.end(); ++iter){
string filename = (*iter)->getAttributeValue("name");
int4 index = stoi((*iter)->getAttributeValue("index"),NULL,10);
fileToIndex[filename] = index;
indexToFile[index] = filename;
}
}
void SourceFileIndexer::saveXml(ostream& s) const {
s << "<sourcefiles>\n";
for (int4 i = 0; i < leastUnusedIndex; ++i){
s << ("<sourcefile name=\"");
const char *str = indexToFile.at(i).c_str();
xml_escape(s,str);
s << "\" index=\"" << dec << i << "\"/>\n";
}
s << "</sourcefiles>\n";
}
SleighBase::SleighBase(void)
@ -155,7 +196,7 @@ void SleighBase::saveXml(ostream &s) const
if (numSections != 0)
a_v_u(s,"numsections",numSections);
s << ">\n";
indexer.saveXml(s);
s << "<spaces";
a_v(s,"defaultspace",getDefaultCodeSpace()->getName());
s << ">\n";
@ -231,6 +272,8 @@ void SleighBase::restoreXml(const Element *el)
floatformats.back().restoreXml(*iter);
++iter;
}
indexer.restoreXml(*iter);
iter++;
restoreXmlSpaces(*iter,this);
iter++;
symtab.restoreXml(*iter,this);

View file

@ -21,7 +21,35 @@
#include "translate.hh"
#include "slghsymbol.hh"
/// \brief class for recording source file information for SLEIGH constructors.
///
/// A SLEIGH specification may contain many source files. This class is
/// used to associate each constructor in a SLEIGH language to the source
/// file where it is defined. This information is useful when debugging
/// SLEIGH specifications. Sourcefiles are assigned a numeric index and
/// the mapping from indices to filenames is written to the generated .sla
/// file. For each constructor, the data written to the .sla file includes
/// the source file index.
class SourceFileIndexer {
public:
SourceFileIndexer() {leastUnusedIndex = 0;}
~SourceFileIndexer(void) { }
///Returns the index of the file. If the file is not in the index it is added.
int4 index(const string filename);
int4 getIndex(const string); ///< get the index of a file. Error if the file is not in the index.
string getFilename(int4); ///< get the filename corresponding to an index
void restoreXml(const Element *el); ///< read a stored index mapping from an XML file
void saveXml(ostream&) const; ///< save the index mapping to an XML file
private:
int4 leastUnusedIndex; ///< one-up count for assigning indices to files
map<int4, string> indexToFile; ///< map from indices to files
map<string, int4> fileToIndex; ///< map from files to indices
};
/// \brief Common core of classes that read or write SLEIGH specification files natively.
///
/// This class represents what's in common across the SLEIGH infrastructure between:
/// - Reading the various SLEIGH specification files
@ -36,6 +64,7 @@ protected:
uint4 maxdelayslotbytes; ///< Maximum number of bytes in a delay-slot directive
uint4 unique_allocatemask; ///< Bits that are guaranteed to be zero in the unique allocation scheme
uint4 numSections; ///< Number of \e named sections
SourceFileIndexer indexer; ///< source file index used when generating SLEIGH constructor debug info
void buildXrefs(vector<string> &errorPairs); ///< Build register map. Collect user-ops and context-fields.
void reregisterContext(void); ///< Reregister context fields for a new executable
void restoreXml(const Element *el); ///< Read a SLEIGH specification from XML

View file

@ -2497,6 +2497,8 @@ Constructor *SleighCompile::createConstructor(SubtableSymbol *sym)
sym->addConstructor(curct);
symtab.addScope(); // Make a new symbol scope for our constructor
pcode.resetLabelCount();
int4 index = indexer.index(ctorLocationMap[curct].getFilename());
curct->setSrcIndex(index);
return curct;
}

View file

@ -1596,7 +1596,7 @@ void Constructor::saveXml(ostream &s) const
s << " parent=\"0x" << hex << parent->getId() << "\"";
s << " first=\"" << dec << firstwhitespace << "\"";
s << " length=\"" << minimumlength << "\"";
s << " line=\"" << lineno << "\">\n";
s << " line=\"" << src_index << ":" << lineno << "\">\n";
for(int4 i=0;i<operands.size();++i)
s << "<oper id=\"0x" << hex << operands[i]->getId() << "\"/>\n";
for(int4 i=0;i<printpiece.size();++i) {
@ -1643,9 +1643,10 @@ void Constructor::restoreXml(const Element *el,SleighBase *trans)
s >> minimumlength;
}
{
istringstream s(el->getAttributeValue("line"));
s.unsetf(ios::dec | ios::hex | ios::oct);
s >> lineno;
string src_and_line = el->getAttributeValue("line");
size_t pos = src_and_line.find(":");
src_index = stoi(src_and_line.substr(0, pos),NULL,10);
lineno = stoi(src_and_line.substr(pos+1,src_and_line.length()),NULL,10);
}
const List &list(el->getChildren());
List::const_iterator iter;

View file

@ -477,6 +477,7 @@ class Constructor { // This is NOT a symbol
int4 firstwhitespace; // Index of first whitespace piece in -printpiece-
int4 flowthruindex; // if >=0 then print only a single operand no markup
int4 lineno;
int4 src_index; //source file index
mutable bool inerror; // An error is associated with this Constructor
void orderOperands(void);
public:
@ -491,6 +492,8 @@ public:
uintm getId(void) const { return id; }
void setLineno(int4 ln) { lineno = ln; }
int4 getLineno(void) const { return lineno; }
void setSrcIndex(int4 index) {src_index = index;}
int4 getSrcIndex(void) {return src_index;}
void addContext(const vector<ContextChange *> &vec) { context = vec; }
void addOperand(OperandSymbol *sym);
void addInvisibleOperand(OperandSymbol *sym);

View file

@ -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;
}
}
}
@ -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,19 +413,22 @@ 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;
}
}

View file

@ -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,8 +112,7 @@ public class SleighDebugLogger {
}
try {
prototype =
new SleighInstructionPrototype((SleighLanguage) language, buf, context,
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(" ");

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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);
}
}