Skip to content

Commit 719841e

Browse files
committed
Merge remote-tracking branch 'origin/patch'
2 parents 26053ae + 77cd164 commit 719841e

File tree

6 files changed

+66
-29
lines changed

6 files changed

+66
-29
lines changed

Ghidra/Features/Decompiler/src/decompile/cpp/database.cc

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -398,42 +398,53 @@ void Symbol::restoreXml(const Element *el)
398398
restoreXmlBody(list.begin());
399399
}
400400

401-
void FunctionSymbol::buildType(int4 size)
401+
/// Get the number of bytes consumed by a SymbolEntry representing \b this Symbol.
402+
/// By default, this is the number of bytes consumed by the Symbol's data-type.
403+
/// This gives the amount of leeway a search has when the address queried does not match
404+
/// the exact address of the Symbol. With functions, the bytes consumed by a SymbolEntry
405+
/// may not match the data-type size.
406+
/// \return the number of bytes in a default SymbolEntry
407+
int4 Symbol::getBytesConsumed(void) const
408+
409+
{
410+
return type->getSize();
411+
}
412+
413+
void FunctionSymbol::buildType(void)
402414

403415
{
404416
TypeFactory *types = scope->getArch()->types;
405417
type = types->getTypeCode();
406-
// Entries for functions have small size starting at the entry address
407-
// of the function in order to deal with non-contiguous functions
408-
// The size used to always be 1, but now we need sizes (slightly) larger than 1
409-
// to accomodate pointer constants that encode extra information in the lower bit(s)
410-
// of an otherwise aligned pointer. If the encoding is not aprior detected, it is interpreted
411-
// initially as a straight address that comes up 1 (or more) bytes off of the start of the function
412-
// In order to detect this, we need to lay down a slightly larger size than 1
413-
if (size > 1)
414-
type = types->getTypeArray(size,type);
415-
416418
flags |= Varnode::namelock | Varnode::typelock;
417419
}
418420

419421
/// Build a function \e shell, made up of just the name of the function and
420422
/// a placeholder data-type, without the underlying Funcdata object.
423+
/// A SymbolEntry for a function has a small size starting at the entry address,
424+
/// in order to deal with non-contiguous functions.
425+
/// We need a size (slightly) larger than 1 to accommodate pointer constants that encode
426+
/// extra information in the lower bit(s) of an otherwise aligned pointer.
427+
/// If the encoding is not initially detected, it is interpreted
428+
/// as a straight address that comes up 1 (or more) bytes off of the start of the function
429+
/// In order to detect this, we need to lay down a slightly larger size than 1
421430
/// \param sc is the Scope that will contain the new Symbol
422431
/// \param nm is the name of the new Symbol
423-
/// \param size is the number of bytes the Symbol should consume
432+
/// \param size is the number of bytes a SymbolEntry should consume
424433
FunctionSymbol::FunctionSymbol(Scope *sc,const string &nm,int4 size)
425434
: Symbol(sc)
426435
{
427436
fd = (Funcdata *)0;
428-
buildType(size);
437+
consumeSize = size;
438+
buildType();
429439
name = nm;
430440
}
431441

432442
FunctionSymbol::FunctionSymbol(Scope *sc,int4 size)
433443
: Symbol(sc)
434444
{
435445
fd = (Funcdata *)0;
436-
buildType(size);
446+
consumeSize = size;
447+
buildType();
437448
}
438449

439450
FunctionSymbol::~FunctionSymbol(void) {
@@ -469,9 +480,9 @@ void FunctionSymbol::restoreXml(const Element *el)
469480
fd = new Funcdata("",scope,Address());
470481
fd->restoreXml(el);
471482
name = fd->getName();
472-
if (type->getSize() < fd->getSize()) {
483+
if (consumeSize < fd->getSize()) {
473484
if ((fd->getSize()>1)&&(fd->getSize() <= 8))
474-
buildType(fd->getSize());
485+
consumeSize = fd->getSize();
475486
}
476487
}
477488
else { // functionshell
@@ -934,16 +945,17 @@ SymbolEntry *Scope::addMap(const SymbolEntry &entry)
934945
entry.symbol->flags |= Varnode::persist;
935946

936947
SymbolEntry *res;
948+
int4 consumeSize = entry.symbol->getBytesConsumed();
937949
if (entry.addr.isInvalid())
938-
res = addDynamicMapInternal(entry.symbol,Varnode::mapped,entry.hash,0,entry.symbol->getType()->getSize(),entry.uselimit);
950+
res = addDynamicMapInternal(entry.symbol,Varnode::mapped,entry.hash,0,consumeSize,entry.uselimit);
939951
else {
940952
if (entry.uselimit.empty()) {
941953
entry.symbol->flags |= Varnode::addrtied;
942954
// Global properties (like readonly and volatile)
943955
// can only happen if use is not limited
944956
entry.symbol->flags |= glb->symboltab->getProperty(entry.addr);
945957
}
946-
res = addMapInternal(entry.symbol,Varnode::mapped,entry.addr,0,entry.symbol->getType()->getSize(),entry.uselimit);
958+
res = addMapInternal(entry.symbol,Varnode::mapped,entry.addr,0,consumeSize,entry.uselimit);
947959
if (entry.addr.isJoin()) {
948960
// The address is a join, we add extra SymbolEntry maps for each of the pieces
949961
JoinRecord *rec = glb->findJoin(entry.addr.getOffset());

Ghidra/Features/Decompiler/src/decompile/cpp/database.hh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ public:
208208
void restoreXmlBody(List::const_iterator iter); ///< Restore details of the Symbol from XML
209209
virtual void saveXml(ostream &s) const; ///< Save \b this Symbol to an XML stream
210210
virtual void restoreXml(const Element *el); ///< Restore \b this Symbol from an XML stream
211+
virtual int4 getBytesConsumed(void) const; ///< Get number of bytes consumed within the address->symbol map
211212
};
212213

213214
/// Force a specific display format for constant symbols
@@ -235,14 +236,16 @@ inline bool SymbolEntry::isAddrTied(void) const {
235236
/// Symbol is thus associated with all the meta-data about the function.
236237
class FunctionSymbol : public Symbol {
237238
Funcdata *fd; ///< The underlying meta-data object for the function
239+
int4 consumeSize; ///< Minimum number of bytes to consume with the start address
238240
virtual ~FunctionSymbol(void);
239-
void buildType(int4 size); ///< Build the data-type associated with \b this Symbol
241+
void buildType(void); ///< Build the data-type associated with \b this Symbol
240242
public:
241243
FunctionSymbol(Scope *sc,const string &nm,int4 size); ///< Construct given the name
242244
FunctionSymbol(Scope *sc,int4 size); ///< Constructor for use with restoreXml
243245
Funcdata *getFunction(void); ///< Get the underlying Funcdata object
244246
virtual void saveXml(ostream &s) const;
245247
virtual void restoreXml(const Element *el);
248+
virtual int4 getBytesConsumed(void) const { return consumeSize; }
246249
};
247250

248251
/// \brief A Symbol that holds \b equate information for a constant

Ghidra/Features/Decompiler/src/decompile/cpp/ruleaction.cc

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6384,15 +6384,18 @@ int4 RulePtrsubCharConstant::applyOp(PcodeOp *op,Funcdata &data)
63846384
if (!isstring) return 0;
63856385

63866386
// If we reach here, the PTRSUB should be converted to a (COPY of a) pointer constant.
6387-
list<PcodeOp *>::const_iterator iter,enditer;
6388-
iter = outvn->beginDescend();
6389-
enditer = outvn->endDescend();
6390-
bool removeCopy = true;
6391-
while(iter != enditer) {
6392-
PcodeOp *subop = *iter; // Give each descendant of op a chance to further propagate the constant
6393-
++iter;
6394-
if (!pushConstFurther(data,outtype,subop,subop->getSlot(outvn),vn1->getOffset()))
6395-
removeCopy = false; // If the descendant does NOT propagate const, do NOT remove op
6387+
bool removeCopy = false;
6388+
if (!outvn->isAddrForce()) {
6389+
removeCopy = true; // Assume we can remove, unless we can't propagate to all descendants
6390+
list<PcodeOp *>::const_iterator iter,enditer;
6391+
iter = outvn->beginDescend();
6392+
enditer = outvn->endDescend();
6393+
while(iter != enditer) {
6394+
PcodeOp *subop = *iter; // Give each descendant of op a chance to further propagate the constant
6395+
++iter;
6396+
if (!pushConstFurther(data,outtype,subop,subop->getSlot(outvn),vn1->getOffset()))
6397+
removeCopy = false; // If the descendant does NOT propagate const, do NOT remove op
6398+
}
63966399
}
63976400
if (removeCopy) {
63986401
data.opDestroy(op);

Ghidra/Features/Decompiler/src/decompile/cpp/type.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,6 +1893,24 @@ Datatype *TypeFactory::downChain(Datatype *ptrtype,uintb &off)
18931893
return getTypePointer(ptype->size,pt,ptype->getWordSize());
18941894
}
18951895

1896+
/// The data-type propagation system can push around data-types that are \e partial or are
1897+
/// otherwise unrepresentable in the source language. This method substitutes those data-types
1898+
/// with a concrete data-type that is representable, or returns the same data-type if is already concrete.
1899+
/// Its important that the returned data-type have the same size as the original data-type regardless.
1900+
/// \param ct is the given data-type
1901+
/// \return the concrete data-type
1902+
Datatype *TypeFactory::concretize(Datatype *ct)
1903+
1904+
{
1905+
type_metatype metatype = ct->getMetatype();
1906+
if (metatype == TYPE_CODE) {
1907+
if (ct->getSize() != 1)
1908+
throw LowlevelError("Primitive code data-type that is not size 1");
1909+
ct = getBase(1, TYPE_UNKNOWN);
1910+
}
1911+
return ct;
1912+
}
1913+
18961914
/// Restore a Datatype object from an XML tag description: either \<type>, \<typeref>, or \<void>
18971915
/// \param el is the XML element describing the data-type
18981916
/// \return the restored Datatype object

Ghidra/Features/Decompiler/src/decompile/cpp/type.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ public:
435435
bool dotdotdot); ///< Create a "function" datatype
436436
void destroyType(Datatype *ct); ///< Remove a data-type from \b this
437437
Datatype *downChain(Datatype *ptrtype,uintb &off); ///< Find a sub-type matching a pointer and offset
438+
Datatype *concretize(Datatype *ct); ///< Convert given data-type to concrete form
438439
void dependentOrder(vector<Datatype *> &deporder) const; ///< Place all data-types in dependency order
439440
void saveXml(ostream &s) const; ///< Save \b this container to stream
440441
void saveXmlCoreTypes(ostream &s) const; ///< Save core types to stream

Ghidra/Features/Decompiler/src/decompile/cpp/varmap.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ void ScopeLocal::createEntry(const RangeHint &a)
516516
{
517517
Address addr(space,a.start);
518518
Address usepoint;
519-
Datatype *ct = a.type;
519+
Datatype *ct = glb->types->concretize(a.type);
520520
int4 num = a.size/ct->getSize();
521521
if (num>1)
522522
ct = glb->types->getTypeArray(num,ct);

0 commit comments

Comments
 (0)