【发布时间】:2016-10-27 20:59:30
【问题描述】:
我已经阅读了Extended Asm - Assembler Instructions with C Expression Operands和A side-by-side look at GNU Assembler (GAS) and Netwide Assembler (NASM),但是有些问题还不能解决。
好吧,我动态设计了一段代码。
; int xx_method_stub(void *fix_arg1, void* fix_arg2, void* arg3)
push ebp ; 55
mov ebp, esp ; 89 E5
sub esp, imm8_local_size ; 83 EC imm8_local_size
mov [ebp-4], imm_ptr_mid ; C7 45 FC imm_ptr_mid
jmp rel16_offset ; E9 rel16_offset
查看详情here,可能有点过头了。
现在它跳转到一个精心设计的地址,栈帧上下文如下:
16(%ebp) - third function parameter
12(%ebp) - second function parameter
8(%ebp) - first function parameter
4(%ebp) - old %EIP (the function's "return address")
0(%ebp) - old %EBP (previous function's base pointer)
-4(%ebp) - first local variable
到目前为止,我需要c 中的 jmp 标签代码。
void stubthunk_init(stubthunk *stub, mid_t mid) {
memcpy(stub, &stubthunk_templet, sizeof(stubthunk));
stub->ph_mid = mid;
stub->ph_eip_to_dispatch = (int) ((uintptr_t) dispatch - ((uintptr_t) stub + sizeof(stubthunk)));
// TODO retrieve stack variables as c-syntax local variables to make a function call in c for for portability.
//stack frame context
void *param_1; // 8(%%ebp)
void* param_2; //12(%%ebp)
void* local_1; //-4(%%ebp)
disp:
#ifdef _MSC_VER
__asm {
mov param_1 [ebp+8]
mov param_2 [ebp+12]
mov local_1 [ebp-4]
}
#else
__asm__ __volatile(
"mov 8(%%ebp), %0\n\t"
"mov 12(%%ebp), %1\n\t"
"mov -4(%%ebp), %2\n\t"
:"=m" (param_1), "=m" (param_2), "=m" (local_1)
:
: /* clobbered register. */
);
#endif
//USE #param_1 to restore or blance the stack
}
所以
有没有办法得到它 get jmp code block in c 并检索堆栈变量作为 c 语法局部变量以在 c 中进行函数调用,这样我就不会必须在asm 中编写更多代码,在这种情况下,无论函数调用约定如何,编译器都会帮助我解决诸如 arm、x86、x64、...
我希望我可以自己设置函数prologue 的堆栈框架和c 中的结语。通过这种方式,我可以将一个函数改造成一个 jmp 代码块,并以我自己的方式手动平衡堆栈。
或者,就像在 masm 中一样,有一个伪指令 invoke,例如invoke MessageBox, NULL, addr MsgBoxText, addr MsgBoxCaption, MB_OK,但它只存在于masm中。
=========已更新===========
我的目标:
static native int foo(int otherArgsMaybeExist);
int stdcall Java_xx_foo(void *fixedArgEnv, void *fixedArgCls, jint otherArgsMaybeExist){
return 0;
}
// TODO release stubthunk *stub
stubthunk *stub = (stubthunk*) alloc_code(sizeof(stubthunk));
stubthunk_init(stub, (intptr_t) argsize);
现在,我在内存中动态创建一个stdcall函数启动代码,它
除了一些必要的数据外,应该尽可能少(这里传递一个jmethodID,以便让关注的interpret_stdcall_x86知道谁被调用)。
在stub 注册一个带有 native 修饰符的 java 方法并进入本地世界后,它将进入我的代码。实际上,它就像 Windows 上的 Detours 一样的蹦床。
跳转后,所有被拦截的方法都会进入interpret_stdcall_x86,
负责堆栈平衡。
原来是这样的:
foo -> Java_xx_foo -> return
现在,会是这样的:
foo -> stubthunk + interpret_stdcall_x86 + blance the stack -> return
这里,thubthunk 是硬编码,但使用指令动态创建。然而,我希望我可以使用 c 为interpret_stdcall_x86 进行编码。
============================
【问题讨论】:
-
jmp rel16_offset???在 32 位或 64 位代码中,您唯一的选择是 rel8 and rel32。当然,汇编程序会为您处理这些。使用操作数大小的前缀来获取 rel16 编码也会用0x0000FFFF屏蔽 EIP。 -
所以你正试图从 asm 跳转到 C 函数的中间?完全不清楚使用 asm 获得了什么。为什么你不能在 C 中编写一个包装函数来操作 args 并调用另一个函数?或者从 asm,通过它的正常入口点尾调用一个 C 函数(根据调用约定,args 在它们通常的位置)。
-
我不是 100% 清楚您在寻找什么,但 GCC's builtins for constructing function calls 似乎它们可能是相关的。
-
有帮助~我下次试试。