diff --git a/include/zipr_dollop_man.h b/include/zipr_dollop_man.h index 42c4cfdb0b2a084ac6a6d90081b5341325f7ea2f..25115ad4e0e87ec8b2508888bd5bc17637edd562 100644 --- a/include/zipr_dollop_man.h +++ b/include/zipr_dollop_man.h @@ -37,21 +37,29 @@ class ZiprDollopManager_t { public: ZiprDollopManager_t() {} void AddDollop(Dollop_t *dollop); - Zipr_SDK::Dollop_t *GetContainingDollop(libIRDB::Instruction_t *insn) { - try { - return m_insn_to_dollop.at(insn); - } catch (const std::out_of_range &oor) { - return NULL; - } + Zipr_SDK::Dollop_t *AddNewDollop(libIRDB::Instruction_t *start); + Zipr_SDK::Dollop_t *GetContainingDollop(libIRDB::Instruction_t *insn); + size_t Size() { + return m_dollops.size(); } - - static Zipr_SDK::Dollop_t *CreateDollop(libIRDB::Instruction_t *start) { - return new Zipr_SDK::Dollop_t(start); + void AddDollopPatch(Zipr_SDK::DollopPatch_t *new_patch) { + m_patches_to_dollops[new_patch->Target()].push_back(new_patch); + } + std::list<DollopPatch_t*> PatchesToDollop(Dollop_t *target) { + /* + * FIXME: This will throw an exception if target is + * not already in the list. [] fixes that but allocates. + * Decide what to do. + */ + return m_patches_to_dollops.at(target); } + void PrintDollopPatches(const std::ostream &); private: std::map<libIRDB::Instruction_t*,Dollop_t*> m_insn_to_dollop; std::list<Dollop_t*> m_dollops; + std::list<DollopPatch_t*> m_patches; + std::map<Dollop_t*, std::list<DollopPatch_t*>> m_patches_to_dollops; }; #endif diff --git a/src/dollop.cpp b/src/dollop.cpp index f89235cae5eb82f5f78f15d81a9eff4a6e7d7dfa..bc24820cc2e060fec89ff869066fa6bce5bcba63 100644 --- a/src/dollop.cpp +++ b/src/dollop.cpp @@ -1,12 +1,22 @@ #include <zipr_all.h> +#include <iostream> namespace Zipr_SDK { using namespace libIRDB; using namespace zipr; Dollop_t::Dollop_t(Instruction_t *start) { + Instruction_t *loop = NULL; m_start = start; m_size = CalculateWorstCaseSize(); + + if (start == NULL) + return; + + loop = start; + do { + push_back(new DollopEntry_t(loop)); + } while (NULL != (loop = loop->GetFallthrough())); } size_t Dollop_t::CalculateWorstCaseSize() @@ -38,6 +48,89 @@ namespace Zipr_SDK { } Dollop_t *Dollop_t::Split(libIRDB::Instruction_t *split_point) { - return new Dollop_t(NULL); + /* + * 1. Find the matching dollop entry. + */ + DollopEntry_t query(split_point); + std::list<DollopEntry_t *>::iterator de_split_point, de_it; + Dollop_t *new_dollop = NULL; + + de_split_point = find_if(begin(),end(), + [&query](const DollopEntry_t *p) { + std::cout << "Checking " + << std::hex << query.Instruction() << " ?= " + << std::hex << p->Instruction() << "." << std::endl; + return query == *p; + }); + /* + * No matching split point. Just return NULL. + */ + if (de_split_point == end()) + return NULL; + + new_dollop = new Dollop_t(); + /* + * 2. Remove them from this one + */ + de_it = de_split_point; + while (de_it != end()) { + /* + * 3. Move them to a new one + */ + DollopEntry_t *to_remove = *de_it, *to_add = NULL; + std::list<DollopEntry_t*>::iterator to_remove_it = de_it; + + de_it++; + + new_dollop->push_back(to_add=new DollopEntry_t(to_remove->Instruction())); + erase(to_remove_it); + delete to_remove; + } + /* + * 4. Return the new one + */ + return new_dollop; + } + + DollopEntry_t::DollopEntry_t(libIRDB::Instruction_t *insn) { + /* + * NB: This does not link if the insn has a target. + */ + m_instruction = insn; + m_target_dollop = NULL; + } + + bool DollopEntry_t::operator==(const DollopEntry_t &comp) { + std::cout << "operator==s being invoked " + << "(" << std::hex << m_instruction + << ", " << std::hex << comp.m_instruction + << ") " + << "(" << std::hex << m_target_dollop + << ", " << std::hex << comp.m_target_dollop + << ") " + << std::endl; + return comp.m_instruction == m_instruction && + comp.m_target_dollop == m_target_dollop; + } + bool DollopEntry_t::operator!=(const DollopEntry_t &comp) { + return !operator==(comp); + } + Dollop_t *Dollop_t::CreateNewDollop(libIRDB::Instruction_t *start) { + return new Zipr_SDK::Dollop_t(start); + } + std::ostream &operator<<(std::ostream &out, const Dollop_t &d) { + std::list<DollopEntry_t*>::const_iterator it, it_end; + + for (it = d.begin(), it_end = d.end(); + it != it_end; + it++) { + out << std::hex << (*it)->Instruction() << ","; + } + return out; + } + + std::ostream &operator<<(std::ostream &out, const DollopPatch_t &p) { + out << std::hex << &p << ":" << std::hex << p.Target(); + return out; } } diff --git a/src/zipr_dollop_man.cpp b/src/zipr_dollop_man.cpp index c08c9ec1e7ff5ecafaa981773a360c2d6495deca..68de6a1ea33f4b3ba60e3b1af80f1e384625626a 100644 --- a/src/zipr_dollop_man.cpp +++ b/src/zipr_dollop_man.cpp @@ -1,9 +1,48 @@ #include <zipr_all.h> +#include <iostream> using namespace zipr; using namespace std; using namespace Zipr_SDK; +using namespace libIRDB; + +Dollop_t *ZiprDollopManager_t::AddNewDollop(Instruction_t *start) { + Dollop_t *new_dollop = Dollop_t::CreateNewDollop(start); + AddDollop(new_dollop); + return new_dollop; +} + +void ZiprDollopManager_t::PrintDollopPatches(const ostream &out) { + std::list<DollopPatch_t*>::const_iterator patch_it, patch_it_end; + + for (patch_it = m_patches.begin(), patch_it_end = m_patches.end(); + patch_it != patch_it_end; + patch_it++) { + cout << *(*patch_it) << endl; + } +} + +Dollop_t *ZiprDollopManager_t::GetContainingDollop(libIRDB::Instruction_t *insn) { + try { + return m_insn_to_dollop.at(insn); + } catch (const std::out_of_range &oor) { + return NULL; + } + return NULL; +} void ZiprDollopManager_t::AddDollop(Dollop_t *dollop) { - return; + /* + * Populate the instruction-to-dollop map. + */ + list<DollopEntry_t*>::const_iterator it, it_end; + for (it = dollop->begin(), it_end = dollop->end(); + it != it_end; + it++) { + m_insn_to_dollop[(*it)->Instruction()] = dollop; + } + /* + * Push the actual dollop onto the list of dollops. + */ + m_dollops.push_back(dollop); } diff --git a/test/SConscript b/test/SConscript index df5eaf4769e2a9a82443c2b13347235782cd64ad..78548f0c176ba50a8bbebfa1b2d4df1bc4cda442 100644 --- a/test/SConscript +++ b/test/SConscript @@ -56,7 +56,7 @@ libpath=''' ''' myenv.Append(CCFLAGS=" -Wall ") -myenv.Append(CXXFLAGS=" -g -O0 ") +myenv.Append(CXXFLAGS=" -std=c++11 -g -O0 ") myenv.Append(LINKFLAGS=" -Wl,-E ") # export all symbols diff --git a/test/ZiprDollop.cpp b/test/ZiprDollop.cpp index 85692e9f7a37b08cacbd39a05a5fdb840f0af8e7..8605e7c03e88751a21500fb1cd355d0b69c4e8f8 100644 --- a/test/ZiprDollop.cpp +++ b/test/ZiprDollop.cpp @@ -23,6 +23,7 @@ using namespace zipr; using namespace std; +using namespace Zipr_SDK; #define INVOKE(a) \ bool __ ## a ## _result = false; \ @@ -37,10 +38,189 @@ else \ printf(" fail\n"); \ } -int main(int argc, char *argv[]) -{ +bool TestGetContainingDollopNoFallthrough() { + ZiprDollopManager_t dollop_man; + libIRDB::Instruction_t *insn_a = new libIRDB::Instruction_t(); + libIRDB::Instruction_t *insn_b = new libIRDB::Instruction_t(); + Dollop_t *dollop_a = NULL; + + dollop_a = Dollop_t::CreateNewDollop(insn_a); + dollop_man.AddDollop(dollop_a); + + return dollop_man.GetContainingDollop(insn_b) == NULL && + dollop_man.GetContainingDollop(insn_a) == dollop_a; +} + +bool TestGetContainingDollopFallthrough(void) { + ZiprDollopManager_t dollop_man; + libIRDB::Instruction_t *insn_a = new libIRDB::Instruction_t(); + libIRDB::Instruction_t *insn_b = new libIRDB::Instruction_t(); + Dollop_t *dollop_a = NULL; + + insn_a->SetFallthrough(insn_b); + + dollop_a = Dollop_t::CreateNewDollop(insn_a); + dollop_man.AddDollop(dollop_a); + + return dollop_man.GetContainingDollop(insn_b) == dollop_a && + dollop_man.GetContainingDollop(insn_a) == dollop_a; +} + +bool TestGetContainingDollop(void) { + ZiprDollopManager_t dollop_man; + libIRDB::Instruction_t *insn_a = new libIRDB::Instruction_t(); + libIRDB::Instruction_t *insn_b = new libIRDB::Instruction_t(); + Dollop_t *dollop_a = Dollop_t::CreateNewDollop(insn_a); + Dollop_t *dollop_b = Dollop_t::CreateNewDollop(insn_b); + dollop_man.AddDollop(dollop_a); + dollop_man.AddDollop(dollop_b); + return dollop_man.GetContainingDollop(insn_a) == dollop_a && + dollop_man.GetContainingDollop(insn_b) == dollop_b; +} + +bool TestAddDollopEntry(void) { ZiprDollopManager_t dollop_man; libIRDB::Instruction_t *insn = new libIRDB::Instruction_t(); - dollop_man.AddDollop(ZiprDollopManager_t::CreateDollop(insn)); + dollop_man.AddDollop(Dollop_t::CreateNewDollop(insn)); + return 1 == dollop_man.Size(); +} + +bool TestDollopPatch(void) { + Dollop_t *a = NULL; + DollopPatch_t patch; + + libIRDB::Instruction_t *insn_a = new libIRDB::Instruction_t(); + a = Dollop_t::CreateNewDollop(insn_a); + + patch.Target(a); + + return patch.Target() == a; +} + +bool TestDollopPatchDollopManager(void) { + ZiprDollopManager_t dollop_man; + DollopPatch_t patch_a, patch_b; + Dollop_t *dollop_a, *dollop_b; + + libIRDB::Instruction_t *insn_a = new libIRDB::Instruction_t(); + libIRDB::Instruction_t *insn_b = new libIRDB::Instruction_t(); + + dollop_a = Dollop_t::CreateNewDollop(insn_a); + dollop_b = Dollop_t::CreateNewDollop(insn_b); + + patch_a.Target(dollop_b); + patch_b.Target(dollop_a); + + dollop_man.AddDollopPatch(&patch_a); + dollop_man.AddDollopPatch(&patch_b); + + dollop_man.PrintDollopPatches(cout); + return true; +} + +bool TestDollopPatchMapDollopManager(void) { + bool success = true; + ZiprDollopManager_t dollop_man; + DollopPatch_t patch_a, patch_aa, patch_c; + Dollop_t *dollop_a, *dollop_c; + std::list<DollopPatch_t *>::const_iterator patches_it, patches_it_end; + + libIRDB::Instruction_t *insn_a = new libIRDB::Instruction_t(); + libIRDB::Instruction_t *insn_c = new libIRDB::Instruction_t(); + + dollop_a = Dollop_t::CreateNewDollop(insn_a); + dollop_c = Dollop_t::CreateNewDollop(insn_c); + + patch_a.Target(dollop_a); + patch_aa.Target(dollop_a); + patch_c.Target(dollop_c); + + dollop_man.AddDollop(dollop_a); + dollop_man.AddDollop(dollop_c); + + dollop_man.AddDollopPatch(&patch_a); + dollop_man.AddDollopPatch(&patch_aa); + dollop_man.AddDollopPatch(&patch_c); + + cout << "&dollop_a: " << std::hex << dollop_a << endl; + cout << "&dollop_c: " << std::hex << dollop_c << endl; + + std::list<DollopPatch_t *> patches = dollop_man.PatchesToDollop(dollop_a); + for (patches_it = patches.begin(), patches_it_end = patches.end(); + patches_it != patches.end(); + patches_it++) { + success &= ((*patches_it)->Target()) == dollop_a; + cout << *(*patches_it) << endl; + } + patches = dollop_man.PatchesToDollop(dollop_c); + for (patches_it = patches.begin(), patches_it_end = patches.end(); + patches_it != patches.end(); + patches_it++) { + success &= ((*patches_it)->Target()) == dollop_c; + cout << *(*patches_it) << endl; + } + return success; +} + +bool TestDollopSplit(void) { + Dollop_t *a, *b; + + libIRDB::Instruction_t *insn_a = new libIRDB::Instruction_t(); + libIRDB::Instruction_t *insn_b = new libIRDB::Instruction_t(); + libIRDB::Instruction_t *insn_c = new libIRDB::Instruction_t(); + libIRDB::Instruction_t *insn_d = new libIRDB::Instruction_t(); + libIRDB::Instruction_t *insn_e = new libIRDB::Instruction_t(); + + insn_a->SetFallthrough(insn_b); + insn_b->SetFallthrough(insn_c); + insn_c->SetFallthrough(insn_d); + insn_d->SetFallthrough(insn_e); + + a = Dollop_t::CreateNewDollop(insn_a); + + cout << "Dollop A: " << endl; + cout << *a << endl; + + b = a->Split(insn_b); + + cout << "Dollop A: " << endl; + cout << *a << endl; + cout << "Dollop B: " << endl; + cout << *b << endl; + + return a->GetDollopEntryCount() == 1 && b->GetDollopEntryCount() == 4; +} + +bool TestDollopEntryEquals(void) { + DollopEntry_t *a, *b, *c, *d; + + libIRDB::Instruction_t *insn_a = new libIRDB::Instruction_t(); + libIRDB::Instruction_t *insn_b = new libIRDB::Instruction_t(); + + a = new DollopEntry_t(insn_a); + b = new DollopEntry_t(insn_b); + c = new DollopEntry_t(insn_a); + d = new DollopEntry_t(insn_a); + d->SetTargetDollop((Dollop_t*)0x5000); + + return *a != *b && + *b != *c && + *a == *a && + *b == *b && + *a == *c && + *a != *d; +} + +int main(int argc, char *argv[]) +{ + INVOKE(TestAddDollopEntry); + INVOKE(TestDollopEntryEquals); + INVOKE(TestDollopSplit); + INVOKE(TestGetContainingDollop); + INVOKE(TestGetContainingDollopFallthrough); + INVOKE(TestGetContainingDollopNoFallthrough); + INVOKE(TestDollopPatch); + INVOKE(TestDollopPatchDollopManager); + INVOKE(TestDollopPatchMapDollopManager); return 0; }