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