mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
Merge remote-tracking branch 'origin/GP-2544_ProtoModelGroupList'
(Closes #4568)
This commit is contained in:
commit
ba70679ee8
4 changed files with 95 additions and 99 deletions
|
@ -78,28 +78,20 @@ void ParamEntry::resolveJoin(list<ParamEntry> &curList)
|
|||
return;
|
||||
}
|
||||
joinrec = spaceid->getManager()->findJoin(addressbase);
|
||||
int4 mingrp = 1000;
|
||||
int4 maxgrp = -1;
|
||||
groupSet.clear();
|
||||
for(int4 i=0;i<joinrec->numPieces();++i) {
|
||||
const ParamEntry *entry = findEntryByStorage(curList, joinrec->getPiece(i));
|
||||
if (entry != (const ParamEntry *)0) {
|
||||
if (entry->group < mingrp)
|
||||
mingrp = entry->group;
|
||||
int4 max = entry->group + entry->groupsize;
|
||||
if (max > maxgrp)
|
||||
maxgrp = max;
|
||||
groupSet.insert(groupSet.end(),entry->groupSet.begin(),entry->groupSet.end());
|
||||
// For output <pentry>, if the most signifigant part overlaps with an earlier <pentry>
|
||||
// the least signifigant part is marked for extra checks, and vice versa.
|
||||
flags |= (i==0) ? extracheck_low : extracheck_high;
|
||||
}
|
||||
}
|
||||
if (maxgrp < 0 || mingrp >= 1000)
|
||||
if (groupSet.empty())
|
||||
throw LowlevelError("<pentry> join must overlap at least one previous entry");
|
||||
group = mingrp;
|
||||
groupsize = (maxgrp - mingrp);
|
||||
sort(groupSet.begin(),groupSet.end());
|
||||
flags |= overlapping;
|
||||
if (groupsize > joinrec->numPieces())
|
||||
throw LowlevelError("<pentry> join must overlap sequential entries");
|
||||
}
|
||||
|
||||
/// Search for overlaps of \b this with any previous entry. If an overlap is discovered,
|
||||
|
@ -111,9 +103,7 @@ void ParamEntry::resolveOverlap(list<ParamEntry> &curList)
|
|||
{
|
||||
if (joinrec != (JoinRecord *)0)
|
||||
return; // Overlaps with join records dealt with in resolveJoin
|
||||
int4 grpsize = 0;
|
||||
int4 mingrp = 1000;
|
||||
int4 maxgrp = -1;
|
||||
vector<int4> overlapSet;
|
||||
list<ParamEntry>::const_iterator iter,enditer;
|
||||
Address addr(spaceid,addressbase);
|
||||
enditer = curList.end();
|
||||
|
@ -123,12 +113,7 @@ void ParamEntry::resolveOverlap(list<ParamEntry> &curList)
|
|||
if (!entry.intersects(addr, size)) continue;
|
||||
if (contains(entry)) { // If this contains the intersecting entry
|
||||
if (entry.isOverlap()) continue; // Don't count resources (already counted overlapped entry)
|
||||
if (entry.group < mingrp)
|
||||
mingrp = entry.group;
|
||||
int4 max = entry.group + entry.groupsize;
|
||||
if (max > maxgrp)
|
||||
maxgrp = max;
|
||||
grpsize += entry.groupsize;
|
||||
overlapSet.insert(overlapSet.end(),entry.groupSet.begin(),entry.groupSet.end());
|
||||
// For output <pentry>, if the most signifigant part overlaps with an earlier <pentry>
|
||||
// the least signifigant part is marked for extra checks, and vice versa.
|
||||
if (addressbase == entry.addressbase)
|
||||
|
@ -140,14 +125,36 @@ void ParamEntry::resolveOverlap(list<ParamEntry> &curList)
|
|||
throw LowlevelError("Illegal overlap of <pentry> in compiler spec");
|
||||
}
|
||||
|
||||
if (grpsize == 0) return; // No overlaps
|
||||
if (grpsize != (maxgrp - mingrp))
|
||||
throw LowlevelError("<pentry> must overlap sequential entries");
|
||||
group = mingrp;
|
||||
groupsize = grpsize;
|
||||
if (overlapSet.empty()) return; // No overlaps
|
||||
sort(overlapSet.begin(),overlapSet.end());
|
||||
groupSet = overlapSet;
|
||||
flags |= overlapping;
|
||||
}
|
||||
|
||||
/// \param op2 is the other entry to compare
|
||||
/// \return \b true if the group sets associated with each ParamEntry intersect at all
|
||||
bool ParamEntry::groupOverlap(const ParamEntry &op2) const
|
||||
|
||||
{
|
||||
int4 i = 0;
|
||||
int4 j = 0;
|
||||
int4 valThis = groupSet[i];
|
||||
int4 valOther = op2.groupSet[j];
|
||||
while(valThis != valOther) {
|
||||
if (valThis < valOther) {
|
||||
i += 1;
|
||||
if (i >= groupSet.size()) return false;
|
||||
valThis = groupSet[i];
|
||||
}
|
||||
else {
|
||||
j += 1;
|
||||
if (j >= op2.groupSet.size()) return false;
|
||||
valOther = op2.groupSet[j];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// This entry must properly contain the other memory range, and
|
||||
/// the entry properties must be compatible. A \e join ParamEntry can
|
||||
/// subsume another \e join ParamEntry, but we expect the addressbase to be identical.
|
||||
|
@ -379,7 +386,7 @@ OpCode ParamEntry::assumedExtension(const Address &addr,int4 sz,VarnodeData &res
|
|||
int4 ParamEntry::getSlot(const Address &addr,int4 skip) const
|
||||
|
||||
{
|
||||
int4 res = group;
|
||||
int4 res = groupSet[0];
|
||||
if (alignment != 0) {
|
||||
uintb diff = addr.getOffset() + skip - addressbase;
|
||||
int4 baseslot = (int4)diff / alignment;
|
||||
|
@ -389,7 +396,7 @@ int4 ParamEntry::getSlot(const Address &addr,int4 skip) const
|
|||
res += baseslot;
|
||||
}
|
||||
else if (skip != 0) {
|
||||
res += (groupsize-1);
|
||||
res = groupSet.back();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -456,7 +463,6 @@ void ParamEntry::decode(Decoder &decoder,bool normalstack,bool grouped,list<Para
|
|||
size = minsize = -1; // Must be filled in
|
||||
alignment = 0; // default
|
||||
numslots = 1;
|
||||
groupsize = 1; // default
|
||||
|
||||
uint4 elemId = decoder.openElement(ELEM_PENTRY);
|
||||
for(;;) {
|
||||
|
@ -646,16 +652,15 @@ Address ParamListStandard::assignAddress(const Datatype *tp,vector<int4> &status
|
|||
const ParamEntry &curEntry( *iter );
|
||||
int4 grp = curEntry.getGroup();
|
||||
if (status[grp]<0) continue;
|
||||
if ((curEntry.getType() != TYPE_UNKNOWN)&&
|
||||
tp->getMetatype() != curEntry.getType())
|
||||
if ((curEntry.getType() != TYPE_UNKNOWN) && tp->getMetatype() != curEntry.getType())
|
||||
continue; // Wrong type
|
||||
|
||||
Address res = curEntry.getAddrBySlot(status[grp],tp->getSize());
|
||||
if (res.isInvalid()) continue; // If -tp- doesn't fit an invalid address is returned
|
||||
if (curEntry.isExclusion()) {
|
||||
int4 maxgrp = grp + curEntry.getGroupSize();
|
||||
for(int4 j=grp;j<maxgrp;++j) // For an exclusion entry
|
||||
status[j] = -1; // some number of groups are taken up
|
||||
const vector<int4> &groupSet(curEntry.getAllGroups());
|
||||
for(int4 j=0;j<groupSet.size();++j) // For an exclusion entry
|
||||
status[groupSet[j]] = -1; // some number of groups are taken up
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -852,18 +857,18 @@ void ParamListStandard::separateSections(ParamActive *active,vector<int4> &trial
|
|||
///
|
||||
/// Only one trial within an exclusion group can have active use, mark all others as unused.
|
||||
/// \param active is the set of trials, which must be sorted on group
|
||||
/// \param groupUpper is the biggest group number to be marked
|
||||
/// \param groupStart is the index of the first trial in the smallest group to be marked
|
||||
/// \param index is the specified trial index that is \e not to be marked
|
||||
void ParamListStandard::markGroupNoUse(ParamActive *active,int4 groupUpper,int4 groupStart,int4 index)
|
||||
/// \param activeTrial is the index of the trial whose groups are to be considered active
|
||||
/// \param trialStart is the index of the first trial to mark
|
||||
void ParamListStandard::markGroupNoUse(ParamActive *active,int4 activeTrial,int4 trialStart)
|
||||
|
||||
{
|
||||
int4 numTrials = active->getNumTrials();
|
||||
for(int4 i=groupStart;i<numTrials;++i) { // Mark entries in the group range as definitely not used
|
||||
if (i == index) continue; // The trial NOT to mark
|
||||
const ParamEntry *activeEntry = active->getTrial(activeTrial).getEntry();
|
||||
for(int4 i=trialStart;i<numTrials;++i) { // Mark entries intersecting the group set as definitely not used
|
||||
if (i == activeTrial) continue; // The trial NOT to mark
|
||||
ParamTrial &othertrial(active->getTrial(i));
|
||||
if (othertrial.isDefinitelyNotUsed()) continue;
|
||||
if (othertrial.getEntry()->getGroup() > groupUpper) break;
|
||||
if (!othertrial.getEntry()->groupOverlap(*activeEntry)) break;
|
||||
othertrial.markNoUse();
|
||||
}
|
||||
}
|
||||
|
@ -889,7 +894,7 @@ void ParamListStandard::markBestInactive(ParamActive *active,int4 group,int4 gro
|
|||
const ParamEntry *entry = trial.getEntry();
|
||||
int4 grp = entry->getGroup();
|
||||
if (grp != group) break;
|
||||
if (entry->getGroupSize() > 1) continue; // Covering multiple slots automatically give low score
|
||||
if (entry->getAllGroups().size() > 1) continue; // Covering multiple slots automatically give low score
|
||||
int4 score = 0;
|
||||
if (trial.hasAncestorRealistic()) {
|
||||
score += 5;
|
||||
|
@ -904,7 +909,7 @@ void ParamListStandard::markBestInactive(ParamActive *active,int4 group,int4 gro
|
|||
}
|
||||
}
|
||||
if (bestTrial >= 0)
|
||||
markGroupNoUse(active, group, groupStart, bestTrial);
|
||||
markGroupNoUse(active, bestTrial, groupStart);
|
||||
}
|
||||
|
||||
/// \brief Enforce exclusion rules for the given set of parameter trials
|
||||
|
@ -932,8 +937,7 @@ void ParamListStandard::forceExclusionGroup(ParamActive *active)
|
|||
inactiveCount = 0;
|
||||
}
|
||||
if (curtrial.isActive()) {
|
||||
int4 groupUpper = grp + curtrial.getEntry()->getGroupSize() - 1; // This entry covers some number of groups
|
||||
markGroupNoUse(active, groupUpper, groupStart, i);
|
||||
markGroupNoUse(active, i, groupStart);
|
||||
}
|
||||
else {
|
||||
inactiveCount += 1;
|
||||
|
@ -969,9 +973,9 @@ void ParamListStandard::forceNoUse(ParamActive *active, int4 start, int4 stop)
|
|||
}
|
||||
else { // First trial in a new group (or next element in same non-exclusion group)
|
||||
if (alldefnouse) // If all in the last group were defnotused
|
||||
seendefnouse = true;// then force everything afterword to be defnotused
|
||||
seendefnouse = true;// then force everything afterward to be defnotused
|
||||
alldefnouse = curtrial.isDefinitelyNotUsed();
|
||||
curgroup = grp + curtrial.getEntry()->getGroupSize() - 1;
|
||||
curgroup = grp;
|
||||
}
|
||||
if (seendefnouse)
|
||||
curtrial.markInactive();
|
||||
|
@ -1131,7 +1135,7 @@ void ParamListStandard::parsePentry(Decoder &decoder,vector<EffectRecord> &effec
|
|||
else if (autokill) // If a register parameter AND we automatically generate killedbycall
|
||||
effectlist.push_back(EffectRecord(entry.back(),EffectRecord::killedbycall));
|
||||
|
||||
int4 maxgroup = entry.back().getGroup() + entry.back().getGroupSize();
|
||||
int4 maxgroup = entry.back().getAllGroups().back() + 1;
|
||||
if (maxgroup > numgroup)
|
||||
numgroup = maxgroup;
|
||||
}
|
||||
|
@ -1250,7 +1254,7 @@ bool ParamListStandard::possibleParamWithSlot(const Address &loc,int4 size,int4
|
|||
if (entryNum == (const ParamEntry *)0) return false;
|
||||
slot = entryNum->getSlot(loc,0);
|
||||
if (entryNum->isExclusion()) {
|
||||
slotsize = entryNum->getGroupSize();
|
||||
slotsize = entryNum->getAllGroups().size();
|
||||
}
|
||||
else {
|
||||
slotsize = ((size-1) / entryNum->getAlign()) + 1;
|
||||
|
|
|
@ -101,8 +101,7 @@ public:
|
|||
private:
|
||||
uint4 flags; ///< Boolean properties of the parameter
|
||||
type_metatype type; ///< Data-type class that this entry must match
|
||||
int4 group; ///< Group of (mutually exclusive) entries that this entry belongs to
|
||||
int4 groupsize; ///< The number of consecutive groups taken by the entry
|
||||
vector<int4> groupSet; ///< Group(s) \b this entry belongs to
|
||||
AddrSpace *spaceid; ///< Address space containing the range
|
||||
uintb addressbase; ///< Starting offset of the range
|
||||
int4 size; ///< Size of the range in bytes
|
||||
|
@ -117,9 +116,10 @@ private:
|
|||
/// \brief Is the logical value left-justified within its container
|
||||
bool isLeftJustified(void) const { return (((flags&force_left_justify)!=0)||(!spaceid->isBigEndian())); }
|
||||
public:
|
||||
ParamEntry(int4 grp) { group=grp; } ///< Constructor for use with decode
|
||||
int4 getGroup(void) const { return group; } ///< Get the group id \b this belongs to
|
||||
int4 getGroupSize(void) const { return groupsize; } ///< Get the number of groups occupied by \b this
|
||||
ParamEntry(int4 grp) { groupSet.push_back(grp); } ///< Constructor for use with decode
|
||||
int4 getGroup(void) const { return groupSet[0]; } ///< Get the group id \b this belongs to
|
||||
const vector<int4> &getAllGroups(void) const { return groupSet; } ///< Get all group numbers \b this overlaps
|
||||
bool groupOverlap(const ParamEntry &op2) const; ///< Check if \b this and op2 occupy any of the same groups
|
||||
int4 getSize(void) const { return size; } ///< Get the size of the memory range in bytes.
|
||||
int4 getMinSize(void) const { return minsize; } ///< Get the minimum size of a logical value contained in \b this
|
||||
int4 getAlign(void) const { return alignment; } ///< Get the alignment of \b this entry
|
||||
|
@ -567,7 +567,7 @@ protected:
|
|||
const ParamEntry *selectUnreferenceEntry(int4 grp,type_metatype prefType) const; ///< Select entry to fill an unreferenced param
|
||||
void buildTrialMap(ParamActive *active) const; ///< Build map from parameter trials to model ParamEntrys
|
||||
void separateSections(ParamActive *active,vector<int4> &trialStart) const;
|
||||
static void markGroupNoUse(ParamActive *active,int4 groupUpper,int4 groupStart,int4 index);
|
||||
static void markGroupNoUse(ParamActive *active,int4 activeTrial,int4 trialStart);
|
||||
static void markBestInactive(ParamActive *active,int4 group,int4 groupStart,type_metatype prefType);
|
||||
static void forceExclusionGroup(ParamActive *active);
|
||||
static void forceNoUse(ParamActive *active,int4 start,int4 stop);
|
||||
|
|
|
@ -50,8 +50,7 @@ public class ParamEntry {
|
|||
|
||||
private int flags;
|
||||
private int type; // Restriction on DataType this entry must match
|
||||
private int group; // Group of (mutually exclusive) entries that this entry belongs to
|
||||
private int groupsize; // The number of consecutive groups taken by the entry
|
||||
private int[] groupSet; // Group(s) this entry belongs to
|
||||
private AddressSpace spaceid; // Space of this range
|
||||
private long addressbase; // Start of the range
|
||||
private int size; // size of the range
|
||||
|
@ -61,15 +60,16 @@ public class ParamEntry {
|
|||
private Varnode[] joinrec;
|
||||
|
||||
public ParamEntry(int grp) { // For use with restoreXml
|
||||
group = grp;
|
||||
groupSet = new int[1];
|
||||
groupSet[0] = grp;
|
||||
}
|
||||
|
||||
public int getGroup() {
|
||||
return group;
|
||||
return groupSet[0];
|
||||
}
|
||||
|
||||
public int getGroupSize() {
|
||||
return groupsize;
|
||||
public int[] getAllGroups() {
|
||||
return groupSet;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
|
@ -265,7 +265,7 @@ public class ParamEntry {
|
|||
* @return the slot index
|
||||
*/
|
||||
public int getSlot(Address addr, int skip) {
|
||||
int res = group;
|
||||
int res = groupSet[0];
|
||||
if (alignment != 0) {
|
||||
long diff = addr.getOffset() + skip - addressbase;
|
||||
int baseslot = (int) diff / alignment;
|
||||
|
@ -277,7 +277,7 @@ public class ParamEntry {
|
|||
}
|
||||
}
|
||||
else if (skip != 0) {
|
||||
res += (groupsize - 1);
|
||||
res = groupSet[groupSet.length - 1];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -366,29 +366,24 @@ public class ParamEntry {
|
|||
if (joinrec == null) {
|
||||
return;
|
||||
}
|
||||
int mingrp = 1000;
|
||||
int maxgrp = -1;
|
||||
ArrayList<Integer> newGroupSet = new ArrayList<>();
|
||||
for (Varnode piece : joinrec) {
|
||||
ParamEntry entry = findEntryByStorage(curList, piece);
|
||||
if (entry != null) {
|
||||
if (entry.group < mingrp) {
|
||||
mingrp = entry.group;
|
||||
}
|
||||
int max = entry.group + entry.groupsize;
|
||||
if (max > maxgrp) {
|
||||
maxgrp = max;
|
||||
for (int group : entry.groupSet) {
|
||||
newGroupSet.add(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (maxgrp < 0 || mingrp >= 1000) {
|
||||
if (newGroupSet.isEmpty()) {
|
||||
throw new XmlParseException("<pentry> join must overlap at least one previous entry");
|
||||
}
|
||||
group = mingrp;
|
||||
groupsize = (maxgrp - mingrp);
|
||||
flags |= OVERLAPPING;
|
||||
if (groupsize > joinrec.length) {
|
||||
throw new XmlParseException("<pentry> join must overlap sequential entries");
|
||||
newGroupSet.sort(null);
|
||||
groupSet = new int[newGroupSet.size()];
|
||||
for (int i = 0; i < groupSet.length; ++i) {
|
||||
groupSet[i] = newGroupSet.get(i);
|
||||
}
|
||||
flags |= OVERLAPPING;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -401,9 +396,7 @@ public class ParamEntry {
|
|||
if (joinrec != null) {
|
||||
return;
|
||||
}
|
||||
int grpsize = 0;
|
||||
int mingrp = 1000;
|
||||
int maxgrp = -1;
|
||||
ArrayList<Integer> newGroupSet = new ArrayList<>();
|
||||
Address addr = spaceid.getAddress(addressbase);
|
||||
for (ParamEntry entry : curList) {
|
||||
if (entry == this) {
|
||||
|
@ -416,27 +409,22 @@ public class ParamEntry {
|
|||
if (entry.isOverlap()) {
|
||||
continue; // Don't count resources (already counted overlapped pentry)
|
||||
}
|
||||
if (entry.group < mingrp) {
|
||||
mingrp = entry.group;
|
||||
for (int group : entry.groupSet) {
|
||||
newGroupSet.add(group);
|
||||
}
|
||||
int max = entry.group + entry.groupsize;
|
||||
if (max > maxgrp) {
|
||||
maxgrp = max;
|
||||
}
|
||||
grpsize += entry.groupsize;
|
||||
}
|
||||
else {
|
||||
throw new XmlParseException("Illegal overlap of <pentry> in compiler spec");
|
||||
}
|
||||
}
|
||||
if (grpsize == 0) {
|
||||
if (newGroupSet.isEmpty()) {
|
||||
return; // No overlaps
|
||||
}
|
||||
if (grpsize != (maxgrp - mingrp)) {
|
||||
throw new XmlParseException("<pentry> must overlap sequential entries");
|
||||
newGroupSet.sort(null);
|
||||
groupSet = new int[newGroupSet.size()];
|
||||
for (int i = 0; i < groupSet.length; ++i) {
|
||||
groupSet[i] = newGroupSet.get(i);
|
||||
}
|
||||
group = mingrp;
|
||||
groupsize = grpsize;
|
||||
flags |= OVERLAPPING;
|
||||
}
|
||||
|
||||
|
@ -486,7 +474,6 @@ public class ParamEntry {
|
|||
size = minsize = -1; // Must be filled in
|
||||
alignment = 0; // default
|
||||
numslots = 1;
|
||||
groupsize = 1; // default
|
||||
|
||||
XmlElement el = parser.start("pentry");
|
||||
Iterator<Entry<String, String>> iter = el.getAttributes().entrySet().iterator();
|
||||
|
@ -606,9 +593,14 @@ public class ParamEntry {
|
|||
if (numslots != obj.numslots) {
|
||||
return false;
|
||||
}
|
||||
if (group != obj.group || groupsize != obj.groupsize) {
|
||||
if (groupSet.length != obj.groupSet.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < groupSet.length; ++i) {
|
||||
if (groupSet[i] != obj.groupSet[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!SystemUtilities.isArrayEqual(joinrec, obj.joinrec)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -107,10 +107,9 @@ public class ParamListStandard implements ParamList {
|
|||
continue; // -tp- does not fit in this entry
|
||||
}
|
||||
if (element.isExclusion()) {
|
||||
int maxgrp = grp + element.getGroupSize();
|
||||
for (int j = grp; j < maxgrp; ++j) {
|
||||
for (int group : element.getAllGroups()) {
|
||||
// For an exclusion entry
|
||||
status[j] = -1; // some number of groups are taken up
|
||||
status[group] = -1; // some number of groups are taken up
|
||||
}
|
||||
if (element.isFloatExtended()) {
|
||||
sz = element.getSize(); // Still use the entire container size, when assigning storage
|
||||
|
@ -264,7 +263,8 @@ public class ParamListStandard implements ParamList {
|
|||
if (pentry.getSpace().isStackSpace()) {
|
||||
spacebase = pentry.getSpace();
|
||||
}
|
||||
int maxgroup = pentry.getGroup() + pentry.getGroupSize();
|
||||
int[] groupSet = pentry.getAllGroups();
|
||||
int maxgroup = groupSet[groupSet.length - 1] + 1;
|
||||
if (maxgroup > numgroup) {
|
||||
numgroup = maxgroup;
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ public class ParamListStandard implements ParamList {
|
|||
ParamEntry curentry = entry[num];
|
||||
res.slot = curentry.getSlot(loc, 0);
|
||||
if (curentry.isExclusion()) {
|
||||
res.slotsize = curentry.getGroupSize();
|
||||
res.slotsize = curentry.getAllGroups().length;
|
||||
}
|
||||
else {
|
||||
res.slotsize = ((size - 1) / curentry.getAlign()) + 1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue