C指针铸造

C pointers casting

我正在尝试打印内核中的函数的第一个字节。 我要打印的函数是'filldir'。 我在内核中使用 /proc/kallsyms

找到了它

它的代码是(地址是ffffffff812e6020)-

    ffffffff812e6020:       e8 0b b9 91 00          callq  0xffffffff81c01930
    ffffffff812e6025:       55                      push   %rbp
    ffffffff812e6026:       48 89 e5                mov    %rsp,%rbp
    ffffffff812e6029:       41 57                   push   %r15

我在我的内核模块中使用这段代码找到了相同的地址(我认为是)-

    typedef unsigned long psize;
    (psize *) filldir;

    filldir= (void *)kallsyms_lookup_name("filldir");
    printk("rooty: sys_call_table found at %p\n", filldir);

并得到 - 000000001663973a,我不知道为什么会有差异,我尝试将其转换为 longunsigned long 但结果相同。

所以我的第一个问题是,为什么会有差异?我很确定它是以不同方式打印的相同地址......我怎样才能获得正确的价值?

我的第二个问题,我正在尝试打印函数的第一个字节 (e8),但我不知道该怎么做。

我尝试了这些选项 -

    printk("%x", *filldir);
    printk("%x", *(unsigned char*)filldir); 
    printk("%x", (unsigned char*)filldir[0]); 

但其中 none 有效,从未得到 e8

当我有指向函数的指针时,如何打印函数的第一个字节?

关于您的第一个问题(为什么不同),%p 格式说明符在打印之前被散列以防止地址泄漏。正确的格式是 %px [1]。在格式字符串之外投射参数不会影响它。

关于第二个,第二个选项应该是有效的。其他的可以在某些环境中工作,但没有定义它们应该做什么。

你可以在用户区试试:

#include <stdio.h>

int square(int num) {
    return num * num;
}

int main() {
    printf("%x\n", *(unsigned char *)square);
    return 0;
}

[1] https://www.kernel.org/doc/html/latest/core-api/printk-formats.html