From d1951790ec81dba3088b350c687741e26059de7d Mon Sep 17 00:00:00 2001 From: bdr7fv <bdr7fv@git.zephyr-software.com> Date: Thu, 16 Aug 2012 14:58:36 +0000 Subject: [PATCH] fileir now has an assembly registry. If assembling large numbers of instructions, register instructions here to speed up performance in assembly. Instructions are assembled on demand, or when fileir is used to write to the db or to generate spri. Former-commit-id: c92c7aa20ff36df6c01d34f949ea1a4248686b4f --- libIRDB/include/core/fileir.hpp | 12 ++++ libIRDB/src/core/fileir.cpp | 95 +++++++++++++++++++++++++++++- libIRDB/src/core/generate_spri.cpp | 3 + 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/libIRDB/include/core/fileir.hpp b/libIRDB/include/core/fileir.hpp index 4c77987f3..e0d699c36 100644 --- a/libIRDB/include/core/fileir.hpp +++ b/libIRDB/include/core/fileir.hpp @@ -1,3 +1,5 @@ + + // A variant of a problem, this // may be an original variant // (i.e., and unmodified Variant) or a modified variant. @@ -27,11 +29,21 @@ class FileIR_t : public BaseObj_t File_t* GetFile() { return fileptr; } + // Used for modifying a large number of instructions. AssembleRegistry + // assembles the assembly isntructions for each registered instruction + // and clears the registry. RegisterAssembly registers the instruction + // to be assembled later. + void AssembleRegistry(); + void RegisterAssembly(Instruction_t *instr, std::string assembly); + private: + typedef std::map<Instruction_t*,std::string> registry_type; + // a pointer to the original variants IR, NULL means not yet loaded. FileIR_t* orig_variant_ir_p; + registry_type assembly_registry; void ReadFromDB(); //accesses DB diff --git a/libIRDB/src/core/fileir.cpp b/libIRDB/src/core/fileir.cpp index 9fe0b90c9..5cd584bb8 100644 --- a/libIRDB/src/core/fileir.cpp +++ b/libIRDB/src/core/fileir.cpp @@ -3,6 +3,7 @@ #include <utils.hpp> #include <stdlib.h> #include <map> +#include <fstream> using namespace libIRDB; using namespace std; @@ -57,6 +58,95 @@ void FileIR_t::ReadFromDB() } +void FileIR_t::AssembleRegistry() +{ + if(assembly_registry.size() == 0) + return; + + const string assemblyFile = "tmp.asm"; + const string binaryOutputFile = "tmp.bin"; + + string command = "rm -f " + assemblyFile; + system(command.c_str()); + + ofstream asmFile; + asmFile.open(assemblyFile.c_str()); + if(!asmFile.is_open()) + assert(false); + + asmFile<<"BITS 32"<<endl; //TODO: probably should use a defined val + + //in case the map is some how updated again, the instructions are placed + //in a vector so the number and order of instructions are guaranteed + vector<Instruction_t*> instructions; + for(registry_type::iterator it = assembly_registry.begin(); + it != assembly_registry.end(); + it++ + ) + { + instructions.push_back(it->first); + asmFile<<it->second<<endl; + } + asmFile.close(); + + //after assembly, clear registry + assembly_registry.clear(); + + command = "nasm " + assemblyFile + " -o " + binaryOutputFile; + system(command.c_str()); + + DISASM disasm; + memset(&disasm, 0, sizeof(DISASM)); + + + ifstream binreader; + unsigned int filesize; + binreader.open(binaryOutputFile.c_str(),ifstream::in|ifstream::binary); + + if(!binreader.is_open()) + assert(false); + + binreader.seekg(0,ios::end); + filesize = binreader.tellg(); + binreader.seekg(0,ios::beg); + + unsigned char *binary_stream = new unsigned char[filesize]; + + binreader.read((char*)binary_stream,filesize); + binreader.close(); + + unsigned int instr_index = 0; + //for(unsigned int index=0; index < filesize; instr_index++) + unsigned int index = 0; + while(index < filesize) + { + disasm.EIP = (int) &binary_stream[index]; + int instr_len = Disasm(&disasm); + string rawBits; + rawBits.resize(instr_len); + for(int i=0;i<instr_len;i++,index++) + { + rawBits[i] = binary_stream[index]; + } + + //if this worked, all the instructions should have been covered + assert(instr_index < instructions.size()); + instructions[instr_index]->SetDataBits(rawBits); + + instr_index++; + } + + assert(instr_index == instructions.size()); + + delete [] binary_stream; + +} + +void FileIR_t::RegisterAssembly(Instruction_t *instr, string assembly) +{ + assembly_registry[instr] = assembly; +} + std::map<db_id_t,Function_t*> FileIR_t::ReadFuncsFromDB ( std::map<db_id_t,AddressID_t*> &addrMap @@ -254,10 +344,11 @@ void FileIR_t::ReadRelocsFromDB } - - void FileIR_t::WriteToDB() { + //Resolve (assemble) any instructions in the registry. + AssembleRegistry(); + /* assign each item a unique ID */ SetBaseIDS(); diff --git a/libIRDB/src/core/generate_spri.cpp b/libIRDB/src/core/generate_spri.cpp index a83d3b36e..39eee64ea 100644 --- a/libIRDB/src/core/generate_spri.cpp +++ b/libIRDB/src/core/generate_spri.cpp @@ -633,6 +633,9 @@ static void generate_unmoved_insn_targets_set(FileIR_t* fileIRp) void FileIR_t::GenerateSPRI(FileIR_t *orig_fileIRp, ostream &fout) { + //Resolve (assemble) any instructions in the registry. + AssembleRegistry(); + // give 'this' a name FileIR_t *fileIRp=this; -- GitLab