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