mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-26 11:46:52 +08:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
@@ -697,7 +697,7 @@ public class ElfHeader implements StructConverter {
|
||||
// p_vaddr to find it relative to a PT_LOAD segment
|
||||
long vaddr = dynamicHeaders[0].getVirtualAddress();
|
||||
if (vaddr == 0 || dynamicHeaders[0].getFileSize() == 0) {
|
||||
Msg.warn(this, "ELF Dynamic table appears to have been stripped from binary");
|
||||
logError("ELF Dynamic table appears to have been stripped from binary");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -931,7 +931,7 @@ public class ElfHeader implements StructConverter {
|
||||
!dynamicTable.containsDynamicValue(ElfDynamicType.DT_SYMENT) ||
|
||||
dynamicHashType == null) {
|
||||
if (dynamicStringTable != null) {
|
||||
Msg.warn(this, "Failed to parse DT_SYMTAB, missing dynamic dependency");
|
||||
logError("Failed to parse DT_SYMTAB, missing dynamic dependency");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -1012,14 +1012,26 @@ public class ElfHeader implements StructConverter {
|
||||
private int deriveGnuHashDynamicSymbolCount(long gnuHashTableOffset) throws IOException {
|
||||
int numBuckets = reader.readInt(gnuHashTableOffset);
|
||||
int symbolBase = reader.readInt(gnuHashTableOffset + 4);
|
||||
int bloomSize = reader.readInt(gnuHashTableOffset + 8);
|
||||
long bloomSize = reader.readUnsignedInt(gnuHashTableOffset + 8);
|
||||
// int bloomShift = reader.readInt(gnuHashTableOffset + 12);
|
||||
int bloomWordSize = is64Bit() ? 8 : 4;
|
||||
long bloomWordSize = is64Bit() ? 8 : 4;
|
||||
long bucketsOffset = gnuHashTableOffset + 16 + (bloomWordSize * bloomSize);
|
||||
|
||||
|
||||
// Identify restricted region which contains GNU hash table (arbitrary min-length)
|
||||
long maxOffset = getMaxOffsetForLoadedRegionContaining(gnuHashTableOffset, 12);
|
||||
if (maxOffset <= 0) {
|
||||
logError("Failed to idenitify loaded GNU Hash table");
|
||||
return 0;
|
||||
}
|
||||
|
||||
long bucketOffset = bucketsOffset;
|
||||
int maxSymbolIndex = 0;
|
||||
for (int i = 0; i < numBuckets; i++) {
|
||||
if (bucketOffset < gnuHashTableOffset || bucketOffset > maxOffset) {
|
||||
logError("Error occured while inspecting GNU Hash table");
|
||||
return 0;
|
||||
}
|
||||
int symbolIndex = reader.readInt(bucketOffset);
|
||||
if (symbolIndex > maxSymbolIndex) {
|
||||
maxSymbolIndex = symbolIndex;
|
||||
@@ -1032,6 +1044,10 @@ public class ElfHeader implements StructConverter {
|
||||
++maxSymbolIndex;
|
||||
long chainOffset = bucketOffset + (4 * chainIndex); // chains immediately follow buckets
|
||||
while (true) {
|
||||
if (chainOffset < gnuHashTableOffset || chainOffset > maxOffset) {
|
||||
logError("Error occured while inspecting GNU Hash table");
|
||||
return 0;
|
||||
}
|
||||
int chainValue = reader.readInt(chainOffset);
|
||||
if ((chainValue & 1) != 0) {
|
||||
break;
|
||||
@@ -1042,6 +1058,25 @@ public class ElfHeader implements StructConverter {
|
||||
return maxSymbolIndex;
|
||||
}
|
||||
|
||||
private long getMaxOffsetForLoadedRegionContaining(long offset, long minSize) {
|
||||
long maxOffset = -1;
|
||||
if (e_shnum != 0) {
|
||||
ElfSectionHeader sectionContaining =
|
||||
getSectionHeaderContainingFileRange(offset, minSize);
|
||||
if (sectionContaining != null) {
|
||||
maxOffset = sectionContaining.getOffset() + sectionContaining.getSize() - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ElfProgramHeader containingSegment =
|
||||
getProgramLoadHeaderContainingFileOffset(offset);
|
||||
if (containingSegment != null) {
|
||||
maxOffset = containingSegment.getOffset() + containingSegment.getFileSize() - 1;
|
||||
}
|
||||
}
|
||||
return maxOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk DT_GNU_XHASH table to determine dynamic symbol count
|
||||
* @param gnuHashTableOffset DT_GNU_XHASH table file offset
|
||||
@@ -1296,6 +1331,7 @@ public class ElfHeader implements StructConverter {
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
logError("Elf prelink read failure (see log)");
|
||||
Msg.error(this, "Elf prelink read failure", e);
|
||||
}
|
||||
return preLinkImageBase;
|
||||
|
||||
@@ -115,6 +115,15 @@ BitFieldTransform::BitFieldTransform(Funcdata *f,Datatype *dt,int4 off)
|
||||
isBigEndian = f->getArch()->getDefaultDataSpace()->isBigEndian();
|
||||
}
|
||||
|
||||
const vector<uint4> BitFieldInsertTransform::allowedFinalWrites = {
|
||||
CPUI_COPY, CPUI_INT_EQUAL, CPUI_INT_NOTEQUAL, CPUI_INT_SLESS, CPUI_INT_SLESSEQUAL,
|
||||
CPUI_INT_LESS, CPUI_INT_LESSEQUAL, CPUI_INT_ZEXT, CPUI_INT_SEXT, CPUI_INT_ADD, CPUI_INT_CARRY,
|
||||
CPUI_INT_SCARRY, CPUI_INT_XOR, CPUI_INT_AND, CPUI_INT_OR, CPUI_INT_LEFT, CPUI_INT_RIGHT,
|
||||
CPUI_INT_SRIGHT, CPUI_INT_MULT, CPUI_BOOL_NEGATE, CPUI_BOOL_XOR, CPUI_BOOL_AND, CPUI_BOOL_OR,
|
||||
CPUI_FLOAT_EQUAL, CPUI_FLOAT_NOTEQUAL, CPUI_FLOAT_LESS, CPUI_FLOAT_LESSEQUAL, CPUI_FLOAT_NAN,
|
||||
CPUI_SUBPIECE
|
||||
};
|
||||
|
||||
/// If the state is for a partial field whose storage location is overwritten
|
||||
/// later in the same basic block, return \b true
|
||||
/// \param state is the field
|
||||
@@ -794,10 +803,17 @@ BitFieldInsertTransform::BitFieldInsertTransform(Funcdata *f,PcodeOp *op,Datatyp
|
||||
outvn = op->getIn(0);
|
||||
if (!outvn->isWritten()) return;
|
||||
finalWriteOp = outvn->getDef(); // But use the op feeding the INDIRECT as the finalWriteOp
|
||||
if (!mappedVn->isAddrTied())
|
||||
return;
|
||||
// Check that op feeding INDIRECT is in the allowed list
|
||||
if (!binary_search(allowedFinalWrites.begin(),allowedFinalWrites.end(),finalWriteOp->code()))
|
||||
return;
|
||||
}
|
||||
else {
|
||||
outvn = finalWriteOp->getOut();
|
||||
mappedVn = outvn;
|
||||
if (!mappedVn->isAddrTied())
|
||||
return;
|
||||
}
|
||||
containerSize = outvn->getSize();
|
||||
originalValue = (Varnode *)0;
|
||||
@@ -1678,13 +1694,8 @@ int4 RuleBitFieldStore::applyOp(PcodeOp *op,Funcdata &data)
|
||||
void RuleBitFieldOut::getOpList(vector<uint4> &oplist) const
|
||||
|
||||
{
|
||||
uint4 list[]={ CPUI_COPY, CPUI_INT_EQUAL, CPUI_INT_NOTEQUAL, CPUI_INT_SLESS, CPUI_INT_SLESSEQUAL,
|
||||
CPUI_INT_LESS, CPUI_INT_LESSEQUAL, CPUI_INT_ZEXT, CPUI_INT_SEXT, CPUI_INT_ADD, CPUI_INT_CARRY,
|
||||
CPUI_INT_SCARRY, CPUI_INT_XOR, CPUI_INT_AND, CPUI_INT_OR, CPUI_INT_LEFT, CPUI_INT_RIGHT,
|
||||
CPUI_INT_SRIGHT, CPUI_INT_MULT, CPUI_BOOL_NEGATE, CPUI_BOOL_XOR, CPUI_BOOL_AND, CPUI_BOOL_OR,
|
||||
CPUI_FLOAT_EQUAL, CPUI_FLOAT_NOTEQUAL, CPUI_FLOAT_LESS, CPUI_FLOAT_LESSEQUAL, CPUI_FLOAT_NAN,
|
||||
CPUI_INDIRECT, CPUI_SUBPIECE };
|
||||
oplist.insert(oplist.end(),list,list+30);
|
||||
oplist.insert(oplist.end(),BitFieldInsertTransform::allowedFinalWrites.begin(),BitFieldInsertTransform::allowedFinalWrites.end());
|
||||
oplist.push_back(CPUI_INDIRECT);
|
||||
}
|
||||
|
||||
int4 RuleBitFieldOut::applyOp(PcodeOp *op,Funcdata &data)
|
||||
|
||||
@@ -112,6 +112,8 @@ public:
|
||||
BitFieldInsertTransform(Funcdata *f,PcodeOp *op,Datatype *dt,int4 off); ///< Construct from a terminating op
|
||||
bool doTrace(void); ///< Trace bitfields backward from the terminating op
|
||||
void apply(void); ///< Transform recovered expressions into INSERT operations
|
||||
|
||||
static const vector<uint4> allowedFinalWrites; ///< List of opcodes allowed for finalWriteOp (must be sorted)
|
||||
};
|
||||
|
||||
/// \brief Class that converts bitfield pull expressions into explicit ZPULL and SPULL operations
|
||||
|
||||
@@ -1806,18 +1806,16 @@ void RuleDoubleSub::getOpList(vector<uint4> &oplist) const
|
||||
int4 RuleDoubleSub::applyOp(PcodeOp *op,Funcdata &data)
|
||||
|
||||
{
|
||||
PcodeOp *op2;
|
||||
Varnode *vn;
|
||||
int4 offset1,offset2;
|
||||
|
||||
vn = op->getIn(0);
|
||||
Varnode *vn = op->getIn(0);
|
||||
if (!vn->isWritten()) return 0;
|
||||
op2 = vn->getDef();
|
||||
PcodeOp *op2 = vn->getDef();
|
||||
if (op2->code() != CPUI_SUBPIECE) return 0;
|
||||
offset1 = op->getIn(1)->getOffset();
|
||||
offset2 = op2->getIn(1)->getOffset();
|
||||
Varnode *inVn = op2->getIn(0);
|
||||
if (inVn->isFree()) return 0;
|
||||
int4 offset1 = op->getIn(1)->getOffset();
|
||||
int4 offset2 = op2->getIn(1)->getOffset();
|
||||
|
||||
data.opSetInput(op,op2->getIn(0),0); // Skip middleman
|
||||
data.opSetInput(op,inVn,0); // Skip middleman
|
||||
data.opSetInput(op,data.newConstant(4,offset1+offset2), 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user