mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-2830 Parsing pspec symbols
This commit is contained in:
parent
3cf13c2533
commit
8f2450e625
13 changed files with 274 additions and 82 deletions
|
@ -29,6 +29,7 @@ vector<ArchitectureCapability *> ArchitectureCapability::thelist;
|
|||
const uint4 ArchitectureCapability::majorversion = 5;
|
||||
const uint4 ArchitectureCapability::minorversion = 0;
|
||||
|
||||
AttributeId ATTRIB_ADDRESS = AttributeId("address",148);
|
||||
AttributeId ATTRIB_ADJUSTVMA = AttributeId("adjustvma",103);
|
||||
AttributeId ATTRIB_ENABLE = AttributeId("enable",104);
|
||||
AttributeId ATTRIB_GROUP = AttributeId("group",105);
|
||||
|
@ -583,15 +584,6 @@ void Architecture::buildAction(DocumentStorage &store)
|
|||
allacts.resetDefaults();
|
||||
}
|
||||
|
||||
/// This builds the database which holds the status registers setings and other
|
||||
/// information that can affect disassembly depending on context.
|
||||
/// \param store may hold configuration information
|
||||
void Architecture::buildContext(DocumentStorage &store)
|
||||
|
||||
{
|
||||
context = new ContextInternal();
|
||||
}
|
||||
|
||||
/// Create the database object, which currently doesn't not depend on any configuration
|
||||
/// data. Then create the root (global) scope and attach it to the database.
|
||||
/// \param store is the storage for any configuration data
|
||||
|
@ -605,72 +597,6 @@ Scope *Architecture::buildDatabase(DocumentStorage &store)
|
|||
return globscope;
|
||||
}
|
||||
|
||||
/// This builds the TypeFactory object specific to this architecture and
|
||||
/// prepopulates it with the \e core types. Core types may be pulled
|
||||
/// from the configuration information, or default core types are used.
|
||||
/// \param store contains possible configuration information
|
||||
void Architecture::buildTypegrp(DocumentStorage &store)
|
||||
|
||||
{
|
||||
const Element *el = store.getTag("coretypes");
|
||||
types = new TypeFactory(this); // Initialize the object
|
||||
if (el != (const Element *)0) {
|
||||
XmlDecode decoder(this,el);
|
||||
types->decodeCoreTypes(decoder);
|
||||
}
|
||||
else {
|
||||
// Put in the core types
|
||||
types->setCoreType("void",1,TYPE_VOID,false);
|
||||
types->setCoreType("bool",1,TYPE_BOOL,false);
|
||||
types->setCoreType("uint1",1,TYPE_UINT,false);
|
||||
types->setCoreType("uint2",2,TYPE_UINT,false);
|
||||
types->setCoreType("uint4",4,TYPE_UINT,false);
|
||||
types->setCoreType("uint8",8,TYPE_UINT,false);
|
||||
types->setCoreType("int1",1,TYPE_INT,false);
|
||||
types->setCoreType("int2",2,TYPE_INT,false);
|
||||
types->setCoreType("int4",4,TYPE_INT,false);
|
||||
types->setCoreType("int8",8,TYPE_INT,false);
|
||||
types->setCoreType("float4",4,TYPE_FLOAT,false);
|
||||
types->setCoreType("float8",8,TYPE_FLOAT,false);
|
||||
types->setCoreType("float10",10,TYPE_FLOAT,false);
|
||||
types->setCoreType("float16",16,TYPE_FLOAT,false);
|
||||
types->setCoreType("xunknown1",1,TYPE_UNKNOWN,false);
|
||||
types->setCoreType("xunknown2",2,TYPE_UNKNOWN,false);
|
||||
types->setCoreType("xunknown4",4,TYPE_UNKNOWN,false);
|
||||
types->setCoreType("xunknown8",8,TYPE_UNKNOWN,false);
|
||||
types->setCoreType("code",1,TYPE_CODE,false);
|
||||
types->setCoreType("char",1,TYPE_INT,true);
|
||||
types->setCoreType("wchar2",2,TYPE_INT,true);
|
||||
types->setCoreType("wchar4",4,TYPE_INT,true);
|
||||
types->cacheCoreTypes();
|
||||
}
|
||||
}
|
||||
|
||||
/// Build the container that holds comments for executable in this Architecture.
|
||||
/// \param store may hold configuration information
|
||||
void Architecture::buildCommentDB(DocumentStorage &store)
|
||||
|
||||
{
|
||||
commentdb = new CommentDatabaseInternal();
|
||||
}
|
||||
|
||||
/// Build container that holds decoded strings
|
||||
/// \param store may hold configuration information
|
||||
void Architecture::buildStringManager(DocumentStorage &store)
|
||||
|
||||
{
|
||||
stringManager = new StringManagerUnicode(this,2048);
|
||||
}
|
||||
|
||||
/// Some processor models (Java byte-code) need a database of constants.
|
||||
/// The database is always built, but may remain empty.
|
||||
/// \param store may hold configuration information
|
||||
void Architecture::buildConstantPool(DocumentStorage &store)
|
||||
|
||||
{
|
||||
cpool = new ConstantPoolInternal();
|
||||
}
|
||||
|
||||
/// This registers the OpBehavior objects for all known p-code OpCodes.
|
||||
/// The Translate and TypeFactory object should already be built.
|
||||
/// \param store may hold configuration information
|
||||
|
@ -1257,6 +1183,7 @@ void Architecture::parseProcessorConfig(DocumentStorage &store)
|
|||
}
|
||||
else if (subId == ELEM_DEFAULT_SYMBOLS) {
|
||||
decoder.openElement();
|
||||
store.registerTag(decoder.getCurrentXmlElement());
|
||||
decoder.closeElementSkipping(subId);
|
||||
}
|
||||
else if (subId == ELEM_DEFAULT_MEMORY_BLOCKS) {
|
||||
|
@ -1449,6 +1376,7 @@ void Architecture::init(DocumentStorage &store)
|
|||
restoreFromSpec(store);
|
||||
print->initializeFromArchitecture();
|
||||
symboltab->adjustCaches(); // In case the specs created additional address spaces
|
||||
buildSymbols(store);
|
||||
postSpecFile(); // Let subclasses do things after translate is ready
|
||||
|
||||
buildInstructions(store); // Must be called after translate is built
|
||||
|
|
|
@ -61,6 +61,7 @@ public:
|
|||
|
||||
class Architecture;
|
||||
|
||||
extern AttributeId ATTRIB_ADDRESS; ///< Marshaling attribute "address"
|
||||
extern AttributeId ATTRIB_ADJUSTVMA; ///< Marshaling attribute "adjustvma"
|
||||
extern AttributeId ATTRIB_ENABLE; ///< Marshaling attribute "enable"
|
||||
extern AttributeId ATTRIB_GROUP; ///< Marshaling attribute "group"
|
||||
|
@ -273,13 +274,48 @@ protected:
|
|||
/// \return the PcodeInjectLibrary object
|
||||
virtual PcodeInjectLibrary *buildPcodeInjectLibrary(void)=0;
|
||||
|
||||
virtual void buildTypegrp(DocumentStorage &store); ///< Build the data-type factory/container
|
||||
virtual void buildCommentDB(DocumentStorage &store); ///< Build the comment database
|
||||
virtual void buildStringManager(DocumentStorage &store); ///< Build the string manager
|
||||
virtual void buildConstantPool(DocumentStorage &store); ///< Build the constant pool
|
||||
/// \brief Build the data-type factory/container
|
||||
///
|
||||
/// Build the TypeFactory object specific to \b this Architecture and
|
||||
/// prepopulate it with the \e core types. Core types may be pulled
|
||||
/// from the configuration information, or default core types are used.
|
||||
/// \param store contains possible configuration information
|
||||
virtual void buildTypegrp(DocumentStorage &store)=0;
|
||||
|
||||
/// \brief Build the comment database
|
||||
///
|
||||
/// Build the container that holds comments in \b this Architecture.
|
||||
/// \param store may hold configuration information
|
||||
virtual void buildCommentDB(DocumentStorage &store)=0;
|
||||
|
||||
/// \brief Build the string manager
|
||||
///
|
||||
/// Build container that holds decoded strings for \b this Architecture.
|
||||
/// \param store may hold configuration information
|
||||
virtual void buildStringManager(DocumentStorage &store)=0;
|
||||
|
||||
/// \brief Build the constant pool
|
||||
///
|
||||
/// Some processor models (Java byte-code) need a database of constants.
|
||||
/// The database is always built, but may remain empty.
|
||||
/// \param store may hold configuration information
|
||||
virtual void buildConstantPool(DocumentStorage &store)=0;
|
||||
|
||||
virtual void buildInstructions(DocumentStorage &store); ///< Register the p-code operations
|
||||
virtual void buildAction(DocumentStorage &store); ///< Build the Action framework
|
||||
virtual void buildContext(DocumentStorage &store); ///< Build the Context database
|
||||
|
||||
/// \brief Build the Context database
|
||||
///
|
||||
/// Build the database which holds status register settings and other
|
||||
/// information that can affect disassembly depending on context.
|
||||
/// \param store may hold configuration information
|
||||
virtual void buildContext(DocumentStorage &store)=0;
|
||||
|
||||
/// \brief Build any symbols from spec files
|
||||
///
|
||||
/// Formal symbols described in a spec file are added to the global scope.
|
||||
/// \param store may hold symbol elements
|
||||
virtual void buildSymbols(DocumentStorage &store)=0;
|
||||
|
||||
/// \brief Load any relevant specification files
|
||||
///
|
||||
|
|
|
@ -3224,6 +3224,32 @@ void Database::setPropertyRange(uint4 flags,const Range &range)
|
|||
}
|
||||
}
|
||||
|
||||
/// The non-zero bits in the \b flags parameter indicate the boolean properties to be cleared.
|
||||
/// No other properties are altered.
|
||||
/// \param flags is the set of properties to clear
|
||||
/// \param range is the memory range to clear
|
||||
void Database::clearPropertyRange(uint4 flags,const Range &range)
|
||||
|
||||
{
|
||||
Address addr1 = range.getFirstAddr();
|
||||
Address addr2 = range.getLastAddrOpen(glb);
|
||||
flagbase.split(addr1);
|
||||
partmap<Address,uint4>::iterator aiter,biter;
|
||||
|
||||
aiter = flagbase.begin(addr1);
|
||||
if (!addr2.isInvalid()) {
|
||||
flagbase.split(addr2);
|
||||
biter = flagbase.begin(addr2);
|
||||
}
|
||||
else
|
||||
biter = flagbase.end();
|
||||
flags = ~flags;
|
||||
while(aiter != biter) { // Update bits across whole range
|
||||
(*aiter).second &= flags;
|
||||
++aiter;
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a single \<db> element to the stream, which contains child elements
|
||||
/// for each Scope (which contain Symbol children in turn).
|
||||
/// \param encoder is the stream encoder
|
||||
|
|
|
@ -925,6 +925,7 @@ public:
|
|||
Scope *mapScope(Scope *qpoint,const Address &addr,const Address &usepoint);
|
||||
uint4 getProperty(const Address &addr) const { return flagbase.getValue(addr); } ///< Get boolean properties at the given address
|
||||
void setPropertyRange(uint4 flags,const Range &range); ///< Set boolean properties over a given memory range
|
||||
void clearPropertyRange(uint4 flags,const Range &range); ///< Clear boolean properties over a given memory range
|
||||
void setProperties(const partmap<Address,uint4> &newflags) { flagbase = newflags; } ///< Replace the property map
|
||||
const partmap<Address,uint4> &getProperties(void) const { return flagbase; } ///< Get the entire property map
|
||||
void encode(Encoder &encoder) const; ///< Encode the whole Database to a stream
|
||||
|
|
|
@ -372,6 +372,55 @@ void ArchitectureGhidra::buildContext(DocumentStorage &store)
|
|||
context = new ContextGhidra(this);
|
||||
}
|
||||
|
||||
void ArchitectureGhidra::buildSymbols(DocumentStorage &store)
|
||||
|
||||
{
|
||||
const Element *symtag = store.getTag(ELEM_DEFAULT_SYMBOLS.getName());
|
||||
if (symtag == (const Element *)0) return;
|
||||
XmlDecode decoder(this,symtag);
|
||||
uint4 el = decoder.openElement(ELEM_DEFAULT_SYMBOLS);
|
||||
while(decoder.peekElement() != 0) {
|
||||
uint4 subel = decoder.openElement(ELEM_SYMBOL);
|
||||
string addrString;
|
||||
string name;
|
||||
int4 size = 0;
|
||||
int4 volatileState = -1;
|
||||
for(;;) {
|
||||
uint4 attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) break;
|
||||
if (attribId == ATTRIB_NAME)
|
||||
name = decoder.readString();
|
||||
else if (attribId == ATTRIB_ADDRESS) {
|
||||
addrString = decoder.readString();
|
||||
}
|
||||
else if (attribId == ATTRIB_VOLATILE) {
|
||||
volatileState = decoder.readBool() ? 1 : 0;
|
||||
}
|
||||
else if (attribId == ATTRIB_SIZE)
|
||||
size = decoder.readSignedInteger();
|
||||
}
|
||||
decoder.closeElement(subel);
|
||||
if (name.size() == 0)
|
||||
throw LowlevelError("Missing name attribute in <symbol> element");
|
||||
if (addrString.size() == 0)
|
||||
throw LowlevelError("Missing address attribute in <symbol> element");
|
||||
|
||||
// Currently we only use the volatile attribute on pspec symbols and let Ghidra
|
||||
// feed the global symbol to the decompiler on a per function basic.
|
||||
if (volatileState < 0)
|
||||
continue;
|
||||
Address addr = parseAddressSimple(addrString);
|
||||
if (size == 0)
|
||||
size = addr.getSpace()->getWordSize();
|
||||
Range range(addr.getSpace(),addr.getOffset(),addr.getOffset() + (size-1));
|
||||
if (volatileState == 0)
|
||||
symboltab->clearPropertyRange(Varnode::volatil, range);
|
||||
else
|
||||
symboltab->setPropertyRange(Varnode::volatil, range);
|
||||
}
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
void ArchitectureGhidra::resolveArchitecture(void)
|
||||
|
||||
{
|
||||
|
|
|
@ -97,6 +97,7 @@ class ArchitectureGhidra : public Architecture {
|
|||
virtual void buildStringManager(DocumentStorage &store);
|
||||
virtual void buildConstantPool(DocumentStorage &store);
|
||||
virtual void buildContext(DocumentStorage &store);
|
||||
virtual void buildSymbols(DocumentStorage &store);
|
||||
virtual void buildSpecFile(DocumentStorage &store);
|
||||
virtual void modifySpaces(Translate *trans) {} // This is handled directly by GhidraTranslate::initialize
|
||||
virtual void postSpecFile(void);
|
||||
|
|
|
@ -1036,7 +1036,7 @@ AttributeId ATTRIB_VAL = AttributeId("val",24);
|
|||
AttributeId ATTRIB_VALUE = AttributeId("value",25);
|
||||
AttributeId ATTRIB_WORDSIZE = AttributeId("wordsize",26);
|
||||
|
||||
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",148); // Number serves as next open index
|
||||
AttributeId ATTRIB_UNKNOWN = AttributeId("XMLunknown",149); // Number serves as next open index
|
||||
|
||||
ElementId ELEM_DATA = ElementId("data",1);
|
||||
ElementId ELEM_INPUT = ElementId("input",2);
|
||||
|
|
|
@ -323,6 +323,7 @@ public:
|
|||
document = (Document *)0; rootElement = root; attributeIndex = -1; } ///< Constructor with preparsed root
|
||||
XmlDecode(const AddrSpaceManager *spc) : Decoder(spc) {
|
||||
document = (Document *)0; rootElement = (const Element *)0; attributeIndex = -1; } ///< Constructor for use with ingestStream
|
||||
const Element *getCurrentXmlElement(void) const { return elStack.back(); } ///< Get pointer to underlying XML element object
|
||||
virtual ~XmlDecode(void);
|
||||
virtual void ingestStream(istream &s);
|
||||
virtual uint4 peekElement(void);
|
||||
|
|
|
@ -194,6 +194,115 @@ PcodeInjectLibrary *SleighArchitecture::buildPcodeInjectLibrary(void)
|
|||
return res;
|
||||
}
|
||||
|
||||
void SleighArchitecture::buildTypegrp(DocumentStorage &store)
|
||||
|
||||
{
|
||||
const Element *el = store.getTag("coretypes");
|
||||
types = new TypeFactory(this); // Initialize the object
|
||||
if (el != (const Element *)0) {
|
||||
XmlDecode decoder(this,el);
|
||||
types->decodeCoreTypes(decoder);
|
||||
}
|
||||
else {
|
||||
// Put in the core types
|
||||
types->setCoreType("void",1,TYPE_VOID,false);
|
||||
types->setCoreType("bool",1,TYPE_BOOL,false);
|
||||
types->setCoreType("uint1",1,TYPE_UINT,false);
|
||||
types->setCoreType("uint2",2,TYPE_UINT,false);
|
||||
types->setCoreType("uint4",4,TYPE_UINT,false);
|
||||
types->setCoreType("uint8",8,TYPE_UINT,false);
|
||||
types->setCoreType("int1",1,TYPE_INT,false);
|
||||
types->setCoreType("int2",2,TYPE_INT,false);
|
||||
types->setCoreType("int4",4,TYPE_INT,false);
|
||||
types->setCoreType("int8",8,TYPE_INT,false);
|
||||
types->setCoreType("float4",4,TYPE_FLOAT,false);
|
||||
types->setCoreType("float8",8,TYPE_FLOAT,false);
|
||||
types->setCoreType("float10",10,TYPE_FLOAT,false);
|
||||
types->setCoreType("float16",16,TYPE_FLOAT,false);
|
||||
types->setCoreType("xunknown1",1,TYPE_UNKNOWN,false);
|
||||
types->setCoreType("xunknown2",2,TYPE_UNKNOWN,false);
|
||||
types->setCoreType("xunknown4",4,TYPE_UNKNOWN,false);
|
||||
types->setCoreType("xunknown8",8,TYPE_UNKNOWN,false);
|
||||
types->setCoreType("code",1,TYPE_CODE,false);
|
||||
types->setCoreType("char",1,TYPE_INT,true);
|
||||
types->setCoreType("wchar2",2,TYPE_INT,true);
|
||||
types->setCoreType("wchar4",4,TYPE_INT,true);
|
||||
types->cacheCoreTypes();
|
||||
}
|
||||
}
|
||||
|
||||
void SleighArchitecture::buildCommentDB(DocumentStorage &store)
|
||||
|
||||
{
|
||||
commentdb = new CommentDatabaseInternal();
|
||||
}
|
||||
|
||||
void SleighArchitecture::buildStringManager(DocumentStorage &store)
|
||||
|
||||
{
|
||||
stringManager = new StringManagerUnicode(this,2048);
|
||||
}
|
||||
|
||||
void SleighArchitecture::buildConstantPool(DocumentStorage &store)
|
||||
|
||||
{
|
||||
cpool = new ConstantPoolInternal();
|
||||
}
|
||||
|
||||
void SleighArchitecture::buildContext(DocumentStorage &store)
|
||||
|
||||
{
|
||||
context = new ContextInternal();
|
||||
}
|
||||
|
||||
void SleighArchitecture::buildSymbols(DocumentStorage &store)
|
||||
|
||||
{
|
||||
const Element *symtag = store.getTag(ELEM_DEFAULT_SYMBOLS.getName());
|
||||
if (symtag == (const Element *)0) return;
|
||||
XmlDecode decoder(this,symtag);
|
||||
uint4 el = decoder.openElement(ELEM_DEFAULT_SYMBOLS);
|
||||
while(decoder.peekElement() != 0) {
|
||||
uint4 subel = decoder.openElement(ELEM_SYMBOL);
|
||||
Address addr;
|
||||
string name;
|
||||
int4 size = 0;
|
||||
int4 volatileState = -1;
|
||||
for(;;) {
|
||||
uint4 attribId = decoder.getNextAttributeId();
|
||||
if (attribId == 0) break;
|
||||
if (attribId == ATTRIB_NAME)
|
||||
name = decoder.readString();
|
||||
else if (attribId == ATTRIB_ADDRESS) {
|
||||
addr = parseAddressSimple(decoder.readString());
|
||||
}
|
||||
else if (attribId == ATTRIB_VOLATILE) {
|
||||
volatileState = decoder.readBool() ? 1 : 0;
|
||||
}
|
||||
else if (attribId == ATTRIB_SIZE)
|
||||
size = decoder.readSignedInteger();
|
||||
}
|
||||
decoder.closeElement(subel);
|
||||
if (name.size() == 0)
|
||||
throw LowlevelError("Missing name attribute in <symbol> element");
|
||||
if (addr.isInvalid())
|
||||
throw LowlevelError("Missing address attribute in <symbol> element");
|
||||
if (size == 0)
|
||||
size = addr.getSpace()->getWordSize();
|
||||
if (volatileState >= 0) {
|
||||
Range range(addr.getSpace(),addr.getOffset(),addr.getOffset() + (size-1));
|
||||
if (volatileState == 0)
|
||||
symboltab->clearPropertyRange(Varnode::volatil, range);
|
||||
else
|
||||
symboltab->setPropertyRange(Varnode::volatil, range);
|
||||
}
|
||||
Datatype *ct = types->getBase(size, TYPE_UNKNOWN);
|
||||
Address usepoint;
|
||||
symboltab->getGlobalScope()->addSymbol(name, ct, addr, usepoint);
|
||||
}
|
||||
decoder.closeElement(el);
|
||||
}
|
||||
|
||||
void SleighArchitecture::resolveArchitecture(void)
|
||||
|
||||
{ // Find best architecture
|
||||
|
|
|
@ -117,6 +117,12 @@ protected:
|
|||
static void collectSpecFiles(ostream &errs); ///< Gather specification files in normal locations
|
||||
virtual Translate *buildTranslator(DocumentStorage &store);
|
||||
virtual PcodeInjectLibrary *buildPcodeInjectLibrary(void);
|
||||
virtual void buildTypegrp(DocumentStorage &store);
|
||||
virtual void buildCommentDB(DocumentStorage &store);
|
||||
virtual void buildStringManager(DocumentStorage &store);
|
||||
virtual void buildConstantPool(DocumentStorage &store);
|
||||
virtual void buildContext(DocumentStorage &store);
|
||||
virtual void buildSymbols(DocumentStorage &store);
|
||||
virtual void buildSpecFile(DocumentStorage &store);
|
||||
virtual void modifySpaces(Translate *trans);
|
||||
virtual void resolveArchitecture(void);
|
||||
|
|
|
@ -864,6 +864,37 @@ void AddrSpaceManager::renormalizeJoinAddress(Address &addr,int4 size)
|
|||
addr = Address(newJoinRecord->unified.space,newJoinRecord->unified.offset);
|
||||
}
|
||||
|
||||
/// The string \e must contain a hexadecimal offset. The offset may be optionally prepended with "0x".
|
||||
/// The string may optionally start with the name of the address space to associate with the offset, followed
|
||||
/// by ':' to separate it from the offset. If the name is not present, the default data space is assumed.
|
||||
/// \param val is the string to parse
|
||||
/// \return the parsed address
|
||||
Address AddrSpaceManager::parseAddressSimple(const string &val)
|
||||
|
||||
{
|
||||
string::size_type col = val.find(':');
|
||||
AddrSpace *spc;
|
||||
if (col==string::npos) {
|
||||
spc = getDefaultDataSpace();
|
||||
col = 0;
|
||||
}
|
||||
else {
|
||||
string spcName = val.substr(0,col);
|
||||
spc = getSpaceByName(spcName);
|
||||
if (spc == (AddrSpace *)0)
|
||||
throw LowlevelError("Unknown address space: " + spcName);
|
||||
col += 1;
|
||||
}
|
||||
if (col + 2 <= val.size()) {
|
||||
if (val[col] == '0' && val[col+1] == 'x')
|
||||
col += 2;
|
||||
}
|
||||
istringstream s(val.substr(col));
|
||||
uintb off;
|
||||
s >> hex >> off;
|
||||
return Address(spc,AddrSpace::addressToByte(off, spc->getWordSize()));
|
||||
}
|
||||
|
||||
/// This constructs only a shell for the Translate object. It
|
||||
/// won't be usable until it is initialized for a specific processor
|
||||
/// The main entry point for this is the Translate::initialize method,
|
||||
|
|
|
@ -278,6 +278,9 @@ public:
|
|||
|
||||
/// \brief Make sure a possibly offset \e join address has a proper JoinRecord
|
||||
void renormalizeJoinAddress(Address &addr,int4 size);
|
||||
|
||||
/// \brief Parse a string with just an \e address \e space name and a hex offset
|
||||
Address parseAddressSimple(const string &val);
|
||||
};
|
||||
|
||||
/// \brief The interface to a translation engine for a processor.
|
||||
|
|
|
@ -243,5 +243,6 @@ public record AttributeId(String name, int id) {
|
|||
// public static final AttributeId ATTRIB_VARIANT = new AttributeId("variant", 143);
|
||||
// public static final AttributeId ATTRIB_VERSION = new AttributeId("version", 144);
|
||||
|
||||
public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 148);
|
||||
// public static final AttributeId ATTRIB_ADDRESS = new AttributeId("address", 148);
|
||||
public static final AttributeId ATTRIB_UNKNOWN = new AttributeId("XMLunknown", 149);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue