/* * patch the call to do_debug inside debug interrupt handler */ int patch_do_debug(void) { int i, call_found = 0; unsigned int rip_offset; unsigned char *ptr = (unsigned char *)get_idt_handler(1); for (i = 0; i < 128; i++) { if (call_found == 2) { patched_addr = (unsigned int *)ptr; old_rip_off = *patched_addr; rip_offset = (unsigned long)my_do_debug - (unsigned long)patched_addr - 4; clear_CR0_WP(); *patched_addr = rip_offset; set_CR0_WP(); return 0; } else if (ptr[0] == 0xe8) { call_found++; } ptr++; } return -1; }
/* * x86_get_kernel_syms: get syscall table addr * ia32 addrs are not mandatory (CONFIG_IA32_EMULATION=n ?) */ int x86_get_kernel_syms(void) { int ret = 0; /* die chain */ ksyms.die_chain = (void *)x86_get_die_chain_addr(); /* * ia32 emulation via sysenter (not used ?) */ rdmsrl(MSR_IA32_SYSENTER_EIP, ksyms.ia32_sysenter); if (ksyms.ia32_sysenter) { ret = __get_sycall_addrs(ksyms.ia32_sysenter, &ksyms.ia32_sys_call_table, &ksyms.ia32_sysenter_sys_call_table_call); if (ret) goto exit; } /* * ia32 emulation via syscall */ ksyms.ia32_syscall = get_idt_handler(0x80); if (ksyms.ia32_syscall) { ret = __get_sycall_addrs(ksyms.ia32_syscall, &ksyms.ia32_sys_call_table, &ksyms.ia32_syscall_sys_call_table_call); if (ret) goto exit; } /* * x86_64 */ rdmsrl(MSR_LSTAR, ksyms.system_call); if (ksyms.system_call) ret = __get_sycall_addrs(ksyms.system_call, &ksyms.sys_call_table, &ksyms.sys_call_table_call); else ret = -1; exit: pr_debug("%s: ia32_sysenter=%lx ia32_sysenter_sys_call_table_call=%lx\n", __func__, ksyms.ia32_sysenter, ksyms.ia32_sysenter_sys_call_table_call); pr_debug("%s: ia32_syscall=%lx ia32_syscall_sys_call_table_call=%lx\n", __func__, ksyms.ia32_syscall, ksyms.ia32_syscall_sys_call_table_call); pr_debug("%s: ia32_sys_call_table=%lx\n", __func__, ksyms.ia32_sys_call_table); pr_debug("%s: die_chain=%p\n", __func__, ksyms.die_chain); return ret; }