当前位置: 首页 > news >正文

Linux 内核获取函数size

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

#objdump -t file_unread.o | grep hook
0000000000000030 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 <hook_vfs_read>:30:   e8 00 00 00 00          callq  35 <hook_vfs_read+0x5>35:   41 57                   push   %r1537:   41 56                   push   %r1439:   31 c0                   xor    %eax,%eax......14f:   eb c3                   jmp    114 <hook_vfs_read+0xe4>151:   48 c7 c7 00 00 00 00    mov    $0x0,%rdi158:   e8 00 00 00 00          callq  15d <hook_vfs_read+0x12d>15d:   eb a3                   jmp    102 <hook_vfs_read+0xd2>15f:   90                      nop

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

-t, --syms               Display the contents of the symbol table(s)
-D, --disassemble-all    Display assembler contents of all sections

方式三:通过内核函数动态获取函数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);

路径1:

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

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

#include <linux/string.h>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 = '\0';value = simple_strtoul(start, NULL, 16);printk(KERN_INFO "Value: 0x%lx\n", value);return 0;
}

路径二:

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

/** 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;
}
http://www.lryc.cn/news/311476.html

相关文章:

  • Python+neo4j构建豆瓣电影知识图谱
  • DolphinScheduler——介绍及架构设计
  • 【Python】约瑟夫环问题
  • Python成功解决AttributeError: ‘Series‘ object has no attribute ‘set_value‘
  • 基于springboot+vue的医院药品管理系统
  • Python爬虫——Urllib库-1
  • 瑞_Redis_短信登录(一)
  • 《剑指 Offer》专项突破版 - 面试题 70 : 排序数组中只出现一次的数字(C++ 实现)
  • Linux安全加固功能
  • 最新AI系统ChatGPT网站H5系统源码,支持Midjourney绘画
  • 【服务器数据恢复】昆腾存储中raid5磁盘阵列数据恢复案例
  • 企业微信变更主体怎么改?
  • 常用生理眼电信号整理合集 (EOG)
  • 【场景题】让你设计一个订单号生成服务,该怎么做?
  • 使用GraphView实现简单的绘图工具
  • javaWebssh教师荣誉库管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计
  • Android minigbm框架普法
  • 01、MongoDB -- 下载、安装、配置文件等配置 及 副本集配置
  • uniapp中导入css和scss的区别
  • RabbitMQ-TTL/死信队列/延迟队列高级特性
  • docker安装php7.4安装(swoole)
  • 身份证识别系统(安卓)
  • Python教程——最后一波来喽
  • 学生管理系统(python实现)
  • Java读取文件
  • 曾桂华:车载座舱音频体验探究与思考| 演讲嘉宾公布
  • 面试题HTML+CSS+网络+浏览器篇
  • wordpress外贸独立站
  • [python] 构建数据流水线(pipeline)
  • 计算机网络-网络互连和互联网(五)