我想将其转换为指针,以便能够从中访问第三个条目。所以我使用sscanf将字符串转换为十六进制指针。
问题是每当我做s_c_t_addr[2]
时,我都会得到一个错误"无效使用void表达式"。关于这个问题的原因有什么提示吗?我应该从void*
更改类型吗?如果是,新的型号应该是什么?
我还是个初学者,所以别对我太苛刻
sys_call_table
的正确类型取决于体系结构。在x86上是sys_call_ptr_t *
,因为它是一个函数指针数组,在ARM64上是syscall_fn_t **
。你可以这样声明它:
sys_call_ptr_t *sys_call_table;
在任何情况下,它应该是好的,即使声明为void **
:
void **sys_call_table;
那么,由于您正在编写一个内核模块,因此没有必要通过读取和解析System.map
的内容来使您的工作复杂化,您可以使用kallsym_lookup_name()
(包括linux/kallsym.h
)。这也可以在启用了KASLR的情况下工作。
sys_call_table = (sys_call_ptr_t)kallsyms_lookup_name("sys_call_table");
在你的例子中,它应该是:
sys_call_ptr_t *sys_call_table;
char *sys_call_table_addr;
unsigned long ul;
// ...
sscanf(sys_call_table_addr, "%lx", &ul);
sys_call_table = (sys_call_ptr_t *)ul;
最后,你可以获得fork
的地址,就像你正在做的一样,但是在正确的变量上(不是char *
),并记住它是一个指针,因此,如果你想打印真实的地址,正确的格式说明符是%px
(或者%p
,如果你想打印散列地址,请参阅本文档页面了解更多细节)。
printk(KERN_INFO "fork address: %pxn", sys_call_table[__NR_fork]);