首页 > 解决方案 > C 指针转换

问题描述

如果内核中有一个函数,我正在尝试打印第一个字节。我要打印的功能是'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]); 

但他们都没有工作,从来没有e8

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

标签: ccastingkernel

解决方案


关于您的第一个问题(为什么不同),%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


推荐阅读