Candidate release of source code.

This commit is contained in:
Dan 2019-03-26 13:45:32 -04:00
parent db81e6b3b0
commit 79d8f164f8
12449 changed files with 2800756 additions and 16 deletions

View file

@ -0,0 +1,320 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "printjava.hh"
#include "funcdata.hh"
OpToken PrintJava::instanceof = { "instanceof", 2, 60, true, OpToken::binary, 1, 0, (OpToken *)0 };
// Constructing this registers the capability
PrintJavaCapability PrintJavaCapability::printJavaCapability;
PrintJavaCapability::PrintJavaCapability(void)
{
name = "java-language";
isdefault = false;
}
PrintLanguage *PrintJavaCapability::buildLanguage(Architecture *glb)
{
return new PrintJava(glb,name);
}
PrintJava::PrintJava(Architecture *glb,const string &nm) : PrintC(glb,nm)
{
option_NULL = true; // Automatically use 'null' token
nullToken = "null"; // Java standard lower-case 'null'
mods |= hide_thisparam; // turn on hiding of 'this' parameter
if (castStrategy != (CastStrategy *)0)
delete castStrategy;
castStrategy = new CastStrategyJava();
}
/// Print a data-type up to the identifier, store off array sizes
/// for printing after the identifier. Find the root type (the one with an identifier)
/// and the count number of wrapping arrays.
/// \param ct is the given data-type
/// \param noident is \b true if no identifier will be pushed with this declaration
void PrintJava::pushTypeStart(const Datatype *ct,bool noident)
{
int4 arrayCount = 0;
for(;;) {
if (ct->getMetatype() == TYPE_PTR) {
if (isArrayType(ct))
arrayCount += 1;
ct = ((TypePointer *)ct)->getPtrTo();
}
else if (ct->getName().size() != 0)
break;
else {
ct = glb->types->getTypeVoid();
break;
}
}
OpToken *tok;
if (noident)
tok = &type_expr_nospace;
else
tok = &type_expr_space;
pushOp(tok,(const PcodeOp *)0);
for(int4 i=0;i<arrayCount;++i)
pushOp(&subscript,(const PcodeOp *)0);
if (ct->getName().size()==0) { // Check for anonymous type
// We could support a struct or enum declaration here
string name = genericTypeName(ct);
pushAtom(Atom(name,typetoken,EmitXml::type_color,ct));
}
else {
pushAtom(Atom(ct->getName(),typetoken,EmitXml::type_color,ct));
}
for(int4 i=0;i<arrayCount;++i)
pushAtom(Atom("",blanktoken,EmitXml::no_color)); // Fill in the blank array index
}
void PrintJava::pushTypeEnd(const Datatype *ct)
{ // This routine doesn't have to do anything
}
void PrintJava::adjustTypeOperators(void)
{
TypeOp::selectJavaOperators(glb->inst,true);
}
/// References to java array objects where the underlying element is a java primitive look like:
/// - Pointer to int
/// - Pointer to bool
/// - Pointer to float
///
/// An array of java class objects is represented as a pointer to pointer data-type.
/// \param ct is the given data-type
/// \return \b true if the data-type references a java array object
bool PrintJava::isArrayType(const Datatype *ct)
{
if (ct->getMetatype() != TYPE_PTR) // Java arrays are always Ghidra pointer types
return false;
ct = ((TypePointer *)ct)->getPtrTo();
switch(ct->getMetatype()) {
case TYPE_UINT: // Pointer to unsigned is placeholder for class reference, not an array
if (ct->isCharPrint())
return true;
break;
case TYPE_INT:
case TYPE_BOOL:
case TYPE_FLOAT: // Pointer to primitive type is an array
case TYPE_PTR: // Pointer to class reference is an array
return true;
default:
break;
}
return false;
}
/// Assuming the given Varnode is a dereferenced pointer, determine whether
/// it needs to be represented using '[0]' syntax.
/// \param vn is the given Varnode
/// \return \b true if '[0]' syntax is required
bool PrintJava::needZeroArray(const Varnode *vn)
{
if (!isArrayType(vn->getType()))
return false;
if (vn->isExplicit()) return true;
if (!vn->isWritten()) return true;
OpCode opc = vn->getDef()->code();
if ((opc == CPUI_PTRADD)||(opc == CPUI_PTRSUB)||(opc == CPUI_CPOOLREF))
return false;
return true;
}
void PrintJava::printUnicode(ostream &s,int4 onechar) const
{
if (unicodeNeedsEscape(onechar)) {
switch(onechar) { // Special escape characters
case 0:
s << "\\0";
return;
case 8:
s << "\\b";
return;
case 9:
s << "\\t";
return;
case 10:
s << "\\n";
return;
case 12:
s << "\\f";
return;
case 13:
s << "\\r";
return;
case 92:
s << "\\\\";
return;
case '"':
s << "\\\"";
return;
case '\'':
s << "\\\'";
return;
}
// Generic unicode escape
if (onechar < 65536) {
s << "\\ux" << setfill('0') << setw(4) << hex << onechar;
}
else
s << "\\ux" << setfill('0') << setw(8) << hex << onechar;
return;
}
writeUtf8(s, onechar); // Emit normally
}
void PrintJava::opLoad(const PcodeOp *op)
{
uint4 m = mods | print_load_value;
bool printArrayRef = needZeroArray(op->getIn(1));
if (printArrayRef)
pushOp(&subscript,op);
pushVnImplied(op->getIn(1),op,m);
if (printArrayRef)
push_integer(0,4,false,(Varnode *)0,op);
}
void PrintJava::opStore(const PcodeOp *op)
{
uint4 m = mods | print_store_value; // Inform sub-tree that we are storing
pushOp(&assignment,op); // This is an assignment
if (needZeroArray(op->getIn(1))) {
pushOp(&subscript,op);
pushVnImplied(op->getIn(1),op,m);
push_integer(0,4,false,(Varnode *)0,op);
pushVnImplied(op->getIn(2),op,mods);
}
else {
// implied vn's pushed on in reverse order for efficiency
// see PrintLanguage::pushVnImplied
pushVnImplied(op->getIn(2),op,mods);
pushVnImplied(op->getIn(1),op,m);
}
}
void PrintJava::opCallind(const PcodeOp *op)
{
pushOp(&function_call,op);
// implied vn's pushed on in reverse order for efficiency
// see PrintLanguage::pushVnImplied
int4 startparam = isSet(hide_thisparam) && op->hasThisPointer() ? 2 : 1;
if (op->numInput()>startparam + 1) { // Multiple parameters
pushVnImplied(op->getIn(0),op,mods);
for(int4 i=startparam;i<op->numInput()-1;++i)
pushOp(&comma,op);
for(int4 i=op->numInput()-1;i>=startparam;--i)
pushVnImplied(op->getIn(i),op,mods);
}
else if (op->numInput()==startparam + 1) { // One parameter
pushVnImplied(op->getIn(startparam),op,mods);
pushVnImplied(op->getIn(0),op,mods);
}
else { // A void function
pushVnImplied(op->getIn(0),op,mods);
pushAtom(Atom("",blanktoken,EmitXml::no_color));
}
}
void PrintJava::opCpoolRefOp(const PcodeOp *op)
{
const Varnode *outvn = op->getOut();
const Varnode *vn0 = op->getIn(0);
vector<uintb> refs;
for(int4 i=1;i<op->numInput();++i)
refs.push_back(op->getIn(i)->getOffset());
const CPoolRecord *rec = glb->cpool->getRecord(refs);
if (rec == (const CPoolRecord *)0) {
pushAtom(Atom("UNKNOWNREF",syntax,EmitXml::const_color,op,outvn));
}
else {
switch(rec->getTag()) {
case CPoolRecord::string_literal:
{
ostringstream str;
int4 len = rec->getByteDataLength();
if (len > 2048)
len = 2048;
str << '\"';
escapeCharacterData(str,rec->getByteData(),len,1,false);
if (len == rec->getByteDataLength())
str << '\"';
else {
str << "...\"";
}
pushAtom(Atom(str.str(),vartoken,EmitXml::const_color,op,outvn));
break;
}
case CPoolRecord::class_reference:
pushAtom(Atom(rec->getToken(),vartoken,EmitXml::type_color,op,outvn));
break;
case CPoolRecord::instance_of:
{
Datatype *dt = rec->getType();
while(dt->getMetatype() == TYPE_PTR) {
dt = ((TypePointer *)dt)->getPtrTo();
}
pushOp(&instanceof,op);
pushVnImplied(vn0,op,mods);
pushAtom(Atom(dt->getName(),syntax,EmitXml::type_color,op,outvn));
break;
}
case CPoolRecord::primitive: // Should be eliminated
case CPoolRecord::pointer_method:
case CPoolRecord::pointer_field:
case CPoolRecord::array_length:
case CPoolRecord::check_cast:
default:
{
Datatype *ct = rec->getType();
EmitXml::syntax_highlight color = EmitXml::var_color;
if (ct->getMetatype() == TYPE_PTR) {
ct = ((TypePointer *)ct)->getPtrTo();
if (ct->getMetatype() == TYPE_CODE)
color = EmitXml::funcname_color;
}
if (vn0->isConstant()) { // If this is NOT relative to an object reference
pushAtom(Atom(rec->getToken(),vartoken,color,op,outvn));
}
else {
pushOp(&object_member,op);
pushVnImplied(vn0,op,mods);
pushAtom(Atom(rec->getToken(),syntax,color,op,outvn));
}
}
}
}
}