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:
caheckman 2019-05-24 17:47:04 -04:00 committed by James
parent cf47a2ee57
commit 612c0d6f3e
40 changed files with 545 additions and 213 deletions

View file

@ -483,7 +483,7 @@ class AddBlockDialog extends DialogComponentProvider implements ChangeListener {
addrField = new AddressInput(); addrField = new AddressInput();
addrField.setName("Start Addr"); addrField.setName("Start Addr");
addrFactory = model.getProgram().getAddressFactory(); addrFactory = model.getProgram().getAddressFactory();
addrField.setAddressFactory(addrFactory, true); addrField.setAddressFactory(addrFactory, true, true);
addrField.addChangeListener(ev -> addrChanged()); addrField.addChangeListener(ev -> addrChanged());
return addrField; return addrField;
} }

View file

@ -258,7 +258,7 @@ class AddBlockModel {
message = ""; message = "";
isValid = hasValidName() && hasValidStartAddress() && hasValidLength() && isValid = hasValidName() && hasValidStartAddress() && hasValidLength() &&
hasNoMemoryConflicts() && hasMappedAddressIfNeeded() && hasUniqueNameIfOverlay() && hasNoMemoryConflicts() && hasMappedAddressIfNeeded() && hasUniqueNameIfOverlay() &&
hasInitialValueIfNeeded() && hasFileBytesInfoIfNeeded(); hasInitialValueIfNeeded() && hasFileBytesInfoIfNeeded() && isOverlayIfOtherSpace();
} }
private boolean hasFileBytesInfoIfNeeded() { private boolean hasFileBytesInfoIfNeeded() {
@ -313,6 +313,17 @@ class AddBlockModel {
return true; 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() { private boolean hasMappedAddressIfNeeded() {
if (blockType == MemoryBlockType.BIT_MAPPED || blockType == MemoryBlockType.BYTE_MAPPED) { if (blockType == MemoryBlockType.BIT_MAPPED || blockType == MemoryBlockType.BYTE_MAPPED) {
if (baseAddr == null) { if (baseAddr == null) {
@ -323,6 +334,7 @@ class AddBlockModel {
} }
return true; return true;
} }
private boolean hasNoMemoryConflicts() { private boolean hasNoMemoryConflicts() {
if (blockType == MemoryBlockType.OVERLAY) { if (blockType == MemoryBlockType.OVERLAY) {
return true; return true;

View file

@ -82,8 +82,8 @@ public class MoveBlockDialog extends DialogComponentProvider implements MoveBloc
changing = true; changing = true;
if (!isVisible()) { if (!isVisible()) {
AddressFactory factory = model.getAddressFactory(); AddressFactory factory = model.getAddressFactory();
newStartField.setAddressFactory(factory, true); newStartField.setAddressFactory(factory, true, false);
newEndField.setAddressFactory(factory, true); newEndField.setAddressFactory(factory, true, false);
} }
Address newStart = model.getNewStartAddress(); Address newStart = model.getNewStartAddress();
if (newStart != null) { if (newStart != null) {

View file

@ -206,7 +206,7 @@ class EditMemoryReferencePanel extends EditReferencePanel {
toAddr = toAddr.subtractWrap(defaultOffset); toAddr = toAddr.subtractWrap(defaultOffset);
} }
toAddressField.setAddressFactory(fromCu.getProgram().getAddressFactory(), false); toAddressField.setAddressFactory(fromCu.getProgram().getAddressFactory(), false, false);
toAddressField.setAddress(toAddr); toAddressField.setAddress(toAddr);
enableOffsetField(editReference.isOffsetReference()); enableOffsetField(editReference.isOffsetReference());
@ -231,7 +231,7 @@ class EditMemoryReferencePanel extends EditReferencePanel {
addrHistoryButton.setEnabled(getAddressHistorySize(p) != 0); addrHistoryButton.setEnabled(getAddressHistorySize(p) != 0);
toAddressField.setAddressFactory(p.getAddressFactory(), false); toAddressField.setAddressFactory(p.getAddressFactory(), false, false);
Address cuAddr = fromCu.getMinAddress(); Address cuAddr = fromCu.getMinAddress();

View file

@ -163,7 +163,7 @@ public class AddressInput extends JPanel {
* if there is more than one space. * if there is more than one space.
*/ */
public void setAddressFactory(AddressFactory factory) { public void setAddressFactory(AddressFactory factory) {
setAddressFactory(factory, false); setAddressFactory(factory, false, false);
} }
public AddressFactory getAddressFactory() { public AddressFactory getAddressFactory() {
@ -176,8 +176,11 @@ public class AddressInput extends JPanel {
* @param factory address factory to use * @param factory address factory to use
* @param filterOverlaySpaces true if overlay spaces should not appear in the combo box * @param filterOverlaySpaces true if overlay spaces should not appear in the combo box
* for the address spaces. * 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; this.addrFactory = factory;
AddressSpace[] spaces = factory.getAddressSpaces(); AddressSpace[] spaces = factory.getAddressSpaces();
@ -187,21 +190,19 @@ public class AddressInput extends JPanel {
FontMetrics fm = combo.getFontMetrics(combo.getFont()); FontMetrics fm = combo.getFontMetrics(combo.getFont());
int width = 0; int width = 0;
for (int i = 0; i < spaces.length; i++) { for (AddressSpace space : spaces) {
if (filterOverlaySpaces && spaces[i].isOverlaySpace()) { if (filterOverlaySpaces && space.isOverlaySpace()) {
continue; continue;
} }
// We don't want to let users create functions in certain memory spaces (eg: OTHER), if (!allowOtherSpace && space.equals(AddressSpace.OTHER_SPACE)) {
// so don't populate the model with them.
if (!spaces[i].isLoadedMemorySpace()) {
continue; continue;
} }
String s = spaces[i].toString(); String s = space.toString();
width = Math.max(width, fm.stringWidth(s)); 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 // // Commented out the following 2 lines since they were causing the Combo to only

View file

@ -206,6 +206,7 @@ AddrSpace *Architecture::getSpaceBySpacebase(const Address &loc,int4 size) const
int4 sz = numSpaces(); int4 sz = numSpaces();
for(int4 i=0;i<sz;++i) { for(int4 i=0;i<sz;++i) {
id = getSpace(i); id = getSpace(i);
if (id == (AddrSpace *)0) continue;
int4 numspace = id->numSpacebase(); int4 numspace = id->numSpacebase();
for(int4 j=0;j<numspace;++j) { for(int4 j=0;j<numspace;++j) {
const VarnodeData &point(id->getSpacebase(j)); const VarnodeData &point(id->getSpacebase(j));
@ -337,6 +338,7 @@ void Architecture::globalify(void)
for(int4 i=0;i<nm;++i) { for(int4 i=0;i<nm;++i) {
AddrSpace *spc = getSpace(i); AddrSpace *spc = getSpace(i);
if (spc == (AddrSpace *)0) continue;
if ((spc->getType() != IPTR_PROCESSOR)&&(spc->getType() != IPTR_SPACEBASE)) continue; if ((spc->getType() != IPTR_PROCESSOR)&&(spc->getType() != IPTR_SPACEBASE)) continue;
symboltab->addRange(scope,spc,(uintb)0,spc->getHighest()); symboltab->addRange(scope,spc,(uintb)0,spc->getHighest());
} }
@ -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) // We need to duplicate the range being marked as global into the overlay space(s)
int4 num = numSpaces(); int4 num = numSpaces();
for(int4 i=0;i<num;++i) { for(int4 i=0;i<num;++i) {
OverlaySpace *ospc = (OverlaySpace *)getSpace(i); OverlaySpace *ospc = (OverlaySpace *)getSpace(i);
if (!ospc->isOverlay()) continue; if (ospc == (AddrSpace *)0 || !ospc->isOverlay()) continue;
if (ospc->getBaseSpace() != range.getSpace()) continue; if (ospc->getBaseSpace() != range.getSpace()) continue;
symboltab->addRange(scope,ospc,range.getFirst(),range.getLast()); 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 /// This applies info from a \<readonly> tag marking a specific region
/// of the executable as \e read-only. /// of the executable as \e read-only.
/// \param el is the XML element /// \param el is the XML element
@ -835,7 +855,7 @@ void Architecture::parseDeadcodeDelay(const Element *el)
int4 delay = -1; int4 delay = -1;
s >> delay; s >> delay;
if (delay >= 0) if (delay >= 0)
setDeadcodeDelay(spc->getIndex(),delay); setDeadcodeDelay(spc,delay);
else else
throw LowlevelError("Bad <deadcodedelay> tag"); throw LowlevelError("Bad <deadcodedelay> tag");
} }
@ -1031,12 +1051,14 @@ void Architecture::parseCompilerConfig(DocumentStorage &store)
else if (elname == "deadcodedelay") else if (elname == "deadcodedelay")
parseDeadcodeDelay(*iter); parseDeadcodeDelay(*iter);
} }
// <global> tags instantiate the base symbol table // <global> tags instantiate the base symbol table
// They need to know about all spaces, so it must come // They need to know about all spaces, so it must come
// after parsing of <stackpointer> and <spacebase> // after parsing of <stackpointer> and <spacebase>
for(int4 i=0;i<globaltags.size();++i) for(int4 i=0;i<globaltags.size();++i)
parseGlobal(globaltags[i]); parseGlobal(globaltags[i]);
addOtherSpace();
if (defaultfp == (ProtoModel *)0) { if (defaultfp == (ProtoModel *)0) {
if (protoModels.size() == 1) if (protoModels.size() == 1)
defaultfp = (*protoModels.begin()).second; defaultfp = (*protoModels.begin()).second;

View file

@ -255,6 +255,7 @@ protected:
void parseProtoEval(const Element *el); ///< Apply prototype evaluation configuration void parseProtoEval(const Element *el); ///< Apply prototype evaluation configuration
void parseDefaultProto(const Element *el); ///< Apply default prototype model configuration void parseDefaultProto(const Element *el); ///< Apply default prototype model configuration
void parseGlobal(const Element *el); ///< Apply global space 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 parseReadOnly(const Element *el); ///< Apply read-only region configuration
void parseVolatile(const Element *el); ///< Apply volatile region configuration void parseVolatile(const Element *el); ///< Apply volatile region configuration
void parseReturnAddress(const Element *el); ///< Apply return address configuration void parseReturnAddress(const Element *el); ///< Apply return address configuration

View file

@ -367,10 +367,11 @@ void ConditionalExecution::buildHeritageArray(void)
{ {
heritageyes.clear(); heritageyes.clear();
Architecture *glb = fd->getArch(); Architecture *glb = fd->getArch();
heritageyes.resize(glb->numSpaces(),false);
for(int4 i=0;i<glb->numSpaces();++i) { for(int4 i=0;i<glb->numSpaces();++i) {
AddrSpace *spc = glb->getSpace(i); AddrSpace *spc = glb->getSpace(i);
if (spc == (AddrSpace *)0) continue;
int4 index = spc->getIndex(); int4 index = spc->getIndex();
heritageyes.push_back(false);
if (!spc->isHeritaged()) continue; if (!spc->isHeritaged()) continue;
if (fd->numHeritagePasses(spc) > 0) if (fd->numHeritagePasses(spc) > 0)
heritageyes[index] = true; // At least one pass has been performed on the space heritageyes[index] = true; // At least one pass has been performed on the space

View file

@ -2239,6 +2239,7 @@ int4 ActionNameVars::apply(Funcdata &data)
for(int4 i=0;i<manage->numSpaces();++i) { // Build a list of nameable highs for(int4 i=0;i<manage->numSpaces();++i) { // Build a list of nameable highs
spc = manage->getSpace(i); spc = manage->getSpace(i);
if (spc == (AddrSpace *)0) continue;
enditer = data.endLoc(spc); enditer = data.endLoc(spc);
for(iter=data.beginLoc(spc);iter!=enditer;++iter) { for(iter=data.beginLoc(spc);iter!=enditer;++iter) {
Varnode *curvn = *iter; Varnode *curvn = *iter;
@ -3094,7 +3095,7 @@ int4 ActionDeadCode::apply(Funcdata &data)
// Set pre-live registers // Set pre-live registers
for(i=0;i<manage->numSpaces();++i) { for(i=0;i<manage->numSpaces();++i) {
spc = manage->getSpace(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 if (data.deadRemovalAllowed(spc)) continue; // Mark consumed if we have NOT heritaged
viter = data.beginLoc(spc); viter = data.beginLoc(spc);
endviter = data.endLoc(spc); endviter = data.endLoc(spc);
@ -3138,7 +3139,7 @@ int4 ActionDeadCode::apply(Funcdata &data)
for(i=0;i<manage->numSpaces();++i) { for(i=0;i<manage->numSpaces();++i) {
spc = manage->getSpace(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 if (!data.deadRemovalAllowed(spc)) continue; // Don't eliminate if we haven't heritaged
viter = data.beginLoc(spc); viter = data.beginLoc(spc);
endviter = data.endLoc(spc); endviter = data.endLoc(spc);

View file

@ -208,6 +208,7 @@ void Funcdata::spacebase(void)
for(j=0;j<glb->numSpaces();++j) { for(j=0;j<glb->numSpaces();++j) {
spc = glb->getSpace(j); spc = glb->getSpace(j);
if (spc == (AddrSpace *)0) continue;
numspace = spc->numSpacebase(); numspace = spc->numSpacebase();
for(i=0;i<numspace;++i) { for(i=0;i<numspace;++i) {
const VarnodeData &point(spc->getSpacebase(i)); const VarnodeData &point(spc->getSpacebase(i));
@ -617,7 +618,7 @@ void Funcdata::saveXmlTree(ostream &s) const
s << "<varnodes>\n"; s << "<varnodes>\n";
for(int4 i=0;i<glb->numSpaces();++i) { for(int4 i=0;i<glb->numSpaces();++i) {
AddrSpace *base = glb->getSpace(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 iter = vbank.beginLoc(base);
VarnodeLocSet::const_iterator enditer = vbank.endLoc(base); VarnodeLocSet::const_iterator enditer = vbank.endLoc(base);
saveVarnodeXml(s,iter,enditer); saveVarnodeXml(s,iter,enditer);

View file

@ -2212,11 +2212,16 @@ void Heritage::buildInfoList(void)
{ {
if (!infolist.empty()) return; if (!infolist.empty()) return;
AddrSpace *spc;
const AddrSpaceManager *manage = fd->getArch(); const AddrSpaceManager *manage = fd->getArch();
infolist.resize(manage->numSpaces());
for(int4 i=0;i<manage->numSpaces();++i) { for(int4 i=0;i<manage->numSpaces();++i) {
spc = manage->getSpace(i); AddrSpace *spc = manage->getSpace(i);
infolist.push_back(HeritageInfo(spc,spc->getDelay(),spc->getDeadcodeDelay())); 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; VarnodeLocSet::const_iterator iter,enditer;
AddrSpace *space;
HeritageInfo *info; HeritageInfo *info;
Varnode *vn; Varnode *vn;
bool needwarning; bool needwarning;
@ -2235,7 +2239,6 @@ void Heritage::heritage(void)
int4 reprocessStackCount = 0; int4 reprocessStackCount = 0;
AddrSpace *stackSpace = (AddrSpace *)0; AddrSpace *stackSpace = (AddrSpace *)0;
vector<PcodeOp *> freeStores; vector<PcodeOp *> freeStores;
const AddrSpaceManager *manage = fd->getArch();
PreferSplitManager splitmanage; PreferSplitManager splitmanage;
if (maxdepth == -1) // Has a restructure been forced if (maxdepth == -1) // Has a restructure been forced
@ -2246,21 +2249,20 @@ void Heritage::heritage(void)
splitmanage.init(fd,&fd->getArch()->splitrecords); splitmanage.init(fd,&fd->getArch()->splitrecords);
splitmanage.split(); splitmanage.split();
} }
for(int4 i=0;i<manage->numSpaces();++i) { for(int4 i=0;i<infolist.size();++i) {
space = manage->getSpace(i); info = &infolist[i];
if (!space->isHeritaged()) continue; if (!info->isHeritaged()) continue;
info = getInfo(space);
if (pass < info->delay) continue; // It is too soon to heritage this space if (pass < info->delay) continue; // It is too soon to heritage this space
if (!info->loadGuardSearch) { if (!info->loadGuardSearch) {
info->loadGuardSearch = true; info->loadGuardSearch = true;
if (discoverIndexedStackPointers(info->space,freeStores,true)) { if (discoverIndexedStackPointers(info->space,freeStores,true)) {
reprocessStackCount += 1; reprocessStackCount += 1;
stackSpace = space; stackSpace = info->space;
} }
} }
needwarning = false; needwarning = false;
iter = fd->beginLoc(space); iter = fd->beginLoc(info->space);
enditer = fd->endLoc(space); enditer = fd->endLoc(info->space);
while(iter != enditer) { while(iter != enditer) {
vn = *iter++; vn = *iter++;
@ -2343,7 +2345,7 @@ int4 Heritage::numHeritagePasses(AddrSpace *spc) const
{ {
const HeritageInfo *info = getInfo(spc); const HeritageInfo *info = getInfo(spc);
if (info == (const HeritageInfo *)0) if (!info->isHeritaged())
throw LowlevelError("Trying to calculate passes for non-heritaged space"); throw LowlevelError("Trying to calculate passes for non-heritaged space");
return (info->delay - pass); return (info->delay - pass);
} }
@ -2355,8 +2357,6 @@ void Heritage::seenDeadCode(AddrSpace *spc)
{ {
HeritageInfo *info = getInfo(spc); HeritageInfo *info = getInfo(spc);
if (info == (HeritageInfo *)0)
throw LowlevelError("Informed of deadcode removal for non-heritaged space");
info->deadremoved = 1; info->deadremoved = 1;
} }
@ -2369,8 +2369,6 @@ int4 Heritage::getDeadCodeDelay(AddrSpace *spc) const
{ {
const HeritageInfo *info = getInfo(spc); const HeritageInfo *info = getInfo(spc);
if (info == (const HeritageInfo *)0)
throw LowlevelError("Could not get heritage delay for space: "+spc->getName());
return info->deadcodedelay; return info->deadcodedelay;
} }
@ -2383,8 +2381,6 @@ void Heritage::setDeadCodeDelay(AddrSpace *spc,int4 delay)
{ {
HeritageInfo *info = getInfo(spc); HeritageInfo *info = getInfo(spc);
if (info == (HeritageInfo *)0)
throw LowlevelError("Setting heritage delay for non-heritaged space");
if (delay < info->delay) if (delay < info->delay)
throw LowlevelError("Illegal deadcode delay setting"); throw LowlevelError("Illegal deadcode delay setting");
info->deadcodedelay = delay; info->deadcodedelay = delay;
@ -2399,8 +2395,6 @@ bool Heritage::deadRemovalAllowed(AddrSpace *spc) const
{ {
const HeritageInfo *info = getInfo(spc); const HeritageInfo *info = getInfo(spc);
if (info == (HeritageInfo *)0)
throw LowlevelError("Heritage query for non-heritaged space");
return (pass > info->deadcodedelay); return (pass > info->deadcodedelay);
} }
@ -2415,8 +2409,6 @@ bool Heritage::deadRemovalAllowedSeen(AddrSpace *spc)
{ {
HeritageInfo *info = getInfo(spc); HeritageInfo *info = getInfo(spc);
if (info == (HeritageInfo *)0)
throw LowlevelError("Heritage query for non-heritaged space");
bool res = (pass > info->deadcodedelay); bool res = (pass > info->deadcodedelay);
if (res) if (res)
info->deadremoved = 1; info->deadremoved = 1;

View file

@ -90,8 +90,9 @@ class HeritageInfo {
int4 deadremoved; ///< >0 if Varnodes in this space have been eliminated 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 loadGuardSearch; ///< \b true if the search for LOAD ops to guard has been performed
bool warningissued; ///< \b true if warning issued previously bool warningissued; ///< \b true if warning issued previously
HeritageInfo(AddrSpace *spc,int4 dl,int4 dcdl) { void set(AddrSpace *spc,int4 dl,int4 dcdl) {
space=spc; delay=dl; deadcodedelay=dcdl; deadremoved=0; loadGuardSearch=false; warningissued=false; } ///< Constructor 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) { void reset(void) {
deadremoved = 0; deadcodedelay = delay; warningissued = false; loadGuardSearch = false; } ///< Reset deadremoved = 0; deadcodedelay = delay; warningissued = false; loadGuardSearch = false; } ///< Reset
}; };

View file

@ -895,6 +895,7 @@ void IfcPrintSpaces::execute(istream &s)
int4 num = manage->numSpaces(); int4 num = manage->numSpaces();
for(int4 i=0;i<num;++i) { for(int4 i=0;i<num;++i) {
AddrSpace *spc = manage->getSpace(i); AddrSpace *spc = manage->getSpace(i);
if (spc == (AddrSpace *)0) continue;
*status->fileoptr << dec << spc->getIndex() << " : '" << spc->getShortcut() << "' " << spc->getName(); *status->fileoptr << dec << spc->getIndex() << " : '" << spc->getShortcut() << "' " << spc->getName();
if (spc->getType() == IPTR_CONSTANT) if (spc->getType() == IPTR_CONSTANT)
*status->fileoptr << " constant "; *status->fileoptr << " constant ";
@ -1468,7 +1469,7 @@ void IfcDeadcodedelay::execute(istream &s)
*status->optr << "Successfully overrided deadcode delay for single function" << endl; *status->optr << "Successfully overrided deadcode delay for single function" << endl;
} }
else { else {
dcp->conf->setDeadcodeDelay(spc->getIndex(),delay); dcp->conf->setDeadcodeDelay(spc,delay);
*status->optr << "Successfully overrided deadcode delay for all functions" << endl; *status->optr << "Successfully overrided deadcode delay for all functions" << endl;
} }
} }

View file

@ -15,6 +15,8 @@
*/ */
#include "sleighbase.hh" #include "sleighbase.hh"
const int4 SleighBase::SLA_FORMAT_VERSION = 2;
SleighBase::SleighBase(void) SleighBase::SleighBase(void)
{ {
@ -146,6 +148,7 @@ void SleighBase::saveXml(ostream &s) const
{ {
s << "<sleigh"; s << "<sleigh";
a_v_i(s,"version",SLA_FORMAT_VERSION);
a_v_b(s,"bigendian",isBigEndian()); a_v_b(s,"bigendian",isBigEndian());
a_v_i(s,"align",alignment); a_v_i(s,"align",alignment);
a_v_u(s,"uniqbase",getUniqueBase()); a_v_u(s,"uniqbase",getUniqueBase());
@ -162,6 +165,7 @@ void SleighBase::saveXml(ostream &s) const
s << ">\n"; s << ">\n";
for(int4 i=0;i<numSpaces();++i) { for(int4 i=0;i<numSpaces();++i) {
AddrSpace *spc = getSpace(i); AddrSpace *spc = getSpace(i);
if (spc == (AddrSpace *)0) continue;
if ((spc->getType()==IPTR_CONSTANT) || if ((spc->getType()==IPTR_CONSTANT) ||
(spc->getType()==IPTR_FSPEC)|| (spc->getType()==IPTR_FSPEC)||
(spc->getType()==IPTR_IOP)|| (spc->getType()==IPTR_IOP)||
@ -183,6 +187,7 @@ void SleighBase::restoreXml(const Element *el)
maxdelayslotbytes = 0; maxdelayslotbytes = 0;
unique_allocatemask = 0; unique_allocatemask = 0;
numSections = 0; numSections = 0;
int4 version = 0;
setBigEndian(xml_readbool(el->getAttributeValue("bigendian"))); setBigEndian(xml_readbool(el->getAttributeValue("bigendian")));
{ {
istringstream s(el->getAttributeValue("align")); istringstream s(el->getAttributeValue("align"));
@ -214,7 +219,14 @@ void SleighBase::restoreXml(const Element *el)
s3.unsetf(ios::dec | ios::hex | ios::oct); s3.unsetf(ios::dec | ios::hex | ios::oct);
s3 >> numSections; 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()); const List &list(el->getChildren());
List::const_iterator iter; List::const_iterator iter;
iter = list.begin(); iter = list.begin();

View file

@ -27,6 +27,7 @@
/// - Reading the various SLEIGH specification files /// - Reading the various SLEIGH specification files
/// - Building and writing out SLEIGH specification files /// - Building and writing out SLEIGH specification files
class SleighBase : public Translate { 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 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 map<VarnodeData,string> varnode_xref; ///< A map from Varnodes in the \e register space to register names
protected: protected:

View file

@ -1476,9 +1476,13 @@ void SleighCompile::predefinedSymbols(void)
// Some predefined symbols // Some predefined symbols
root = new SubtableSymbol("instruction"); // Base constructors root = new SubtableSymbol("instruction"); // Base constructors
symtab.addSymbol(root); 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 SpaceSymbol *spacesym = new SpaceSymbol(getConstantSpace()); // Constant space
symtab.addSymbol(spacesym); 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)); insertSpace(new UniqueSpace(this,this,"unique",numSpaces(),0));
spacesym = new SpaceSymbol(getUniqueSpace()); // Temporary register space spacesym = new SpaceSymbol(getUniqueSpace()); // Temporary register space
symtab.addSymbol(spacesym); symtab.addSymbol(spacesym);

View file

@ -24,14 +24,6 @@ void AddrSpace::calcScaleMask(void)
highest = highest * wordsize + (wordsize-1); // Maximum byte address 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 /// Initialize an address space with its basic attributes
/// \param m is the space manager associated with the new space /// \param m is the space manager associated with the new space
/// \param t is the processor translator 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; index = ind;
delay = dl; delay = dl;
deadcodedelay = dl; // Deadcode delay initially starts the same as heritage delay 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 // These are the flags we allow to be set from constructor
flags = (fl & hasphysical); 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 flags |= (heritaged | does_deadcode); // Always on unless explicitly turned off in derived constructor
calcScaleMask(); calcScaleMask();
assignShortcut();
} }
/// This is a partial constructor, for initializing a space /// This is a partial constructor, for initializing a space
@ -80,6 +72,7 @@ AddrSpace::AddrSpace(AddrSpaceManager *m,const Translate *t,spacetype tp)
type = tp; type = tp;
flags = (heritaged | does_deadcode); // Always on unless explicitly turned off in derived constructor flags = (heritaged | does_deadcode); // Always on unless explicitly turned off in derived constructor
wordsize = 1; wordsize = 1;
shortcut = ' ';
// We let big_endian get set by attribute // We let big_endian get set by attribute
} }
@ -349,7 +342,6 @@ void AddrSpace::restoreXml(const Element *el)
if (deadcodedelay == -1) if (deadcodedelay == -1)
deadcodedelay = delay; // If deadcodedelay attribute not present, set it to delay deadcodedelay = delay; // If deadcodedelay attribute not present, set it to delay
calcScaleMask(); calcScaleMask();
assignShortcut();
} }
/// This constructs the unique constant space /// 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"); 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 /// This is the constructor for the \b unique space, which is
/// automatically constructed by the analysis engine, and /// automatically constructed by the analysis engine, and
/// constructed only once. The name should always be \b unique. /// constructed only once. The name should always be \b unique.
@ -653,7 +681,6 @@ void OverlaySpace::restoreXml(const Element *el)
delay = baseSpace->getDelay(); delay = baseSpace->getDelay();
deadcodedelay = baseSpace->getDeadcodeDelay(); deadcodedelay = baseSpace->getDeadcodeDelay();
calcScaleMask(); calcScaleMask();
assignShortcut();
if (baseSpace->isBigEndian()) if (baseSpace->isBigEndian())
setFlags(big_endian); setFlags(big_endian);

View file

@ -82,7 +82,12 @@ public:
overlay = 32, ///< This space is an overlay of another space overlay = 32, ///< This space is an overlay of another space
overlaybase = 64, ///< This is the base space for overlay space(s) 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 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: private:
spacetype type; ///< Type of space (PROCESSOR, CONSTANT, INTERNAL, ...) spacetype type; ///< Type of space (PROCESSOR, CONSTANT, INTERNAL, ...)
@ -100,7 +105,6 @@ protected:
int4 delay; ///< Delay in heritaging this space int4 delay; ///< Delay in heritaging this space
int4 deadcodedelay; ///< Delay before deadcode removal is allowed on this space int4 deadcodedelay; ///< Delay before deadcode removal is allowed on this space
void calcScaleMask(void); ///< Calculate scale and mask 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 setFlags(uint4 fl); ///< Set a cached attribute
void clearFlags(uint4 fl); ///< Clear a cached attribute void clearFlags(uint4 fl); ///< Clear a cached attribute
void saveBasicAttributes(ostream &s) const; ///< Write the XML attributes of this space 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 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 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 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 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 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); 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 /// \brief The pool of temporary storage registers
/// ///
/// It is convenient both for modelling processor instructions /// It is convenient both for modelling processor instructions
@ -181,7 +195,7 @@ public:
/// \b unique. /// \b unique.
class UniqueSpace : public AddrSpace { class UniqueSpace : public AddrSpace {
public: 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 UniqueSpace(AddrSpaceManager *m,const Translate *t); ///< For use with restoreXml
virtual void saveXml(ostream &s) const; virtual void saveXml(ostream &s) const;
}; };
@ -392,6 +406,10 @@ inline bool AddrSpace::isOverlayBase(void) const {
return ((flags&overlaybase)!=0); 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 /// 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 /// Pointers may refer to this original size put the most significant bytes are ignored
inline bool AddrSpace::isTruncated(void) const { inline bool AddrSpace::isTruncated(void) const {

View file

@ -170,6 +170,8 @@ AddrSpace *AddrSpaceManager::restoreXmlSpace(const Element *el,const Translate *
res = new SpacebaseSpace(this,trans); res = new SpacebaseSpace(this,trans);
else if (tp == "space_unique") else if (tp == "space_unique")
res = new UniqueSpace(this,trans); res = new UniqueSpace(this,trans);
else if (tp == "space_other")
res = new OtherSpace(this,trans);
else if (tp == "space_overlay") else if (tp == "space_overlay")
res = new OverlaySpace(this,trans); res = new OverlaySpace(this,trans);
else else
@ -191,7 +193,7 @@ void AddrSpaceManager::restoreXmlSpaces(const Element *el,const Translate *trans
{ {
// The first space should always be the constant space // 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")); string defname(el->getAttributeValue("defaultspace"));
const List &list(el->getChildren()); const List &list(el->getChildren());
@ -203,6 +205,8 @@ void AddrSpaceManager::restoreXmlSpaces(const Element *el,const Translate *trans
++iter; ++iter;
} }
AddrSpace *spc = getSpaceByName(defname); AddrSpace *spc = getSpaceByName(defname);
if (spc == (AddrSpace *)0)
throw LowlevelError("Bad 'defaultspace' attribute: "+defname);
setDefaultSpace(spc->getIndex()); setDefaultSpace(spc->getIndex());
} }
@ -217,7 +221,7 @@ void AddrSpaceManager::setDefaultSpace(int4 index)
{ {
if (defaultspace != (AddrSpace *)0) if (defaultspace != (AddrSpace *)0)
throw LowlevelError("Default space set multiple times"); 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"); throw LowlevelError("Bad index for default space");
defaultspace = baselist[index]; defaultspace = baselist[index];
} }
@ -244,48 +248,49 @@ void AddrSpaceManager::setReverseJustified(AddrSpace *spc)
void AddrSpaceManager::insertSpace(AddrSpace *spc) void AddrSpaceManager::insertSpace(AddrSpace *spc)
{ {
bool nametype_mismatch = false; bool nameTypeMismatch = false;
bool duplicatedefine = false; bool duplicateName = false;
bool duplicateId = false;
switch(spc->getType()) { switch(spc->getType()) {
case IPTR_CONSTANT: case IPTR_CONSTANT:
if (spc->getName() != "const") if (spc->getName() != "const")
nametype_mismatch = true; nameTypeMismatch = true;
if (baselist.size()!=0) if (spc->index != AddrSpace::constant_space_index)
throw LowlevelError("const space must be initialized first"); throw LowlevelError("const space must be assigned index 0");
constantspace = spc; constantspace = spc;
break; break;
case IPTR_INTERNAL: case IPTR_INTERNAL:
if (spc->getName() != "unique") if (spc->getName() != "unique")
nametype_mismatch = true; nameTypeMismatch = true;
if (uniqspace != (AddrSpace *)0) if (uniqspace != (AddrSpace *)0)
duplicatedefine = true; duplicateName = true;
uniqspace = spc; uniqspace = spc;
break; break;
case IPTR_FSPEC: case IPTR_FSPEC:
if (spc->getName() != "fspec") if (spc->getName() != "fspec")
nametype_mismatch = true; nameTypeMismatch = true;
if (fspecspace != (AddrSpace *)0) if (fspecspace != (AddrSpace *)0)
duplicatedefine = true; duplicateName = true;
fspecspace = spc; fspecspace = spc;
break; break;
case IPTR_JOIN: case IPTR_JOIN:
if (spc->getName() != "join") if (spc->getName() != "join")
nametype_mismatch = true; nameTypeMismatch = true;
if (joinspace != (AddrSpace *)0) if (joinspace != (AddrSpace *)0)
duplicatedefine = true; duplicateName = true;
joinspace = spc; joinspace = spc;
break; break;
case IPTR_IOP: case IPTR_IOP:
if (spc->getName() != "iop") if (spc->getName() != "iop")
nametype_mismatch = true; nameTypeMismatch = true;
if (iopspace != (AddrSpace *)0) if (iopspace != (AddrSpace *)0)
duplicatedefine = true; duplicateName = true;
iopspace = spc; iopspace = spc;
break; break;
case IPTR_SPACEBASE: case IPTR_SPACEBASE:
if (spc->getName() == "stack") { if (spc->getName() == "stack") {
if (stackspace != (AddrSpace *)0) if (stackspace != (AddrSpace *)0)
duplicatedefine = true; duplicateName = true;
stackspace = spc; stackspace = spc;
} }
// fallthru // fallthru
@ -294,19 +299,36 @@ void AddrSpaceManager::insertSpace(AddrSpace *spc)
OverlaySpace *ospc = (OverlaySpace *)spc; OverlaySpace *ospc = (OverlaySpace *)spc;
ospc->getBaseSpace()->setFlags(AddrSpace::overlaybase); // Mark the base as being overlayed ospc->getBaseSpace()->setFlags(AddrSpace::overlaybase); // Mark the base as being overlayed
} }
for(uint4 i=0;i<baselist.size();++i) else if (spc->isOtherSpace()) {
if (baselist[i]->getName() == spc->getName()) if (spc->index != AddrSpace::other_space_index)
duplicatedefine = true; throw LowlevelError("OTHER space must be assigned index 1");
}
break; 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"); throw LowlevelError("Space "+spc->getName()+" was initialized with wrong type");
if (duplicatedefine) if (duplicateName)
throw LowlevelError("Space "+spc->getName()+" was initialized more than once"); throw LowlevelError("Space "+spc->getName()+" was initialized more than once");
if (baselist.size() != spc->getIndex()) if (duplicateId)
throw LowlevelError("Space "+spc->getName()+" was initialized with a bad id"); throw LowlevelError("Space "+spc->getName()+" was assigned as id duplicating: "+baselist[spc->index]->getName());
baselist.push_back(spc); baselist[spc->index] = spc;
spc->refcount += 1; spc->refcount += 1;
assignShortcut(spc);
} }
/// Different managers may need to share the same spaces. I.e. if different programs being /// 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) void AddrSpaceManager::copySpaces(const AddrSpaceManager *op2)
{ // Insert every space in -op2- into -this- manager { // Insert every space in -op2- into -this- manager
for(int4 i=0;i<op2->baselist.size();++i) for(int4 i=0;i<op2->baselist.size();++i) {
insertSpace(op2->baselist[i]); AddrSpace *spc = op2->baselist[i];
if (spc != (AddrSpace *)0)
insertSpace(spc);
}
setDefaultSpace(op2->getDefaultSpace()->getIndex()); setDefaultSpace(op2->getDefaultSpace()->getIndex());
} }
@ -353,6 +378,7 @@ AddrSpaceManager::~AddrSpaceManager(void)
{ {
for(vector<AddrSpace *>::iterator iter=baselist.begin();iter!=baselist.end();++iter) { for(vector<AddrSpace *>::iterator iter=baselist.begin();iter!=baselist.end();++iter) {
AddrSpace *spc = *iter; AddrSpace *spc = *iter;
if (spc == (AddrSpace *)0) continue;
if (spc->refcount > 1) if (spc->refcount > 1)
spc->refcount -= 1; spc->refcount -= 1;
else else
@ -366,24 +392,29 @@ AddrSpaceManager::~AddrSpaceManager(void)
delete splitlist[i]; // Delete any join records 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 /// This routine makes use of the desired type of the new space
/// and info about shortcuts for spaces that already exist to /// and info about shortcuts for spaces that already exist to
/// pick a unique and consistent character. /// pick a unique and consistent character. This method also builds
/// This is currently invoked by the AddrSpace initialization /// up a map from short to AddrSpace object.
/// process. /// \param spc is the given AddrSpace
/// \param tp is the type of the new space void AddrSpaceManager::assignShortcut(AddrSpace *spc)
/// \return the shortcut character
char AddrSpaceManager::assignShortcut(spacetype tp) const
{ {
char shortcut = 'x'; if (spc->shortcut != ' ') { // If the shortcut is already assigned
switch(tp) { shortcut2Space.insert(pair<int4,AddrSpace *>(spc->shortcut,spc));
return;
}
char shortcut;
switch(spc->getType()) {
case IPTR_CONSTANT: case IPTR_CONSTANT:
shortcut = '#'; shortcut = '#';
break; break;
case IPTR_PROCESSOR: case IPTR_PROCESSOR:
shortcut = 'r'; if (spc->getName() == "register")
shortcut = '%';
else
shortcut = spc->getName()[0];
break; break;
case IPTR_SPACEBASE: case IPTR_SPACEBASE:
shortcut = 's'; shortcut = 's';
@ -400,25 +431,29 @@ char AddrSpaceManager::assignShortcut(spacetype tp) const
case IPTR_IOP: case IPTR_IOP:
shortcut = 'i'; shortcut = 'i';
break; break;
default:
shortcut = 'x';
break;
} }
// if ((shortcut >= 'A') && (shortcut <= 'R'))
// shortcut |= 0x20;
for(int4 i=0x61;i<0x7a;++i) { if (shortcut >= 'A' && shortcut <= 'Z')
int4 j; shortcut += 0x20;
for(j=0;j<baselist.size();++j) {
if (baselist[j]->getShortcut() == shortcut) int4 collisionCount = 0;
break; 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 += 1;
shortcut = (char) i; if (shortcut < 'a' || shortcut > 'z')
if (shortcut == 'a') shortcut = 'a';
shortcut = '%'; // Second processor space is usually the register space
} }
// Could not find a unique shortcut, but we just re-use 'z' as we spc->shortcut = (char)shortcut;
// 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;
} }
/// All address spaces have a unique name associated with them. /// 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 AddrSpace *AddrSpaceManager::getSpaceByName(const string &nm) const
{ {
for(int4 i=0;i<baselist.size();++i) map<string,AddrSpace *>::const_iterator iter = name2Space.find(nm);
if (baselist[i]->getName() == nm) if (iter == name2Space.end())
return baselist[i]; return (AddrSpace *)0;
return (AddrSpace *)0; return (*iter).second;
} }
/// All address spaces have a unique shortcut (ASCII) character /// 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 AddrSpace *AddrSpaceManager::getSpaceByShortcut(char sc) const
{ {
for(int4 i=0;i<baselist.size();++i) map<int4,AddrSpace *>::const_iterator iter;
if (baselist[i]->getShortcut() == sc) iter = shortcut2Space.find(sc);
return baselist[i]; if (iter == shortcut2Space.end())
return (AddrSpace *)0; return (AddrSpace *)0;
return (*iter).second;
} }
Address AddrSpaceManager::resolveConstant(AddrSpace *spc,uintb val,int4 sz,const Address &point) const 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)) { if (spc == (AddrSpace *) ~((uintp)0)) {
return (AddrSpace *)0; return (AddrSpace *)0;
} }
int4 index = spc->getIndex(); int4 index = spc->getIndex() + 1;
if (index < baselist.size()-1) { while (index < baselist.size()) {
return baselist[index+1]; AddrSpace *res = baselist[index];
if (res != (AddrSpace *)0)
return res;
index += 1;
} }
return (AddrSpace *) ~((uintp)0); 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 /// Set the number of passes for a specific AddrSpace before deadcode removal is allowed
/// for that space. /// 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 /// \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 /// Mark the named space as truncated from its original size

View file

@ -212,6 +212,8 @@ struct JoinRecordCompare {
class AddrSpaceManager { class AddrSpaceManager {
vector<AddrSpace *> baselist; ///< Every space we know about for this architecture vector<AddrSpace *> baselist; ///< Every space we know about for this architecture
vector<AddressResolver *> resolvelist; ///< Special constant resolvers 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 *constantspace; ///< Quick reference to constant space
AddrSpace *defaultspace; ///< Generally primary RAM, where assembly pointers point to AddrSpace *defaultspace; ///< Generally primary RAM, where assembly pointers point to
AddrSpace *iopspace; ///< Space for internal pcode op pointers 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 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 setDefaultSpace(int4 index); ///< Set the default address space
void setReverseJustified(AddrSpace *spc); ///< Set reverse justified property on this 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 insertSpace(AddrSpace *spc); ///< Add a new address space to the model
void copySpaces(const AddrSpaceManager *op2); ///< Copy spaces from another manager 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 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: public:
AddrSpaceManager(void); ///< Construct an empty address space manager AddrSpaceManager(void); ///< Construct an empty address space manager
virtual ~AddrSpaceManager(void); ///< Destroy the 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 int4 getDefaultSize(void) const; ///< Get size of addresses for the default space
AddrSpace *getSpaceByName(const string &nm) const; ///< Get address space by name AddrSpace *getSpaceByName(const string &nm) const; ///< Get address space by name
AddrSpace *getSpaceByShortcut(char sc) const; ///< Get address space from its shortcut 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 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 *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 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 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 /// \brief Build a logically lower precision storage location for a bigger floating point register

View file

@ -216,7 +216,8 @@ public class DecompInterface {
// use static uniqueBase since we don't know how many dynamically generated // use static uniqueBase since we don't know how many dynamically generated
// variables Ghidra may add to the language/compile-spec uniqueBase // variables Ghidra may add to the language/compile-spec uniqueBase
long uniqueBase = 0x10000000; long uniqueBase = 0x10000000;
String tspec = pcodelanguage.buildTranslatorTag(program.getAddressFactory(), uniqueBase, null); String tspec =
pcodelanguage.buildTranslatorTag(program.getAddressFactory(), uniqueBase, null);
String coretypes = dtmanage.buildCoreTypes(); String coretypes = dtmanage.buildCoreTypes();
SleighLanguageDescription sleighdescription = SleighLanguageDescription sleighdescription =
(SleighLanguageDescription) pcodelanguage.getLanguageDescription(); (SleighLanguageDescription) pcodelanguage.getLanguageDescription();
@ -233,7 +234,8 @@ public class DecompInterface {
if (xmlOptions != null) { if (xmlOptions != null) {
decompProcess.setMaxResultSize(xmlOptions.getMaxPayloadMBytes()); decompProcess.setMaxResultSize(xmlOptions.getMaxPayloadMBytes());
decompProcess.setShowNamespace(xmlOptions.isDisplayNamespaces()); 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"); throw new IOException("Did not accept decompiler options");
} }
} }
@ -241,12 +243,14 @@ public class DecompInterface {
throw new IOException("Decompile action not specified"); throw new IOException("Decompile action not specified");
} }
if (!actionname.equals("decompile")) { 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"); throw new IOException("Could not set decompile action");
} }
} }
if (!printSyntaxTree) { 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"); throw new IOException("Could not turn off syntax tree");
} }
} }
@ -256,12 +260,14 @@ public class DecompInterface {
} }
} }
if (sendParamMeasures) { 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"); throw new IOException("Could not turn on sending of parameter measures");
} }
} }
if (jumpLoad) { 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"); throw new IOException("Could not turn on jumptable loads");
} }
} }
@ -298,7 +304,7 @@ public class DecompInterface {
decompileMessage = "Language does not support PCode."; decompileMessage = "Language does not support PCode.";
return false; return false;
} }
pcodelanguage = (SleighLanguage)lang; pcodelanguage = (SleighLanguage) lang;
CompilerSpec spec = prog.getCompilerSpec(); CompilerSpec spec = prog.getCompilerSpec();
if (!(spec instanceof BasicCompilerSpec)) { if (!(spec instanceof BasicCompilerSpec)) {
decompileMessage = decompileMessage =
@ -405,7 +411,8 @@ public class DecompInterface {
} }
try { try {
verifyProcess(); verifyProcess();
return decompProcess.sendCommand2Params("setAction", actionstring, "").toString().equals("t"); return decompProcess.sendCommand2Params("setAction", actionstring,
"").toString().equals("t");
} }
catch (IOException e) { catch (IOException e) {
// don't care // don't care
@ -441,7 +448,8 @@ public class DecompInterface {
String printstring = val ? "tree" : "notree"; String printstring = val ? "tree" : "notree";
try { try {
verifyProcess(); verifyProcess();
return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals("t"); return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals(
"t");
} }
catch (IOException e) { catch (IOException e) {
// don't care // don't care
@ -478,7 +486,8 @@ public class DecompInterface {
String printstring = val ? "c" : "noc"; String printstring = val ? "c" : "noc";
try { try {
verifyProcess(); verifyProcess();
return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals("t"); return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals(
"t");
} }
catch (IOException e) { catch (IOException e) {
// don't care // don't care
@ -514,7 +523,8 @@ public class DecompInterface {
String printstring = val ? "parammeasures" : "noparammeasures"; String printstring = val ? "parammeasures" : "noparammeasures";
try { try {
verifyProcess(); verifyProcess();
return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals("t"); return decompProcess.sendCommand2Params("setAction", "", printstring).toString().equals(
"t");
} }
catch (IOException e) { catch (IOException e) {
// don't care // don't care
@ -543,7 +553,8 @@ public class DecompInterface {
String jumpstring = val ? "jumpload" : "nojumpload"; String jumpstring = val ? "jumpload" : "nojumpload";
try { try {
verifyProcess(); verifyProcess();
return decompProcess.sendCommand2Params("setAction", "", jumpstring).toString().equals("t"); return decompProcess.sendCommand2Params("setAction", "", jumpstring).toString().equals(
"t");
} }
catch (IOException e) { catch (IOException e) {
// don't care // don't care
@ -580,8 +591,8 @@ public class DecompInterface {
verifyProcess(); verifyProcess();
decompProcess.setMaxResultSize(xmlOptions.getMaxPayloadMBytes()); decompProcess.setMaxResultSize(xmlOptions.getMaxPayloadMBytes());
decompProcess.setShowNamespace(xmlOptions.isDisplayNamespaces()); decompProcess.setShowNamespace(xmlOptions.isDisplayNamespaces());
return decompProcess.sendCommand1Param("setOptions", xmloptions.getXML(this)).toString().equals( return decompProcess.sendCommand1Param("setOptions",
"t"); xmloptions.getXML(this)).toString().equals("t");
} }
catch (IOException e) { catch (IOException e) {
// don't care // don't care
@ -630,22 +641,27 @@ public class DecompInterface {
return res; 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 = ""; decompileMessage = "";
if (monitor != null && monitor.isCancelled()) if (monitor != null && monitor.isCancelled()) {
return null; return null;
if (monitor != null) }
if (monitor != null) {
monitor.addCancelledListener(monitorListener); monitor.addCancelledListener(monitorListener);
}
LimitedByteBuffer res = null; LimitedByteBuffer res = null;
BlockGraph resgraph = null; BlockGraph resgraph = null;
try { try {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
ingraph.saveXml(writer); ingraph.saveXml(writer);
verifyProcess(); verifyProcess();
res = decompProcess.sendCommand1ParamTimeout("structureGraph", writer.toString(), timeoutSecs); res = decompProcess.sendCommand1ParamTimeout("structureGraph", writer.toString(),
timeoutSecs);
decompileMessage = decompCallback.getNativeMessage(); decompileMessage = decompCallback.getNativeMessage();
if (res != null) { 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 = new BlockGraph();
resgraph.restoreXml(parser, factory); resgraph.restoreXml(parser, factory);
resgraph.transferObjectRef(ingraph); resgraph.transferObjectRef(ingraph);
@ -661,6 +677,7 @@ public class DecompInterface {
} }
return resgraph; return resgraph;
} }
/** /**
* Decompile function * Decompile function
* @param func function to be decompiled * @param func function to be decompiled
@ -697,13 +714,13 @@ public class DecompInterface {
decompCallback.setFunction(func, funcEntry, debug); decompCallback.setFunction(func, funcEntry, debug);
String addrstring = Varnode.buildXMLAddress(funcEntry); String addrstring = Varnode.buildXMLAddress(funcEntry);
verifyProcess(); verifyProcess();
res = res = decompProcess.sendCommand1ParamTimeout("decompileAt", addrstring.toString(),
decompProcess.sendCommand1ParamTimeout("decompileAt", addrstring.toString(), timeoutSecs);
timeoutSecs);
decompileMessage = decompCallback.getNativeMessage(); decompileMessage = decompCallback.getNativeMessage();
} }
catch (Exception ex) { catch (Exception ex) {
decompileMessage = "Exception while decompiling " +func.getEntryPoint() + ": "+ ex.getMessage() + '\n'; decompileMessage = "Exception while decompiling " + func.getEntryPoint() + ": " +
ex.getMessage() + '\n';
} }
finally { finally {
if (monitor != null) { if (monitor != null) {
@ -727,8 +744,9 @@ public class DecompInterface {
} }
InputStream stream = null; InputStream stream = null;
if (res != null) if (res != null) {
stream = res.getInputStream(); stream = res.getInputStream();
}
return new DecompileResults(func, pcodelanguage, compilerSpec, dtmanage, decompileMessage, return new DecompileResults(func, pcodelanguage, compilerSpec, dtmanage, decompileMessage,
stream, processState, isDisplayNamespace()); 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() { public void dispose() {
if (program == null) { if (program == null) {
if (decompProcess != null) { if (decompProcess != null) {
@ -772,4 +804,5 @@ public class DecompInterface {
} }
return xmlOptions.isDisplayNamespaces(); return xmlOptions.isDisplayNamespaces();
} }
} }

View file

@ -223,7 +223,7 @@ public class DecompileProcess {
if (type != 14) { if (type != 14) {
throw new IOException("GHIDRA/decompiler alignment error"); throw new IOException("GHIDRA/decompiler alignment error");
} }
LimitedByteBuffer buf = new LimitedByteBuffer(16,1<<16); LimitedByteBuffer buf = new LimitedByteBuffer(16, 1 << 16);
type = readToBuffer(buf); type = readToBuffer(buf);
if (type != 15) { if (type != 15) {
throw new IOException("GHIDRA/decompiler alignment error"); throw new IOException("GHIDRA/decompiler alignment error");
@ -426,8 +426,8 @@ public class DecompileProcess {
* @throws DecompileException * @throws DecompileException
*/ */
public synchronized void registerProgram(DecompileCallback cback, String pspecxml, public synchronized void registerProgram(DecompileCallback cback, String pspecxml,
String cspecxml, String tspecxml, String coretypesxml) throws IOException, String cspecxml, String tspecxml, String coretypesxml)
DecompileException { throws IOException, DecompileException {
callback = cback; callback = cback;
callback.setShowNamespace(showNamespace); callback.setShowNamespace(showNamespace);
@ -481,7 +481,8 @@ public class DecompileProcess {
* @throws IOException * @throws IOException
* @throws DecompileException * @throws DecompileException
*/ */
public synchronized LimitedByteBuffer sendCommand(String command) throws IOException, DecompileException { public synchronized LimitedByteBuffer sendCommand(String command)
throws IOException, DecompileException {
if (!statusGood) { if (!statusGood) {
throw new IOException(command + " called on bad process"); throw new IOException(command + " called on bad process");
} }
@ -552,8 +553,8 @@ public class DecompileProcess {
* @throws IOException * @throws IOException
* @throws DecompileException * @throws DecompileException
*/ */
public synchronized LimitedByteBuffer sendCommand2Params(String command, String param1, String param2) public synchronized LimitedByteBuffer sendCommand2Params(String command, String param1,
throws IOException, DecompileException { String param2) throws IOException, DecompileException {
if (!statusGood) { if (!statusGood) {
throw new IOException(command + " called on bad process"); throw new IOException(command + " called on bad process");
} }
@ -591,8 +592,8 @@ public class DecompileProcess {
* @throws IOException * @throws IOException
* @throws DecompileException * @throws DecompileException
*/ */
public synchronized LimitedByteBuffer sendCommand1Param(String command, String param1) throws IOException, public synchronized LimitedByteBuffer sendCommand1Param(String command, String param1)
DecompileException { throws IOException, DecompileException {
if (!statusGood) { if (!statusGood) {
throw new IOException(command + " called on bad process"); throw new IOException(command + " called on bad process");
} }
@ -671,7 +672,7 @@ public class DecompileProcess {
private void getPcodeInject(int type) throws IOException { private void getPcodeInject(int type) throws IOException {
String name = readQueryString(); String name = readQueryString();
String context = readQueryString(); String context = readQueryString();
String res = callback.getPcodeInject(name, context,type); String res = callback.getPcodeInject(name, context, type);
write(query_response_start); write(query_response_start);
if ((res != null) && (res.length() != 0)) { if ((res != null) && (res.length() != 0)) {
writeString(res); writeString(res);
@ -683,7 +684,7 @@ public class DecompileProcess {
String liststring = readQueryString(); String liststring = readQueryString();
String[] split = liststring.split(","); String[] split = liststring.split(",");
long[] refs = new long[split.length]; 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); refs[i] = Long.parseUnsignedLong(split[i], 16);
} }
String res = callback.getCPoolRef(refs); String res = callback.getCPoolRef(refs);

View file

@ -24,19 +24,19 @@ import ghidra.util.Msg;
/** /**
* Factory that returns a DecompileProcess. * Factory that returns a DecompileProcess.
*/ */
class DecompileProcessFactory { public class DecompileProcessFactory {
private static String exepath; private static String exepath;
private static final String EXECNAME = "decompile"; private static final String EXECNAME = "decompile";
private static final String WIN32_EXECNAME = "decompile.exe"; private static final String WIN32_EXECNAME = "decompile.exe";
synchronized static DecompileProcess get() { public synchronized static DecompileProcess get() {
getExePath(); getExePath();
DecompileProcess currentProcess = new DecompileProcess(exepath); DecompileProcess currentProcess = new DecompileProcess(exepath);
return currentProcess; return currentProcess;
} }
synchronized static void release(DecompileProcess dp) { public synchronized static void release(DecompileProcess dp) {
dp.dispose(); dp.dispose();
} }

View file

@ -89,4 +89,14 @@ class Decompiler {
cancelCurrentAction(); 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();
}
}
} }

View file

@ -155,6 +155,14 @@ public class DecompilerController {
decompilerPanel.setMouseNavigationEnabled(enabled); 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 // Methods call by the DecompilerManager
//================================================================================================== //==================================================================================================
@ -296,4 +304,5 @@ public class DecompilerController {
} }
} }
} }
} }

View file

@ -71,6 +71,14 @@ public class DecompilerManager {
return runManager.getMonitorComponent(); 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, * 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 * the new request is checked to see if represents the same function. If so, only the

View file

@ -44,8 +44,8 @@ import ghidra.program.model.address.*;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.*; import ghidra.program.model.symbol.*;
import ghidra.program.util.ProgramLocation; import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.ProgramSelection; import ghidra.program.util.*;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
import ghidra.util.Swing; import ghidra.util.Swing;
import ghidra.util.bean.field.AnnotatedTextFieldElement; import ghidra.util.bean.field.AnnotatedTextFieldElement;
@ -104,7 +104,7 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
private ViewerPosition pendingViewerPosition; private ViewerPosition pendingViewerPosition;
private SwingUpdateManager swingUpdateManager; private SwingUpdateManager redecompilerUpdater;
private ServiceListener serviceListener = new ServiceListener() { private ServiceListener serviceListener = new ServiceListener() {
@Override @Override
@ -156,7 +156,7 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
setHelpLocation(new HelpLocation(plugin.getName(), "Decompiler")); setHelpLocation(new HelpLocation(plugin.getName(), "Decompiler"));
addToTool(); addToTool();
swingUpdateManager = new SwingUpdateManager(500, 5000, () -> doRefresh()); redecompilerUpdater = new SwingUpdateManager(500, 5000, () -> doRefresh());
plugin.getTool().addServiceListener(serviceListener); plugin.getTool().addServiceListener(serviceListener);
} }
@ -282,7 +282,14 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
if (!isVisible()) { if (!isVisible()) {
return; 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() { private void doRefresh() {
@ -326,7 +333,7 @@ public class DecompilerProvider extends NavigatableComponentProviderAdapter
public void dispose() { public void dispose() {
super.dispose(); super.dispose();
swingUpdateManager.dispose(); redecompilerUpdater.dispose();
if (clipboardService != null) { if (clipboardService != null) {
clipboardService.deRegisterClipboardContentProvider(clipboardProvider); clipboardService.deRegisterClipboardContentProvider(clipboardProvider);

View file

@ -52,6 +52,8 @@ import utilities.util.FileUtilities;
public class SleighLanguage implements Language { 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 Map<CompilerSpecID, SleighCompilerSpecDescription> compilerSpecDescriptions;
private HashMap<CompilerSpecID, BasicCompilerSpec> compilerSpecs; private HashMap<CompilerSpecID, BasicCompilerSpec> compilerSpecs;
private List<InjectPayloadSleigh> additionalInject = null; private List<InjectPayloadSleigh> additionalInject = null;
@ -805,6 +807,10 @@ public class SleighLanguage implements Language {
private void restoreXml(XmlPullParser parser) throws UnknownInstructionException { private void restoreXml(XmlPullParser parser) throws UnknownInstructionException {
XmlElement el = parser.start("sleigh"); 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")); boolean isBigEndian = SpecXmlUtils.decodeBoolean(el.getAttribute("bigendian"));
// check the instruction endianess, not the program data endianess // check the instruction endianess, not the program data endianess
if (isBigEndian ^ description.getInstructionEndian().isBigEndian()) { if (isBigEndian ^ description.getInstructionEndian().isBigEndian()) {
@ -840,8 +846,16 @@ public class SleighLanguage implements Language {
// Slot zero is always the constant space // Slot zero is always the constant space
AddressSpace constspc = new GenericAddressSpace("const", 64, AddressSpace.TYPE_CONSTANT, 0); AddressSpace constspc = new GenericAddressSpace("const", 64, AddressSpace.TYPE_CONSTANT, 0);
spacetable.put("const", constspc); spacetable.put("const", constspc);
//spacetable.put("OTHER", AddressSpace.OTHER_SPACE);
default_space = null; 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) { while ((subel = parser.softStart("space", "space_unique")) != null) {
String name = subel.getAttribute("name"); String name = subel.getAttribute("name");
int index = SpecXmlUtils.decodeInt(subel.getAttribute("index")); int index = SpecXmlUtils.decodeInt(subel.getAttribute("index"));
@ -1319,14 +1333,13 @@ public class SleighLanguage implements Language {
int delay; int delay;
boolean physical; boolean physical;
boolean global; boolean global;
int index = 1;
for (AddressSpace element : spclist) { for (AddressSpace element : spclist) {
if ((element instanceof OverlayAddressSpace) && if ((element instanceof OverlayAddressSpace)) {
(element.getType() == AddressSpace.TYPE_RAM)) {
OverlayAddressSpace ospace = (OverlayAddressSpace) element; OverlayAddressSpace ospace = (OverlayAddressSpace) element;
resBuf.append("<space_overlay"); resBuf.append("<space_overlay");
SpecXmlUtils.encodeStringAttribute(resBuf, "name", ospace.getName()); SpecXmlUtils.encodeStringAttribute(resBuf, "name", ospace.getName());
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", index++); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", ospace.getUnique());
SpecXmlUtils.encodeStringAttribute(resBuf, "base", SpecXmlUtils.encodeStringAttribute(resBuf, "base",
ospace.getOverlayedSpace().getName()); ospace.getOverlayedSpace().getName());
resBuf.append("/>\n"); resBuf.append("/>\n");
@ -1351,12 +1364,18 @@ public class SleighLanguage implements Language {
physical = true; physical = true;
global = false; global = false;
break; break;
case AddressSpace.TYPE_OTHER:
tag = "space_other";
delay = 0;
physical = true;
global = true;
break;
default: default:
continue; continue;
} }
resBuf.append("<").append(tag); resBuf.append("<").append(tag);
SpecXmlUtils.encodeStringAttribute(resBuf, "name", element.getName()); SpecXmlUtils.encodeStringAttribute(resBuf, "name", element.getName());
SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", index++); SpecXmlUtils.encodeSignedIntegerAttribute(resBuf, "index", element.getUnique());
int size = element.getSize(); // Size in bits int size = element.getSize(); // Size in bits
if (size == 20) { if (size == 20) {

View file

@ -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 // 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 VectorSTL<String> userop = new VectorSTL<>();
private address_set varnode_xref = new address_set(); // Cross-reference registers by address private address_set varnode_xref = new address_set(); // Cross-reference registers by address
protected SubtableSymbol root; protected SubtableSymbol root;
@ -187,6 +189,7 @@ public abstract class SleighBase extends Translate implements NamedSymbolProvide
public void saveXml(PrintStream s) { public void saveXml(PrintStream s) {
s.append("<sleigh"); s.append("<sleigh");
XmlUtils.a_v_i(s, "version", SLA_FORMAT_VERSION);
XmlUtils.a_v_b(s, "bigendian", isBigEndian()); XmlUtils.a_v_b(s, "bigendian", isBigEndian());
XmlUtils.a_v_i(s, "align", alignment); XmlUtils.a_v_i(s, "align", alignment);
XmlUtils.a_v_u(s, "uniqbase", getUniqueBase()); XmlUtils.a_v_u(s, "uniqbase", getUniqueBase());

View file

@ -36,6 +36,7 @@ import ghidra.pcodeCPort.slghsymbol.*;
import ghidra.pcodeCPort.space.*; import ghidra.pcodeCPort.space.*;
import ghidra.pcodeCPort.utils.Utils; import ghidra.pcodeCPort.utils.Utils;
import ghidra.pcodeCPort.xml.DocumentStorage; import ghidra.pcodeCPort.xml.DocumentStorage;
import ghidra.program.model.lang.BasicCompilerSpec;
import ghidra.sleigh.grammar.Location; import ghidra.sleigh.grammar.Location;
import ghidra.util.Msg; import ghidra.util.Msg;
@ -273,10 +274,15 @@ public class SleighCompile extends SleighBase {
// Some predefined symbols // Some predefined symbols
root = new SubtableSymbol(location, "instruction"); // Base constructors root = new SubtableSymbol(location, "instruction"); // Base constructors
symtab.addSymbol(root); 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 SpaceSymbol spacesym = new SpaceSymbol(location, getConstantSpace()); // Constant
// space // space
symtab.addSymbol(spacesym); 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)); insertSpace(new UniqueSpace(this, "unique", numSpaces(), 0));
spacesym = new SpaceSymbol(location, getUniqueSpace()); // Temporary register spacesym = new SpaceSymbol(location, getUniqueSpace()); // Temporary register
// space // space

View file

@ -19,6 +19,11 @@ import java.io.PrintStream;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import org.jdom.Element; 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 /// \brief A region where processor data is stored
/// ///
/// An AddrSpace (Address Space) is an arbitrary sequence of /// 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 MIN_SPACE = new AddrSpace("MIN_SPACE", -1);
public static final AddrSpace MAX_SPACE = new AddrSpace("MAX_SPACE", Integer.MAX_VALUE); 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; //see space.hh
public static final int hasphysical = 4; 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 int flags;
private long highest; private long highest;
@ -188,6 +202,10 @@ public class AddrSpace {
return ((flags & big_endian) != 0); return ((flags & big_endian) != 0);
} }
public boolean isOtherSpace() {
return ((flags & is_otherspace) != 0);
}
public AddrSpace getContain() { public AddrSpace getContain() {
return null; return null;
} }

View file

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

View file

@ -28,6 +28,7 @@ import ghidra.pcodeCPort.pcoderaw.VarnodeData;
import ghidra.pcodeCPort.space.*; import ghidra.pcodeCPort.space.*;
import ghidra.pcodeCPort.utils.AddrSpaceToIdSymmetryMap; import ghidra.pcodeCPort.utils.AddrSpaceToIdSymmetryMap;
import ghidra.pcodeCPort.xml.DocumentStorage; import ghidra.pcodeCPort.xml.DocumentStorage;
import ghidra.program.model.lang.BasicCompilerSpec;
public abstract class Translate implements BasicSpaceProvider { public abstract class Translate implements BasicSpaceProvider {
@ -245,6 +246,9 @@ public abstract class Translate implements BasicSpaceProvider {
else if ("space_unique".equals(tp)) { else if ("space_unique".equals(tp)) {
res = new UniqueSpace(this); res = new UniqueSpace(this);
} }
else if ("space_other".equals(tp)) {
res = new OtherSpace(this);
}
else { else {
res = new AddrSpace(this, spacetype.IPTR_PROCESSOR); res = new AddrSpace(this, spacetype.IPTR_PROCESSOR);
} }
@ -255,7 +259,11 @@ public abstract class Translate implements BasicSpaceProvider {
protected void restoreXmlSpaces(Element el) { protected void restoreXmlSpaces(Element el) {
// The first space should always be the constant space // 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"); String defname = el.getAttributeValue("defaultspace");
List<?> children = el.getChildren(); List<?> children = el.getChildren();
@ -399,6 +407,11 @@ public abstract class Translate implements BasicSpaceProvider {
} }
// fallthru // fallthru
case IPTR_PROCESSOR: 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) { for (AddrSpace space : baselist) {
if (space.getName().equals(spc.getName())) { if (space.getName().equals(spc.getName())) {
duplicatedefine = true; duplicatedefine = true;

View file

@ -101,11 +101,13 @@ public class ProgramAddressFactory extends DefaultAddressFactory {
addAddressSpace(ovSpace); addAddressSpace(ovSpace);
} }
public OverlayAddressSpace addOverlayAddressSpace(String name,AddressSpace originalSpace, public OverlayAddressSpace addOverlayAddressSpace(String name, AddressSpace originalSpace,
long minOffset, long maxOffset) throws DuplicateNameException { long minOffset, long maxOffset) throws DuplicateNameException {
int unique = 0; int unique = 0;
if (originalSpace.getType() == AddressSpace.TYPE_RAM) if (originalSpace.getType() == AddressSpace.TYPE_RAM ||
originalSpace.getType() == AddressSpace.TYPE_OTHER) {
unique = getNextUniqueID(); unique = getNextUniqueID();
}
OverlayAddressSpace ovSpace = OverlayAddressSpace ovSpace =
new OverlayAddressSpace(name, originalSpace, unique, minOffset, maxOffset); new OverlayAddressSpace(name, originalSpace, unique, minOffset, maxOffset);
addAddressSpace(ovSpace); addAddressSpace(ovSpace);
@ -145,15 +147,16 @@ public class ProgramAddressFactory extends DefaultAddressFactory {
} }
@Override @Override
protected void renameOverlaySpace(String oldName, String newName) throws DuplicateNameException { protected void renameOverlaySpace(String oldName, String newName)
throws DuplicateNameException {
super.renameOverlaySpace(oldName, newName); super.renameOverlaySpace(oldName, newName);
} }
private int getNextUniqueID() { private int getNextUniqueID() {
int maxID = 0; int maxID = 0;
AddressSpace[] spaces = getAllAddressSpaces(); AddressSpace[] spaces = getAllAddressSpaces();
for (int i = 0; i < spaces.length; i++) { for (AddressSpace space : spaces) {
maxID = Math.max(maxID, spaces[i].getUnique()); maxID = Math.max(maxID, space.getUnique());
} }
return maxID + 1; return maxID + 1;
} }

View file

@ -1776,6 +1776,7 @@ public class MemoryMapDB implements Memory, ManagerDB, LiveMemoryListener {
finally { finally {
program.setEventsEnabled(true); program.setEventsEnabled(true);
} }
fireBlockRemoved(startAddress); fireBlockRemoved(startAddress);
if (startAddress.getAddressSpace().isOverlaySpace()) { if (startAddress.getAddressSpace().isOverlaySpace()) {
checkRemoveAddressSpace(startAddress.getAddressSpace()); checkRemoveAddressSpace(startAddress.getAddressSpace());

View file

@ -17,6 +17,7 @@ package ghidra.program.model.address;
import java.math.BigInteger; import java.math.BigInteger;
import ghidra.program.model.lang.BasicCompilerSpec;
import ghidra.program.model.listing.Program; 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 * 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, public static final AddressSpace OTHER_SPACE = new GenericAddressSpace(
0); 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) * 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 * defined within a given library namespace. All external locations within a program
* are given a unique offset within the EXTERNAL space. * are given a unique offset within the EXTERNAL space.
*/ */
public static final AddressSpace EXTERNAL_SPACE = new GenericAddressSpace("EXTERNAL", 32, public static final AddressSpace EXTERNAL_SPACE =
TYPE_EXTERNAL, 0); new GenericAddressSpace("EXTERNAL", 32, TYPE_EXTERNAL, 0);
/** /**
* The <code>VARIABLE_SPACE</code> is used to contain all variables and parameters * 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 * defined within a given namespace (i.e., function). All variables within a program
* are given a unique offset within the VARIABLE space. * are given a unique offset within the VARIABLE space.
*/ */
public static final AddressSpace VARIABLE_SPACE = new GenericAddressSpace("VARIABLE", 32, public static final AddressSpace VARIABLE_SPACE =
TYPE_VARIABLE, 0); new GenericAddressSpace("VARIABLE", 32, TYPE_VARIABLE, 0);
/** /**
* The <code>HASH_SPACE</code> provides a 60-bit space for encoding of unique hashcodes. * 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, public static final AddressSpace HASH_SPACE =
0); new GenericAddressSpace("HASH", 60, TYPE_UNKNOWN, 0);
/** /**
* A language may only define a single REGISTER space. If one is not defined, this * A language may only define a single REGISTER space. If one is not defined, this
* DEFAULT_REGISTER_SPACE definition will be used. * DEFAULT_REGISTER_SPACE definition will be used.
*/ */
public static final AddressSpace DEFAULT_REGISTER_SPACE = new GenericAddressSpace("REGISTER", public static final AddressSpace DEFAULT_REGISTER_SPACE =
32, TYPE_REGISTER, 0); new GenericAddressSpace("REGISTER", 32, TYPE_REGISTER, 0);
/** /**
* Returns the name of this address space. * Returns the name of this address space.

View file

@ -46,6 +46,11 @@ public class BasicCompilerSpec implements CompilerSpec {
public static final String STACK_SPACE_NAME = "stack"; public static final String STACK_SPACE_NAME = "stack";
public static final String JOIN_SPACE_NAME = "join"; 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 final CompilerSpecDescription description;
private String sourceName; private String sourceName;
@ -117,8 +122,9 @@ public class BasicCompilerSpec implements CompilerSpec {
parseException = e; parseException = e;
Throwable cause = e.getCause(); // Recover the cause (from the validator exception) Throwable cause = e.getCause(); // Recover the cause (from the validator exception)
if (cause != null) { if (cause != null) {
if (cause instanceof SAXException || cause instanceof IOException) if (cause instanceof SAXException || cause instanceof IOException) {
parseException = (Exception) cause; parseException = (Exception) cause;
}
} }
} }
catch (FileNotFoundException e) { catch (FileNotFoundException e) {
@ -361,6 +367,9 @@ public class BasicCompilerSpec implements CompilerSpec {
else { else {
space = language.getAddressFactory().getAddressSpace(spaceName); space = language.getAddressFactory().getAddressSpace(spaceName);
} }
if (spaceName.equals(OTHER_SPACE_NAME)) {
space = AddressSpace.OTHER_SPACE;
}
if (space == null) { if (space == null) {
throw new SleighException("Unknown address space: " + spaceName); throw new SleighException("Unknown address space: " + spaceName);
} }

View file

@ -406,8 +406,13 @@ public class Varnode {
public static void appendSpaceOffset(StringBuilder buf, Address addr) { public static void appendSpaceOffset(StringBuilder buf, Address addr) {
AddressSpace space = addr.getAddressSpace(); AddressSpace space = addr.getAddressSpace();
if (space.isOverlaySpace()) { if (space.isOverlaySpace()) {
space = space.getPhysicalSpace(); //if the address is contained within the overlay space, stay in the overlay
addr = space.getAddress(addr.getOffset()); //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.encodeStringAttribute(buf, "space", space.getName());
SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "offset", addr.getUnsignedOffset()); SpecXmlUtils.encodeUnsignedIntegerAttribute(buf, "offset", addr.getUnsignedOffset());

View file

@ -38,7 +38,7 @@ define register offset=0x5000 size=$(SIZE) [ TPC1 TPC2 TPC3 TPC4
TT1 TT2 TT3 TT4 TT1 TT2 TT3 TT4
TCK TBA PSTATE TL TCK TBA PSTATE TL
PIL CWP CANSAVE CANRESTORE CLEANWIN 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 define register offset=0x6000 size=$(SIZE) [ HPSTATE1 HPSTATE2 HPSTATE3 HPSTATE4
HTSTATE1 HTSTATE2 HTSTATE3 HTSTATE4 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(); } :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 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 ]; 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;} tnpc: "%tnpc" is fcn {local reloc = zext(TL == 1)*&TNPC1 + zext(TL == 2)*&TNPC2 + zext(TL == 3)*&TNPC3 + zext(TL ==4)*&TNPC4; export reloc;}

View file

@ -24,6 +24,7 @@
</data_organization> </data_organization>
<global> <global>
<range space="ram"/> <range space="ram"/>
<range space="OTHER"/>
</global> </global>
<stackpointer register="ESP" space="ram"/> <stackpointer register="ESP" space="ram"/>
<returnaddress> <returnaddress>