Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sort switch cases based on address (make it optional, or not?) #7253

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions Ghidra/Features/Decompiler/src/decompile/cpp/block.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3455,7 +3455,7 @@ void BlockSwitch::addCase(FlowBlock *switchbl,FlowBlock *bl,uint4 gt)
const FlowBlock *basicbl = bl->getFrontLeaf()->subBlock(0);
curcase.block = bl;
curcase.basicblock = basicbl;
curcase.label = 0;
curcase.addr = Address(Address::m_minimal);
curcase.depth = 0;
curcase.chain = -1;
int4 inindex = basicbl->getInIndex(switchbl);
Expand Down Expand Up @@ -3512,8 +3512,8 @@ void BlockSwitch::finalizePrinting(Funcdata &data) const

{
BlockGraph::finalizePrinting(data); // Make sure to still recurse
// We need to order the cases based on the label
// First populate the label and depth fields of the CaseOrder objects
// We need to order the cases based on the address
// First populate the address and depth fields of the CaseOrder objects
for(int4 i=0;i<caseblocks.size();++i) { // Construct the depth parameter, to sort fall-thru cases
CaseOrder &curcase( caseblocks[i] );
int4 j = curcase.chain;
Expand All @@ -3528,21 +3528,21 @@ void BlockSwitch::finalizePrinting(Funcdata &data) const
if (jump->numIndicesByBlock(curcase.basicblock) > 0) {
if (curcase.depth == 0) { // Only set label on chain roots
int4 ind = jump->getIndexByBlock(curcase.basicblock,0);
curcase.label = jump->getLabelByIndex(ind);
curcase.addr = jump->getAddressByIndex(ind);
int4 j = curcase.chain;
int4 depthcount = 1;
while(j != -1) {
if (caseblocks[j].depth > 0) break; // Has this node had its depth set. Break any possible loops.
caseblocks[j].depth = depthcount++;
caseblocks[j].label = curcase.label;
caseblocks[j].addr = curcase.addr;
j = caseblocks[j].chain;
}
}
}
else
curcase.label = 0; // Should never happen
curcase.addr = Address(Address::m_minimal); // Should never happen
}
// Do actual sort of the cases based on label
// Do actual sort of the cases based on address
stable_sort(caseblocks.begin(),caseblocks.end(),CaseOrder::compare);
}

Expand Down
9 changes: 5 additions & 4 deletions Ghidra/Features/Decompiler/src/decompile/cpp/block.hh
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ class BlockSwitch : public BlockGraph {
struct CaseOrder {
FlowBlock *block; ///< The structured \e case block
const FlowBlock *basicblock; ///< The first basic-block to execute within the \e case block
uintb label; ///< The \e label for this case, as an untyped constant
Address addr; ///< The \e address for this case
int4 depth; ///< How deep in a fall-thru chain we are
int4 chain; ///< Who we immediately chain to, expressed as caseblocks index, -1 for no chaining
int4 outindex; ///< Index coming out of switch to this case
Expand Down Expand Up @@ -777,6 +777,7 @@ public:
bool isDefaultCase(int4 i) const { return caseblocks[i].isdefault; } ///< Is the i-th \e case the \e default case
uint4 getGotoType(int4 i) const { return caseblocks[i].gototype; } ///< Get the edge type for the i-th \e case block
bool isExit(int4 i) const { return caseblocks[i].isexit; } ///< Does the i-th \e case block exit the switch?
//Address getAddress(int4 i,int4 j) const { return jump->getAddressByBlock(jump->getIndexByBlock(caseblocks[i].basicblock,j)); }
const Datatype *getSwitchType(void) const; ///< Get the data-type of the switch variable
virtual block_type getType(void) const { return t_switch; }
virtual void markUnstructured(void);
Expand Down Expand Up @@ -884,15 +885,15 @@ inline bool FlowBlock::compareBlockIndex(const FlowBlock *bl1,const FlowBlock *b
return (bl1->getIndex() < bl2->getIndex());
}

/// Cases are compared by their label
/// Cases are compared by their address
/// \param a is the first case to compare
/// \param b is the second
/// \return \b true if the first comes before the second
inline bool BlockSwitch::CaseOrder::compare(const CaseOrder &a,const CaseOrder &b)

{
if (a.label != b.label)
return (a.label < b.label);
if (a.addr != b.addr)
return (a.addr < b.addr);
return (a.depth < b.depth);
}

Expand Down