小工具知识网

当前位置: 首页 > 行业知识 > Linux 内核获取函数size

行业知识

Linux 内核获取函数size

2026-11-04 21:44:09 来源:互联网转载

方式一:通过objdump -t直接从目标文件中获取函数size

#objdump -t file_unread.o | grep hook0000000000000030 l     F .text  000000000000012f hook_vfs_read

0000000000000030 l F .text 000000000000012f hook_vfs_read各个字段说明

()
  • 0000000000000030:符号的地址或值,这里是一个相对地址,表示该符号在.text节中的偏移量。
  • l:符号的绑定属性,这里是小写字母l,表示该符号是一个局部符号,只在当前目标文件中可见。
  • F:符号所在的节(section)的类型,这里是大写字母F,表示该符号所在的节是一个函数节(function section)。
  • .text:符号所在的节的名称,这里是.text,表示该符号所在的节是代码节。
  • 000000000000012f:符号的大小,以字节为单位,这里是0x12f,表示该函数的大小为303字节。
  • hook_vfs_read:符号的名称,这里是hook_vfs_read,表示该符号是一个名为hook_vfs_read的函数。

    vfs_read+0xe6/0x2c0 表示什么意思呢?

    其中vfs_read 是函数名,+0xe6/0x2c0 是函数在代码中的偏移量。具体来说,+0xe6 表示函数内部代码的偏移量,/ 后面的 0x2c0 表示函数的总大小(以字节为单位)。

    ()

    hook_vfs_read+0xe4/0x130 [fi_file]为动态打印进程调用栈信息。

    方式二:通过objdump -D反汇编后计算函数size

    用objdump对目标文件进行反汇编,从汇编代码中计算hook_vfs_read的函数size

    0000000000000030 :  30:   e8 00 00 00 00          callq  35   35:   41 57                   push   %r15  37:   41 56                   push   %r14  39:   31 c0                   xor    %eax,%eax  ......  14f:   eb c3                   jmp    114   151:   48 c7 c7 00 00 00 00    mov    
    -t, --syms               Display the contents of the symbol table(s)-D, --disassemble-all    Display assembler contents of all sections
    x0,%rdi 158: e8 00 00 00 00 callq 15d 15d: eb a3 jmp 102 15f: 90 nop

    hook_vfs_read_size = 0x15f - 0x30 = 0x12f + 1,从计算的结果来看,加上偏移与调用栈打印的函数size是一致的。

    方式三:通过内核函数动态获取函数size

    /** * sprint_symbol - Look up a kernel symbol and return it in a text buffer * @buffer: buffer to be stored * @address: address to lookup * * This function looks up a kernel symbol with @address and stores its name, * offset, size and module name to @buffer if possible. If no symbol was found, * just saves its @address as is. * * This function returns the number of bytes stored in @buffer. */int sprint_symbol(char *buffer, unsigned long address){        return __sprint_symbol(buffer, address, 0, 1);}EXPORT_SYMBOL_GPL(sprint_symbol);
    #include static int __init my_init(void){    const char *str = "hook_vfs_read+0x0/0x130 [fi_file]";    const char *prefix = "/0x";    const char *suffix = " [";    char *start, *end;    unsigned long value;    // 查找前缀字符串    start = strstr(str, prefix);    if (!start) {        printk(KERN_ERR "Failed to find prefix string\n");        return -EINVAL;    }    start += strlen(prefix);    // 查找后缀字符串    end = strstr(start, suffix);    if (!end) {        printk(KERN_ERR "Failed to find suffix string\n");        return -EINVAL;    }    // 截取字符串    *end = '
    /* * Lookup an address * - modname is set to NULL if it's in the kernel. * - We guarantee that the returned name is valid until we reschedule even if. *   It resides in a module. * - We also guarantee that modname will be valid until rescheduled. */const char *kallsyms_lookup(unsigned long addr,    unsigned long *symbolsize,    unsigned long *offset,    char **modname, char *namebuf){const char *ret;namebuf[KSYM_NAME_LEN - 1] = 0;namebuf[0] = 0;if (is_ksym_addr(addr)) {unsigned long pos;pos = get_symbol_pos(addr, symbolsize, offset);/* Grab name */kallsyms_expand_symbol(get_symbol_offset(pos),       namebuf, KSYM_NAME_LEN);if (modname)*modname = NULL;return namebuf;}/* See if it's in a module or a BPF JITed image. */ret = module_address_lookup(addr, symbolsize, offset,    modname, namebuf);if (!ret)ret = bpf_address_lookup(addr, symbolsize, offset, modname, namebuf);if (!ret)ret = ftrace_mod_address_lookup(addr, symbolsize,offset, modname, namebuf);return ret;}
    '; value = simple_strtoul(start, NULL, 16); printk(KERN_INFO "Value: 0x%lx\n", value); return 0;}

    路径1:

    获取到的字符串信息示例为hook_vfs_read+0x0/0x130 [fi_file],这种方式需要从数组str中解析出函数大小0x130

    解析字符串中的函数size,还是要骚操作获取,在内核中没有看到直接获取函数size的函数。

    路径二:

    内核代码v4.18.20中sprint_symbol最终调用kallsyms_lookup获取函数size,因此也可以直接调用该函数获取函数size,免去上述复杂的字符串解析过程。

上一篇:怎么查出网站服务器位置?

下一篇:Android UI 测试工具- Espresso的配置及使用