mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Program specific, user-defined, cspec extensions
Documentation for spec extensions Handle extensions with parse errors Export button for spec extensions Pop-up dialog for parse errors in user-defined specification extensions GP-653 corrected some minor issues and established new ProgramDB version make incremental initialization constructor for AddressSized private Make AddressSized fields private More adjustments to AddressSized Review fixes for BasicCompilerSpec Take restoreXml out of DataOrganization interface Remove restoreXml from BitFieldPacking interface More review fixes Prevent callotherfixup extension with non-existent target Suggested export name More documentation for SpecExtension Support for undo/redo with spec extensions Documentation for ConstructTpl Split out ProgramCompilerSpec and other changes for review Changes after next round of reviews
This commit is contained in:
parent
27fbe7278d
commit
a5d4ca3cab
108 changed files with 7997 additions and 1997 deletions
|
@ -1218,6 +1218,26 @@ void Architecture::parseCompilerConfig(DocumentStorage &store)
|
|||
else if (elname == "inferptrbounds")
|
||||
parseInferPtrBounds(*iter);
|
||||
}
|
||||
|
||||
el = store.getTag("specextensions"); // Look for any user-defined configuration document
|
||||
if (el != (const Element *)0) {
|
||||
const List &userlist(el->getChildren());
|
||||
for(iter=userlist.begin();iter!=userlist.end();++iter) {
|
||||
const string &elname( (*iter)->getName() );
|
||||
if (elname == "prototype")
|
||||
parseProto(*iter);
|
||||
else if (elname == "callfixup") {
|
||||
pcodeinjectlib->restoreXmlInject(archid+" : compiler spec", (*iter)->getAttributeValue("name"),
|
||||
InjectPayload::CALLFIXUP_TYPE, *iter);
|
||||
}
|
||||
else if (elname == "callotherfixup") {
|
||||
userops.parseCallOtherFixup(*iter,this);
|
||||
}
|
||||
else if (elname == "global")
|
||||
globaltags.push_back(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
// <global> tags instantiate the base symbol table
|
||||
// They need to know about all spaces, so it must come
|
||||
// after parsing of <stackpointer> and <spacebase>
|
||||
|
|
|
@ -314,7 +314,7 @@ public:
|
|||
enum {
|
||||
unaffected = 1, ///< The sub-function does not change the value at all
|
||||
killedbycall = 2, ///< The memory is changed and is completely unrelated to its original value
|
||||
return_address = 3, ///< The memory is being used to pass back a return value from the sub-function
|
||||
return_address = 3, ///< The memory is being used to store the return address
|
||||
unknown_effect = 4 ///< An unknown effect (indicates the absence of an EffectRecord)
|
||||
};
|
||||
private:
|
||||
|
|
|
@ -284,7 +284,7 @@ void ArchitectureGhidra::buildSpecFile(DocumentStorage &store)
|
|||
istringstream cstream(cspecxml);
|
||||
doc = store.parseDocument(cstream);
|
||||
store.registerTag(doc->getRoot());
|
||||
|
||||
|
||||
istringstream tstream(tspecxml);
|
||||
doc = store.parseDocument(tstream);
|
||||
store.registerTag(doc->getRoot());
|
||||
|
@ -293,10 +293,10 @@ void ArchitectureGhidra::buildSpecFile(DocumentStorage &store)
|
|||
doc = store.parseDocument(corestream);
|
||||
store.registerTag(doc->getRoot());
|
||||
|
||||
pspecxml = ""; // Strings aren't used again free memory
|
||||
cspecxml = "";
|
||||
tspecxml = "";
|
||||
corespecxml = "";
|
||||
pspecxml.clear(); // Strings aren't used again free memory
|
||||
cspecxml.clear();
|
||||
tspecxml.clear();
|
||||
corespecxml.clear();
|
||||
}
|
||||
|
||||
void ArchitectureGhidra::postSpecFile(void)
|
||||
|
|
|
@ -82,7 +82,8 @@ class ArchitectureGhidra : public Architecture {
|
|||
virtual void postSpecFile(void);
|
||||
virtual void resolveArchitecture(void);
|
||||
public:
|
||||
ArchitectureGhidra(const string &pspec,const string &cspec,const string &tspec,const string &corespec,istream &i,ostream &o);
|
||||
ArchitectureGhidra(const string &pspec,const string &cspec,const string &tspec,const string &corespec,
|
||||
istream &i,ostream &o);
|
||||
const string &getWarnings(void) const { return warnings; } ///< Get warnings produced by the last decompilation
|
||||
void clearWarnings(void) { warnings.clear(); } ///< Clear warnings
|
||||
Document *getRegister(const string ®name); ///< Retrieve a register description given a name
|
||||
|
|
|
@ -174,6 +174,10 @@ void RegisterProgram::rawAction(void)
|
|||
}
|
||||
}
|
||||
ghidra = new ArchitectureGhidra(pspec,cspec,tspec,corespec,sin,sout);
|
||||
pspec.clear();
|
||||
cspec.clear();
|
||||
tspec.clear();
|
||||
corespec.clear();
|
||||
|
||||
DocumentStorage store; // temp storage of initialization xml docs
|
||||
ghidra->init(store);
|
||||
|
|
|
@ -293,6 +293,23 @@ int4 PcodeInjectLibrarySleigh::registerDynamicInject(InjectPayload *payload)
|
|||
return id;
|
||||
}
|
||||
|
||||
/// \brief Force a payload to be dynamic for debug purposes
|
||||
///
|
||||
/// Debug information may include inject information for payloads that aren't dynamic.
|
||||
/// We substitute a dynamic payload so that analysis uses the debug info to inject, rather
|
||||
/// than the hard-coded payload information.
|
||||
/// \param injectid is the id of the payload to treat dynamic
|
||||
/// \return the new dynamic payload object
|
||||
InjectPayloadDynamic *PcodeInjectLibrarySleigh::forceDebugDynamic(int4 injectid)
|
||||
|
||||
{
|
||||
InjectPayload *oldPayload = injection[injectid];
|
||||
InjectPayloadDynamic *newPayload = new InjectPayloadDynamic(glb,oldPayload->getName(),oldPayload->getType());
|
||||
delete oldPayload;
|
||||
injection[injectid] = newPayload;
|
||||
return newPayload;
|
||||
}
|
||||
|
||||
void PcodeInjectLibrarySleigh::parseInject(InjectPayload *payload)
|
||||
|
||||
{
|
||||
|
@ -399,9 +416,10 @@ void PcodeInjectLibrarySleigh::restoreDebug(const Element *el)
|
|||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> type;
|
||||
int4 id = getPayloadId(type,name);
|
||||
InjectPayloadDynamic *payload = (InjectPayloadDynamic *)getPayload(id);
|
||||
if (payload->getSource() != "dynamic")
|
||||
throw LowlevelError("Mismatch with debug inject XML");
|
||||
InjectPayloadDynamic *payload = dynamic_cast<InjectPayloadDynamic *>(getPayload(id));
|
||||
if (payload == (InjectPayloadDynamic *)0) {
|
||||
payload = forceDebugDynamic(id);
|
||||
}
|
||||
payload->restoreEntry(subel);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@ class PcodeInjectLibrarySleigh : public PcodeInjectLibrary {
|
|||
vector<OpBehavior *> inst;
|
||||
InjectContextSleigh contextCache;
|
||||
int4 registerDynamicInject(InjectPayload *payload);
|
||||
InjectPayloadDynamic *forceDebugDynamic(int4 injectid);
|
||||
void parseInject(InjectPayload *payload);
|
||||
protected:
|
||||
virtual int4 allocateInject(const string &sourceName,const string &name,int4 type);
|
||||
|
|
|
@ -216,10 +216,10 @@ void SegmentOp::restoreXml(const Element *el)
|
|||
throw LowlevelError("Bad segment pattern tag: "+subel->getName());
|
||||
}
|
||||
if (injectId < 0)
|
||||
throw LowlevelError("Missing <execute> child in <segmentop> tag");
|
||||
throw LowlevelError("Missing <pcode> child in <segmentop> tag");
|
||||
InjectPayload *payload = glb->pcodeinjectlib->getPayload(injectId);
|
||||
if (payload->sizeOutput() != 1)
|
||||
throw LowlevelError("<execute> child of <segmentop> tag must declare one <output>");
|
||||
throw LowlevelError("<pcode> child of <segmentop> tag must declare one <output>");
|
||||
if (payload->sizeInput() == 1) {
|
||||
innerinsize = payload->getInput(0).getSize();
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ void SegmentOp::restoreXml(const Element *el)
|
|||
innerinsize = payload->getInput(1).getSize();
|
||||
}
|
||||
else
|
||||
throw LowlevelError("<execute> child of <segmentop> tag must declare one or two <input> tags");
|
||||
throw LowlevelError("<pcode> child of <segmentop> tag must declare one or two <input> tags");
|
||||
}
|
||||
|
||||
/// \param g is the Architecture owning this set of jump assist scripts
|
||||
|
|
|
@ -127,6 +127,12 @@ void XmlArchitecture::restoreXml(DocumentStorage &store)
|
|||
++iter;
|
||||
}
|
||||
}
|
||||
if (iter != list.end()) {
|
||||
if ((*iter)->getName() == "specextensions") {
|
||||
store.registerTag(*iter);
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
if (iter!=list.end()) {
|
||||
if ((*iter)->getName() == "coretypes") {
|
||||
store.registerTag(*iter);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue