mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-02-18 16:40:08 +00:00
name to address space map
shortcut to address space map more adjustments to shortcuts allow null AddrSpace pointer in raw baselist holes in the space indices almost working GT-2873 decompiler, other, and overlays GT-2873 added OTHER space to java sleigh compiler, fixed decompiler exception isOtherSpace method isOtherSpace java, addressing code review comments GT-2873 added null check in decompiler reset GT-2873 code review changes Read and write space_other tag in SLA files Version number for .sla file GT-2873 fixups after merge GT-2873 renamed Sparc registers: OTHER->OTHERWIN, WINWSTATE->WSTATE GT-2873 added option in AddressInput to control OTHER space visibility GT-2873 OTHER space now global GT-2873 fixing comments refering to decompiler code in BasicCompilerSpec
This commit is contained in:
parent
cf47a2ee57
commit
612c0d6f3e
@ -483,7 +483,7 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
|
||||
addrField = new AddressInput();
|
||||
addrField.setName("Start Addr");
|
||||
addrFactory = model.getProgram().getAddressFactory();
|
||||
addrField.setAddressFactory(addrFactory, true);
|
||||
addrField.setAddressFactory(addrFactory, true, true);
|
||||
addrField.addChangeListener(ev -> addrChanged());
|
||||
return addrField;
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ class AddBlockModel {
|
||||
message = "";
|
||||
isValid = hasValidName() && hasValidStartAddress() && hasValidLength() &&
|
||||
hasNoMemoryConflicts() && hasMappedAddressIfNeeded() && hasUniqueNameIfOverlay() &&
|
||||
hasInitialValueIfNeeded() && hasFileBytesInfoIfNeeded();
|
||||
hasInitialValueIfNeeded() && hasFileBytesInfoIfNeeded() && isOverlayIfOtherSpace();
|
||||
}
|
||||
|
||||
private boolean hasFileBytesInfoIfNeeded() {
|
||||
@ -313,6 +313,17 @@ class AddBlockModel {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isOverlayIfOtherSpace() {
|
||||
if (startAddr.getAddressSpace().equals(AddressSpace.OTHER_SPACE)) {
|
||||
if (blockType != MemoryBlockType.OVERLAY) {
|
||||
message = "Blocks defined in the " + AddressSpace.OTHER_SPACE.getName() +
|
||||
" space must be overlay blocks";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hasMappedAddressIfNeeded() {
|
||||
if (blockType == MemoryBlockType.BIT_MAPPED || blockType == MemoryBlockType.BYTE_MAPPED) {
|
||||
if (baseAddr == null) {
|
||||
@ -323,6 +334,7 @@ class AddBlockModel {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hasNoMemoryConflicts() {
|
||||
if (blockType == MemoryBlockType.OVERLAY) {
|
||||
return true;
|
||||
|
@ -82,8 +82,8 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
|
||||
changing = true;
|
||||
if (!isVisible()) {
|
||||
AddressFactory factory = model.getAddressFactory();
|
||||
newStartField.setAddressFactory(factory, true);
|
||||
newEndField.setAddressFactory(factory, true);
|
||||
newStartField.setAddressFactory(factory, true, false);
|
||||
newEndField.setAddressFactory(factory, true, false);
|
||||
}
|
||||
Address newStart = model.getNewStartAddress();
|
||||
if (newStart != null) {
|
||||
|
@ -206,7 +206,7 @@ class EditMemoryReferencePanel extends EditReferencePanel {
|
||||
toAddr = toAddr.subtractWrap(defaultOffset);
|
||||
}
|
||||
|
||||
toAddressField.setAddressFactory(fromCu.getProgram().getAddressFactory(), false);
|
||||
toAddressField.setAddressFactory(fromCu.getProgram().getAddressFactory(), false, false);
|
||||
toAddressField.setAddress(toAddr);
|
||||
enableOffsetField(editReference.isOffsetReference());
|
||||
|
||||
@ -231,7 +231,7 @@ class EditMemoryReferencePanel extends EditReferencePanel {
|
||||
|
||||
addrHistoryButton.setEnabled(getAddressHistorySize(p) != 0);
|
||||
|
||||
toAddressField.setAddressFactory(p.getAddressFactory(), false);
|
||||
toAddressField.setAddressFactory(p.getAddressFactory(), false, false);
|
||||
|
||||
Address cuAddr = fromCu.getMinAddress();
|
||||
|
||||
|
@ -163,7 +163,7 @@ public class AddressInput extends JPanel {
|
||||
* if there is more than one space.
|
||||
*/
|
||||
public void setAddressFactory(AddressFactory factory) {
|
||||
setAddressFactory(factory, false);
|
||||
setAddressFactory(factory, false, false);
|
||||
}
|
||||
|
||||
public AddressFactory getAddressFactory() {
|
||||
@ -176,8 +176,11 @@ public class AddressInput extends JPanel {
|
||||
* @param factory address factory to use
|
||||
* @param filterOverlaySpaces true if overlay spaces should not appear in the combo box
|
||||
* for the address spaces.
|
||||
* @param allowOtherSpace true if the OTHER space should appear in the combo box for
|
||||
* the address spaces
|
||||
*/
|
||||
public void setAddressFactory(AddressFactory factory, boolean filterOverlaySpaces) {
|
||||
public void setAddressFactory(AddressFactory factory, boolean filterOverlaySpaces,
|
||||
boolean allowOtherSpace) {
|
||||
this.addrFactory = factory;
|
||||
AddressSpace[] spaces = factory.getAddressSpaces();
|
||||
|
||||
@ -187,21 +190,19 @@ public class AddressInput extends JPanel {
|
||||
|
||||
FontMetrics fm = combo.getFontMetrics(combo.getFont());
|
||||
int width = 0;
|
||||
for (int i = 0; i < spaces.length; i++) {
|
||||
if (filterOverlaySpaces && spaces[i].isOverlaySpace()) {
|
||||
for (AddressSpace space : spaces) {
|
||||
if (filterOverlaySpaces && space.isOverlaySpace()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We don't want to let users create functions in certain memory spaces (eg: OTHER),
|
||||
// so don't populate the model with them.
|
||||
if (!spaces[i].isLoadedMemorySpace()) {
|
||||
if (!allowOtherSpace && space.equals(AddressSpace.OTHER_SPACE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String s = spaces[i].toString();
|
||||
String s = space.toString();
|
||||
width = Math.max(width, fm.stringWidth(s));
|
||||
|
||||
model.addElement(spaces[i]);
|
||||
model.addElement(space);
|
||||
}
|
||||
|
||||
// // Commented out the following 2 lines since they were causing the Combo to only
|
||||
|
@ -206,6 +206,7 @@ AddrSpace *Architecture::getSpaceBySpacebase(const Address &loc,int4 size) const
|
||||
int4 sz = numSpaces();
|
||||
for(int4 i=0;i<sz;++i) {
|
||||
id = getSpace(i);
|
||||
if (id == (AddrSpace *)0) continue;
|
||||
int4 numspace = id->numSpacebase();
|
||||
for(int4 j=0;j<numspace;++j) {
|
||||
const VarnodeData &point(id->getSpacebase(j));
|
||||
@ -337,6 +338,7 @@ void Architecture::globalify(void)
|
||||
|
||||
for(int4 i=0;i<nm;++i) {
|
||||
AddrSpace *spc = getSpace(i);
|
||||
if (spc == (AddrSpace *)0) continue;
|
||||
if ((spc->getType() != IPTR_PROCESSOR)&&(spc->getType() != IPTR_SPACEBASE)) continue;
|
||||
symboltab->addRange(scope,spc,(uintb)0,spc->getHighest());
|
||||
}
|
||||
@ -707,7 +709,7 @@ void Architecture::parseGlobal(const Element *el)
|
||||
Scope *scope = buildGlobalScope();
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
|
||||
|
||||
for(iter=list.begin();iter!=list.end();++iter) {
|
||||
Range range;
|
||||
range.restoreXml(*iter,this);
|
||||
@ -716,15 +718,33 @@ void Architecture::parseGlobal(const Element *el)
|
||||
// We need to duplicate the range being marked as global into the overlay space(s)
|
||||
int4 num = numSpaces();
|
||||
for(int4 i=0;i<num;++i) {
|
||||
OverlaySpace *ospc = (OverlaySpace *)getSpace(i);
|
||||
if (!ospc->isOverlay()) continue;
|
||||
if (ospc->getBaseSpace() != range.getSpace()) continue;
|
||||
symboltab->addRange(scope,ospc,range.getFirst(),range.getLast());
|
||||
OverlaySpace *ospc = (OverlaySpace *)getSpace(i);
|
||||
if (ospc == (AddrSpace *)0 || !ospc->isOverlay()) continue;
|
||||
if (ospc->getBaseSpace() != range.getSpace()) continue;
|
||||
symboltab->addRange(scope,ospc,range.getFirst(),range.getLast());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//explictly add the OTHER space and any overlays to the global scope
|
||||
void Architecture::addOtherSpace(void)
|
||||
|
||||
{
|
||||
Scope *scope = buildGlobalScope();
|
||||
AddrSpace *otherSpace = getSpaceByName("OTHER");
|
||||
symboltab->addRange(scope,otherSpace,0,otherSpace->getHighest());
|
||||
if (otherSpace->isOverlayBase()) {
|
||||
int4 num = numSpaces();
|
||||
for(int4 i=0;i<num;++i){
|
||||
OverlaySpace *ospc = (OverlaySpace *)getSpace(i);
|
||||
if (ospc->getBaseSpace() != otherSpace) continue;
|
||||
if (ospc->getBaseSpace() != otherSpace) continue;
|
||||
symboltab->addRange(scope,ospc,0,otherSpace->getHighest());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This applies info from a \<readonly> tag marking a specific region
|
||||
/// of the executable as \e read-only.
|
||||
/// \param el is the XML element
|
||||
@ -835,7 +855,7 @@ void Architecture::parseDeadcodeDelay(const Element *el)
|
||||
int4 delay = -1;
|
||||
s >> delay;
|
||||
if (delay >= 0)
|
||||
setDeadcodeDelay(spc->getIndex(),delay);
|
||||
setDeadcodeDelay(spc,delay);
|
||||
else
|
||||
throw LowlevelError("Bad <deadcodedelay> tag");
|
||||
}
|
||||
@ -1031,11 +1051,13 @@ void Architecture::parseCompilerConfig(DocumentStorage &store)
|
||||
else if (elname == "deadcodedelay")
|
||||
parseDeadcodeDelay(*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>
|
||||
// <global> tags instantiate the base symbol table
|
||||
// They need to know about all spaces, so it must come
|
||||
// after parsing of <stackpointer> and <spacebase>
|
||||
for(int4 i=0;i<globaltags.size();++i)
|
||||
parseGlobal(globaltags[i]);
|
||||
|
||||
addOtherSpace();
|
||||
|
||||
if (defaultfp == (ProtoModel *)0) {
|
||||
if (protoModels.size() == 1)
|
||||
|
@ -255,6 +255,7 @@ protected:
|
||||
void parseProtoEval(const Element *el); ///< Apply prototype evaluation configuration
|
||||
void parseDefaultProto(const Element *el); ///< Apply default prototype model configuration
|
||||
void parseGlobal(const Element *el); ///< Apply global space configuration
|
||||
void addOtherSpace(void); ////add OTHER space and all of its overlays to the symboltab
|
||||
void parseReadOnly(const Element *el); ///< Apply read-only region configuration
|
||||
void parseVolatile(const Element *el); ///< Apply volatile region configuration
|
||||
void parseReturnAddress(const Element *el); ///< Apply return address configuration
|
||||
|
@ -367,10 +367,11 @@ void ConditionalExecution::buildHeritageArray(void)
|
||||
{
|
||||
heritageyes.clear();
|
||||
Architecture *glb = fd->getArch();
|
||||
heritageyes.resize(glb->numSpaces(),false);
|
||||
for(int4 i=0;i<glb->numSpaces();++i) {
|
||||
AddrSpace *spc = glb->getSpace(i);
|
||||
if (spc == (AddrSpace *)0) continue;
|
||||
int4 index = spc->getIndex();
|
||||
heritageyes.push_back(false);
|
||||
if (!spc->isHeritaged()) continue;
|
||||
if (fd->numHeritagePasses(spc) > 0)
|
||||
heritageyes[index] = true; // At least one pass has been performed on the space
|
||||
|
@ -2239,6 +2239,7 @@ int4 ActionNameVars::apply(Funcdata &data)
|
||||
|
||||
for(int4 i=0;i<manage->numSpaces();++i) { // Build a list of nameable highs
|
||||
spc = manage->getSpace(i);
|
||||
if (spc == (AddrSpace *)0) continue;
|
||||
enditer = data.endLoc(spc);
|
||||
for(iter=data.beginLoc(spc);iter!=enditer;++iter) {
|
||||
Varnode *curvn = *iter;
|
||||
@ -3094,7 +3095,7 @@ int4 ActionDeadCode::apply(Funcdata &data)
|
||||
// Set pre-live registers
|
||||
for(i=0;i<manage->numSpaces();++i) {
|
||||
spc = manage->getSpace(i);
|
||||
if (!spc->doesDeadcode()) continue;
|
||||
if (spc == (AddrSpace *)0 || !spc->doesDeadcode()) continue;
|
||||
if (data.deadRemovalAllowed(spc)) continue; // Mark consumed if we have NOT heritaged
|
||||
viter = data.beginLoc(spc);
|
||||
endviter = data.endLoc(spc);
|
||||
@ -3138,7 +3139,7 @@ int4 ActionDeadCode::apply(Funcdata &data)
|
||||
|
||||
for(i=0;i<manage->numSpaces();++i) {
|
||||
spc = manage->getSpace(i);
|
||||
if (!spc->doesDeadcode()) continue;
|
||||
if (spc == (AddrSpace *)0 || !spc->doesDeadcode()) continue;
|
||||
if (!data.deadRemovalAllowed(spc)) continue; // Don't eliminate if we haven't heritaged
|
||||
viter = data.beginLoc(spc);
|
||||
endviter = data.endLoc(spc);
|
||||
|
@ -208,6 +208,7 @@ void Funcdata::spacebase(void)
|
||||
|
||||
for(j=0;j<glb->numSpaces();++j) {
|
||||
spc = glb->getSpace(j);
|
||||
if (spc == (AddrSpace *)0) continue;
|
||||
numspace = spc->numSpacebase();
|
||||
for(i=0;i<numspace;++i) {
|
||||
const VarnodeData &point(spc->getSpacebase(i));
|
||||
@ -617,7 +618,7 @@ void Funcdata::saveXmlTree(ostream &s) const
|
||||
s << "<varnodes>\n";
|
||||
for(int4 i=0;i<glb->numSpaces();++i) {
|
||||
AddrSpace *base = glb->getSpace(i);
|
||||
if (base->getType()==IPTR_IOP) continue;
|
||||
if (base == (AddrSpace *)0 || base->getType()==IPTR_IOP) continue;
|
||||
VarnodeLocSet::const_iterator iter = vbank.beginLoc(base);
|
||||
VarnodeLocSet::const_iterator enditer = vbank.endLoc(base);
|
||||
saveVarnodeXml(s,iter,enditer);
|
||||
|
@ -2212,11 +2212,16 @@ void Heritage::buildInfoList(void)
|
||||
|
||||
{
|
||||
if (!infolist.empty()) return;
|
||||
AddrSpace *spc;
|
||||
const AddrSpaceManager *manage = fd->getArch();
|
||||
infolist.resize(manage->numSpaces());
|
||||
for(int4 i=0;i<manage->numSpaces();++i) {
|
||||
spc = manage->getSpace(i);
|
||||
infolist.push_back(HeritageInfo(spc,spc->getDelay(),spc->getDeadcodeDelay()));
|
||||
AddrSpace *spc = manage->getSpace(i);
|
||||
if (spc == (AddrSpace *)0)
|
||||
infolist[i].set((AddrSpace *)0,0,0);
|
||||
else if (!spc->isHeritaged())
|
||||
infolist[i].set((AddrSpace *)0,spc->getDelay(),spc->getDeadcodeDelay());
|
||||
else
|
||||
infolist[i].set(spc,spc->getDelay(),spc->getDeadcodeDelay());
|
||||
}
|
||||
}
|
||||
|
||||
@ -2227,7 +2232,6 @@ void Heritage::heritage(void)
|
||||
|
||||
{
|
||||
VarnodeLocSet::const_iterator iter,enditer;
|
||||
AddrSpace *space;
|
||||
HeritageInfo *info;
|
||||
Varnode *vn;
|
||||
bool needwarning;
|
||||
@ -2235,7 +2239,6 @@ void Heritage::heritage(void)
|
||||
int4 reprocessStackCount = 0;
|
||||
AddrSpace *stackSpace = (AddrSpace *)0;
|
||||
vector<PcodeOp *> freeStores;
|
||||
const AddrSpaceManager *manage = fd->getArch();
|
||||
PreferSplitManager splitmanage;
|
||||
|
||||
if (maxdepth == -1) // Has a restructure been forced
|
||||
@ -2246,21 +2249,20 @@ void Heritage::heritage(void)
|
||||
splitmanage.init(fd,&fd->getArch()->splitrecords);
|
||||
splitmanage.split();
|
||||
}
|
||||
for(int4 i=0;i<manage->numSpaces();++i) {
|
||||
space = manage->getSpace(i);
|
||||
if (!space->isHeritaged()) continue;
|
||||
info = getInfo(space);
|
||||
for(int4 i=0;i<infolist.size();++i) {
|
||||
info = &infolist[i];
|
||||
if (!info->isHeritaged()) continue;
|
||||
if (pass < info->delay) continue; // It is too soon to heritage this space
|
||||
if (!info->loadGuardSearch) {
|
||||
info->loadGuardSearch = true;
|
||||
if (discoverIndexedStackPointers(info->space,freeStores,true)) {
|
||||
reprocessStackCount += 1;
|
||||
stackSpace = space;
|
||||
reprocessStackCount += 1;
|
||||
stackSpace = info->space;
|
||||
}
|
||||
}
|
||||
needwarning = false;
|
||||
iter = fd->beginLoc(space);
|
||||
enditer = fd->endLoc(space);
|
||||
iter = fd->beginLoc(info->space);
|
||||
enditer = fd->endLoc(info->space);
|
||||
|
||||
while(iter != enditer) {
|
||||
vn = *iter++;
|
||||
@ -2343,7 +2345,7 @@ int4 Heritage::numHeritagePasses(AddrSpace *spc) const
|
||||
|
||||
{
|
||||
const HeritageInfo *info = getInfo(spc);
|
||||
if (info == (const HeritageInfo *)0)
|
||||
if (!info->isHeritaged())
|
||||
throw LowlevelError("Trying to calculate passes for non-heritaged space");
|
||||
return (info->delay - pass);
|
||||
}
|
||||
@ -2355,8 +2357,6 @@ void Heritage::seenDeadCode(AddrSpace *spc)
|
||||
|
||||
{
|
||||
HeritageInfo *info = getInfo(spc);
|
||||
if (info == (HeritageInfo *)0)
|
||||
throw LowlevelError("Informed of deadcode removal for non-heritaged space");
|
||||
info->deadremoved = 1;
|
||||
}
|
||||
|
||||
@ -2369,8 +2369,6 @@ int4 Heritage::getDeadCodeDelay(AddrSpace *spc) const
|
||||
|
||||
{
|
||||
const HeritageInfo *info = getInfo(spc);
|
||||
if (info == (const HeritageInfo *)0)
|
||||
throw LowlevelError("Could not get heritage delay for space: "+spc->getName());
|
||||
return info->deadcodedelay;
|
||||
}
|
||||
|
||||
@ -2383,8 +2381,6 @@ void Heritage::setDeadCodeDelay(AddrSpace *spc,int4 delay)
|
||||
|
||||
{
|
||||
HeritageInfo *info = getInfo(spc);
|
||||
if (info == (HeritageInfo *)0)
|
||||
throw LowlevelError("Setting heritage delay for non-heritaged space");
|
||||
if (delay < info->delay)
|
||||
throw LowlevelError("Illegal deadcode delay setting");
|
||||
info->deadcodedelay = delay;
|
||||
@ -2399,8 +2395,6 @@ bool Heritage::deadRemovalAllowed(AddrSpace *spc) const
|
||||
|
||||
{
|
||||
const HeritageInfo *info = getInfo(spc);
|
||||
if (info == (HeritageInfo *)0)
|
||||
throw LowlevelError("Heritage query for non-heritaged space");
|
||||
return (pass > info->deadcodedelay);
|
||||
}
|
||||
|
||||
@ -2415,8 +2409,6 @@ bool Heritage::deadRemovalAllowedSeen(AddrSpace *spc)
|
||||
|
||||
{
|
||||
HeritageInfo *info = getInfo(spc);
|
||||
if (info == (HeritageInfo *)0)
|
||||
throw LowlevelError("Heritage query for non-heritaged space");
|
||||
bool res = (pass > info->deadcodedelay);
|
||||
if (res)
|
||||
info->deadremoved = 1;
|
||||
|
@ -90,8 +90,9 @@ class HeritageInfo {
|
||||
int4 deadremoved; ///< >0 if Varnodes in this space have been eliminated
|
||||
bool loadGuardSearch; ///< \b true if the search for LOAD ops to guard has been performed
|
||||
bool warningissued; ///< \b true if warning issued previously
|
||||
HeritageInfo(AddrSpace *spc,int4 dl,int4 dcdl) {
|
||||
space=spc; delay=dl; deadcodedelay=dcdl; deadremoved=0; loadGuardSearch=false; warningissued=false; } ///< Constructor
|
||||
void set(AddrSpace *spc,int4 dl,int4 dcdl) {
|
||||
space=spc; delay=dl; deadcodedelay=dcdl; deadremoved=0; warningissued=false; loadGuardSearch = false; } ///< Set all fields
|
||||
bool isHeritaged(void) const { return (space != (AddrSpace *)0); }
|
||||
void reset(void) {
|
||||
deadremoved = 0; deadcodedelay = delay; warningissued = false; loadGuardSearch = false; } ///< Reset
|
||||
};
|
||||
|
@ -895,6 +895,7 @@ void IfcPrintSpaces::execute(istream &s)
|
||||
int4 num = manage->numSpaces();
|
||||
for(int4 i=0;i<num;++i) {
|
||||
AddrSpace *spc = manage->getSpace(i);
|
||||
if (spc == (AddrSpace *)0) continue;
|
||||
*status->fileoptr << dec << spc->getIndex() << " : '" << spc->getShortcut() << "' " << spc->getName();
|
||||
if (spc->getType() == IPTR_CONSTANT)
|
||||
*status->fileoptr << " constant ";
|
||||
@ -1468,7 +1469,7 @@ void IfcDeadcodedelay::execute(istream &s)
|
||||
*status->optr << "Successfully overrided deadcode delay for single function" << endl;
|
||||
}
|
||||
else {
|
||||
dcp->conf->setDeadcodeDelay(spc->getIndex(),delay);
|
||||
dcp->conf->setDeadcodeDelay(spc,delay);
|
||||
*status->optr << "Successfully overrided deadcode delay for all functions" << endl;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
*/
|
||||
#include "sleighbase.hh"
|
||||
|
||||
const int4 SleighBase::SLA_FORMAT_VERSION = 2;
|
||||
|
||||
SleighBase::SleighBase(void)
|
||||
|
||||
{
|
||||
@ -146,6 +148,7 @@ void SleighBase::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
s << "<sleigh";
|
||||
a_v_i(s,"version",SLA_FORMAT_VERSION);
|
||||
a_v_b(s,"bigendian",isBigEndian());
|
||||
a_v_i(s,"align",alignment);
|
||||
a_v_u(s,"uniqbase",getUniqueBase());
|
||||
@ -162,6 +165,7 @@ void SleighBase::saveXml(ostream &s) const
|
||||
s << ">\n";
|
||||
for(int4 i=0;i<numSpaces();++i) {
|
||||
AddrSpace *spc = getSpace(i);
|
||||
if (spc == (AddrSpace *)0) continue;
|
||||
if ((spc->getType()==IPTR_CONSTANT) ||
|
||||
(spc->getType()==IPTR_FSPEC)||
|
||||
(spc->getType()==IPTR_IOP)||
|
||||
@ -183,6 +187,7 @@ void SleighBase::restoreXml(const Element *el)
|
||||
maxdelayslotbytes = 0;
|
||||
unique_allocatemask = 0;
|
||||
numSections = 0;
|
||||
int4 version = 0;
|
||||
setBigEndian(xml_readbool(el->getAttributeValue("bigendian")));
|
||||
{
|
||||
istringstream s(el->getAttributeValue("align"));
|
||||
@ -214,7 +219,14 @@ void SleighBase::restoreXml(const Element *el)
|
||||
s3.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s3 >> numSections;
|
||||
}
|
||||
else if (attrname == "version") {
|
||||
istringstream s(el->getAttributeValue(i));
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
s >> version;
|
||||
}
|
||||
}
|
||||
if (version != SLA_FORMAT_VERSION)
|
||||
throw LowlevelError(".sla file has wrong format");
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
iter = list.begin();
|
||||
|
@ -27,6 +27,7 @@
|
||||
/// - Reading the various SLEIGH specification files
|
||||
/// - Building and writing out SLEIGH specification files
|
||||
class SleighBase : public Translate {
|
||||
static const int4 SLA_FORMAT_VERSION; ///< Current version of the .sla file read/written by SleighBash
|
||||
vector<string> userop; ///< Names of user-define p-code ops for \b this Translate object
|
||||
map<VarnodeData,string> varnode_xref; ///< A map from Varnodes in the \e register space to register names
|
||||
protected:
|
||||
|
@ -1476,9 +1476,13 @@ void SleighCompile::predefinedSymbols(void)
|
||||
// Some predefined symbols
|
||||
root = new SubtableSymbol("instruction"); // Base constructors
|
||||
symtab.addSymbol(root);
|
||||
insertSpace(new ConstantSpace(this,this,"const",0));
|
||||
insertSpace(new ConstantSpace(this,this,"const",AddrSpace::constant_space_index));
|
||||
SpaceSymbol *spacesym = new SpaceSymbol(getConstantSpace()); // Constant space
|
||||
symtab.addSymbol(spacesym);
|
||||
OtherSpace *otherSpace = new OtherSpace(this,this,"OTHER",AddrSpace::other_space_index);
|
||||
insertSpace(otherSpace);
|
||||
spacesym = new SpaceSymbol(otherSpace);
|
||||
symtab.addSymbol(spacesym);
|
||||
insertSpace(new UniqueSpace(this,this,"unique",numSpaces(),0));
|
||||
spacesym = new SpaceSymbol(getUniqueSpace()); // Temporary register space
|
||||
symtab.addSymbol(spacesym);
|
||||
|
@ -24,14 +24,6 @@ void AddrSpace::calcScaleMask(void)
|
||||
highest = highest * wordsize + (wordsize-1); // Maximum byte address
|
||||
}
|
||||
|
||||
/// Called once during initialization to assign a single character shortcut for the space
|
||||
/// The character is used as a shorthand when typing addresses on the console command line
|
||||
void AddrSpace::assignShortcut(void)
|
||||
|
||||
{
|
||||
shortcut = manage->assignShortcut(type);
|
||||
}
|
||||
|
||||
/// Initialize an address space with its basic attributes
|
||||
/// \param m is the space manager associated with the new space
|
||||
/// \param t is the processor translator associated with the new space
|
||||
@ -55,6 +47,7 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp,const s
|
||||
index = ind;
|
||||
delay = dl;
|
||||
deadcodedelay = dl; // Deadcode delay initially starts the same as heritage delay
|
||||
shortcut = ' '; // Placeholder meaning shortcut is unassigned
|
||||
|
||||
// These are the flags we allow to be set from constructor
|
||||
flags = (fl & hasphysical);
|
||||
@ -63,7 +56,6 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp,const s
|
||||
flags |= (heritaged | does_deadcode); // Always on unless explicitly turned off in derived constructor
|
||||
|
||||
calcScaleMask();
|
||||
assignShortcut();
|
||||
}
|
||||
|
||||
/// This is a partial constructor, for initializing a space
|
||||
@ -80,6 +72,7 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp)
|
||||
type = tp;
|
||||
flags = (heritaged | does_deadcode); // Always on unless explicitly turned off in derived constructor
|
||||
wordsize = 1;
|
||||
shortcut = ' ';
|
||||
// We let big_endian get set by attribute
|
||||
}
|
||||
|
||||
@ -349,7 +342,6 @@ void AddrSpace::restoreXml(const Element *el)
|
||||
if (deadcodedelay == -1)
|
||||
deadcodedelay = delay; // If deadcodedelay attribute not present, set it to delay
|
||||
calcScaleMask();
|
||||
assignShortcut();
|
||||
}
|
||||
|
||||
/// This constructs the unique constant space
|
||||
@ -392,6 +384,42 @@ void ConstantSpace::restoreXml(const Element *el)
|
||||
throw LowlevelError("Should never restore the constant space from XML");
|
||||
}
|
||||
|
||||
/// Construct the \b other space, which is automatically constructed
|
||||
/// by the compiler, and is only constructed once. The name should
|
||||
/// always by \b OTHER.
|
||||
/// \param m is the associated address space manager
|
||||
/// \param t is the associated processor translator
|
||||
/// \param nm is the name of the space
|
||||
/// \param ind is the integer identifier
|
||||
OtherSpace::OtherSpace(AddrSpaceManager *m,const Translate *t,
|
||||
const string &nm,int4 ind)
|
||||
: AddrSpace(m,t,IPTR_PROCESSOR,nm,sizeof(uintb),1,ind,0,0)
|
||||
{
|
||||
clearFlags(heritaged|does_deadcode);
|
||||
setFlags(is_otherspace);
|
||||
}
|
||||
|
||||
OtherSpace::OtherSpace(AddrSpaceManager *m,const Translate *t)
|
||||
: AddrSpace(m,t,IPTR_PROCESSOR)
|
||||
{
|
||||
clearFlags(heritaged|does_deadcode);
|
||||
setFlags(is_otherspace);
|
||||
}
|
||||
|
||||
void OtherSpace::printRaw(ostream &s,uintb offset) const
|
||||
|
||||
{
|
||||
s << "0x" << hex << offset;
|
||||
}
|
||||
|
||||
void OtherSpace::saveXml(ostream &s) const
|
||||
|
||||
{
|
||||
s << "<space_other";
|
||||
saveBasicAttributes(s);
|
||||
s << "/>\n";
|
||||
}
|
||||
|
||||
/// This is the constructor for the \b unique space, which is
|
||||
/// automatically constructed by the analysis engine, and
|
||||
/// constructed only once. The name should always be \b unique.
|
||||
@ -653,7 +681,6 @@ void OverlaySpace::restoreXml(const Element *el)
|
||||
delay = baseSpace->getDelay();
|
||||
deadcodedelay = baseSpace->getDeadcodeDelay();
|
||||
calcScaleMask();
|
||||
assignShortcut();
|
||||
|
||||
if (baseSpace->isBigEndian())
|
||||
setFlags(big_endian);
|
||||
|
@ -82,7 +82,12 @@ public:
|
||||
overlay = 32, ///< This space is an overlay of another space
|
||||
overlaybase = 64, ///< This is the base space for overlay space(s)
|
||||
truncated = 128, ///< Space is truncated from its original size, expect pointers larger than this size
|
||||
hasphysical = 256 ///< Has physical memory associated with it
|
||||
hasphysical = 256, ///< Has physical memory associated with it
|
||||
is_otherspace = 512 ///< Quick check for the OtherSpace derived class
|
||||
};
|
||||
enum {
|
||||
constant_space_index = 0, ///< Reserved index for the constant space
|
||||
other_space_index = 1 ///< Reserved index for the other space
|
||||
};
|
||||
private:
|
||||
spacetype type; ///< Type of space (PROCESSOR, CONSTANT, INTERNAL, ...)
|
||||
@ -100,7 +105,6 @@ protected:
|
||||
int4 delay; ///< Delay in heritaging this space
|
||||
int4 deadcodedelay; ///< Delay before deadcode removal is allowed on this space
|
||||
void calcScaleMask(void); ///< Calculate scale and mask
|
||||
void assignShortcut(void); ///< Assign a shortcut character to the space
|
||||
void setFlags(uint4 fl); ///< Set a cached attribute
|
||||
void clearFlags(uint4 fl); ///< Clear a cached attribute
|
||||
void saveBasicAttributes(ostream &s) const; ///< Write the XML attributes of this space
|
||||
@ -128,6 +132,7 @@ public:
|
||||
bool isReverseJustified(void) const; ///< Return \b true if alignment justification does not match endianness
|
||||
bool isOverlay(void) const; ///< Return \b true if this is an overlay space
|
||||
bool isOverlayBase(void) const; ///< Return \b true if other spaces overlay this space
|
||||
bool isOtherSpace(void) const; ///< Return \b true if \b this is the \e other address space
|
||||
bool isTruncated(void) const; ///< Return \b true if this space is truncated from its original size
|
||||
void printOffset(ostream &s,uintb offset) const; ///< Write an address offset to a stream
|
||||
|
||||
@ -170,6 +175,15 @@ public:
|
||||
virtual void restoreXml(const Element *el);
|
||||
};
|
||||
|
||||
/// \brief Special AddrSpace for special/user-defined address spaces
|
||||
class OtherSpace : public AddrSpace {
|
||||
public:
|
||||
OtherSpace(AddrSpaceManager *m, const Translate *t, const string &nm, int4 ind); ///< Constructor
|
||||
OtherSpace(AddrSpaceManager *m, const Translate *t); ///< For use with restoreXml
|
||||
virtual void printRaw(ostream &s, uintb offset) const;
|
||||
virtual void saveXml(ostream &s) const;
|
||||
};
|
||||
|
||||
/// \brief The pool of temporary storage registers
|
||||
///
|
||||
/// It is convenient both for modelling processor instructions
|
||||
@ -181,7 +195,7 @@ public:
|
||||
/// \b unique.
|
||||
class UniqueSpace : public AddrSpace {
|
||||
public:
|
||||
UniqueSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,uint4 fl);
|
||||
UniqueSpace(AddrSpaceManager *m,const Translate *t,const string &nm,int4 ind,uint4 fl); ///< Constructor
|
||||
UniqueSpace(AddrSpaceManager *m,const Translate *t); ///< For use with restoreXml
|
||||
virtual void saveXml(ostream &s) const;
|
||||
};
|
||||
@ -392,6 +406,10 @@ inline bool AddrSpace::isOverlayBase(void) const {
|
||||
return ((flags&overlaybase)!=0);
|
||||
}
|
||||
|
||||
inline bool AddrSpace::isOtherSpace(void) const {
|
||||
return ((flags&is_otherspace)!=0);
|
||||
}
|
||||
|
||||
/// If this method returns \b true, the logical form of this space is truncated from its actual size
|
||||
/// Pointers may refer to this original size put the most significant bytes are ignored
|
||||
inline bool AddrSpace::isTruncated(void) const {
|
||||
|
@ -170,6 +170,8 @@ AddrSpace *AddrSpaceManager::restoreXmlSpace(const Element *el,const Translate *
|
||||
res = new SpacebaseSpace(this,trans);
|
||||
else if (tp == "space_unique")
|
||||
res = new UniqueSpace(this,trans);
|
||||
else if (tp == "space_other")
|
||||
res = new OtherSpace(this,trans);
|
||||
else if (tp == "space_overlay")
|
||||
res = new OverlaySpace(this,trans);
|
||||
else
|
||||
@ -191,7 +193,7 @@ void AddrSpaceManager::restoreXmlSpaces(const Element *el,const Translate *trans
|
||||
|
||||
{
|
||||
// The first space should always be the constant space
|
||||
insertSpace(new ConstantSpace(this,trans,"const",0));
|
||||
insertSpace(new ConstantSpace(this,trans,"const",AddrSpace::constant_space_index));
|
||||
|
||||
string defname(el->getAttributeValue("defaultspace"));
|
||||
const List &list(el->getChildren());
|
||||
@ -203,6 +205,8 @@ void AddrSpaceManager::restoreXmlSpaces(const Element *el,const Translate *trans
|
||||
++iter;
|
||||
}
|
||||
AddrSpace *spc = getSpaceByName(defname);
|
||||
if (spc == (AddrSpace *)0)
|
||||
throw LowlevelError("Bad 'defaultspace' attribute: "+defname);
|
||||
setDefaultSpace(spc->getIndex());
|
||||
}
|
||||
|
||||
@ -217,7 +221,7 @@ void AddrSpaceManager::setDefaultSpace(int4 index)
|
||||
{
|
||||
if (defaultspace != (AddrSpace *)0)
|
||||
throw LowlevelError("Default space set multiple times");
|
||||
if (baselist.size()<=index)
|
||||
if (baselist.size()<=index || baselist[index] == (AddrSpace *)0)
|
||||
throw LowlevelError("Bad index for default space");
|
||||
defaultspace = baselist[index];
|
||||
}
|
||||
@ -244,48 +248,49 @@ void AddrSpaceManager::setReverseJustified(AddrSpace *spc)
|
||||
void AddrSpaceManager::insertSpace(AddrSpace *spc)
|
||||
|
||||
{
|
||||
bool nametype_mismatch = false;
|
||||
bool duplicatedefine = false;
|
||||
bool nameTypeMismatch = false;
|
||||
bool duplicateName = false;
|
||||
bool duplicateId = false;
|
||||
switch(spc->getType()) {
|
||||
case IPTR_CONSTANT:
|
||||
if (spc->getName() != "const")
|
||||
nametype_mismatch = true;
|
||||
if (baselist.size()!=0)
|
||||
throw LowlevelError("const space must be initialized first");
|
||||
nameTypeMismatch = true;
|
||||
if (spc->index != AddrSpace::constant_space_index)
|
||||
throw LowlevelError("const space must be assigned index 0");
|
||||
constantspace = spc;
|
||||
break;
|
||||
case IPTR_INTERNAL:
|
||||
if (spc->getName() != "unique")
|
||||
nametype_mismatch = true;
|
||||
nameTypeMismatch = true;
|
||||
if (uniqspace != (AddrSpace *)0)
|
||||
duplicatedefine = true;
|
||||
duplicateName = true;
|
||||
uniqspace = spc;
|
||||
break;
|
||||
case IPTR_FSPEC:
|
||||
if (spc->getName() != "fspec")
|
||||
nametype_mismatch = true;
|
||||
nameTypeMismatch = true;
|
||||
if (fspecspace != (AddrSpace *)0)
|
||||
duplicatedefine = true;
|
||||
duplicateName = true;
|
||||
fspecspace = spc;
|
||||
break;
|
||||
case IPTR_JOIN:
|
||||
if (spc->getName() != "join")
|
||||
nametype_mismatch = true;
|
||||
nameTypeMismatch = true;
|
||||
if (joinspace != (AddrSpace *)0)
|
||||
duplicatedefine = true;
|
||||
duplicateName = true;
|
||||
joinspace = spc;
|
||||
break;
|
||||
case IPTR_IOP:
|
||||
if (spc->getName() != "iop")
|
||||
nametype_mismatch = true;
|
||||
nameTypeMismatch = true;
|
||||
if (iopspace != (AddrSpace *)0)
|
||||
duplicatedefine = true;
|
||||
duplicateName = true;
|
||||
iopspace = spc;
|
||||
break;
|
||||
case IPTR_SPACEBASE:
|
||||
if (spc->getName() == "stack") {
|
||||
if (stackspace != (AddrSpace *)0)
|
||||
duplicatedefine = true;
|
||||
duplicateName = true;
|
||||
stackspace = spc;
|
||||
}
|
||||
// fallthru
|
||||
@ -294,19 +299,36 @@ void AddrSpaceManager::insertSpace(AddrSpace *spc)
|
||||
OverlaySpace *ospc = (OverlaySpace *)spc;
|
||||
ospc->getBaseSpace()->setFlags(AddrSpace::overlaybase); // Mark the base as being overlayed
|
||||
}
|
||||
for(uint4 i=0;i<baselist.size();++i)
|
||||
if (baselist[i]->getName() == spc->getName())
|
||||
duplicatedefine = true;
|
||||
else if (spc->isOtherSpace()) {
|
||||
if (spc->index != AddrSpace::other_space_index)
|
||||
throw LowlevelError("OTHER space must be assigned index 1");
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (nametype_mismatch)
|
||||
|
||||
if (baselist.size() <= spc->index)
|
||||
baselist.resize(spc->index+1, (AddrSpace *)0);
|
||||
|
||||
duplicateId = baselist[spc->index] != (AddrSpace *)0;
|
||||
|
||||
if (!nameTypeMismatch && !duplicateName && !duplicateId) {
|
||||
duplicateName = !name2Space.insert(pair<string,AddrSpace *>(spc->getName(),spc)).second;
|
||||
}
|
||||
|
||||
if (nameTypeMismatch || duplicateName || duplicateId) {
|
||||
if (spc->refcount == 0)
|
||||
delete spc;
|
||||
spc = (AddrSpace *)0;
|
||||
}
|
||||
if (nameTypeMismatch)
|
||||
throw LowlevelError("Space "+spc->getName()+" was initialized with wrong type");
|
||||
if (duplicatedefine)
|
||||
if (duplicateName)
|
||||
throw LowlevelError("Space "+spc->getName()+" was initialized more than once");
|
||||
if (baselist.size() != spc->getIndex())
|
||||
throw LowlevelError("Space "+spc->getName()+" was initialized with a bad id");
|
||||
baselist.push_back(spc);
|
||||
if (duplicateId)
|
||||
throw LowlevelError("Space "+spc->getName()+" was assigned as id duplicating: "+baselist[spc->index]->getName());
|
||||
baselist[spc->index] = spc;
|
||||
spc->refcount += 1;
|
||||
assignShortcut(spc);
|
||||
}
|
||||
|
||||
/// Different managers may need to share the same spaces. I.e. if different programs being
|
||||
@ -316,8 +338,11 @@ void AddrSpaceManager::insertSpace(AddrSpace *spc)
|
||||
void AddrSpaceManager::copySpaces(const AddrSpaceManager *op2)
|
||||
|
||||
{ // Insert every space in -op2- into -this- manager
|
||||
for(int4 i=0;i<op2->baselist.size();++i)
|
||||
insertSpace(op2->baselist[i]);
|
||||
for(int4 i=0;i<op2->baselist.size();++i) {
|
||||
AddrSpace *spc = op2->baselist[i];
|
||||
if (spc != (AddrSpace *)0)
|
||||
insertSpace(spc);
|
||||
}
|
||||
setDefaultSpace(op2->getDefaultSpace()->getIndex());
|
||||
}
|
||||
|
||||
@ -353,6 +378,7 @@ AddrSpaceManager::~AddrSpaceManager(void)
|
||||
{
|
||||
for(vector<AddrSpace *>::iterator iter=baselist.begin();iter!=baselist.end();++iter) {
|
||||
AddrSpace *spc = *iter;
|
||||
if (spc == (AddrSpace *)0) continue;
|
||||
if (spc->refcount > 1)
|
||||
spc->refcount -= 1;
|
||||
else
|
||||
@ -366,24 +392,29 @@ AddrSpaceManager::~AddrSpaceManager(void)
|
||||
delete splitlist[i]; // Delete any join records
|
||||
}
|
||||
|
||||
/// Assign a \e shortcut character to an address space
|
||||
/// Assign a \e shortcut character to the given address space.
|
||||
/// This routine makes use of the desired type of the new space
|
||||
/// and info about shortcuts for spaces that already exist to
|
||||
/// pick a unique and consistent character.
|
||||
/// This is currently invoked by the AddrSpace initialization
|
||||
/// process.
|
||||
/// \param tp is the type of the new space
|
||||
/// \return the shortcut character
|
||||
char AddrSpaceManager::assignShortcut(spacetype tp) const
|
||||
/// pick a unique and consistent character. This method also builds
|
||||
/// up a map from short to AddrSpace object.
|
||||
/// \param spc is the given AddrSpace
|
||||
void AddrSpaceManager::assignShortcut(AddrSpace *spc)
|
||||
|
||||
{
|
||||
char shortcut = 'x';
|
||||
switch(tp) {
|
||||
if (spc->shortcut != ' ') { // If the shortcut is already assigned
|
||||
shortcut2Space.insert(pair<int4,AddrSpace *>(spc->shortcut,spc));
|
||||
return;
|
||||
}
|
||||
char shortcut;
|
||||
switch(spc->getType()) {
|
||||
case IPTR_CONSTANT:
|
||||
shortcut = '#';
|
||||
break;
|
||||
case IPTR_PROCESSOR:
|
||||
shortcut = 'r';
|
||||
if (spc->getName() == "register")
|
||||
shortcut = '%';
|
||||
else
|
||||
shortcut = spc->getName()[0];
|
||||
break;
|
||||
case IPTR_SPACEBASE:
|
||||
shortcut = 's';
|
||||
@ -400,25 +431,29 @@ char AddrSpaceManager::assignShortcut(spacetype tp) const
|
||||
case IPTR_IOP:
|
||||
shortcut = 'i';
|
||||
break;
|
||||
default:
|
||||
shortcut = 'x';
|
||||
break;
|
||||
}
|
||||
// if ((shortcut >= 'A') && (shortcut <= 'R'))
|
||||
// shortcut |= 0x20;
|
||||
|
||||
for(int4 i=0x61;i<0x7a;++i) {
|
||||
int4 j;
|
||||
for(j=0;j<baselist.size();++j) {
|
||||
if (baselist[j]->getShortcut() == shortcut)
|
||||
break;
|
||||
if (shortcut >= 'A' && shortcut <= 'Z')
|
||||
shortcut += 0x20;
|
||||
|
||||
int4 collisionCount = 0;
|
||||
while(!shortcut2Space.insert(pair<int4,AddrSpace *>(shortcut,spc)).second) {
|
||||
collisionCount += 1;
|
||||
if (collisionCount >26) {
|
||||
// Could not find a unique shortcut, but we just re-use 'z' as we
|
||||
// can always use the long form to specify the address if there are really so many
|
||||
// spaces that need to be distinguishable (in the console mode)
|
||||
spc->shortcut = 'z';
|
||||
return;
|
||||
}
|
||||
if (j == baselist.size()) return shortcut; // Found an open shortcut
|
||||
shortcut = (char) i;
|
||||
if (shortcut == 'a')
|
||||
shortcut = '%'; // Second processor space is usually the register space
|
||||
shortcut += 1;
|
||||
if (shortcut < 'a' || shortcut > 'z')
|
||||
shortcut = 'a';
|
||||
}
|
||||
// Could not find a unique shortcut, but we just re-use 'z' as we
|
||||
// can always use the long form to specify the address if there are really so many
|
||||
// spaces that need to be distinguishable (in the console mode)
|
||||
return shortcut;
|
||||
spc->shortcut = (char)shortcut;
|
||||
}
|
||||
|
||||
/// All address spaces have a unique name associated with them.
|
||||
@ -429,10 +464,10 @@ char AddrSpaceManager::assignShortcut(spacetype tp) const
|
||||
AddrSpace *AddrSpaceManager::getSpaceByName(const string &nm) const
|
||||
|
||||
{
|
||||
for(int4 i=0;i<baselist.size();++i)
|
||||
if (baselist[i]->getName() == nm)
|
||||
return baselist[i];
|
||||
return (AddrSpace *)0;
|
||||
map<string,AddrSpace *>::const_iterator iter = name2Space.find(nm);
|
||||
if (iter == name2Space.end())
|
||||
return (AddrSpace *)0;
|
||||
return (*iter).second;
|
||||
}
|
||||
|
||||
/// All address spaces have a unique shortcut (ASCII) character
|
||||
@ -443,10 +478,11 @@ AddrSpace *AddrSpaceManager::getSpaceByName(const string &nm) const
|
||||
AddrSpace *AddrSpaceManager::getSpaceByShortcut(char sc) const
|
||||
|
||||
{
|
||||
for(int4 i=0;i<baselist.size();++i)
|
||||
if (baselist[i]->getShortcut() == sc)
|
||||
return baselist[i];
|
||||
return (AddrSpace *)0;
|
||||
map<int4,AddrSpace *>::const_iterator iter;
|
||||
iter = shortcut2Space.find(sc);
|
||||
if (iter == shortcut2Space.end())
|
||||
return (AddrSpace *)0;
|
||||
return (*iter).second;
|
||||
}
|
||||
|
||||
Address AddrSpaceManager::resolveConstant(AddrSpace *spc,uintb val,int4 sz,const Address &point) const
|
||||
@ -475,9 +511,12 @@ AddrSpace *AddrSpaceManager::getNextSpaceInOrder(AddrSpace *spc) const
|
||||
if (spc == (AddrSpace *) ~((uintp)0)) {
|
||||
return (AddrSpace *)0;
|
||||
}
|
||||
int4 index = spc->getIndex();
|
||||
if (index < baselist.size()-1) {
|
||||
return baselist[index+1];
|
||||
int4 index = spc->getIndex() + 1;
|
||||
while (index < baselist.size()) {
|
||||
AddrSpace *res = baselist[index];
|
||||
if (res != (AddrSpace *)0)
|
||||
return res;
|
||||
index += 1;
|
||||
}
|
||||
return (AddrSpace *) ~((uintp)0);
|
||||
}
|
||||
@ -558,12 +597,12 @@ JoinRecord *AddrSpaceManager::findJoin(uintb offset) const
|
||||
|
||||
/// Set the number of passes for a specific AddrSpace before deadcode removal is allowed
|
||||
/// for that space.
|
||||
/// \param spcnum is the index of the AddrSpace to change
|
||||
/// \param spc is the AddrSpace to change
|
||||
/// \param delaydelta is the number of rounds to the delay should be set to
|
||||
void AddrSpaceManager::setDeadcodeDelay(int4 spcnum,int4 delaydelta)
|
||||
void AddrSpaceManager::setDeadcodeDelay(AddrSpace *spc,int4 delaydelta)
|
||||
|
||||
{
|
||||
baselist[spcnum]->deadcodedelay = delaydelta;
|
||||
spc->deadcodedelay = delaydelta;
|
||||
}
|
||||
|
||||
/// Mark the named space as truncated from its original size
|
||||
|
@ -212,6 +212,8 @@ struct JoinRecordCompare {
|
||||
class AddrSpaceManager {
|
||||
vector<AddrSpace *> baselist; ///< Every space we know about for this architecture
|
||||
vector<AddressResolver *> resolvelist; ///< Special constant resolvers
|
||||
map<string,AddrSpace *> name2Space; ///< Map from name -> space
|
||||
map<int4,AddrSpace *> shortcut2Space; ///< Map from shortcut -> space
|
||||
AddrSpace *constantspace; ///< Quick reference to constant space
|
||||
AddrSpace *defaultspace; ///< Generally primary RAM, where assembly pointers point to
|
||||
AddrSpace *iopspace; ///< Space for internal pcode op pointers
|
||||
@ -227,6 +229,7 @@ protected:
|
||||
void restoreXmlSpaces(const Element *el,const Translate *trans); ///< Restore address spaces in the model from an XML tag
|
||||
void setDefaultSpace(int4 index); ///< Set the default address space
|
||||
void setReverseJustified(AddrSpace *spc); ///< Set reverse justified property on this space
|
||||
void assignShortcut(AddrSpace *spc); ///< Select a shortcut character for a new space
|
||||
void insertSpace(AddrSpace *spc); ///< Add a new address space to the model
|
||||
void copySpaces(const AddrSpaceManager *op2); ///< Copy spaces from another manager
|
||||
void addSpacebasePointer(SpacebaseSpace *basespace,const VarnodeData &ptrdata,int4 truncSize,bool stackGrowth); ///< Set the base register of a spacebase space
|
||||
@ -234,7 +237,6 @@ protected:
|
||||
public:
|
||||
AddrSpaceManager(void); ///< Construct an empty address space manager
|
||||
virtual ~AddrSpaceManager(void); ///< Destroy the manager
|
||||
char assignShortcut(spacetype tp) const; ///< Select a shortcut character for a new space
|
||||
int4 getDefaultSize(void) const; ///< Get size of addresses for the default space
|
||||
AddrSpace *getSpaceByName(const string &nm) const; ///< Get address space by name
|
||||
AddrSpace *getSpaceByShortcut(char sc) const; ///< Get address space from its shortcut
|
||||
@ -253,7 +255,7 @@ public:
|
||||
AddrSpace *getNextSpaceInOrder(AddrSpace *spc) const; ///< Get the next \e contiguous address space
|
||||
JoinRecord *findAddJoin(const vector<VarnodeData> &pieces,uint4 logicalsize); ///< Get (or create) JoinRecord for \e pieces
|
||||
JoinRecord *findJoin(uintb offset) const; ///< Find JoinRecord for \e offset in the join space
|
||||
void setDeadcodeDelay(int4 spcnum,int4 delaydelta); ///< Set the deadcodedelay for a specific space
|
||||
void setDeadcodeDelay(AddrSpace *spc,int4 delaydelta); ///< Set the deadcodedelay for a specific space
|
||||
void truncateSpace(const TruncationTag &tag); ///< Mark a space as truncated from its original size
|
||||
|
||||
/// \brief Build a logically lower precision storage location for a bigger floating point register
|
||||
|
@ -216,7 +216,8 @@ public class DecompInterface {
|
||||
// use static uniqueBase since we don't know how many dynamically generated
|
||||
// variables Ghidra may add to the language/compile-spec uniqueBase
|
||||
long uniqueBase = 0x10000000;
|
||||
String tspec = pcodelanguage.buildTranslatorTag(program.getAddressFactory(), uniqueBase, null);
|
||||
String tspec =
|
||||
pcodelanguage.buildTranslatorTag(program.getAddressFactory(), uniqueBase, null);
|
||||
String coretypes = dtmanage.buildCoreTypes();
|
||||
SleighLanguageDescription sleighdescription =
|
||||
(SleighLanguageDescription) pcodelanguage.getLanguageDescription();
|
||||
@ -233,7 +234,8 @@ public class DecompInterface {
|
||||
if (xmlOptions != null) {
|
||||
decompProcess.setMaxResultSize(xmlOptions.getMaxPayloadMBytes());
|
||||
decompProcess.setShowNamespace(xmlOptions.isDisplayNamespaces());
|
||||
if (!decompProcess.sendCommand1Param("setOptions", xmlOptions.getXML(this)).toString().equals("t")) {
|
||||
if (!decompProcess.sendCommand1Param("setOptions",
|
||||
xmlOptions.getXML(this)).toString().equals("t")) {
|
||||
throw new IOException("Did not accept decompiler options");
|
||||
}
|
||||
}
|
||||
@ -241,12 +243,14 @@ public class DecompInterface {
|
||||
throw new IOException("Decompile action not specified");
|
||||
}
|
||||
if (!actionname.equals("decompile")) {
|
||||
if (!decompProcess.sendCommand2Params("setAction", actionname, "").toString().equals("t")) {
|
||||
if (!decompProcess.sendCommand2Params("setAction", actionname, "").toString().equals(
|
||||
"t")) {
|
||||
throw new IOException("Could not set decompile action");
|
||||
}
|
||||
}
|
||||
if (!printSyntaxTree) {
|
||||
if (!decompProcess.sendCommand2Params("setAction", "", "notree").toString().equals("t")) {
|
||||
if (!decompProcess.sendCommand2Params("setAction", "", "notree").toString().equals(
|
||||
"t")) {
|
||||
throw new IOException("Could not turn off syntax tree");
|
||||
}
|
||||
}
|
||||
@ -256,12 +260,14 @@ public class DecompInterface {
|
||||
}
|
||||
}
|
||||
if (sendParamMeasures) {
|
||||
if (!decompProcess.sendCommand2Params("setAction", "", "parammeasures").toString().equals("t")) {
|
||||
if (!decompProcess.sendCommand2Params("setAction", "",
|
||||
"parammeasures").toString().equals("t")) {
|
||||
throw new IOException("Could not turn on sending of parameter measures");
|
||||
}
|
||||
}
|
||||
if (jumpLoad) {
|
||||
if (!decompProcess.sendCommand2Params("setAction", "", "jumpload").toString().equals("t")) {
|
||||
if (!decompProcess.sendCommand2Params("setAction", "", "jumpload").toString().equals(
|
||||
"t")) {
|
||||
throw new IOException("Could not turn on jumptable loads");
|
||||
}
|
||||
}
|
||||
@ -298,7 +304,7 @@ public class DecompInterface {
|
||||
decompileMessage = "Language does not support PCode.";
|
||||
return false;
|
||||
}
|
||||
pcodelanguage = (SleighLanguage)lang;
|
||||
pcodelanguage = (SleighLanguage) lang;
|
||||
CompilerSpec spec = prog.getCompilerSpec();
|
||||
if (!(spec instanceof BasicCompilerSpec)) {
|
||||
decompileMessage =
|
||||
@ -405,7 +411,8 @@ public class DecompInterface {
|
||||
}
|
||||
try {
|
||||
verifyProcess();
|
||||
return decompProcess.sendCommand2Params("setAction", actionstring, "").toString().equals("t");
|
||||
return decompProcess.sendCommand2Params("setAction", actionstring,
|
||||
"").toString().equals("t");
|
||||
}
|
||||
catch (IOException e) {
|
||||
// don't care
|
||||
@ -441,7 +448,8 @@ public class DecompInterface {
|
||||
String printstring = val ? "tree" : "notree";
|
||||
try {
|
||||
verifyProcess();
|
||||
return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals("t");
|
||||
return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals(
|
||||
"t");
|
||||
}
|
||||
catch (IOException e) {
|
||||
// don't care
|
||||
@ -478,7 +486,8 @@ public class DecompInterface {
|
||||
String printstring = val ? "c" : "noc";
|
||||
try {
|
||||
verifyProcess();
|
||||
return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals("t");
|
||||
return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals(
|
||||
"t");
|
||||
}
|
||||
catch (IOException e) {
|
||||
// don't care
|
||||
@ -514,7 +523,8 @@ public class DecompInterface {
|
||||
String printstring = val ? "parammeasures" : "noparammeasures";
|
||||
try {
|
||||
verifyProcess();
|
||||
return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals("t");
|
||||
return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals(
|
||||
"t");
|
||||
}
|
||||
catch (IOException e) {
|
||||
// don't care
|
||||
@ -543,7 +553,8 @@ public class DecompInterface {
|
||||
String jumpstring = val ? "jumpload" : "nojumpload";
|
||||
try {
|
||||
verifyProcess();
|
||||
return decompProcess.sendCommand2Params("setAction", "", jumpstring).toString().equals("t");
|
||||
return decompProcess.sendCommand2Params("setAction", "", jumpstring).toString().equals(
|
||||
"t");
|
||||
}
|
||||
catch (IOException e) {
|
||||
// don't care
|
||||
@ -580,8 +591,8 @@ public class DecompInterface {
|
||||
verifyProcess();
|
||||
decompProcess.setMaxResultSize(xmlOptions.getMaxPayloadMBytes());
|
||||
decompProcess.setShowNamespace(xmlOptions.isDisplayNamespaces());
|
||||
return decompProcess.sendCommand1Param("setOptions", xmloptions.getXML(this)).toString().equals(
|
||||
"t");
|
||||
return decompProcess.sendCommand1Param("setOptions",
|
||||
xmloptions.getXML(this)).toString().equals("t");
|
||||
}
|
||||
catch (IOException e) {
|
||||
// don't care
|
||||
@ -630,22 +641,27 @@ public class DecompInterface {
|
||||
return res;
|
||||
}
|
||||
|
||||
public synchronized BlockGraph structureGraph(BlockGraph ingraph,AddressFactory factory,int timeoutSecs,TaskMonitor monitor) {
|
||||
public synchronized BlockGraph structureGraph(BlockGraph ingraph, AddressFactory factory,
|
||||
int timeoutSecs, TaskMonitor monitor) {
|
||||
decompileMessage = "";
|
||||
if (monitor != null && monitor.isCancelled())
|
||||
if (monitor != null && monitor.isCancelled()) {
|
||||
return null;
|
||||
if (monitor != null)
|
||||
}
|
||||
if (monitor != null) {
|
||||
monitor.addCancelledListener(monitorListener);
|
||||
}
|
||||
LimitedByteBuffer res = null;
|
||||
BlockGraph resgraph = null;
|
||||
try {
|
||||
StringWriter writer = new StringWriter();
|
||||
ingraph.saveXml(writer);
|
||||
verifyProcess();
|
||||
res = decompProcess.sendCommand1ParamTimeout("structureGraph", writer.toString(), timeoutSecs);
|
||||
res = decompProcess.sendCommand1ParamTimeout("structureGraph", writer.toString(),
|
||||
timeoutSecs);
|
||||
decompileMessage = decompCallback.getNativeMessage();
|
||||
if (res != null) {
|
||||
XmlPullParser parser = HighFunction.stringTree(res.getInputStream(), HighFunction.getErrorHandler(this, "Results for structureGraph command"));
|
||||
XmlPullParser parser = HighFunction.stringTree(res.getInputStream(),
|
||||
HighFunction.getErrorHandler(this, "Results for structureGraph command"));
|
||||
resgraph = new BlockGraph();
|
||||
resgraph.restoreXml(parser, factory);
|
||||
resgraph.transferObjectRef(ingraph);
|
||||
@ -661,6 +677,7 @@ public class DecompInterface {
|
||||
}
|
||||
return resgraph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompile function
|
||||
* @param func function to be decompiled
|
||||
@ -697,13 +714,13 @@ public class DecompInterface {
|
||||
decompCallback.setFunction(func, funcEntry, debug);
|
||||
String addrstring = Varnode.buildXMLAddress(funcEntry);
|
||||
verifyProcess();
|
||||
res =
|
||||
decompProcess.sendCommand1ParamTimeout("decompileAt", addrstring.toString(),
|
||||
timeoutSecs);
|
||||
res = decompProcess.sendCommand1ParamTimeout("decompileAt", addrstring.toString(),
|
||||
timeoutSecs);
|
||||
decompileMessage = decompCallback.getNativeMessage();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
decompileMessage = "Exception while decompiling " +func.getEntryPoint() + ": "+ ex.getMessage() + '\n';
|
||||
decompileMessage = "Exception while decompiling " + func.getEntryPoint() + ": " +
|
||||
ex.getMessage() + '\n';
|
||||
}
|
||||
finally {
|
||||
if (monitor != null) {
|
||||
@ -727,8 +744,9 @@ public class DecompInterface {
|
||||
}
|
||||
|
||||
InputStream stream = null;
|
||||
if (res != null)
|
||||
if (res != null) {
|
||||
stream = res.getInputStream();
|
||||
}
|
||||
return new DecompileResults(func, pcodelanguage, compilerSpec, dtmanage, decompileMessage,
|
||||
stream, processState, isDisplayNamespace());
|
||||
}
|
||||
@ -746,6 +764,20 @@ public class DecompInterface {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the native decompiler process. Call this method when the decompiler's view
|
||||
* of a program has been invalidated, such as when a new overlay space has been added.
|
||||
*/
|
||||
public void resetDecompiler() {
|
||||
stopProcess();
|
||||
try {
|
||||
initializeProcess();
|
||||
}
|
||||
catch (IOException | DecompileException e) {
|
||||
decompileMessage = "Exception while resetting decompiler: " + e.getMessage() + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (program == null) {
|
||||
if (decompProcess != null) {
|
||||
@ -772,4 +804,5 @@ public class DecompInterface {
|
||||
}
|
||||
return xmlOptions.isDisplayNamespaces();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ public class DecompileProcess {
|
||||
if (type != 14) {
|
||||
throw new IOException("GHIDRA/decompiler alignment error");
|
||||
}
|
||||
LimitedByteBuffer buf = new LimitedByteBuffer(16,1<<16);
|
||||
LimitedByteBuffer buf = new LimitedByteBuffer(16, 1 << 16);
|
||||
type = readToBuffer(buf);
|
||||
if (type != 15) {
|
||||
throw new IOException("GHIDRA/decompiler alignment error");
|
||||
@ -426,8 +426,8 @@ public class DecompileProcess {
|
||||
* @throws DecompileException
|
||||
*/
|
||||
public synchronized void registerProgram(DecompileCallback cback, String pspecxml,
|
||||
String cspecxml, String tspecxml, String coretypesxml) throws IOException,
|
||||
DecompileException {
|
||||
String cspecxml, String tspecxml, String coretypesxml)
|
||||
throws IOException, DecompileException {
|
||||
callback = cback;
|
||||
callback.setShowNamespace(showNamespace);
|
||||
|
||||
@ -481,7 +481,8 @@ public class DecompileProcess {
|
||||
* @throws IOException
|
||||
* @throws DecompileException
|
||||
*/
|
||||
public synchronized LimitedByteBuffer sendCommand(String command) throws IOException, DecompileException {
|
||||
public synchronized LimitedByteBuffer sendCommand(String command)
|
||||
throws IOException, DecompileException {
|
||||
if (!statusGood) {
|
||||
throw new IOException(command + " called on bad process");
|
||||
}
|
||||
@ -552,8 +553,8 @@ public class DecompileProcess {
|
||||
* @throws IOException
|
||||
* @throws DecompileException
|
||||
*/
|
||||
public synchronized LimitedByteBuffer sendCommand2Params(String command, String param1, String param2)
|
||||
throws IOException, DecompileException {
|
||||
public synchronized LimitedByteBuffer sendCommand2Params(String command, String param1,
|
||||
String param2) throws IOException, DecompileException {
|
||||
if (!statusGood) {
|
||||
throw new IOException(command + " called on bad process");
|
||||
}
|
||||
@ -591,8 +592,8 @@ public class DecompileProcess {
|
||||
* @throws IOException
|
||||
* @throws DecompileException
|
||||
*/
|
||||
public synchronized LimitedByteBuffer sendCommand1Param(String command, String param1) throws IOException,
|
||||
DecompileException {
|
||||
public synchronized LimitedByteBuffer sendCommand1Param(String command, String param1)
|
||||
throws IOException, DecompileException {
|
||||
if (!statusGood) {
|
||||
throw new IOException(command + " called on bad process");
|
||||
}
|
||||
@ -671,7 +672,7 @@ public class DecompileProcess {
|
||||
private void getPcodeInject(int type) throws IOException {
|
||||
String name = readQueryString();
|
||||
String context = readQueryString();
|
||||
String res = callback.getPcodeInject(name, context,type);
|
||||
String res = callback.getPcodeInject(name, context, type);
|
||||
write(query_response_start);
|
||||
if ((res != null) && (res.length() != 0)) {
|
||||
writeString(res);
|
||||
@ -683,7 +684,7 @@ public class DecompileProcess {
|
||||
String liststring = readQueryString();
|
||||
String[] split = liststring.split(",");
|
||||
long[] refs = new long[split.length];
|
||||
for(int i=0;i<split.length;++i) {
|
||||
for (int i = 0; i < split.length; ++i) {
|
||||
refs[i] = Long.parseUnsignedLong(split[i], 16);
|
||||
}
|
||||
String res = callback.getCPoolRef(refs);
|
||||
@ -691,7 +692,7 @@ public class DecompileProcess {
|
||||
if ((res != null) && (res.length() != 0)) {
|
||||
writeString(res);
|
||||
}
|
||||
write(query_response_end);
|
||||
write(query_response_end);
|
||||
}
|
||||
|
||||
private void getMappedSymbolsXML() throws IOException {
|
||||
|
@ -24,19 +24,19 @@ import ghidra.util.Msg;
|
||||
/**
|
||||
* Factory that returns a DecompileProcess.
|
||||
*/
|
||||
class DecompileProcessFactory {
|
||||
public class DecompileProcessFactory {
|
||||
|
||||
private static String exepath;
|
||||
private static final String EXECNAME = "decompile";
|
||||
private static final String WIN32_EXECNAME = "decompile.exe";
|
||||
|
||||
synchronized static DecompileProcess get() {
|
||||
public synchronized static DecompileProcess get() {
|
||||
getExePath();
|
||||
DecompileProcess currentProcess = new DecompileProcess(exepath);
|
||||
return currentProcess;
|
||||
}
|
||||
|
||||
synchronized static void release(DecompileProcess dp) {
|
||||
public synchronized static void release(DecompileProcess dp) {
|
||||
dp.dispose();
|
||||
}
|
||||
|
||||
|
@ -89,4 +89,14 @@ class Decompiler {
|
||||
cancelCurrentAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the native decompiler process. Call this method when the decompiler's view
|
||||
* of a program has been invalidated, such as when a new overlay space has been added.
|
||||
*/
|
||||
public void resetDecompiler() {
|
||||
if (cachedDecompInterface != null) {
|
||||
cachedDecompInterface.resetDecompiler();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -155,6 +155,14 @@ public class DecompilerController {
|
||||
decompilerPanel.setMouseNavigationEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the native decompiler process. Call this method when the decompiler's view
|
||||
* of a program has been invalidated, such as when a new overlay space has been added.
|
||||
*/
|
||||
public void resetDecompiler() {
|
||||
decompilerMgr.resetDecompiler();
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Methods call by the DecompilerManager
|
||||
//==================================================================================================
|
||||
@ -296,4 +304,5 @@ public class DecompilerController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -71,6 +71,14 @@ public class DecompilerManager {
|
||||
return runManager.getMonitorComponent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the native decompiler process. Call this method when the decompiler's view
|
||||
* of a program has been invalidated, such as when a new overlay space has been added.
|
||||
*/
|
||||
public void resetDecompiler() {
|
||||
decompiler.resetDecompiler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a new decompile be scheduled. If a current decompile is already in progress,
|
||||
* the new request is checked to see if represents the same function. If so, only the
|
||||
|
@ -44,8 +44,8 @@ import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.util.*;
|
||||
import ghidra.util.HelpLocation;
|
||||
import ghidra.util.Swing;
|
||||
import ghidra.util.bean.field.AnnotatedTextFieldElement;
|
||||
@ -104,7 +104,7 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
|
||||
|
||||
private ViewerPosition pendingViewerPosition;
|
||||
|
||||
private SwingUpdateManager swingUpdateManager;
|
||||
private SwingUpdateManager redecompilerUpdater;
|
||||
private ServiceListener serviceListener = new ServiceListener() {
|
||||
|
||||
@Override
|
||||
@ -156,7 +156,7 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
|
||||
setHelpLocation(new HelpLocation(plugin.getName(), "Decompiler"));
|
||||
addToTool();
|
||||
|
||||
swingUpdateManager = new SwingUpdateManager(500, 5000, () -> doRefresh());
|
||||
redecompilerUpdater = new SwingUpdateManager(500, 5000, () -> doRefresh());
|
||||
|
||||
plugin.getTool().addServiceListener(serviceListener);
|
||||
}
|
||||
@ -282,7 +282,14 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
|
||||
if (!isVisible()) {
|
||||
return;
|
||||
}
|
||||
swingUpdateManager.update();
|
||||
|
||||
if (ev.containsEvent(ChangeManager.DOCR_MEMORY_BLOCK_ADDED) ||
|
||||
ev.containsEvent(ChangeManager.DOCR_MEMORY_BLOCK_REMOVED)) {
|
||||
controller.resetDecompiler();
|
||||
}
|
||||
|
||||
redecompilerUpdater.update();
|
||||
|
||||
}
|
||||
|
||||
private void doRefresh() {
|
||||
@ -326,7 +333,7 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
|
||||
swingUpdateManager.dispose();
|
||||
redecompilerUpdater.dispose();
|
||||
|
||||
if (clipboardService != null) {
|
||||
clipboardService.deRegisterClipboardContentProvider(clipboardProvider);
|
||||
|
@ -52,6 +52,8 @@ 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
|
||||
private Map<CompilerSpecID, SleighCompilerSpecDescription> compilerSpecDescriptions;
|
||||
private HashMap<CompilerSpecID, BasicCompilerSpec> compilerSpecs;
|
||||
private List<InjectPayloadSleigh> additionalInject = null;
|
||||
@ -805,6 +807,10 @@ public class SleighLanguage implements Language {
|
||||
|
||||
private void restoreXml(XmlPullParser parser) throws UnknownInstructionException {
|
||||
XmlElement el = parser.start("sleigh");
|
||||
int version = SpecXmlUtils.decodeInt(el.getAttribute("version"));
|
||||
if (version != SLA_FORMAT_VERSION) {
|
||||
throw new SleighException(".sla file for " + getLanguageID() + " has the wrong format");
|
||||
}
|
||||
boolean isBigEndian = SpecXmlUtils.decodeBoolean(el.getAttribute("bigendian"));
|
||||
// check the instruction endianess, not the program data endianess
|
||||
if (isBigEndian ^ description.getInstructionEndian().isBigEndian()) {
|
||||
@ -840,8 +846,16 @@ public class SleighLanguage implements Language {
|
||||
// Slot zero is always the constant space
|
||||
AddressSpace constspc = new GenericAddressSpace("const", 64, AddressSpace.TYPE_CONSTANT, 0);
|
||||
spacetable.put("const", constspc);
|
||||
//spacetable.put("OTHER", AddressSpace.OTHER_SPACE);
|
||||
default_space = null;
|
||||
XmlElement subel;
|
||||
XmlElement subel = parser.peek();
|
||||
if (subel.getName().equals("space_other")) { // tag must be present
|
||||
parser.discardSubTree(); // We don't process it
|
||||
// Instead the ProgramAddressFactory maps in the static OTHER_SPACE automatically
|
||||
}
|
||||
else {
|
||||
throw new SleighException(".sla file missing required OTHER space tag");
|
||||
}
|
||||
while ((subel = parser.softStart("space", "space_unique")) != null) {
|
||||
String name = subel.getAttribute("name");
|
||||
int index = SpecXmlUtils.decodeInt(subel.getAttribute("index"));
|
||||
@ -1319,14 +1333,13 @@ public class SleighLanguage implements Language {
|
||||
int delay;
|
||||
boolean physical;
|
||||
boolean global;
|
||||
int index = 1;
|
||||
|
||||
for (AddressSpace element : spclist) {
|
||||
if ((element instanceof OverlayAddressSpace) &&
|
||||
(element.getType() == AddressSpace.TYPE_RAM)) {
|
||||
if ((element instanceof OverlayAddressSpace)) {
|
||||
OverlayAddressSpace ospace = (OverlayAddressSpace) element;
|
||||
resBuf.append("<space_overlay");
|
||||
SpecXmlUtils.encodeStringAttribute(resBuf, "name", ospace.getName());
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", index++);
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", ospace.getUnique());
|
||||
SpecXmlUtils.encodeStringAttribute(resBuf, "base",
|
||||
ospace.getOverlayedSpace().getName());
|
||||
resBuf.append("/>\n");
|
||||
@ -1351,12 +1364,18 @@ public class SleighLanguage implements Language {
|
||||
physical = true;
|
||||
global = false;
|
||||
break;
|
||||
case AddressSpace.TYPE_OTHER:
|
||||
tag = "space_other";
|
||||
delay = 0;
|
||||
physical = true;
|
||||
global = true;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
resBuf.append("<").append(tag);
|
||||
SpecXmlUtils.encodeStringAttribute(resBuf, "name", element.getName());
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", index++);
|
||||
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", element.getUnique());
|
||||
|
||||
int size = element.getSize(); // Size in bits
|
||||
if (size == 20) {
|
||||
|
@ -31,6 +31,8 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
|
||||
|
||||
// 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
|
||||
private VectorSTL<String> userop = new VectorSTL<>();
|
||||
private address_set varnode_xref = new address_set(); // Cross-reference registers by address
|
||||
protected SubtableSymbol root;
|
||||
@ -187,6 +189,7 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
|
||||
|
||||
public void saveXml(PrintStream s) {
|
||||
s.append("<sleigh");
|
||||
XmlUtils.a_v_i(s, "version", SLA_FORMAT_VERSION);
|
||||
XmlUtils.a_v_b(s, "bigendian", isBigEndian());
|
||||
XmlUtils.a_v_i(s, "align", alignment);
|
||||
XmlUtils.a_v_u(s, "uniqbase", getUniqueBase());
|
||||
|
@ -36,6 +36,7 @@ import ghidra.pcodeCPort.slghsymbol.*;
|
||||
import ghidra.pcodeCPort.space.*;
|
||||
import ghidra.pcodeCPort.utils.Utils;
|
||||
import ghidra.pcodeCPort.xml.DocumentStorage;
|
||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
||||
import ghidra.sleigh.grammar.Location;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
@ -273,10 +274,15 @@ public class SleighCompile extends SleighBase {
|
||||
// Some predefined symbols
|
||||
root = new SubtableSymbol(location, "instruction"); // Base constructors
|
||||
symtab.addSymbol(root);
|
||||
insertSpace(new ConstantSpace(this, "const", 0));
|
||||
insertSpace(new ConstantSpace(this, "const", BasicCompilerSpec.CONSTANT_SPACE_INDEX));
|
||||
SpaceSymbol spacesym = new SpaceSymbol(location, getConstantSpace()); // Constant
|
||||
// space
|
||||
symtab.addSymbol(spacesym);
|
||||
OtherSpace otherSpace = new OtherSpace(this, BasicCompilerSpec.OTHER_SPACE_NAME,
|
||||
BasicCompilerSpec.OTHER_SPACE_INDEX);
|
||||
insertSpace(otherSpace);
|
||||
spacesym = new SpaceSymbol(location, otherSpace);
|
||||
symtab.addSymbol(spacesym);
|
||||
insertSpace(new UniqueSpace(this, "unique", numSpaces(), 0));
|
||||
spacesym = new SpaceSymbol(location, getUniqueSpace()); // Temporary register
|
||||
// space
|
||||
|
@ -19,6 +19,11 @@ import java.io.PrintStream;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.jdom.Element;
|
||||
|
||||
import ghidra.pcodeCPort.error.LowlevelError;
|
||||
import ghidra.pcodeCPort.pcoderaw.VarnodeData;
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
import ghidra.pcodeCPort.utils.*;
|
||||
/// \brief A region where processor data is stored
|
||||
///
|
||||
/// An AddrSpace (Address Space) is an arbitrary sequence of
|
||||
@ -59,9 +64,18 @@ public class AddrSpace {
|
||||
|
||||
public static final AddrSpace MIN_SPACE = new AddrSpace("MIN_SPACE", -1);
|
||||
public static final AddrSpace MAX_SPACE = new AddrSpace("MAX_SPACE", Integer.MAX_VALUE);
|
||||
protected static final int big_endian = 1;
|
||||
protected static final int heritaged = 2;
|
||||
public static final int hasphysical = 4;
|
||||
|
||||
//see space.hh
|
||||
protected static final int big_endian = 1; // Space is big endian if set, little endian otherwise
|
||||
protected static final int heritaged = 2; // This space is heritaged
|
||||
protected static final int does_deadcode = 4; // Dead-code analysis is done on this space
|
||||
protected static final int programspecific = 8; // Space is specific to a particular loadimage
|
||||
protected static final int reverse_justification = 16; // Justification within aligned word is opposite of endianness
|
||||
protected static final int overlay = 32; // This space is an overlay of another space
|
||||
protected static final int overlaybase = 64; // This is the base space for overlay space(s)
|
||||
protected static final int truncated = 128; // Space is truncated from its original size, expect pointers larger than this size
|
||||
public static final int hasphysical = 256; // Has physical memory associated with it
|
||||
protected static final int is_otherspace = 512; // Quick check for OtherSpace
|
||||
|
||||
private int flags;
|
||||
private long highest;
|
||||
@ -188,6 +202,10 @@ public class AddrSpace {
|
||||
return ((flags & big_endian) != 0);
|
||||
}
|
||||
|
||||
public boolean isOtherSpace() {
|
||||
return ((flags & is_otherspace) != 0);
|
||||
}
|
||||
|
||||
public AddrSpace getContain() {
|
||||
return null;
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
/* ###
|
||||
* 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.pcodeCPort.space;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import ghidra.pcodeCPort.translate.Translate;
|
||||
|
||||
public class OtherSpace extends AddrSpace {
|
||||
|
||||
public OtherSpace(Translate t, String nm, int ind) {
|
||||
super(t, spacetype.IPTR_PROCESSOR, nm, 8, 1, ind, 0, 0);
|
||||
clearFlags(heritaged);
|
||||
setFlags(is_otherspace);
|
||||
}
|
||||
|
||||
public OtherSpace(Translate t) {
|
||||
super(t, spacetype.IPTR_PROCESSOR);
|
||||
clearFlags(heritaged);
|
||||
setFlags(is_otherspace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int printRaw(PrintStream s, long offset) {
|
||||
s.append("0x");
|
||||
s.append(Long.toHexString(offset));
|
||||
return getTrans().getDefaultSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveXml(PrintStream s) {
|
||||
s.print("<space_other");
|
||||
save_basic_attributes(s);
|
||||
s.println("/>");
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ import ghidra.pcodeCPort.pcoderaw.VarnodeData;
|
||||
import ghidra.pcodeCPort.space.*;
|
||||
import ghidra.pcodeCPort.utils.AddrSpaceToIdSymmetryMap;
|
||||
import ghidra.pcodeCPort.xml.DocumentStorage;
|
||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
||||
|
||||
public abstract class Translate implements BasicSpaceProvider {
|
||||
|
||||
@ -245,6 +246,9 @@ public abstract class Translate implements BasicSpaceProvider {
|
||||
else if ("space_unique".equals(tp)) {
|
||||
res = new UniqueSpace(this);
|
||||
}
|
||||
else if ("space_other".equals(tp)) {
|
||||
res = new OtherSpace(this);
|
||||
}
|
||||
else {
|
||||
res = new AddrSpace(this, spacetype.IPTR_PROCESSOR);
|
||||
}
|
||||
@ -255,7 +259,11 @@ public abstract class Translate implements BasicSpaceProvider {
|
||||
|
||||
protected void restoreXmlSpaces(Element el) {
|
||||
// The first space should always be the constant space
|
||||
insertSpace(new ConstantSpace(this, "const", 0));
|
||||
insertSpace(new ConstantSpace(this, "const", BasicCompilerSpec.CONSTANT_SPACE_INDEX));
|
||||
|
||||
// The second space should always be the other space
|
||||
insertSpace(new OtherSpace(this, BasicCompilerSpec.OTHER_SPACE_NAME,
|
||||
BasicCompilerSpec.OTHER_SPACE_INDEX));
|
||||
|
||||
String defname = el.getAttributeValue("defaultspace");
|
||||
List<?> children = el.getChildren();
|
||||
@ -399,6 +407,11 @@ public abstract class Translate implements BasicSpaceProvider {
|
||||
}
|
||||
// fallthru
|
||||
case IPTR_PROCESSOR:
|
||||
if (spc.isOtherSpace()) {
|
||||
if (spc.getIndex() != BasicCompilerSpec.OTHER_SPACE_INDEX) {
|
||||
throw new LowlevelError("OTHER space must be assigned index 1");
|
||||
}
|
||||
}
|
||||
for (AddrSpace space : baselist) {
|
||||
if (space.getName().equals(spc.getName())) {
|
||||
duplicatedefine = true;
|
||||
|
@ -101,11 +101,13 @@ public class ProgramAddressFactory extends DefaultAddressFactory {
|
||||
addAddressSpace(ovSpace);
|
||||
}
|
||||
|
||||
public OverlayAddressSpace addOverlayAddressSpace(String name,AddressSpace originalSpace,
|
||||
public OverlayAddressSpace addOverlayAddressSpace(String name, AddressSpace originalSpace,
|
||||
long minOffset, long maxOffset) throws DuplicateNameException {
|
||||
int unique = 0;
|
||||
if (originalSpace.getType() == AddressSpace.TYPE_RAM)
|
||||
if (originalSpace.getType() == AddressSpace.TYPE_RAM ||
|
||||
originalSpace.getType() == AddressSpace.TYPE_OTHER) {
|
||||
unique = getNextUniqueID();
|
||||
}
|
||||
OverlayAddressSpace ovSpace =
|
||||
new OverlayAddressSpace(name, originalSpace, unique, minOffset, maxOffset);
|
||||
addAddressSpace(ovSpace);
|
||||
@ -145,15 +147,16 @@ public class ProgramAddressFactory extends DefaultAddressFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renameOverlaySpace(String oldName, String newName) throws DuplicateNameException {
|
||||
protected void renameOverlaySpace(String oldName, String newName)
|
||||
throws DuplicateNameException {
|
||||
super.renameOverlaySpace(oldName, newName);
|
||||
}
|
||||
|
||||
private int getNextUniqueID() {
|
||||
int maxID = 0;
|
||||
AddressSpace[] spaces = getAllAddressSpaces();
|
||||
for (int i = 0; i < spaces.length; i++) {
|
||||
maxID = Math.max(maxID, spaces[i].getUnique());
|
||||
for (AddressSpace space : spaces) {
|
||||
maxID = Math.max(maxID, space.getUnique());
|
||||
}
|
||||
return maxID + 1;
|
||||
}
|
||||
|
@ -1776,6 +1776,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
|
||||
finally {
|
||||
program.setEventsEnabled(true);
|
||||
}
|
||||
|
||||
fireBlockRemoved(startAddress);
|
||||
if (startAddress.getAddressSpace().isOverlaySpace()) {
|
||||
checkRemoveAddressSpace(startAddress.getAddressSpace());
|
||||
|
@ -17,6 +17,7 @@ package ghidra.program.model.address;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import ghidra.program.model.lang.BasicCompilerSpec;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
/**
|
||||
@ -66,39 +67,39 @@ public interface AddressSpace extends Comparable<AddressSpace> {
|
||||
|
||||
/**
|
||||
* The <code>OTHER_SPACE</code> is used to store data from the original program file that doesn't
|
||||
* get loaded into the final memory image.
|
||||
* get loaded into the final memory image and for user-defined spaces.
|
||||
*/
|
||||
public static final AddressSpace OTHER_SPACE = new GenericAddressSpace("OTHER", 64, TYPE_OTHER,
|
||||
0);
|
||||
public static final AddressSpace OTHER_SPACE = new GenericAddressSpace(
|
||||
BasicCompilerSpec.OTHER_SPACE_NAME, 64, TYPE_OTHER, BasicCompilerSpec.OTHER_SPACE_INDEX);
|
||||
|
||||
/**
|
||||
* The <code>EXTERNAL_SPACE</code> is used to contain all external locations (i.e., data and functions)
|
||||
* defined within a given library namespace. All external locations within a program
|
||||
* are given a unique offset within the EXTERNAL space.
|
||||
*/
|
||||
public static final AddressSpace EXTERNAL_SPACE = new GenericAddressSpace("EXTERNAL", 32,
|
||||
TYPE_EXTERNAL, 0);
|
||||
public static final AddressSpace EXTERNAL_SPACE =
|
||||
new GenericAddressSpace("EXTERNAL", 32, TYPE_EXTERNAL, 0);
|
||||
|
||||
/**
|
||||
* The <code>VARIABLE_SPACE</code> is used to contain all variables and parameters
|
||||
* defined within a given namespace (i.e., function). All variables within a program
|
||||
* are given a unique offset within the VARIABLE space.
|
||||
*/
|
||||
public static final AddressSpace VARIABLE_SPACE = new GenericAddressSpace("VARIABLE", 32,
|
||||
TYPE_VARIABLE, 0);
|
||||
public static final AddressSpace VARIABLE_SPACE =
|
||||
new GenericAddressSpace("VARIABLE", 32, TYPE_VARIABLE, 0);
|
||||
|
||||
/**
|
||||
* The <code>HASH_SPACE</code> provides a 60-bit space for encoding of unique hashcodes.
|
||||
*/
|
||||
public static final AddressSpace HASH_SPACE = new GenericAddressSpace("HASH", 60, TYPE_UNKNOWN,
|
||||
0);
|
||||
public static final AddressSpace HASH_SPACE =
|
||||
new GenericAddressSpace("HASH", 60, TYPE_UNKNOWN, 0);
|
||||
|
||||
/**
|
||||
* A language may only define a single REGISTER space. If one is not defined, this
|
||||
* DEFAULT_REGISTER_SPACE definition will be used.
|
||||
*/
|
||||
public static final AddressSpace DEFAULT_REGISTER_SPACE = new GenericAddressSpace("REGISTER",
|
||||
32, TYPE_REGISTER, 0);
|
||||
public static final AddressSpace DEFAULT_REGISTER_SPACE =
|
||||
new GenericAddressSpace("REGISTER", 32, TYPE_REGISTER, 0);
|
||||
|
||||
/**
|
||||
* Returns the name of this address space.
|
||||
|
@ -46,6 +46,11 @@ public class BasicCompilerSpec implements CompilerSpec {
|
||||
|
||||
public static final String STACK_SPACE_NAME = "stack";
|
||||
public static final String JOIN_SPACE_NAME = "join";
|
||||
public static final String OTHER_SPACE_NAME = "OTHER";
|
||||
|
||||
//must match AddrSpace enum (see space.hh)
|
||||
public static final int CONSTANT_SPACE_INDEX = 0;
|
||||
public static final int OTHER_SPACE_INDEX = 1;
|
||||
|
||||
private final CompilerSpecDescription description;
|
||||
private String sourceName;
|
||||
@ -117,8 +122,9 @@ public class BasicCompilerSpec implements CompilerSpec {
|
||||
parseException = e;
|
||||
Throwable cause = e.getCause(); // Recover the cause (from the validator exception)
|
||||
if (cause != null) {
|
||||
if (cause instanceof SAXException || cause instanceof IOException)
|
||||
if (cause instanceof SAXException || cause instanceof IOException) {
|
||||
parseException = (Exception) cause;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
@ -361,6 +367,9 @@ public class BasicCompilerSpec implements CompilerSpec {
|
||||
else {
|
||||
space = language.getAddressFactory().getAddressSpace(spaceName);
|
||||
}
|
||||
if (spaceName.equals(OTHER_SPACE_NAME)) {
|
||||
space = AddressSpace.OTHER_SPACE;
|
||||
}
|
||||
if (space == null) {
|
||||
throw new SleighException("Unknown address space: " + spaceName);
|
||||
}
|
||||
|
@ -406,8 +406,13 @@ public class Varnode {
|
||||
public static void appendSpaceOffset(StringBuilder buf, Address addr) {
|
||||
AddressSpace space = addr.getAddressSpace();
|
||||
if (space.isOverlaySpace()) {
|
||||
space = space.getPhysicalSpace();
|
||||
addr = space.getAddress(addr.getOffset());
|
||||
//if the address is contained within the overlay space, stay in the overlay
|
||||
//otherwise default to the underlying space
|
||||
if (addr.compareTo(space.getMinAddress()) < 0 ||
|
||||
addr.compareTo(space.getMaxAddress()) > 0) {
|
||||
space = space.getPhysicalSpace();
|
||||
addr = space.getAddress(addr.getOffset());
|
||||
}
|
||||
}
|
||||
SpecXmlUtils.encodeStringAttribute(buf, "space", space.getName());
|
||||
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "offset", addr.getUnsignedOffset());
|
||||
|
@ -38,7 +38,7 @@ define register offset=0x5000 size=$(SIZE) [ TPC1 TPC2 TPC3 TPC4
|
||||
TT1 TT2 TT3 TT4
|
||||
TCK TBA PSTATE TL
|
||||
PIL CWP CANSAVE CANRESTORE CLEANWIN
|
||||
OTHER WINWSTATE FQ VER GL ];
|
||||
OTHERWIN WSTATE FQ VER GL ];
|
||||
|
||||
define register offset=0x6000 size=$(SIZE) [ HPSTATE1 HPSTATE2 HPSTATE3 HPSTATE4
|
||||
HTSTATE1 HTSTATE2 HTSTATE3 HTSTATE4
|
||||
@ -939,7 +939,7 @@ membar_mask: is cmask & mmask { tmp:1 = (cmask << 4) | mmask; export tmp; }
|
||||
:sir simm13 is op=0x2 & rd=0xF & op3=0x30 & rs1=0x0 & i=1 & simm13 { reset(); }
|
||||
|
||||
attach variables [ prs1 prd ] [ TPC1 TNPC1 TSTATE1 TT1 TCK TBA PSTATE TL
|
||||
PIL CWP CANSAVE CANRESTORE CLEANWIN OTHER WINWSTATE FQ
|
||||
PIL CWP CANSAVE CANRESTORE CLEANWIN OTHERWIN WSTATE FQ
|
||||
GL _ _ _ _ _ _ _ _ _ _ _ _ _ _ VER ];
|
||||
|
||||
tnpc: "%tnpc" is fcn {local reloc = zext(TL == 1)*&TNPC1 + zext(TL == 2)*&TNPC2 + zext(TL == 3)*&TNPC3 + zext(TL ==4)*&TNPC4; export reloc;}
|
||||
|
@ -24,6 +24,7 @@
|
||||
</data_organization>
|
||||
<global>
|
||||
<range space="ram"/>
|
||||
<range space="OTHER"/>
|
||||
</global>
|
||||
<stackpointer register="ESP" space="ram"/>
|
||||
<returnaddress>
|
||||
|
Loading…
Reference in New Issue
Block a user