/* * Copyright (C) NAKAMURA Minoru */ #include #include #include #include #include #include #define UNW_LOCAL_ONLY #include #ifdef __ia64__ struct fdesc { long code; long gp; }; # define get_fdesc(fdesc,func) (fdesc = *(struct fdesc *) &(func)) # define get_funcp(fdesc) ((template_t) &(fdesc)) # define get_gp(fdesc) ((fdesc).gp) #endif typedef void (*functype)(int); void print_message(int a) { printf("invoke print_message : arg = %d\n", a); } void cause_null_exception(int a) { *(int*)0 = 0; } void generated(functype f, int a) { f(a); } void (*funcp)(functype f, int a); void test(void) { int i; long pagesize = sysconf(_SC_PAGESIZE); char* p = (char*)mmap(0, pagesize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); assert(p != MAP_FAILED); #if defined(__ia64__) const int generated_size = 0xa0; // IA-64 は関数ポインタが直接命令アドレスを指すのではなく、 // struct fdesc のような関数ディスクリプタをさしているため // 少し工夫が必要。 memcpy(p, ((long*)generated)[0], 0xa0); // コードをフラッシュしないとダメ for (i=0 ; inext = NULL; region->insn_count = generated_size / 16 * 3; region->op_count = 2; _U_dyn_op_alias (®ion->op[0], 0, -1, fdesc.code); _U_dyn_op_stop (®ion->op[1]); memset (&di, 0, sizeof (di)); di.start_ip = (long) p; di.end_ip = (long) p + 16 * region->insn_count/3; di.gp = get_gp(fdesc); di.format = UNW_INFO_FORMAT_DYNAMIC; di.u.pi.name_ptr = (unw_word_t) "copy_of_generated"; di.u.pi.regions = region; _U_dyn_register (&di); fdesc.code = p; funcp = (functype)&fdesc; #else memcpy(p, generated, pagesize); funcp = p; #endif /* 動的コードをはさんで print_message を呼び出す */ funcp(print_message, 123); /* 動的コードをはさんで cause_null_exception を呼び出す */ funcp(cause_null_exception, 0 ); } int main(int argc, char** argv) { test(); return 0; }