阅读hotspot的代码,须要先弄清楚这两个很容易混淆的概念。
最近我想到一个办法去区分折扣两个,就是在中间加个“的”:java
指针
函数
这样就很容易区分了。数组
其实在C语言中,指针数组和数组指针也是同样的区分办法。 加个“的”即可以解决。
为何会有这样的问题?老外怎么理解这个事情?我得回去翻翻K&R的那本C的英文教材。TODO。函数
是指返回指针的函数,好比:指针
int *fun (int a, int b) { int c = a + b; return &c; // 返回一个指针 }
是指指向函数的指针code
#include <stdio.h> int (* fun)(int a, int b); // fun 就是指向函数的指针变量 int add (int a, int b) { int c = a + b; return c; } int main(){ fun = add; int result = fun(100, 200); printf("result=%d\n", result); }
还能够结合类型声明将函数指针定义成类型blog
#include <stdio.h> // 定义一个 返回值是int 参数是两个int的函数指针 typedef int (* FunRefTypeTwoIntArgs)(int a, int b); // 将上面的函数指针变量 演化为类型 FunRefTypeTwoIntArgs 就是个类型 这样就好用多了 FunRefTypeTwoIntArgs addFun; FunRefTypeTwoIntArgs subFun; int add (int a, int b) { int c = a + b; return c; } int sub (int a, int b) { int c = a - b; return c; } int main(){ addFun = add; int result = addFun(100, 200); printf("result=%d\n", result); subFun = add; int result = subFun(500, 100); // 也能够写成 result = (*subFun)(500, 100); printf("result=%d\n", result); }
这就有点相似java中接口的样子了。接口
先是类型定义结合函数指针定义一个CallStub类型,该类型是 一个 指向函数的指针内存
// share/vm/runtime/stubRoutines.hpp // Calls to Java SimonNote: 函数指针结合typedef类型定义 最终调用是在 javaCalls中的call_helper() typedef void (*CallStub)( address link, intptr_t* result, BasicType result_type, Method* method, address entry_point, intptr_t* parameters, int size_of_parameters, TRAPS );
再定义一个返回函数指针的函数,拆开讲:本质是一个函数,是一个返回函数指针的函数,是一个返回 指向函数的指针的 函数,此处还涉及将内存地址直接转成函数指针(指向函数的指针)string
// share/vm/runtime/stubRoutines.hpp // Calls to Java SimonNote: 将内存地址 转换成函数指针 CAST_TO_FN_PTR call_stub 就是一个××返回函数指针×× 的 指针函数 ((CallStub)(castable_address(_call_stub_entry))) static CallStub call_stub() { return CAST_TO_FN_PTR(CallStub, _call_stub_entry); }
调用上面定义的io
// share/vm/runtime/javaCalls.cpp // 发起调用的地方 StubRoutines::call_stub()( (address)&link, // (intptr_t*)&(result->_value), // see NOTE above (compiler problem) result_val_address, // see NOTE above (compiler problem) result_type, method(), entry_point, args->parameters(), args->size_of_parameters(), CHECK );
下面这段 代码 还有遗留问题 仍是没能跑成功,至于缘由,我目前尚未答案。
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/mman.h> typedef int (* addFun)(int a, int b); int addWrap(int a, int b) { int c = add(a, b); return c; } int add(int a, int b) { return a + b; } int main() { int codeSize = sizeof(char) * 42; char* pCode = (char*)malloc(codeSize); char* pGen = pCode; mprotect(pCode, codeSize, PROT_READ | PROT_WRITE | PROT_EXEC); // 加了这一行也是core。 *pGen++ = 0x55; // 0x00000000004004fd <+0>: 55 push %rbp *pGen++ = 0x48; *pGen++ = 0x89; *pGen++ = 0xe5; // 0x00000000004004fe <+1>: 48 89 e5 mov %rsp,%rbp *pGen++ = 0x48; *pGen++ = 0x83; *pGen++ = 0xec; *pGen++ = 0x20; // 0x0000000000400501 <+4>: 48 83 ec 20 sub $0x20,%rsp *pGen++ = 0x89; *pGen++ = 0x7d; *pGen++ = 0xec; // 0x0000000000400505 <+8>: 89 7d ec mov %edi,-0x14(%rbp) *pGen++ = 0x89; *pGen++ = 0x75; *pGen++ = 0xe8; // 0x0000000000400508 <+11>: 89 75 e8 mov %esi,-0x18(%rbp) *pGen++ = 0x8b; *pGen++ = 0x55; *pGen++ = 0xe8; // 0x000000000040050b <+14>: 8b 55 e8 mov -0x18(%rbp),%edx *pGen++ = 0x8b; *pGen++ = 0x45; *pGen++ = 0xec; // 0x000000000040050e <+17>: 8b 45 ec mov -0x14(%rbp),%eax *pGen++ = 0x89; *pGen++ = 0xd6; // 0x0000000000400511 <+20>: 89 d6 mov %edx,%esi *pGen++ = 0x89; *pGen++ = 0xc7; // 0x0000000000400513 <+22>: 89 c7 mov %eax,%edi *pGen++ = 0xb8; *pGen++ = 0x00; *pGen++ = 0x00; *pGen++ = 0x00; *pGen++ = 0x00; // 0x0000000000400515 <+24>: b8 00 00 00 00 mov $0x0,%eax *pGen++ = 0xe8; *pGen++ = 0x08; *pGen++ = 0x00; *pGen++ = 0x00; *pGen++ = 0x00; // 0x000000000040051a <+29>: e8 08 00 00 00 callq 0x400527 <add> *pGen++ = 0x89; *pGen++ = 0x45; *pGen++ = 0xfc; // 0x000000000040051f <+34>: 89 45 fc mov %eax,-0x4(%rbp) *pGen++ = 0x8b; *pGen++ = 0x45; *pGen++ = 0xfc; // 0x0000000000400522 <+37>: 8b 45 fc mov -0x4(%rbp),%eax *pGen++ = 0xc9; // 0x0000000000400525 <+40>: c9 leaveq *pGen++ = 0xc3; // 0x0000000000400526 <+41>: c3 retq // addFun af = addWrap; addFun af = (addFun)pCode; // 若是我把这行注释掉 上一行行去掉注释 用上一行的方式 就没问题 可是反之 跑起来就会core core在下一行 int r = af(5, 15); printf("%d\n", r); free(pCode); return 0; }
有人说用mmap才能够解决core的问题
我有空试试