static knh_xblock_t *knh_generateWrapper(CTX ctx, void *callee, int argc, knh_ffiparam_t *argv) { knh_xblock_t *blk = get_unused_xblock(ctx); knh_xblock_t *function = blk->block; size_t fidx = 0; int i = 0; knh_ffiparam_t *t; // local ffiarguments; ffi_cif *cif = (ffi_cif*)KNH_MALLOC(ctx, sizeof(ffi_cif)); ffi_type **args = (ffi_type**)KNH_MALLOC(ctx, sizeof(ffi_type) * argc); void *values[1]; for (i = 0; i < argc; i++) { t = &argv[i]; if (t->sfpidx != -1) { // it means arguments switch(t->type) { case CLASS_Tvoid: // do nothing break; case CLASS_Int: args[i] = &ffi_type_uint64; break; case CLASS_Float: args[i] = &ffi_type_double; break; default: args[i] = &ffi_type_pointer; break; } } } if (ffi_prep_cif(cif, FFI_DEFAULT_ABI, argc, &ffi_type_void, args) == FFI_OK) { fprintf(stderr, "OKAY!\n"); } else { fprintf(stderr, "this is not okay!\n"); } }
static knh_xblock_t* knh_generateWrapper(CTX ctx, void* callee, int argc, knh_ffiparam_t *argv) { //unsigned char *FUNCTION = (unsigned char*)knh_xmalloc(ctx, 1); knh_xblock_t *blk = get_unused_xblock(ctx); unsigned char *function = blk->block; size_t fidx = 0; // magick word WRITE_HEX(0x55); // push ebp WRITE_HEX(0x89); // mov esp->ebp WRITE_ASM(MOD_IMD, _ESP, _EBP); // incase we use ebp, store it. WRITE_HEX(0x53); // push ebx // we need stack argc * 8bytes at most size_t stacksize = argc * 8; // allocate stack (sub esp 0x38) WRITE_HEX(0x83); WRITE_HEX(0xec); WRITE_HEX((unsigned char)(stacksize + 0x8)); // before going, we need edx to be store; // mov edx --> -0x4(ebp) WRITE_HEX(0x89); // mov r+disp r WRITE_ASM(MOD_PLUS8, _EDX, _EBP); WRITE_HEX(0xfc); //now, process first argument; int i; knh_ffiparam_t *t; for (i = 0; i < argc; i++) { t = &(argv[i]); if (t->sfpidx != -1) { // if sfpidx == -1, its ret value; // prepare ebx (put sfp from edx); WRITE_HEX(0x89); WRITE_ASM(MOD_IMD, _EDX, _EBX); switch(t->type) { case CLASS_Tvoid: // do noting. break; case CLASS_Int: // its 64bit int //TODO: we need to call translater, but now, we ignore //TODO: assume we cast Int --> int; // add ebx[sfp] + sfpidx * 16; WRITE_HEX(0x83); //add WRITE_ASM(MOD_IMD, _EAX , _EBX); WRITE_HEX((unsigned char)(t->sfpidx * 16)); // move ivalue(offset is 8); WRITE_HEX(0x8b); // mov r+disp, r WRITE_ASM(MOD_PLUS8, _EAX, _EBX); WRITE_HEX(0x8); // move eax to local value //WRITE_HEX(0x89); //WRITE_ASM(MOD_IMD, _EBP, _EAX); // WRITE_HEX(0xf4); break; case CLASS_Float: WRITE_HEX(0x83); WRITE_ASM(MOD_IMD, _EAX, _EBX); WRITE_HEX((unsigned char)(t->sfpidx * 16)); // load fvalue; WRITE_HEX(0xdd);// fld 64bit WRITE_HEX(0x43);// eax WRITE_HEX(0x8); // offset // push it to eax; WRITE_HEX(0xdd); // fstp : store & pop 64 WRITE_HEX(0x1c); WRITE_HEX(0x24); break; default: break; } } else continue; // if its ret value } // now, call foreign function // NOT SURE??? since konoha is using FASTCALL, // call convension is always Fastcall. unsigned char default_disp = 0x8; unsigned char disp = 0x0; // argc contains ret value. remeber... // TODO :only for a single argument... for (i = argc - 1; i > 0; i--) { // push aruguments on the stack; // mov argument to eax! // TODO : now, we only consider 32 bit values if (argv[i].type == CLASS_Int) { function[fidx++] = 0x89; // mov r+disp r function[fidx++] = 0x45; // 0xXX(ebp) disp = default_disp + i * 4; disp = 0x100 - disp; function[fidx++] = disp; // -0x8 //move to esp function[fidx++] = 0x89; function[fidx++] = 0x04; function[fidx++] = 0x24; } } //now call. // call foreign function // intptr_t ucallee = (intptr_t)callee; // intptr_t next_addr = (intptr_t)function + (intptr_t)fidx + 5 /*for call instruction */; //intptr_t rel = (ucallee > next_addr) ? ucallee - next_addr : next_addr - ucallee; //rel = -rel; //unsigned char *src = (unsigned char*)&rel; // absolute call unsigned char *src = (unsigned char*)&callee; // mov this to eax; WRITE_HEX(0xb8); // mov to eax WRITE_HEX(src[0]); WRITE_HEX(src[1]); WRITE_HEX(src[2]); WRITE_HEX(src[3]); // now call WRITE_HEX(0xff); WRITE_HEX(0xd0); // function[fidx++] = 0xcc; // after calling, restore edx; // restore edx; WRITE_HEX(0x8b); WRITE_ASM(MOD_PLUS8, _EDX, _EBP); WRITE_HEX(0xfc); if (argv[0].sfpidx == -1) { switch(argv[0].type) { case CLASS_Tvoid: goto STEP_OUT; break; case CLASS_Int: // get return value, and give it to Konoha // ret value is on eax; // push eax function[fidx++] = 0x50; // push eax break; case CLASS_Float: // it is on FPU. we need no concern. break; } } // get rix (at 0x8(ebp)) --> eax WRITE_HEX(0x8b); // mov WRITE_ASM(MOD_PLUS8, _EAX, _EBP); // 0xXX(ebp) eax WRITE_HEX(0x8); // 8 // get edx --> ebx WRITE_HEX(0x89); WRITE_ASM(MOD_IMD, _EDX, _EBX); // ebx[sfp] + 16 * rix // first, 16 * rix = 2^4 * rix WRITE_HEX(0xc1); // shl WRITE_ASM(MOD_IMD, _ESP, _EAX); WRITE_HEX(0x4); // second, add eax to ebx; WRITE_HEX(0x01); //add WRITE_ASM(MOD_IMD, _EAX, _EBX); // add eax -> ebx; // now at ebx is pointing to sfp[K_RIX]; // copy retvalue to sfp[K_RIX].ivalue (offset is 0x8) // pop eax; // offset is different for each types if (argv[0].sfpidx == -1) { switch (argv[0].type) { case CLASS_Int: function[fidx++] = 0x58; // pop eax // mov eax --> 0x8(%ebx) function[fidx++] = 0x89; // mov r+disp r function[fidx++] = 0x43; // eax: ebx function[fidx++] = 0x8; // 0x8 break; case CLASS_Float: //fstpl 0x8(ebx) WRITE_HEX(0xdd); WRITE_ASM(MOD_PLUS8, _EBX, _EBX); WRITE_HEX(0x8); break; } } // from here, closing this function // close stack; add 0xXX esp STEP_OUT: WRITE_HEX(0x83); WRITE_HEX(0xc4); WRITE_HEX((unsigned char)(stacksize + 0x8)); // restore ebx WRITE_HEX(0x5b); // pop ebx WRITE_HEX(0x5d); // pop ebp; // ret $0x4 WRITE_HEX(0xc2); // ret WRITE_HEX(0x4); WRITE_HEX(0x0); // return function; return blk; }