diff --git a/.gitattributes b/.gitattributes index acacbe10b14a2b4a97db621a61c078cdc058200a..ff4be8ed7f6270b2e5c85bfd9d4240b39a3e88a4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -198,6 +198,7 @@ libIRDB/include/core/function.hpp -text libIRDB/include/core/instruction.hpp -text libIRDB/include/core/pqxxdb.hpp -text libIRDB/include/core/reloc.hpp -text +libIRDB/include/core/type.hpp -text libIRDB/include/core/variantid.hpp -text libIRDB/include/libIRDB-cfg.hpp -text libIRDB/include/libIRDB-core.hpp -text @@ -223,6 +224,7 @@ libIRDB/src/core/function.cpp -text libIRDB/src/core/generate_spri.cpp -text libIRDB/src/core/instruction.cpp -text libIRDB/src/core/pqxxdb.cpp -text +libIRDB/src/core/type.cpp -text libIRDB/src/core/variantid.cpp -text libIRDB/src/syscall/Makefile.in -text libIRDB/src/syscall/syscall.cpp -text @@ -259,6 +261,7 @@ libMEDSannotation/include/MEDS_AnnotationParser.hpp -text libMEDSannotation/include/MEDS_FPTRShadowAnnotation.hpp -text libMEDSannotation/include/MEDS_FRSafeAnnotation.hpp -text libMEDSannotation/include/MEDS_FuncAnnotation.hpp -text +libMEDSannotation/include/MEDS_FuncPrototypeAnnotation.hpp -text libMEDSannotation/include/MEDS_InstructionCheckAnnotation.hpp -text libMEDSannotation/include/MEDS_ProblemFuncAnnotation.hpp -text libMEDSannotation/include/MEDS_Register.hpp -text @@ -269,6 +272,7 @@ libMEDSannotation/src/FuncExitAnnotation.cpp -text libMEDSannotation/src/MEDS_AnnotationParser.cpp -text libMEDSannotation/src/MEDS_FPTRShadowAnnotation.cpp -text libMEDSannotation/src/MEDS_FRSafeAnnotation.cpp -text +libMEDSannotation/src/MEDS_FuncPrototypeAnnotation.cpp -text libMEDSannotation/src/MEDS_InstructionCheckAnnotation.cpp -text libMEDSannotation/src/MEDS_ProblemFuncAnnotation.cpp -text libMEDSannotation/src/MEDS_Register.cpp -text diff --git a/libIRDB/include/core/address.hpp b/libIRDB/include/core/address.hpp index df806d335d812bab218ec76b1de2aadce581a19b..dd267e9aa1eb2a1ad738aa87b2b3761d3e725574 100644 --- a/libIRDB/include/core/address.hpp +++ b/libIRDB/include/core/address.hpp @@ -46,8 +46,7 @@ class AddressID_t : public BaseObj_t virtual_offset_t GetVirtualOffset() { return virtual_offset; } void SetVirtualOffset(virtual_offset_t voff) { virtual_offset=voff; } - void WriteToDB() { assert(0); } - std::string WriteToDB(File_t *vid, db_id_t newid, bool p_withHeader); + std::string WriteToDB(File_t *vid, db_id_t newid, bool p_withHeader); inline bool operator<(const AddressID_t& cmp) const { return fileID < cmp.fileID || (fileID == cmp.fileID && virtual_offset < cmp.virtual_offset);} diff --git a/libIRDB/include/core/baseobj.hpp b/libIRDB/include/core/baseobj.hpp index 96606299729574c0fe4d03be7f96238d9f31c322..b3d78a64cce6b34944a1d55a535ea1c90b85178c 100644 --- a/libIRDB/include/core/baseobj.hpp +++ b/libIRDB/include/core/baseobj.hpp @@ -39,11 +39,8 @@ class BaseObj_t db_id_t GetDoipID() const { return doip ? doip->GetBaseID() : NOT_IN_DATABASE; } void SetDoipID(doip_t *dp) { doip=dp; } void SetBaseID(db_id_t id) {base_id=id; } - - // A derived class must provide functionality to write to the database. - virtual void WriteToDB()=0; - static const db_id_t NOT_IN_DATABASE; + static const db_id_t NOT_IN_DATABASE; protected: static DBinterface_t *dbintr; @@ -51,6 +48,5 @@ class BaseObj_t private: doip_t* doip; db_id_t base_id; // -1 means not yet in the DB. - }; diff --git a/libIRDB/include/core/file.hpp b/libIRDB/include/core/file.hpp index 500bd84db3c77776cb3cacde2e63649bda6b92bc..65c5ac8faa9b5de05356d7fd6d6185249a3f4277 100644 --- a/libIRDB/include/core/file.hpp +++ b/libIRDB/include/core/file.hpp @@ -24,7 +24,7 @@ class File_t : public BaseObj_t public: // create new item. File_t(db_id_t file_id, db_id_t orig_fid, std::string url, std::string hash, std::string arch, int elfoid, - std::string atn, std::string ftn, std::string itn, std::string rtn, db_id_t doipid); + std::string atn, std::string ftn, std::string itn, std::string rtn, std::string typ, db_id_t doipid); File_t(db_id_t file_id) : BaseObj_t(NULL) { assert(0);} // read from DB void WriteToDB() { assert(0); } // writes to DB ID is not -1. @@ -33,6 +33,7 @@ class File_t : public BaseObj_t std::string GetFunctionTableName() { return function_table_name; } std::string GetInstructionTableName() { return instruction_table_name; } std::string GetRelocationsTableName() { return relocs_table_name; } + std::string GetTypesTableName() { return types_table_name; } std::string GetURL() { return url; } void CreateTables(); @@ -45,8 +46,11 @@ class File_t : public BaseObj_t friend class Instruction_t; friend class VariantID_t; friend class Relocation_t; - - + friend class Type_t; + friend class BasicType_t; + friend class PointerType_t; + friend class AggregateType_t; + friend class FuncType_t; private: db_id_t orig_fid; @@ -57,5 +61,6 @@ class File_t : public BaseObj_t std::string function_table_name; std::string instruction_table_name; std::string relocs_table_name; + std::string types_table_name; int elfoid; }; diff --git a/libIRDB/include/core/fileir.hpp b/libIRDB/include/core/fileir.hpp index 25a07d9798f2f2b8a41dc5e0b8c007372b71046a..41da122ae61594b0857f61e975ee5fdfcb8e5c85 100644 --- a/libIRDB/include/core/fileir.hpp +++ b/libIRDB/include/core/fileir.hpp @@ -18,9 +18,10 @@ * */ +#include "type.hpp" typedef std::set<Function_t*> FunctionSet_t; -typedef std::set<AddressID_t*> AddressSet_t;; +typedef std::set<AddressID_t*> AddressSet_t; // A variant of a problem, this // may be an original variant @@ -90,13 +91,15 @@ class FileIR_t : public BaseObj_t InstructionSet_t insns; AddressSet_t addrs; RelocationSet_t relocs; + TypeSet_t types; VariantID_t progid; File_t* fileptr; std::map<db_id_t,AddressID_t*> ReadAddrsFromDB(); std::map<db_id_t,Function_t*> ReadFuncsFromDB ( - std::map<db_id_t,AddressID_t*> &addrMap + std::map<db_id_t,AddressID_t*> &addrMap, + std::map<db_id_t,Type_t*> &typeMap ); std::map<db_id_t,Instruction_t*> ReadInsnsFromDB ( @@ -108,7 +111,10 @@ class FileIR_t : public BaseObj_t std::map<db_id_t,Instruction_t*> &insnMap ); + std::map<db_id_t, Type_t*> ReadTypesFromDB(TypeSet_t& types); + + // @TODO: need types }; diff --git a/libIRDB/include/core/function.hpp b/libIRDB/include/core/function.hpp index 2877dc1bac1a46c29d080dd027a451ea61c4d267..b7feeb19565352d188455400b9eef8e5f3251123 100644 --- a/libIRDB/include/core/function.hpp +++ b/libIRDB/include/core/function.hpp @@ -18,6 +18,7 @@ * */ +#include "core/type.hpp" typedef std::set<Instruction_t*> InstructionSet_t; @@ -29,7 +30,7 @@ class Function_t : public BaseObj_t Function_t() : BaseObj_t(NULL) {} // create a new function not in the db // create a function that's already in the DB - Function_t(db_id_t id, std::string name, int size, int oa_size, bool use_fp, Instruction_t *entry); + Function_t(db_id_t id, std::string name, int size, int oa_size, bool use_fp, FuncType_t *, Instruction_t *entry); InstructionSet_t& GetInstructions() { return my_insns; } @@ -42,14 +43,16 @@ class Function_t : public BaseObj_t void SetOutArgsRegionSize(int oa_size) {out_args_region_size=oa_size;} void SetEntryPoint(Instruction_t *insn) {entry_point=insn;} - Instruction_t* GetEntryPoint() { return entry_point;} + Instruction_t* GetEntryPoint() const { return entry_point;} - void WriteToDB(); // we need the variant ID to write into a program. std::string WriteToDB(File_t *fid, db_id_t newid); - bool GetUseFramePointer() { return use_fp; } + bool GetUseFramePointer() const { return use_fp; } void SetUseFramePointer(bool useFP) { use_fp = useFP; } + void SetType(FuncType_t *t) { function_type = t; } + FuncType_t* GetType() const { return function_type; } + private: Instruction_t *entry_point; @@ -58,5 +61,6 @@ class Function_t : public BaseObj_t std::string name; int out_args_region_size; bool use_fp; + FuncType_t *function_type; }; diff --git a/libIRDB/include/core/type.hpp b/libIRDB/include/core/type.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ad9bbb379a6e6649f1ccd9229b1da8ee60114330 --- /dev/null +++ b/libIRDB/include/core/type.hpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2014 - Zephyr Software LLC + * + * This file may be used and modified for non-commercial purposes as long as + * all copyright, permission, and nonwarranty notices are preserved. + * Redistribution is prohibited without prior written consent from Zephyr + * Software. + * + * Please contact the authors for restrictions applying to commercial use. + * + * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Author: Zephyr Software + * e-mail: jwd@zephyr-software.com + * URL : http://www.zephyr-software.com/ + * + */ + +#ifndef _IRDB_TYPE_H_ +#define _IRDB_TYPE_H_ + +// add as many types as you want here +// MUST MATCH code in meds2pdb!!! +typedef enum IRDB_Type { + T_UNKNOWN = 0, // must be 0, leave this value alone + T_NUMERIC = 1, T_POINTER = 2, + T_VOID = 10, T_VARIADIC = 11, T_INT = 12, T_CHAR = 13, T_FLOAT = 14, T_DOUBLE = 15, + T_TYPEDEF = 21, T_SUBTYPE = 22, + T_FUNC = 100, T_AGGREGATE = 101 +} IRDB_Type; + +class Type_t; + +typedef std::set<Type_t*> TypeSet_t; +typedef std::vector<Type_t*> TypeVector_t; + +class Type_t : public BaseObj_t +{ + public: + Type_t() : BaseObj_t(NULL) { + typeID = T_UNKNOWN; + } + Type_t(db_id_t dbid, IRDB_Type t, std::string n) : BaseObj_t(NULL) { + SetBaseID(dbid); + typeID = t; + name = n; + } + virtual ~Type_t() {} + + virtual std::string WriteToDB(File_t *fid, db_id_t newid) = 0; + + std::string GetName() const { return name; } + void SetName(std::string newname) { name=newname; } + IRDB_Type GetTypeID() const { return typeID; } + void SetTypeID(IRDB_Type t) { typeID = t; } + + virtual bool IsUnknownType() const { return typeID == T_UNKNOWN; } + virtual bool IsVariadicType() const { return typeID == T_VARIADIC; } + virtual bool IsAggregateType() const { return typeID == T_AGGREGATE; } + virtual bool IsFuncType() const { return typeID == T_FUNC; } + virtual bool IsBasicType() const { return false; } + virtual bool IsPointerType() const { return false; } + virtual bool IsNumericType() const { return false; } + + private: + std::string name; + IRDB_Type typeID; +}; + +class BasicType_t : public Type_t +{ + public: + BasicType_t() : Type_t() {} + BasicType_t(db_id_t id, IRDB_Type type, std::string name) : Type_t(id, type, name) {} + virtual ~BasicType_t() {} + + virtual bool IsBasicType() const { return true; } + virtual bool IsNumericType() const; + + std::string WriteToDB(File_t *fid, db_id_t newid); +}; + +class PointerType_t : public Type_t +{ + public: + PointerType_t() : Type_t() { SetTypeID(T_POINTER); referentType = NULL; } + PointerType_t(db_id_t id, Type_t* ref, std::string name) : Type_t(id, T_POINTER, name) { + SetReferentType(ref); + } + virtual ~PointerType_t() {} + virtual bool IsPointerType() const { return true; } + + Type_t* GetReferentType() const { return referentType; } + void SetReferentType(Type_t* r) { referentType = r; } + + std::string WriteToDB(File_t *fid, db_id_t newid); + + private: + Type_t* referentType; +}; + +class AggregateType_t : public Type_t +{ + public: + AggregateType_t() : Type_t() { SetTypeID(T_AGGREGATE); } + AggregateType_t(db_id_t id, std::string name) : Type_t(id, T_AGGREGATE, name) {} + virtual ~AggregateType_t() {} + virtual bool IsAggregateType() const { return true; } + + void AddAggregatedType(Type_t *t, int pos); + virtual int GetNumAggregatedTypes() const { return refTypes.size(); } + Type_t* GetAggregatedType(int pos) const { + return (pos >= 0 && pos < refTypes.size()) ? refTypes.at(pos) : NULL; + } + + std::string toString() { + return GetName(); + } + + std::string WriteToDB(File_t *fid, db_id_t newid); + + private: + TypeVector_t refTypes; +}; + +class FuncType_t : public Type_t +{ + public: + FuncType_t() : Type_t() { SetTypeID(T_FUNC); _init(); } + FuncType_t(db_id_t id, std::string name) : Type_t(id, T_FUNC, name) { _init(); } + virtual ~FuncType_t() {} + + virtual bool IsFuncType() const { return true; } + + std::string WriteToDB(File_t *fid, db_id_t newid); + + Type_t* GetReturnType() const { return returnType; } + void SetReturnType(Type_t *t) { returnType = t; } + AggregateType_t* GetArgumentsType() const { return argsType; } + void SetArgumentsType(AggregateType_t *t) { argsType = t; } + + private: + void _init() { + returnType = NULL; + argsType = NULL; + } + + private: + Type_t* returnType; + AggregateType_t* argsType; +}; + +#endif diff --git a/libIRDB/include/libIRDB-core.hpp b/libIRDB/include/libIRDB-core.hpp index 2839f8343abbcf12e08009d95789234fa077210b..60ba8643cfb3f06bbdc3c2697c25b4ab4e5947fe 100644 --- a/libIRDB/include/libIRDB-core.hpp +++ b/libIRDB/include/libIRDB-core.hpp @@ -47,6 +47,7 @@ class Instruction_t; // forward decl for many classes #include <core/function.hpp> #include <core/variantid.hpp> #include <core/archdesc.hpp> +#include <core/type.hpp> #include <core/fileir.hpp> #include <core/pqxxdb.hpp> diff --git a/libIRDB/src/core/Makefile b/libIRDB/src/core/Makefile index a22f505dc84185d7ce62f157e4cf3f996397608d..21680626fb0e068dd52219f8ebc1b5a771e9776e 100644 --- a/libIRDB/src/core/Makefile +++ b/libIRDB/src/core/Makefile @@ -2,7 +2,7 @@ LIB=../../lib/libIRDB-core.a -OBJS=baseobj.o variantid.o pqxxdb.o dbinterface.o function.o fileir.o file.o instruction.o address.o generate_spri.o +OBJS=baseobj.o type.o variantid.o pqxxdb.o dbinterface.o function.o fileir.o file.o instruction.o address.o generate_spri.o all: $(OBJS) diff --git a/libIRDB/src/core/file.cpp b/libIRDB/src/core/file.cpp index ab5738523adbeecdda7f62a2f5babb499c007e86..9418828b8d300cd6495ecaf5d02471b70c411b28 100644 --- a/libIRDB/src/core/file.cpp +++ b/libIRDB/src/core/file.cpp @@ -32,13 +32,12 @@ using namespace std; File_t::File_t(db_id_t myfile_id, db_id_t my_orig_fid, std::string myurl, std::string myhash, std::string myarch, int myoid, - std::string atn, std::string ftn, std::string itn, std::string rtn, db_id_t mydoipid) : + std::string atn, std::string ftn, std::string itn, std::string rtn, std::string typ, db_id_t mydoipid) : BaseObj_t(NULL), url(myurl), hash(myhash), arch(myarch), elfoid(myoid), address_table_name(atn), function_table_name(ftn), instruction_table_name(itn), - relocs_table_name(rtn), orig_fid(my_orig_fid) + relocs_table_name(rtn), types_table_name(typ), orig_fid(my_orig_fid) { SetBaseID(myfile_id); - } @@ -55,6 +54,7 @@ void File_t::CreateTables() function_table_name+" "+ instruction_table_name+" "+ relocs_table_name+" "+ + types_table_name+" "+ tmpfile; system(command.c_str()); diff --git a/libIRDB/src/core/fileir.cpp b/libIRDB/src/core/fileir.cpp index b86c7cb1e8ed60b91fb722275588fcc3ff853824..cbf346b62a79fb5b67bc5dc55483d50bb5380e24 100644 --- a/libIRDB/src/core/fileir.cpp +++ b/libIRDB/src/core/fileir.cpp @@ -89,6 +89,11 @@ FileIR_t::~FileIR_t() { delete *i; } + + for(std::set<Type_t*>::const_iterator i=types.begin(); i!=types.end(); ++i) + { + delete *i; + } } // DB operations @@ -96,8 +101,9 @@ void FileIR_t::ReadFromDB() { entry_points.clear(); + std::map<db_id_t,Type_t*> typesMap = ReadTypesFromDB(types); std::map<db_id_t,AddressID_t*> addrMap=ReadAddrsFromDB(); - std::map<db_id_t,Function_t*> funcMap=ReadFuncsFromDB(addrMap); + std::map<db_id_t,Function_t*> funcMap=ReadFuncsFromDB(addrMap, typesMap); std::map<db_id_t,Instruction_t*> insnMap=ReadInsnsFromDB(funcMap,addrMap); ReadRelocsFromDB(insnMap); @@ -236,7 +242,8 @@ std::string FileIR_t::LookupAssembly(Instruction_t *instr) std::map<db_id_t,Function_t*> FileIR_t::ReadFuncsFromDB ( - std::map<db_id_t,AddressID_t*> &addrMap + std::map<db_id_t,AddressID_t*> &addrMap, + std::map<db_id_t,Type_t*> &typesMap ) { std::map<db_id_t,Function_t*> idMap; @@ -254,6 +261,7 @@ std::map<db_id_t,Function_t*> FileIR_t::ReadFuncsFromDB std::string name=dbintr->GetResultColumn("name"); int sfsize=atoi(dbintr->GetResultColumn("stack_frame_size").c_str()); int oasize=atoi(dbintr->GetResultColumn("out_args_region_size").c_str()); + db_id_t function_type_id=atoi(dbintr->GetResultColumn("type_id").c_str()); // postgresql encoding of boolean can be 'true', '1', 'T', 'y' bool useFP=false; const char *useFPstr= dbintr->GetResultColumn("use_frame_pointer").c_str(); @@ -265,7 +273,10 @@ std::map<db_id_t,Function_t*> FileIR_t::ReadFuncsFromDB db_id_t doipid=atoi(dbintr->GetResultColumn("doip_id").c_str()); - Function_t *newfunc=new Function_t(fid,name,sfsize,oasize,useFP,NULL); + FuncType_t* fnType = NULL; + if (typesMap.count(function_type_id) > 0) + fnType = dynamic_cast<FuncType_t*>(typesMap[function_type_id]); + Function_t *newfunc=new Function_t(fid,name,sfsize,oasize,useFP,fnType, NULL); entry_points[newfunc]=entry_point_id; //std::cout<<"Found function "<<name<<"."<<std::endl; @@ -445,12 +456,27 @@ void FileIR_t::WriteToDB() dbintr->IssueQuery(string("TRUNCATE TABLE ")+ fileptr->function_table_name + string(" cascade;")); dbintr->IssueQuery(string("TRUNCATE TABLE ")+ fileptr->address_table_name + string(" cascade;")); dbintr->IssueQuery(string("TRUNCATE TABLE ")+ fileptr->relocs_table_name + string(" cascade;")); + dbintr->IssueQuery(string("TRUNCATE TABLE ")+ fileptr->types_table_name + string(" cascade;")); /* and now that everything has an ID, let's write to the DB */ + + // write out the types + string q=string(""); + for(std::set<Type_t*>::const_iterator t=types.begin(); t!=types.end(); ++t) + { + q+=(*t)->WriteToDB(fileptr,j); // @TODO: wtf is j? + if(q.size()>1024*1024) + { + dbintr->IssueQuery(q); + q=string(""); + } + } + dbintr->IssueQuery(q); + bool withHeader; withHeader = true; - string q=string(""); + q=string(""); for(std::set<Function_t*>::const_iterator f=funcs.begin(); f!=funcs.end(); ++f) { q+=(*f)->WriteToDB(fileptr,j); @@ -536,6 +562,7 @@ void FileIR_t::WriteToDB() Relocation_t* reloc=*it; r+=reloc->WriteToDB(fileptr,*i); } + dbintr->IssueQuery(r); } dbintr->IssueQuery(q); @@ -573,6 +600,9 @@ void FileIR_t::SetBaseIDS() for(std::set<Relocation_t*>::const_iterator i=relocs.begin(); i!=relocs.end(); ++i) if((*i)->GetBaseID()==NOT_IN_DATABASE) (*i)->SetBaseID(j++); + for(std::set<Type_t*>::const_iterator i=types.begin(); i!=types.end(); ++i) + if((*i)->GetBaseID()==NOT_IN_DATABASE) + (*i)->SetBaseID(j++); } std::string Relocation_t::WriteToDB(File_t* fid, Instruction_t* myinsn) @@ -648,3 +678,193 @@ void FileIR_t::SetArchitecture() } ArchitectureDescription_t* FileIR_t::archdesc=NULL; + +std::map<db_id_t, Type_t*> FileIR_t::ReadTypesFromDB (TypeSet_t& types) +{ + std::map<db_id_t, Type_t*> tMap; + + // 3 pass algorithm. Must be done in this exact order as: + // aggregrate type depend on basic types + // function type depends on both aggregate and basic types + // + // pass 1: retrieve all basic types + // pass 2: retrieve all aggregate types + // pass 3: retrieve all function types + // + + // pass 1, get all the basic types first +// std::string q= "select * from " + fileptr->types_table_name + " WHERE ref_type_id = -1 AND ref_type_id2 = -1 AND pos = -1 order by type; "; + std::string q= "select * from " + fileptr->types_table_name + " WHERE ref_type_id = -1 order by type; "; + +// cout << "pass1: query: " << q; + + dbintr->IssueQuery(q); + + while(!dbintr->IsDone()) + { +// type_id integer, +// type integer DEFAULT 0, -- possible types (0: UNKNOWN) +// name text DEFAULT '', -- string representation of the type +// ref_type_id integer DEFAULT -1, -- for aggregate types and func +// pos integer DEFAULT -1, -- for aggregate types, position in aggregate +// ref_type_id2 integer DEFAULT -1, -- for func types +// doip_id integer DEFAULT -1 -- the DOIP + + db_id_t tid=atoi(dbintr->GetResultColumn("type_id").c_str()); + IRDB_Type type=(IRDB_Type)atoi(dbintr->GetResultColumn("type").c_str()); + std::string name=dbintr->GetResultColumn("name"); + BasicType_t *t = NULL; + +// cout << "fileir::ReadFromDB(): pass1: " << name << endl; + switch(type) { + case T_UNKNOWN: + case T_VOID: + case T_NUMERIC: + case T_VARIADIC: + case T_INT: + case T_CHAR: + case T_FLOAT: + case T_DOUBLE: + t = new BasicType_t(tid, type, name); + types.insert(t); + tMap[tid] = t; + break; + + case T_POINTER: + // do nothing for pointers + break; + + default: + cerr << "ReadTypesFromDB(): ERROR: pass 1 should only see basic types or pointer" << endl; + assert(0); + break; + } + + dbintr->MoveToNextRow(); + } // end pass1 + + char query[2048]; + + // pass2 get pointers + sprintf(query,"select * from %s WHERE type = %d;", fileptr->types_table_name.c_str(), T_POINTER); + dbintr->IssueQuery(query); + + while(!dbintr->IsDone()) + { + db_id_t tid=atoi(dbintr->GetResultColumn("type_id").c_str()); + IRDB_Type type=(IRDB_Type)atoi(dbintr->GetResultColumn("type").c_str()); + std::string name=dbintr->GetResultColumn("name"); + db_id_t ref1=atoi(dbintr->GetResultColumn("ref_type_id").c_str()); + cout << "fileir::ReadFromDB(): pass2 (pointers): " << name << endl; + switch(type) { + case T_POINTER: + { + cout << " pointer type: ref1: " << ref1 << endl; + Type_t *referentType = NULL; + if (ref1 >= 0) + { + assert(tMap.count(ref1) > 0); + referentType = tMap[ref1]; + } + PointerType_t *ptr = new PointerType_t(tid, referentType, name); + types.insert(ptr); + tMap[tid] = ptr; + } + break; + + default: + cerr << "ReadTypesFromDB(): ERROR: pass3: unhandled type id = " << type << endl; + assert(0); // not yet handled + break; + + } + + dbintr->MoveToNextRow(); + } // end pass3 + + // pass3 get all aggregates + sprintf(query,"select * from %s WHERE type = %d order by type_id, pos;", fileptr->types_table_name.c_str(), T_AGGREGATE); + dbintr->IssueQuery(query); + + while(!dbintr->IsDone()) + { + db_id_t tid=atoi(dbintr->GetResultColumn("type_id").c_str()); + IRDB_Type type=(IRDB_Type)atoi(dbintr->GetResultColumn("type").c_str()); + std::string name=dbintr->GetResultColumn("name"); + db_id_t ref1=atoi(dbintr->GetResultColumn("ref_type_id").c_str()); + int pos=atoi(dbintr->GetResultColumn("pos").c_str()); + AggregateType_t *agg = NULL; + cout << "fileir::ReadFromDB(): pass3 (aggregates): " << name << endl; + switch(type) { + case T_AGGREGATE: + { + if (tMap.count(tid) == 0) // new aggregate + { + cout << "fileir::ReadFromDB(): pass3: new aggregate type: typeid: " << tid << " name: " << name << endl; + agg = new AggregateType_t(tid, name); + types.insert(agg); + tMap[tid] = agg; + } + else + agg = dynamic_cast<AggregateType_t*>(tMap[tid]); + + assert(agg); + // ref1 has the id of a basic type, look it up + Type_t *ref = tMap.at(ref1); + assert(ref); + agg->AddAggregatedType(ref, pos); + } + break; + + default: + cerr << "ReadTypesFromDB(): ERROR: pass2: unhandled type id = " << type << endl; + assert(0); // not yet handled + break; + + } + + dbintr->MoveToNextRow(); + } // end pass3 + + // pass4 get all functions + sprintf(query,"select * from %s WHERE type = %d;", fileptr->types_table_name.c_str(), T_FUNC); + dbintr->IssueQuery(query); + + while(!dbintr->IsDone()) + { + db_id_t tid=atoi(dbintr->GetResultColumn("type_id").c_str()); + IRDB_Type type=(IRDB_Type)atoi(dbintr->GetResultColumn("type").c_str()); + std::string name=dbintr->GetResultColumn("name"); + db_id_t ref1=atoi(dbintr->GetResultColumn("ref_type_id").c_str()); + db_id_t ref2=atoi(dbintr->GetResultColumn("ref_type_id2").c_str()); + FuncType_t *fn = NULL; + + switch(type) { + case T_FUNC: + { + assert(tMap.count(tid) == 0); + + fn = new FuncType_t(tid, name); + types.insert(fn); + tMap[tid] = fn; + assert(tMap.at(ref1)); // return type + assert(tMap.at(ref2)); // argument type (which is an aggregate) + fn->SetReturnType(tMap[ref1]); + AggregateType_t *args = dynamic_cast<AggregateType_t*>(tMap[ref2]); + assert(args); + fn->SetArgumentsType(args); + } + break; + + default: + cerr << "ReadTypesFromDB(): ERROR: pass4: unhandled type id = " << type << endl; + assert(0); // not yet handled + break; + + } + + dbintr->MoveToNextRow(); + } // end pass4 + + return tMap; +} diff --git a/libIRDB/src/core/function.cpp b/libIRDB/src/core/function.cpp index 87c17264140044b8b7d823fc14e2b8f0dc731533..44b505e5b31326bd19e37612783fae97cb0ee0ef 100644 --- a/libIRDB/src/core/function.cpp +++ b/libIRDB/src/core/function.cpp @@ -21,25 +21,19 @@ #include <all.hpp> #include <utils.hpp> #include <stdlib.h> + using namespace libIRDB; using namespace std; - - -Function_t::Function_t(db_id_t id, std::string myname, int size, int oa_size, bool useFP, Instruction_t* entry) +Function_t::Function_t(db_id_t id, std::string myname, int size, int oa_size, bool useFP, FuncType_t *fn_type, Instruction_t* entry) : BaseObj_t(NULL), entry_point(entry) { SetBaseID(id); name=myname; stack_frame_size=size; out_args_region_size=oa_size; - use_fp = useFP; -} - - -void Function_t::WriteToDB() -{ - assert(0); + use_fp = useFP; + function_type = fn_type; } string Function_t::WriteToDB(File_t *fid, db_id_t newid) @@ -53,8 +47,12 @@ string Function_t::WriteToDB(File_t *fid, db_id_t newid) if(GetBaseID()==NOT_IN_DATABASE) SetBaseID(newid); + int function_type_id = NOT_IN_DATABASE; + if (GetType()) + function_type_id = GetType()->GetBaseID(); + string q=string("insert into ")+fid->function_table_name + - string(" (function_id, entry_point_id, name, stack_frame_size, out_args_region_size, use_frame_pointer, doip_id) ")+ + string(" (function_id, entry_point_id, name, stack_frame_size, out_args_region_size, use_frame_pointer, type_id, doip_id) ")+ string(" VALUES (") + string("'") + to_string(GetBaseID()) + string("', ") + string("'") + to_string(entryid) + string("', ") + @@ -62,6 +60,7 @@ string Function_t::WriteToDB(File_t *fid, db_id_t newid) string("'") + to_string(stack_frame_size) + string("', ") + string("'") + to_string(out_args_region_size) + string("', ") + string("'") + to_string(use_fp) + string("', ") + + string("'") + to_string(function_type_id) + string("', ") + string("'") + to_string(GetDoipID()) + string("') ; ") ; return q; diff --git a/libIRDB/src/core/type.cpp b/libIRDB/src/core/type.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f7171bae6c90738d8c7adb04c39e933c2a83bb44 --- /dev/null +++ b/libIRDB/src/core/type.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014 - Zephyr Software LLC + * + * This file may be used and modified for non-commercial purposes as long as + * all copyright, permission, and nonwarranty notices are preserved. + * Redistribution is prohibited without prior written consent from Zephyr + * Software. + * + * Please contact the authors for restrictions applying to commercial use. + * + * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Author: Zephyr Software + * e-mail: jwd@zephyr-software.com + * URL : http://www.zephyr-software.com/ + * + */ + +#include "all.hpp" +#include <utils.hpp> + +using namespace std; +using namespace libIRDB; + +bool BasicType_t::IsNumericType() const +{ + int type = GetTypeID(); + return type == T_NUMERIC || type == T_INT || type == T_FLOAT || type == T_DOUBLE || type == T_CHAR; +} + +/* +CREATE TABLE #TYP# +( + type_id integer, + type integer DEFAULT 0, -- possible types (0: UNKNOWN) + name text DEFAULT '', -- string representation of the type + ref_type_id integer DEFAULT -1, -- for aggregate types + pos integer DEFAULT -1, -- for aggregate types, position in aggregate + ref_type_id2 integer DEFAULT -1, -- for func types + doip_id integer DEFAULT -1 -- the DOIP +); +*/ + +string BasicType_t::WriteToDB(File_t *fid, db_id_t newid) +{ + assert(fid); + +// if(GetBaseID()==NOT_IN_DATABASE) +// SetBaseID(newid); + + string q=string("insert into ")+fid->types_table_name + + string(" (type_id, type, name, ref_type_id, pos, ref_type_id2) ")+ + string(" VALUES (") + + string("'") + to_string(GetBaseID()) + string("', ") + + string("'") + to_string(GetTypeID()) + string("', ") + + string("'") + GetName() + string("','-1','-1','-1') ; ") ; + +// cout << "BasicType_t::WriteToDB(): " << q << endl; + return q; +} + +string PointerType_t::WriteToDB(File_t *fid, db_id_t newid) +{ + assert(fid && GetReferentType()); + string q=string("insert into ")+fid->types_table_name + + string(" (type_id, type, name, ref_type_id,pos,ref_type_id2) ")+ + string(" VALUES (") + + string("'") + to_string(GetBaseID()) + string("', ") + + string("'") + to_string(GetTypeID()) + string("', ") + + string("'") + GetName() + string("', ") + + string("'") + to_string(GetReferentType()->GetBaseID()) + + string("','-1','-1') ; ") ; + +// cout << "PointerType_t::WriteToDB(): " << q << endl; + return q; +} + +string AggregateType_t::WriteToDB(File_t *fid, db_id_t newid) +{ + assert(fid); + assert(GetNumAggregatedTypes() > 0); + + string q; + + for (int i = 0; i < GetNumAggregatedTypes(); ++i) + { + Type_t* t = GetAggregatedType(i); + q+=string("insert into ")+fid->types_table_name + + string(" (type_id, type, name, ref_type_id, pos,ref_type_id2) ")+ + string(" VALUES (") + + string("'") + to_string(GetBaseID()) + string("', ") + + string("'") + to_string(GetTypeID()) + string("', ") + + string("'") + GetName() + string("', ") + + string("'") + to_string(t->GetBaseID()) + string("', ") + + string("'") + to_string(i) + + string("','-1') ; ") ; + } + + // cout << "AggregatedType_t::WriteToDB(): " << q << endl; + return q; +} + +void AggregateType_t::AddAggregatedType(Type_t *t, int pos) +{ + refTypes.push_back(t); + +// cout << "AggregatedType_t::AddAggregatedType(): new size: " << refTypes.size() << endl; +} + +/* +CREATE TABLE #TYP# +( + type_id integer, + type integer DEFAULT 0, -- possible types (0: UNKNOWN) + name text DEFAULT '', -- string representation of the type + ref_type_id integer DEFAULT -1, -- for aggregate types + pos integer DEFAULT -1, -- for aggregate types, position in aggregate + ref_type_id2 integer DEFAULT -1, -- for func types + doip_id integer DEFAULT -1 -- the DOIP +); +*/ +string FuncType_t::WriteToDB(File_t *fid, db_id_t newid) +{ + assert(fid); + assert(GetReturnType()); + assert(GetArgumentsType()); + string q=string("insert into ")+fid->types_table_name + + string(" (type_id, type, name, ref_type_id, ref_type_id2,pos) ")+ + string(" VALUES (") + + string("'") + to_string(GetBaseID()) + string("', ") + + string("'") + to_string(GetTypeID()) + string("', ") + + string("'") + GetName() + string("', ") + + string("'") + to_string(GetReturnType()->GetBaseID()) + string("', ") + + string("'") + to_string(GetArgumentsType()->GetBaseID()) + + string("','-1') ; ") ; + +// cout << "FuncType_t::WriteToDB(): " << q << endl; + return q; +} + diff --git a/libIRDB/src/core/variantid.cpp b/libIRDB/src/core/variantid.cpp index 9de133fb3953457b9b137b661bdad163c0170572..b7d9cd640d2ad233ab032a0909650ad6b79b279b 100644 --- a/libIRDB/src/core/variantid.cpp +++ b/libIRDB/src/core/variantid.cpp @@ -186,6 +186,7 @@ File_t* VariantID_t::CloneFile(File_t* fptr) std::string ftn="ftnfid"+to_string(newfid); std::string itn="itnfid"+to_string(newfid); std::string rtn="rtnfid"+to_string(newfid); + std::string typ="typfid"+to_string(newfid); q ="update file_info set address_table_name='"; q+=atn; @@ -195,6 +196,8 @@ File_t* VariantID_t::CloneFile(File_t* fptr) q+=itn; q+="', relocs_table_name='"; q+=rtn; + q+="', types_table_name='"; + q+=typ; q+="' where file_id='"; q+=to_string(newfid); q+="' ; "; @@ -202,7 +205,7 @@ File_t* VariantID_t::CloneFile(File_t* fptr) dbintr->IssueQuery(q); File_t* newfile=new File_t(newfid, fptr->orig_fid, fptr->url, fptr->hash, fptr->arch, fptr->elfoid, - atn, ftn, itn, rtn, fptr->GetDoipID()); + atn, ftn, itn, rtn, typ, fptr->GetDoipID()); newfile->CreateTables(); @@ -227,6 +230,10 @@ File_t* VariantID_t::CloneFile(File_t* fptr) q+=" ; "; dbintr->IssueQuery(q); + q="drop table "; + q+=typ; + q+=" ; "; + dbintr->IssueQuery(q); // next issue SQL to clone each table q="select * into "; @@ -257,6 +264,13 @@ File_t* VariantID_t::CloneFile(File_t* fptr) q+=" ;"; dbintr->IssueQuery(q); + q="select * into "; + q+=typ; + q+=" from "; + q+=fptr->types_table_name; + q+=" ;"; + dbintr->IssueQuery(q); + // update the variant dependency table to represent the deep clone // update the variant dependency table to represent the deep clone @@ -339,7 +353,7 @@ void VariantID_t::ReadFilesFromDB() { std::string q= "select file_info.orig_file_id, file_info.address_table_name, file_info.instruction_table_name, " - " file_info.function_table_name, file_info.relocs_table_name, file_info.file_id, file_info.url, file_info.hash," + " file_info.function_table_name, file_info.relocs_table_name, file_info.types_table_name, file_info.file_id, file_info.url, file_info.hash," " file_info.arch, file_info.type, file_info.elfoid, file_info.doip_id " " from file_info,variant_dependency " " where variant_dependency.variant_id = '" + to_string(GetBaseID()) + "' AND " @@ -362,13 +376,14 @@ void VariantID_t::ReadFilesFromDB() std::string ftn=(BaseObj_t::dbintr->GetResultColumn("function_table_name")); std::string itn=(BaseObj_t::dbintr->GetResultColumn("instruction_table_name")); std::string rtn=(BaseObj_t::dbintr->GetResultColumn("relocs_table_name")); + std::string typ=(BaseObj_t::dbintr->GetResultColumn("types_table_name")); - File_t *newfile=new File_t(file_id,orig_fid,url,hash,type,oid,atn,ftn,itn,rtn,doipid); - -//std::cout<<"Found file "<<file_id<<"."<<std::endl; + File_t *newfile=new File_t(file_id,orig_fid,url,hash,type,oid,atn,ftn,itn,rtn,typ,doipid); +std::cout<<"Found file "<<file_id<<"."<<std::endl; +std::cout<<" atn: " << atn << " ftn: " << ftn << " rtn: " << rtn << " typ: " << typ << std::endl; files.insert(newfile); diff --git a/libMEDSannotation/include/MEDS_AnnotationBase.hpp b/libMEDSannotation/include/MEDS_AnnotationBase.hpp index 60a6832156c2aa4f69f0a652d83b4cd050e49911..c60c0bc94e976b3f62861557abf387d2132e1c0c 100644 --- a/libMEDSannotation/include/MEDS_AnnotationBase.hpp +++ b/libMEDSannotation/include/MEDS_AnnotationBase.hpp @@ -55,6 +55,7 @@ class MEDS_AnnotationBase virtual void init() { m_isValid = false; m_size = 0; } virtual bool isFuncAnnotation() const { return false; } // false by default + virtual bool isFuncPrototypeAnnotation() const { return false; } // false by default protected: bool m_isValid; diff --git a/libMEDSannotation/include/MEDS_AnnotationParser.hpp b/libMEDSannotation/include/MEDS_AnnotationParser.hpp index 2eca52662791ee563d7864333899beeaf7c167cc..15b054224f6871a36fbb13a74661bfd318e59fb8 100644 --- a/libMEDSannotation/include/MEDS_AnnotationParser.hpp +++ b/libMEDSannotation/include/MEDS_AnnotationParser.hpp @@ -45,10 +45,12 @@ class MEDS_AnnotationParser void parseFile(const std::string &); /* pass filename */ MEDS_Annotations_t & getAnnotations() { return m_annotations; } MEDS_FuncAnnotations_t & getFuncAnnotations() { return m_func_annotations; } + MEDS_Annotations_t & getFuncPrototypeAnnotations() { return m_func_prototype_annotations; } private: MEDS_Annotations_t m_annotations; MEDS_FuncAnnotations_t m_func_annotations; + MEDS_Annotations_t m_func_prototype_annotations; }; } diff --git a/libMEDSannotation/include/MEDS_FuncAnnotation.hpp b/libMEDSannotation/include/MEDS_FuncAnnotation.hpp index 781042aeac5a27e9884df5030ae85f3c568e9f91..c2c246ff7319c20cdc34baebc0bae764b50759dc 100644 --- a/libMEDSannotation/include/MEDS_FuncAnnotation.hpp +++ b/libMEDSannotation/include/MEDS_FuncAnnotation.hpp @@ -30,6 +30,9 @@ namespace MEDS_Annotation { +// These strings must match those emitted by MEDS in the information annotation file exactly +#define MEDS_ANNOT_FUNC "FUNC" + using namespace std; using namespace MEDS_Annotation; @@ -42,7 +45,7 @@ class MEDS_FuncAnnotation : public MEDS_AnnotationBase MEDS_FuncAnnotation() {} virtual ~MEDS_FuncAnnotation(){} - virtual bool isFuncAnnotation() const { return true; } + virtual bool isFuncAnnotation() const { return true; } virtual string getFuncName() const { return m_func_name; } virtual void setFuncName(const string &p_func_name) { m_func_name=p_func_name; } diff --git a/libMEDSannotation/include/MEDS_FuncPrototypeAnnotation.hpp b/libMEDSannotation/include/MEDS_FuncPrototypeAnnotation.hpp new file mode 100644 index 0000000000000000000000000000000000000000..75055f29aaab46e2ea1ed9dc6257b61a8cef2f24 --- /dev/null +++ b/libMEDSannotation/include/MEDS_FuncPrototypeAnnotation.hpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014 - Zephyr Software LLC + * + * This file may be used and modified for non-commercial purposes as long as + * all copyright, permission, and nonwarranty notices are preserved. + * Redistribution is prohibited without prior written consent from Zephyr + * Software. + * + * Please contact the authors for restrictions applying to commercial use. + * + * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Author: Zephyr Software + * e-mail: jwd@zephyr-software.com + * URL : http://www.zephyr-software.com/ + * + */ + +#ifndef _MEDS_FUNCPROTOTYPEANNOTATION_H_ +#define _MEDS_FUNCPROTOTYPEANNOTATION_H_ + +#include <string> +#include <vector> +#include "VirtualOffset.hpp" +#include "MEDS_Register.hpp" +#include "MEDS_FuncAnnotation.hpp" + + +namespace MEDS_Annotation +{ + +using namespace std; +using namespace MEDS_Annotation; + +// +// Must match STARS type system +// UNINIT = 0, // Operand type not yet analyzed; type lattice top +// NUMERIC = 1, // Definitely holds non-pointer value (char, int, etc.) +// CODEPTR = 2, // Definitely holds a code address; mmStrata considers this NUMERIC +// POINTER = 4, // Definitely holds a data address +// STACKPTR = 8, // Definitely holds a stack data address (refinement of POINTER) +// GLOBALPTR = 16, // Definitely holds a global static data address (refinement of POINTER) +// HEAPPTR = 32, // Definitely holds a heap data address (refinement of POINTER) +// PTROFFSET = 64, // Offset from a pointer, e.g. a difference between two pointers +// NEGATEDPTR = 65, // Temporary ptr arithmetic leaves NUMERIC-POINTER; should get +POINTER later to make PTROFFSET +// UNKNOWN = 96, // Might hold an address, might not (Bad!); type lattice bottom +// +typedef enum { + MEDS_TYPE_UNINIT = 0, + MEDS_TYPE_NUMERIC = 1, + MEDS_TYPE_CODEPTR = 2, + MEDS_TYPE_POINTER = 4, + MEDS_TYPE_STACKPTR = 8, + MEDS_TYPE_GLOBALPTR = 16, + MEDS_TYPE_HEAPPTR = 32, + MEDS_TYPE_PTROFFSET = 64, + MEDS_TYPE_NEGATEDPTR = 65, + MEDS_TYPE_UNKNOWN = 96 +} MEDS_ArgType; + +// wrapper class around MEDS typing system +class MEDS_Arg { + public: + MEDS_Arg() { m_type = MEDS_TYPE_UNKNOWN; m_reg = Register::UNKNOWN; } + MEDS_Arg(int p_type, Register::RegisterName p_reg = Register::UNKNOWN) { m_type = (MEDS_ArgType) p_type; m_reg = p_reg; } + virtual ~MEDS_Arg() {} + bool isNumericType() { return m_type == MEDS_TYPE_NUMERIC; } + bool isPointerType() { + return m_type == MEDS_TYPE_CODEPTR || m_type == MEDS_TYPE_POINTER || + m_type == MEDS_TYPE_STACKPTR || m_type == MEDS_TYPE_GLOBALPTR || + m_type == MEDS_TYPE_HEAPPTR; + } + bool isUnknownType() { return !(isNumericType() || isPointerType()); } + + private: + MEDS_ArgType m_type; + Register::RegisterName m_reg; +}; + +// +// Class to handle one function prototype annotations +// +class MEDS_FuncPrototypeAnnotation : public MEDS_FuncAnnotation +{ + public: + MEDS_FuncPrototypeAnnotation() { init(); }; + MEDS_FuncPrototypeAnnotation(const string &p_rawLine); + virtual ~MEDS_FuncPrototypeAnnotation(){} + virtual bool isFuncPrototypeAnnotation() const { return true; } + + virtual const string toString() const { return "func proto: " + m_rawInputLine; } + + int getNumArgs() const { return m_arguments ? m_arguments->size() : 0; } + std::vector<MEDS_Arg>* getArgs() { return m_arguments; } + void addArg(MEDS_Arg p_arg) { + if (!m_arguments) m_arguments = new std::vector<MEDS_Arg>; + m_arguments->push_back(p_arg); + } + void setReturnArg(MEDS_Arg p_arg) { + if (!m_returnArg) m_returnArg = new MEDS_Arg; + *m_returnArg = p_arg; + } + MEDS_Arg* getReturnArg() const { return m_returnArg; } + + private: + void init(); + void parse(); + + private: + string m_rawInputLine; + + std::vector<MEDS_Arg> *m_arguments; + MEDS_Arg *m_returnArg; +}; + +} + +#endif diff --git a/libMEDSannotation/src/MEDS_AnnotationParser.cpp b/libMEDSannotation/src/MEDS_AnnotationParser.cpp index 8973cca67e6a7e8a434311882a6f7dfa81e8a77a..cf795d07d824f8aa82c05f43d9fc796570fcf4ef 100644 --- a/libMEDSannotation/src/MEDS_AnnotationParser.cpp +++ b/libMEDSannotation/src/MEDS_AnnotationParser.cpp @@ -24,6 +24,7 @@ #include "MEDS_AnnotationParser.hpp" #include "MEDS_InstructionCheckAnnotation.hpp" #include "FuncExitAnnotation.hpp" +#include "MEDS_FuncPrototypeAnnotation.hpp" #include "MEDS_SafeFuncAnnotation.hpp" #include "MEDS_ProblemFuncAnnotation.hpp" #include "MEDS_FRSafeAnnotation.hpp" @@ -55,36 +56,48 @@ void MEDS_AnnotationParser::parseFile(istream &p_inputStream) while (!p_inputStream.eof()) { - getline(p_inputStream, line); + getline(p_inputStream, line); if (line.empty()) continue; -cerr << "MEDS_AnnotationParser: line: " << line << endl; +//cerr << "MEDS_AnnotationParser: line: " << line << endl; #define ADD_AND_CONTINUE_IF_VALID(type) \ { \ type * annot=new type(line); \ if (annot->isValid()) \ { \ - if(annot->isFuncAnnotation()) \ + if(annot->isFuncPrototypeAnnotation()) \ + { \ + MEDS_FuncPrototypeAnnotation* fpannot=dynamic_cast<MEDS_FuncPrototypeAnnotation*>(annot); \ + assert(fpannot); \ + m_func_prototype_annotations.insert(MEDS_Annotations_Pair_t(annot->getVirtualOffset(), annot)); \ + cout << "Insert func prototype annot: " << line << endl; \ + } \ + else if(annot->isFuncAnnotation()) \ { \ MEDS_FuncAnnotation* fannot=dynamic_cast<MEDS_FuncAnnotation*>(annot); \ assert(fannot); \ string nam=fannot->getFuncName(); \ m_func_annotations.insert(MEDS_Annotations_FuncPair_t(nam, annot)); \ + cout << "Insert func annot: " << line << endl; \ } \ else \ { \ VirtualOffset vo = annot->getVirtualOffset(); \ m_annotations.insert(MEDS_Annotations_Pair_t(vo, annot)); \ + cout << "Insert instruction annot: " << hex << vo.getOffset() << dec << " | " << line << endl; \ } \ continue; \ } \ else \ + { \ delete annot; \ + } \ } ADD_AND_CONTINUE_IF_VALID(MEDS_FPTRShadowAnnotation); ADD_AND_CONTINUE_IF_VALID(MEDS_InstructionCheckAnnotation); + ADD_AND_CONTINUE_IF_VALID(MEDS_FuncPrototypeAnnotation); ADD_AND_CONTINUE_IF_VALID(MEDS_SafeFuncAnnotation); ADD_AND_CONTINUE_IF_VALID(MEDS_ProblemFuncAnnotation); ADD_AND_CONTINUE_IF_VALID(MEDS_FRSafeAnnotation); diff --git a/libMEDSannotation/src/MEDS_FPTRShadowAnnotation.cpp b/libMEDSannotation/src/MEDS_FPTRShadowAnnotation.cpp index ef45af9f6fbc55d7bb87104691f39ae0395578c0..cc09d08991e3636142f8359d7487703d7e7998fd 100644 --- a/libMEDSannotation/src/MEDS_FPTRShadowAnnotation.cpp +++ b/libMEDSannotation/src/MEDS_FPTRShadowAnnotation.cpp @@ -68,8 +68,6 @@ MEDS_FPTRShadowAnnotation::MEDS_FPTRShadowAnnotation(const string &p_rawLine) : void MEDS_FPTRShadowAnnotation::parse() { - cerr << "MEDS_FPTRShadowAnnotation::parse(): enter" << endl; - if (m_rawInputLine.find(" INSTR ")==string::npos) return; diff --git a/libMEDSannotation/src/MEDS_FuncPrototypeAnnotation.cpp b/libMEDSannotation/src/MEDS_FuncPrototypeAnnotation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4d939e7e8c6cd9b40f5bb867e7186e0e04125c7 --- /dev/null +++ b/libMEDSannotation/src/MEDS_FuncPrototypeAnnotation.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2014, 2015 - Zephyr Software LLC + * + * This file may be used and modified for non-commercial purposes as long as + * all copyright, permission, and nonwarranty notices are preserved. + * Redistribution is prohibited without prior written consent from Zephyr + * Software. + * + * Please contact the authors for restrictions applying to commercial use. + * + * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Author: Zephyr Software + * e-mail: jwd@zephyr-software.com + * URL : http://www.zephyr-software.com/ + * + */ + +#include <stdlib.h> + +#include <iostream> +#include <cstdio> +#include <string> +#include <string.h> + +#include "MEDS_Register.hpp" +#include "MEDS_FuncPrototypeAnnotation.hpp" + +using namespace std; +using namespace MEDS_Annotation; + +MEDS_FuncPrototypeAnnotation::MEDS_FuncPrototypeAnnotation(const string &p_rawLine) +{ + init(); + m_rawInputLine=p_rawLine; + parse(); +} + +void MEDS_FuncPrototypeAnnotation::init() +{ + MEDS_AnnotationBase::init(); + m_returnArg = NULL; + m_arguments = NULL; +} + + +/* +4046e0 71 FUNC INARGS 4 ARG0 1 ARG1 0 ARG2 0 ARG3 0 +404740 697 FUNC RETURNTYPE RAX 1 +*/ +void MEDS_FuncPrototypeAnnotation::parse() +{ + bool about_inargs = false; + bool about_return = false; + + if (m_rawInputLine.find("FUNC ")==string::npos) + return; + + if (m_rawInputLine.find("INARGS")!=string::npos) + { + about_inargs = true; + } + + if (m_rawInputLine.find("RETURNTYPE")!=string::npos) + { + about_return = true; + } + + if (!about_inargs && !about_return) + return; + + // get offset + VirtualOffset vo(m_rawInputLine); + m_virtualOffset = vo; + + if (about_inargs) + { +// 4046e0 71 FUNC INARGS 4 ARG0 1 ARG1 0 ARG2 0 ARG3 0 + int numargs = 0; + char buf[1024]; + strcpy(buf, m_rawInputLine.c_str()); + sscanf(buf, "%*x %*d %*s %*s %d %*s", &numargs); + for (int i = 0; i < numargs; ++i) + { + char arg[24]; + sprintf(arg, "ARG%d", i); + char *zarg = strstr(buf, arg); + if (zarg) + { + char tmp[1024]; + int meds_type; + sscanf(tmp,"%*s %d %*s", &meds_type); + MEDS_Arg marg(meds_type); + addArg(marg); + } + else + { + setInvalid(); + return; + } + } + } + else if (about_return) + { + // 404740 697 FUNC RETURNTYPE RAX 1 + char regbuf[1024]; + int meds_retType; + sscanf(m_rawInputLine.c_str(), "%*x %*d %*s %*s %s %d", regbuf, &meds_retType); + Register::RegisterName reg = Register::getRegister(regbuf); + MEDS_Arg marg(meds_retType, reg); + setReturnArg(marg); + cout << " adding return argument: " << Register::toString(reg) << " type: " << meds_retType << endl; + } + else + { + assert(0); + return; + } + + setValid(); +} + diff --git a/libMEDSannotation/src/Makefile b/libMEDSannotation/src/Makefile index ef6cfce3eba7fe102ee97e35ea95ae7f6c571126..4144a820560c3646549ab94223064ab8651939d3 100644 --- a/libMEDSannotation/src/Makefile +++ b/libMEDSannotation/src/Makefile @@ -1,7 +1,7 @@ LIB=../lib/libMEDSannotation.a -OBJS=VirtualOffset.o MEDS_Register.o MEDS_AnnotationParser.o MEDS_InstructionCheckAnnotation.o MEDS_SafeFuncAnnotation.o MEDS_ProblemFuncAnnotation.o MEDS_FRSafeAnnotation.o FuncExitAnnotation.o MEDS_FPTRShadowAnnotation.o +OBJS=VirtualOffset.o MEDS_Register.o MEDS_AnnotationParser.o MEDS_InstructionCheckAnnotation.o MEDS_SafeFuncAnnotation.o MEDS_ProblemFuncAnnotation.o MEDS_FRSafeAnnotation.o FuncExitAnnotation.o MEDS_FPTRShadowAnnotation.o MEDS_FuncPrototypeAnnotation.o all: $(OBJS) diff --git a/libMEDSannotation/src/VirtualOffset.cpp b/libMEDSannotation/src/VirtualOffset.cpp index 917ba7fbc0bcfe50b0f0595a5a6c38b56479f6f1..fe1b616af57f126e851b733adb48f9804b4f9796 100644 --- a/libMEDSannotation/src/VirtualOffset.cpp +++ b/libMEDSannotation/src/VirtualOffset.cpp @@ -19,31 +19,34 @@ */ #include <cstdio> +#include <iostream> #include "VirtualOffset.hpp" +using namespace std; VirtualOffset::VirtualOffset() { m_offset = 0; + m_libraryName = std::string(DEFAULT_LIBRARY_NAME); } VirtualOffset::VirtualOffset(const std::string &p_offset, const std::string &p_libraryName) { - sscanf(p_offset.c_str(), "%x", &m_offset); + sscanf(p_offset.c_str(), "%llx", &m_offset); m_libraryName = p_libraryName; } - VirtualOffset::VirtualOffset(const std::string &p_offset) { - sscanf(p_offset.c_str(), "%x", &m_offset); + sscanf(p_offset.c_str(), "%llx", &m_offset); m_libraryName = std::string(DEFAULT_LIBRARY_NAME); } VirtualOffset::VirtualOffset(const int p_offset) { m_offset = p_offset; + m_libraryName = std::string(DEFAULT_LIBRARY_NAME); } ApplicationAddress VirtualOffset::getOffset() const @@ -56,8 +59,6 @@ std::string VirtualOffset::getLibraryName() const return m_libraryName; } -// /usr/include/c++/4.4/bits/stl_function.h:230: error: passing ‘const VirtualOffset’ as ‘this’ argument of ‘bool VirtualOffset::operator<(VirtualOffset)’ discards qualifiers - bool VirtualOffset::operator < (const VirtualOffset &p_other) const { if (&p_other == this) return false; @@ -69,7 +70,9 @@ bool VirtualOffset::operator == (const VirtualOffset &p_other) const if (&p_other == this) return true; else + { return (m_offset == p_other.getOffset() && m_libraryName == p_other.getLibraryName()); + } } VirtualOffset& VirtualOffset::operator = (const VirtualOffset &p_other) diff --git a/libtransform/src/integertransform64.cpp b/libtransform/src/integertransform64.cpp index a1a886f1550e962fc5d5ee2b84a6063b9e88dae4..634dae20458e56d0d6644847eb502cfe95c1f69f 100644 --- a/libtransform/src/integertransform64.cpp +++ b/libtransform/src/integertransform64.cpp @@ -127,6 +127,7 @@ int IntegerTransform64::execute() if (getAnnotations()->count(vo) == 0) continue; + std::pair<MEDS_Annotations_t::iterator,MEDS_Annotations_t::iterator> ret; ret = getAnnotations()->equal_range(vo); MEDS_InstructionCheckAnnotation annotation; diff --git a/tools/meds2pdb/Makefile b/tools/meds2pdb/Makefile index 96eef39a6aa8901aefb5f38c095379f677f1da26..ee69c2a96fe009e1cba13e6e3da86f5faaaa744c 100644 --- a/tools/meds2pdb/Makefile +++ b/tools/meds2pdb/Makefile @@ -1,7 +1,7 @@ CC=g++ CFLAGS= -g -INCLUDE=-I. -I../../include -I../../xform -I../../beaengine/include -LIBS=-L../../lib -lxform -lBeaEngine_s_d -lpq -lpqxx +INCLUDE=-I. -I../../include -I../../xform -I../../beaengine/include -I../../libMEDSannotation/include -I../../libIRDB/include +LIBS=-L../../lib -lxform -lBeaEngine_s_d -lpq -lpqxx -lIRDB-core -lMEDSannotation .SUFFIXES: .o .c .cpp diff --git a/tools/meds2pdb/meds2pdb.cpp b/tools/meds2pdb/meds2pdb.cpp index e353f556b6b7242e50202b0a5ab3c0f87f270869..abb6cd9744b0fa95db4bb5591b950aa247978e09 100644 --- a/tools/meds2pdb/meds2pdb.cpp +++ b/tools/meds2pdb/meds2pdb.cpp @@ -25,15 +25,21 @@ #include "rewriter.h" #include <pqxx/pqxx> #include <stdlib.h> +#include "MEDS_AnnotationParser.hpp" +#include "MEDS_FuncPrototypeAnnotation.hpp" +#include "libIRDB-core.hpp" using namespace std; using namespace pqxx; +using namespace libIRDB; +using namespace MEDS_Annotation; #include <sstream> string functionTable; string addressTable; string instructionTable; +string typesTable; static const int STRIDE = 50; @@ -50,7 +56,6 @@ int next_address_id=0; map<app_iaddr_t,int> address_to_instructionid_map; - // extract the file id from the md5 hash and the program name int get_file_id(char *progName, char *md5hash) { @@ -272,35 +277,181 @@ void update_functions(int fileID, const vector<wahoo::Function*> &functions ) txn.commit(); // must commit o/w everything will be rolled back } +/* + typedef enum IRDB_Type { + T_UNKNOWN = 0, T_NUMERIC = 1, T_POINTER = 2, + T_INT = 10, T_CHAR = 11, T_FLOAT = 12, T_DOUBLE = 13, + T_VARIADIC = 20, T_TYPEDEF = 21, T_SUBTYPE = 22, + T_FUNC = 100, T_AGGREGATE = 101 + } IRDB_Type; +// MUST MATCH typedef in type.hpp in libIRDB-core!!! +*/ + +static int getNewTypeId() +{ + // start at 5000 so we don't clash with predefined type ids + static int next_type_id=5000; + return next_type_id++; +} + +void populate_predefined_types() +{ + connection conn; + work txn(conn); + string q = "SET client_encoding='LATIN1';"; + q += "INSERT into " + typesTable + " (type_id, type, name, ref_type_id, ref_type_id2) values ('0', '0','unknown','-1','-1');"; + q += "INSERT into " + typesTable + " (type_id, type, name, ref_type_id, ref_type_id2) values ('1', '1','numeric','-1','-1');"; + q += "INSERT into " + typesTable + " (type_id, type, name, ref_type_id, ref_type_id2) values ('2', '2','pointer','0','-1');"; + txn.exec(q); + txn.commit(); +} + +void update_function_prototype(vector<wahoo::Function*> functions, char* annotFile) +{ + populate_predefined_types(); + + connection conn; + work txn(conn); + txn.exec("SET client_encoding='LATIN1';"); + + ifstream annotationif(annotFile, ifstream::in); + assert(annotationif.is_open()); + + MEDS_AnnotationParser annotationParser(annotationif); + MEDS_Annotations_t annotations = annotationParser.getFuncPrototypeAnnotations(); + + for (int i = 0; i < functions.size(); i += STRIDE) + { + string q = ""; + for (int j = i; j < i + STRIDE; ++j) + { + if (j >= functions.size()) break; + wahoo::Function *f = functions[j]; + int function_id = f->getFunctionID(); + app_iaddr_t functionAddress = f->getAddress(); + VirtualOffset vo(functionAddress); + + MEDS_FuncPrototypeAnnotation* fn_prototype_annot = NULL; + MEDS_FuncPrototypeAnnotation* fn_returntotype_annot = NULL; + + std::vector<MEDS_Arg> *args = NULL; + MEDS_Arg *returnArg = NULL; + + if (annotations.count(vo) > 0) + { + std::pair<MEDS_Annotations_t::iterator,MEDS_Annotations_t::iterator> ret; + ret = annotations.equal_range(vo); + MEDS_FuncPrototypeAnnotation* p_annotation; + for ( MEDS_Annotations_t::iterator it = ret.first; it != ret.second; ++it) + { + MEDS_AnnotationBase *base_type=(it->second); + p_annotation = dynamic_cast<MEDS_FuncPrototypeAnnotation*>(base_type); + if(p_annotation == NULL || !p_annotation->isValid()) + continue; + + if (p_annotation->getArgs()) + args = p_annotation->getArgs(); + + if (p_annotation->getReturnArg()) + returnArg = p_annotation->getReturnArg(); + } + } + + // we should have 2 valid annotations per function + // one for the args, one for the return type + if (args) + { + // (1) define new aggregate type + // (2) define new return type + // (3) define new function type (combo (1) + (2)) + int aggregate_type_id = getNewTypeId(); + int func_type_id = getNewTypeId(); + int basic_type_id = T_UNKNOWN; + + for (int i = 0; i < args->size(); ++i) + { + if ((*args)[i].isNumericType()) + basic_type_id = T_NUMERIC; + else if ((*args)[i].isPointerType()) + basic_type_id = T_POINTER; + + q += "INSERT into " + typesTable + " (type_id, type, name, ref_type_id, pos) VALUES ("; + q += txn.quote(my_to_string(aggregate_type_id)) + ","; + q += txn.quote(my_to_string(T_AGGREGATE)) + ","; + q += txn.quote(string(f->getName()) + "_arg" + my_to_string(i)) + ","; + q += txn.quote(my_to_string(basic_type_id)) + ","; + q += txn.quote(my_to_string(i)) + ");"; + } + + int return_type_id = T_UNKNOWN; + if (returnArg) + { + if (returnArg->isNumericType()) + return_type_id = T_NUMERIC; + else if (returnArg->isPointerType()) + return_type_id = T_POINTER; + else + return_type_id = T_UNKNOWN; + } + + // new function type id (ok to have duplicate prototypes) + // ref_type_id is the return type id + // ref_type_id2 is the type id for the aggregated type + // that describes the function arguments + q += "INSERT into " + typesTable + " (type_id, type, name, ref_type_id, ref_type_id2) VALUES ("; + + q += txn.quote(my_to_string(func_type_id)) + ","; + q += txn.quote(my_to_string(T_FUNC)) + ","; + q += txn.quote(string(f->getName()) + "_func") + ","; + q += txn.quote(my_to_string(return_type_id)) + ","; + q += txn.quote(my_to_string(aggregate_type_id)) + ");"; + + // update the type id in the function table + q += "UPDATE " + functionTable; + q += " SET type_id = " + txn.quote(my_to_string(func_type_id)); + q += " where function_id = " + txn.quote(my_to_string(function_id)) + "; "; + } // update function prototype + } // strided + + if (q.size() > 0) + txn.exec(q); + } // outer loop + + txn.commit(); // must commit o/w everything will be rolled back +} int main(int argc, char **argv) { - if (argc != 8) + if (argc != 10) { - cerr << "usage: " << argv[0] << " <annotations file> <file id> <func tab name> <insn tab name> <addr tab name> <elf file> <STARSxref file>" << endl; + cerr << "usage: " << argv[0] << " <annotations file> <info annotation file> <file id> <func tab name> <insn tab name> <addr tab name> <types tab name> <elf file> <STARSxref file>" << endl; return 1; } char *annotFile = argv[1]; - char *fid=argv[2]; - char *myFunctionTable=argv[3]; - char *myInstructionTable=argv[4]; - char *myAddressTable=argv[5]; - char *elfFile=argv[6]; - char *starsXrefFile=argv[7]; + char *infoAnnotFile = argv[2]; + char *fid=argv[3]; + char *myFunctionTable=argv[4]; + char *myInstructionTable=argv[5]; + char *myAddressTable=argv[6]; + char *myTypesTable=argv[7]; + char *elfFile=argv[8]; + char *starsXrefFile=argv[9]; cout<<"Annotation file: "<< annotFile<<endl; + cout<<"Info annotation file: "<< infoAnnotFile<<endl; cout<<"File ID: "<< fid<<endl; cout<<"FTN:: "<< myFunctionTable<<endl; cout<<"ITN: "<< myInstructionTable<<endl; cout<<"ATN: "<< myAddressTable<<endl; + cout<<"TYP: "<< myTypesTable<<endl; // set global vars for importing. functionTable=myFunctionTable; addressTable=myAddressTable; instructionTable=myInstructionTable; - + typesTable=myTypesTable; Rewriter *rewriter = new Rewriter(elfFile, annotFile, starsXrefFile); @@ -321,6 +472,7 @@ int main(int argc, char **argv) insert_instructions(fileID, instructions, functions); update_functions(fileID, functions); - + // add function prototype information to the IRDB + update_function_prototype(functions, infoAnnotFile); exit(0); } diff --git a/tools/transforms/integertransformdriver.cpp b/tools/transforms/integertransformdriver.cpp index b798974bcfe10227293fc240871774e8f40dc290..9df2a38f8ea5584ce2e5d0dae2c06848bafba8f9 100644 --- a/tools/transforms/integertransformdriver.cpp +++ b/tools/transforms/integertransformdriver.cpp @@ -180,6 +180,8 @@ int main(int argc, char **argv) MEDS_Annotations_t annotations = annotationParser.getAnnotations(); + cout << "integer transform driver: found " << annotations.size() << " annotaitons" << endl; + // do the transformation libTransform::IntegerTransform *intxform = NULL;