diff --git a/.gitattributes b/.gitattributes index 12270cdf7bf66ae01b9f0115ff01894f9965707f..edb8e96f833259d6a3c636f6e0413047cb20d551 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14,13 +14,16 @@ include/zipr_impl.h -text include/zipr_mem_space.h -text include/zipr_optimizations.h -text include/zipr_stats.h -text +include/zipr_utils.h -text /install-sh -text src/Makefile.in -text src/SConscript -text src/SConstruct -text +src/dollop.cpp -text src/main.cpp -text src/memory_space.cpp -text src/plugin_man.cpp -text +src/utils.cpp -text src/zipr.cpp -text src/zipr_options.cpp -text src/zipr_stats.cpp -text diff --git a/include/plugin_man.h b/include/plugin_man.h index 658a4257dd364a9216cc2406af7b0fb08bb6f3fd..c98faf428c3b2762c28402d1f6b8b5c8284cbe22 100644 --- a/include/plugin_man.h +++ b/include/plugin_man.h @@ -42,6 +42,7 @@ class ZiprPluginManager_t : public ZiprPluginInterface_t virtual bool DoesPluginPlop(libIRDB::Instruction_t*,DLFunctionHandle_t&); + virtual bool DoesPluginPlace(const RangeAddress_t &, const Dollop_t &, Range_t &, DLFunctionHandle_t &); private: void open_plugins diff --git a/include/unresolved.h b/include/unresolved.h index a7e89d381867e1f6fd302e2e487a225cdf7130b7..312ff29dd7ef064bf83ad458ad69f1433e9c0032 100644 --- a/include/unresolved.h +++ b/include/unresolved.h @@ -125,7 +125,7 @@ class Patch_t public: Patch_t(RangeAddress_t p_from_addr, UnresolvedType_t p_t) : from_addr(p_from_addr), type(p_t) {} - RangeAddress_t GetAddress() { return from_addr; } + RangeAddress_t GetAddress() const { return from_addr; } UnresolvedType_t GetType() { return type; } private: diff --git a/include/zipr_all.h b/include/zipr_all.h index d705355f4d03c94a02b38cf8198e0dbc3fea3ab3..34cec6c0a0381104c5526713ac6c85c7cbce0f4d 100644 --- a/include/zipr_all.h +++ b/include/zipr_all.h @@ -52,6 +52,7 @@ using namespace Zipr_SDK; #include <unresolved.h> #include <zipr_mem_space.h> #include <plugin_man.h> +#include <zipr_utils.h> #include <zipr_impl.h> #include <zipr_optimizations.h> #include <zipr_stats.h> diff --git a/include/zipr_mem_space.h b/include/zipr_mem_space.h index a99c128ee927eb96951e7cc65151d6bd9491c63e..18a782761f55e513535f21e7bcbfc034aeba857c 100644 --- a/include/zipr_mem_space.h +++ b/include/zipr_mem_space.h @@ -46,6 +46,7 @@ class ZiprMemorySpace_t : public MemorySpace_t void MergeFreeRange(RangeAddress_t addr); RangeSet_t::iterator FindFreeRange(RangeAddress_t addr); Range_t GetFreeRange(int size); + Range_t GetNearbyFreeRange(const RangeAddress_t hint); void AddFreeRange(Range_t newRange); void RemoveFreeRange(Range_t newRange); diff --git a/include/zipr_utils.h b/include/zipr_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..4209ad69b91a8e2d8a14d565beafae18b4fd3e71 --- /dev/null +++ b/include/zipr_utils.h @@ -0,0 +1,9 @@ + +#ifndef zipr_utils_h +#define zipr_utils_h + +namespace Utils { + extern size_t CALLBACK_TRAMPOLINE_SIZE; + int DetermineWorstCaseInsnSize(libIRDB::Instruction_t*); +} +#endif diff --git a/src/SConscript b/src/SConscript index 535db7909fbbe187ecf79128a5356c40f91434b5..6404294c1dc6daf69af1738692a42e7f167e7b68 100644 --- a/src/SConscript +++ b/src/SConscript @@ -18,6 +18,8 @@ files= ''' zipr.cpp zipr_options.cpp zipr_stats.cpp + utils.cpp + dollop.cpp ''' # ELFIO needs to be first so we get the zipr version instead of the sectrans version. the zipr version is modified to include get_offset. diff --git a/src/dollop.cpp b/src/dollop.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64cb89ae4e2deeed7b7e636d8c90f47c425d71c3 --- /dev/null +++ b/src/dollop.cpp @@ -0,0 +1,39 @@ +#include <zipr_all.h> + +namespace Zipr_SDK { + using namespace libIRDB; + using namespace zipr; + Dollop_t::Dollop_t(Instruction_t *start) + { + m_start = start; + m_size = CalculateWorstCaseSize(); + } + + size_t Dollop_t::CalculateWorstCaseSize() + { + size_t dollop_size = 0; + Instruction_t *cur_insn = m_start; + while (cur_insn != NULL) + { + /* + * TODO: Take into consideration the dollop might + * be MUCH shorter if it is going to jump to a + * previously placed dollop at this insn. + */ + #if 0 + if ((to_addr=final_insn_locations[cur_insn]) != 0) + { + if (!m_replop) + { + if (m_verbose) + printf("Fallthrough loop detected. "); + break; + } + } + #endif + dollop_size += Utils::DetermineWorstCaseInsnSize(cur_insn); + cur_insn=cur_insn->GetFallthrough(); + } + return dollop_size; + } +} diff --git a/src/memory_space.cpp b/src/memory_space.cpp index b409e298c7a7a89d8e6e6991868ec8186a3e360b..3932ff6ba8e4b0b4eaaff329999a1c44bedb9c55 100644 --- a/src/memory_space.cpp +++ b/src/memory_space.cpp @@ -161,6 +161,20 @@ bool ZiprMemorySpace_t::IsValidRange(RangeSet_t::iterator it) return it!=free_ranges.end(); } +Range_t ZiprMemorySpace_t::GetNearbyFreeRange(const RangeAddress_t hint) +{ + RangeSet_t::iterator result; + Range_t search(hint, hint+1); + /* + * TODO: Not quite sure what to make of this. + */ + if (free_ranges.end() == (result = free_ranges.upper_bound(search))) { + cout << "Oops: GetNearbyFreeRange() is BAD" << endl; + return Range_t(0,0); + } + return *result; +} + Range_t ZiprMemorySpace_t::GetFreeRange(int size) { vector<Range_t> v; diff --git a/src/plugin_man.cpp b/src/plugin_man.cpp index bdde51fa3d20df5dfb05412c733bca75bc4b8046..2e3885e54fba30ff05bde8f5c0afddee28b0d29e 100644 --- a/src/plugin_man.cpp +++ b/src/plugin_man.cpp @@ -81,6 +81,21 @@ void ZiprPluginManager_t::CallbackLinkingEnd() dispatch_to(CallbackLinkingEnd); } +bool ZiprPluginManager_t::DoesPluginPlace(const RangeAddress_t &jump, const Dollop_t &dollop, Range_t &place, DLFunctionHandle_t &placer) +{ + DLFunctionHandleSet_t::iterator it=m_handleList.begin(); + for(m_handleList.begin();it!=m_handleList.end();++it) + { + ZiprPluginInterface_t* zpi=(ZiprPluginInterface_t*)*it; + if (Zipr_SDK::ZiprPreference::Must == zpi->PlopAddress(jump, dollop, place)) + { + placer = zpi; + return true; + } + } + return false; +} + bool ZiprPluginManager_t::DoesPluginPlop(Instruction_t *insn, DLFunctionHandle_t &callback) { DLFunctionHandleSet_t::iterator it=m_handleList.begin(); diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..735f91101be562380140a06521fdb740269fb824 --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,70 @@ +#include <zipr_all.h> + +namespace zipr { +namespace Utils { +size_t CALLBACK_TRAMPOLINE_SIZE=9; +using namespace libIRDB; +int DetermineWorstCaseInsnSize(Instruction_t* insn) +{ + + int required_size=0; + + switch(insn->GetDataBits()[0]) + { + case (char)0x71: + case (char)0x72: + case (char)0x73: + case (char)0x74: + case (char)0x75: + case (char)0x76: + case (char)0x77: + case (char)0x78: + case (char)0x79: + case (char)0x7a: + case (char)0x7b: + case (char)0x7c: + case (char)0x7d: + case (char)0x7e: + case (char)0x7f: + { + // two byte JCC -> 6byte JCC + required_size=6; + break; + } + + case (char)0xeb: + { + // two byte JMP -> 5byte JMP + required_size=5; + break; + } + + case (char)0xe0: + case (char)0xe1: + case (char)0xe2: + case (char)0xe3: + { + // loop, loopne, loopeq, jecxz + // convert to: + // <op> +5: + // jmp fallthrough + // +5: jmp target + // 2+5+5; + required_size=10; + break; + } + + + default: + { + required_size=insn->GetDataBits().size(); + if (insn->GetCallback()!="") required_size+=CALLBACK_TRAMPOLINE_SIZE; + break; + } + } + + // add an extra 5 for a "trampoline" in case we have to end this fragment early + return required_size+5; +} +} +} diff --git a/src/zipr.cpp b/src/zipr.cpp index 722eb452490f5ec3fff00c613d37e88f79fdfebc..28bd031c582ab49d83dd786185be631f5c3ebf3e 100644 --- a/src/zipr.cpp +++ b/src/zipr.cpp @@ -1224,77 +1224,44 @@ int ZiprImpl_t::_DetermineWorstCaseInsnSize(Instruction_t* insn) return worst_case_size; } -#define CALLBACK_TRAMPOLINE_SIZE 9 //static int DetermineWorstCaseInsnSize(Instruction_t* insn) int ZiprImpl_t::DetermineWorstCaseInsnSize(Instruction_t* insn) { - - int required_size=0; - - switch(insn->GetDataBits()[0]) - { - case (char)0x71: - case (char)0x72: - case (char)0x73: - case (char)0x74: - case (char)0x75: - case (char)0x76: - case (char)0x77: - case (char)0x78: - case (char)0x79: - case (char)0x7a: - case (char)0x7b: - case (char)0x7c: - case (char)0x7d: - case (char)0x7e: - case (char)0x7f: - { - // two byte JCC -> 6byte JCC - required_size=6; - break; - } - - case (char)0xeb: - { - // two byte JMP -> 5byte JMP - required_size=5; - break; - } - - case (char)0xe0: - case (char)0xe1: - case (char)0xe2: - case (char)0xe3: - { - // loop, loopne, loopeq, jecxz - // convert to: - // <op> +5: - // jmp fallthrough - // +5: jmp target - // 2+5+5; - required_size=10; - break; - } - - - default: - { - required_size=insn->GetDataBits().size(); - if (insn->GetCallback()!="") required_size+=CALLBACK_TRAMPOLINE_SIZE; - break; - } - } - - // add an extra 5 for a "trampoline" in case we have to end this fragment early - return required_size+5; + return Utils::DetermineWorstCaseInsnSize(insn); } void ZiprImpl_t::ProcessUnpinnedInstruction(const UnresolvedUnpinned_t &uu, const Patch_t &p) { int req_size=_DetermineWorstCaseInsnSize(uu.GetInstruction()); - Range_t r=memory_space.GetFreeRange(req_size); + Range_t r; + //Range_t r=memory_space.GetFreeRange(req_size); + //Range_t r=memory_space.GetNearbyFreeRange(p.GetAddress()); int insn_count=0; const char* truncated="not truncated."; + bool placed = false; + DLFunctionHandle_t placer = NULL; + + /* + * + */ + if (plugman.DoesPluginPlace(p.GetAddress(), Dollop_t(uu.GetInstruction()), r, placer)) + { + if (m_verbose) + cout << placer->ToString() << " placed this dollop." << endl; + placed = true; + if ((r.GetEnd()-r.GetStart()) < req_size) { + if (m_verbose) + printf("Bad GetNearbyFreeRange() result.\n"); + placed = false; + } + } + if (!placed) { + cout << "Using default place locator." << endl; + r=memory_space.GetFreeRange(req_size); + } + /* + * + */ RangeAddress_t fr_end=r.GetEnd(); RangeAddress_t fr_start=r.GetStart(); @@ -2182,7 +2149,7 @@ RangeAddress_t ZiprImpl_t::PlopWithCallback(Instruction_t* insn, RangeAddress_t else assert(0); - assert(CALLBACK_TRAMPOLINE_SIZE<=(at-originalAt)); + assert(Utils::CALLBACK_TRAMPOLINE_SIZE<=(at-originalAt)); return at; }