Advertisement
Guest User

Untitled

a guest
Dec 10th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.00 KB | None | 0 0
  1. uint64_t PLH::ILCallback::getJitFunc(const asmjit::FuncSignature& sig, const PLH::ILCallback::tUserCallback callback, const uint64_t retAddr /* = 0 */) {
  2.     /*AsmJit is smart enough to track register allocations and will forward
  3.       the proper registers the right values and fixup any it dirtied earlier.
  4.       This can only be done if it knows the signature, and ABI, so we give it
  5.       them. It also only does this mapping for calls, so we need to generate
  6.       calls on our boundaries of transfers when we want argument order correct
  7.       (ABI stuff is managed for us when calling C code within this project via host mode).
  8.     */
  9.     asmjit::CodeHolder code;                      
  10.     code.init(asmjit::CodeInfo(asmjit::ArchInfo::kIdHost));        
  11.    
  12.     // initialize function
  13.     asmjit::x86::Compiler cc(&code);            
  14.     cc.addFunc(sig);              
  15.  
  16.     // to small to really need it
  17.     cc.func()->frame().resetPreservedFP();
  18.    
  19.     // map argument slots to registers, following abi.
  20.     std::vector<asmjit::x86::Reg> argRegisters;
  21.     for (uint8_t arg_idx = 0; arg_idx < sig.argCount(); arg_idx++) {
  22.         const uint8_t argType = sig.args()[arg_idx];
  23.  
  24.         asmjit::x86::Reg arg;
  25.         if (isGeneralReg(argType)) {
  26.             arg = cc.newInt32();
  27.         } else if (isXmmReg(argType)) {
  28.             arg = cc.newXmm();
  29.         } else {
  30.             ErrorLog::singleton().push("Parameters wider than 64bits not supported", ErrorLevel::SEV);
  31.             return 0;
  32.         }
  33.  
  34.         cc.setArg(arg_idx, arg);
  35.         argRegisters.push_back(arg);
  36.     }
  37.  
  38.     // setup the stack structure to hold arguments for user callback
  39.     argsStack = cc.newStack((uint32_t)(sizeof(uint64_t) * sig.argCount()), 4);
  40.     asmjit::x86::Mem argsStackIdx(argsStack);              
  41.  
  42.     // assigns some register as index reg
  43.     asmjit::x86::Gp i = cc.newUIntPtr();
  44.  
  45.     // stackIdx <- stack[i].
  46.     argsStackIdx.setIndex(i);                  
  47.  
  48.     // r/w are sizeof(uint64_t) width now
  49.     argsStackIdx.setSize(sizeof(uint64_t));
  50.    
  51.     // set i = 0
  52.     cc.mov(i, 0);  
  53.     UNREFERENCED_PARAMETER(callback);
  54.     //// mov from arguments registers into the stack structure
  55.     for (uint8_t arg_idx = 0; arg_idx < sig.argCount(); arg_idx++) {
  56.         const uint8_t argType = sig.args()[arg_idx];
  57.  
  58.         // have to cast back to explicit register types to gen right mov type
  59.         if (isGeneralReg(argType)) {
  60.             cc.mov(argsStackIdx, argRegisters.at(arg_idx).as<asmjit::x86::Gp>());
  61.         } else if(isXmmReg(argType)) {
  62.             cc.movq(argsStackIdx, argRegisters.at(arg_idx).as<asmjit::x86::Xmm>());
  63.         } else {
  64.             ErrorLog::singleton().push("Parameters wider than 64bits not supported", ErrorLevel::SEV);
  65.             return 0;
  66.         }
  67.  
  68.         // next structure slot (+= sizeof(uint64_t))
  69.         cc.add(i, sizeof(uint64_t));
  70.     }
  71.  
  72.     // get pointer to stack structure and pass it to the user callback
  73.     asmjit::x86::Gp argStruct = cc.newUIntPtr("argStruct");
  74.     cc.lea(argStruct, argsStack);
  75.  
  76.     // fill reg to pass struct arg count to callback
  77.     asmjit::x86::Gp argCountParam = cc.newU8();
  78.     cc.mov(argCountParam, (uint8_t)sig.argCount());
  79.  
  80.     // call to user provided function (use ABI of host compiler)
  81.     auto call = cc.call(asmjit::Imm(static_cast<int64_t>((intptr_t)callback)), asmjit::FuncSignatureT<void, Parameters*, uint8_t>(asmjit::CallConv::kIdHost));
  82.     call->setArg(0, argStruct);
  83.     call->setArg(1, argCountParam);
  84.    
  85.     // deref the trampoline ptr (must live longer)
  86.     asmjit::x86::Gp orig_ptr = cc.newUIntPtr();;
  87.     cc.mov(orig_ptr, (uintptr_t)getTrampolineHolder());
  88.     cc.mov(orig_ptr, asmjit::x86::ptr(orig_ptr));
  89.  
  90.     /*-- OPTIONALLY SPOOF RET ADDR --
  91.     If the retAddr param is != 0 then we transfer via a push of dest addr, ret addr, and jmp.
  92.     Other wise we just call. Potentially useful for defensive binaries.
  93.     */
  94.     /*unsigned char* retBufTmp = (unsigned char*)m_mem.getBlock(10);
  95.     *(unsigned char*)retBufTmp = 0xC3;*/
  96.    
  97.     uint64_t retAddrReal = retAddr;
  98.     //retAddrReal = (uint64_t)retBufTmp;
  99.     if (retAddrReal == 0) {
  100.         /* call trampoline, map input args same order they were passed to us.*/
  101.         auto orig_call = cc.call(orig_ptr, sig);
  102.         for (uint8_t arg_idx = 0; arg_idx < sig.argCount(); arg_idx++) {
  103.             orig_call->setArg(arg_idx, argRegisters.at(arg_idx));
  104.         }
  105.  
  106.         cc.endFunc();
  107.         cc.finalize();
  108.     } else {
  109.         //asmjit::Label ret_jit_stub = cc.newLabel();
  110.         //asmjit::X86Gp tmpReg = cc.newUIntPtr();
  111.         //cc.lea(tmpReg, asmjit::x86::ptr(ret_jit_stub));
  112.         //
  113.         //cc.push(tmpReg); // push ret
  114.         //cc.push((uintptr_t)retAddrReal); // push &ret_inst
  115.         //cc.jmp(orig_ptr); // jmp orig
  116.         //cc.bind(ret_jit_stub); // ret_inst:
  117.         //cc.endFunc(); // omit prolog cleanup
  118.         //cc.finalize();
  119.     }
  120.    
  121.     // end function
  122.  
  123.    
  124.     // worst case, overestimates for case trampolines needed
  125.     code.flatten();
  126.     size_t size = code.codeSize();
  127.  
  128.     // Allocate a virtual memory (executable).
  129.     m_callbackBuf = (uint64_t)m_mem.getBlock(size);
  130.     if (!m_callbackBuf) {
  131.         __debugbreak();
  132.         return 0;
  133.     }
  134.  
  135.     if (code.hasUnresolvedLinks()) {
  136.         code.resolveUnresolvedLinks();
  137.     }
  138.  
  139.      // Relocate to the base-address of the allocated memory.
  140.     code.relocateToBase(m_callbackBuf);
  141.     code.copyFlattenedData((unsigned char*)m_callbackBuf, size);
  142.     return m_callbackBuf;
  143. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement