首页 > 系统相关 >内核模块踩内存问题定位利器- hardware breakpoint

内核模块踩内存问题定位利器- hardware breakpoint

时间:2024-08-28 20:03:25浏览次数:11  
标签:ksym hw per CPU hardware breakpoint cpu 内核模块

内核由于共享内存地址空间,如果没有合适的工具,很多踩内存的问题即使复现,也无法快速定位;

在新的内核版本中引入了一个新工具hardware breakpoint,其能够监视对指定的地址的特定类型(读/写)的数据访问,有利于该类问题的定位;

以下是一个使用该工具的例子(来自内核代码linux-3.10/samples/hw_breakpoint/data_breakpoint.c)

struct perf_event * __percpu *sample_hbp;

static char ksym_name[KSYM_NAME_LEN] = "pid_max";
module_param_string(ksym, ksym_name, KSYM_NAME_LEN, S_IRUGO);
MODULE_PARM_DESC(ksym, "Kernel symbol to monitor; this module will report any"
			" write operations on the kernel symbol");

static void sample_hbp_handler(struct perf_event *bp,
			       struct perf_sample_data *data,
			       struct pt_regs *regs)
{
	printk(KERN_INFO "%s value is changed\n", ksym_name);
	dump_stack();
	printk(KERN_INFO "Dump stack from sample_hbp_handler\n");
}

static int __init hw_break_module_init(void)
{
	int ret;
	struct perf_event_attr attr;

	hw_breakpoint_init(&attr);
	attr.bp_addr = kallsyms_lookup_name(ksym_name);
	attr.bp_len = HW_BREAKPOINT_LEN_4;
	attr.bp_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R;

	sample_hbp = register_wide_hw_breakpoint(&attr, sample_hbp_handler, NULL);
	if (IS_ERR((void __force *)sample_hbp)) {
		ret = PTR_ERR((void __force *)sample_hbp);
		goto fail;
	}

	printk(KERN_INFO "HW Breakpoint for %s write installed\n", ksym_name);

	return 0;

fail:
	printk(KERN_INFO "Breakpoint registration failed\n");

	return ret;
}

static void __exit hw_break_module_exit(void)
{
	unregister_wide_hw_breakpoint(sample_hbp);
	printk(KERN_INFO "HW Breakpoint for %s write uninstalled\n", ksym_name);
}

module_init(hw_break_module_init);
module_exit(hw_break_module_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("K.Prasad");
MODULE_DESCRIPTION("ksym breakpoint");

注意:

  • 1、各个不同的CPU有同时支持的hardwarebreakpoint数量限制,对X86,为4个.
    所以对于随机的内存踩踏(频繁的申请、使用、释放)是很难处理的,比较适合固定的地址踩踏

  • 2、指定的回调函数的调用时机:对X86,如果监视的是数据地址,则是在访问该数据的指令执行完成后,通过exception触发回调,如果监视的是指令地址,则是在该指令被执行前通过exception触发回调

    1. 该方式只能监视通过CPU访问地址的情况,对DMA就无能为力了

补充:
如何跟踪指令地址

  • 1、该工具用于跟踪指令地址(函数等)的访问,这个时候attr.bp_type需要设置为HW_BREAKPOINT_X
    关于PER_CPU变量的跟踪

1、获取per_cpu变量的地址

如果跟踪的是内核的per_cpu变量,那么用kallsyms_lookup_name获取到的地址不是per_cpu变量的实际地址,仅仅是该per_cpu变量相对于各个cpu自己的per_cpu数据存放区起始地址的偏移,需要通过per_cpu_ptr获取到真实的地址,比如:

	addr = kallsyms_lookup_name("gcwq_nr_running");
	addr = (unsigned long)per_cpu_ptr((atomic_t *)addr,cpu);
	attr.bp_addr = addr

2、关于可用的hw breakpoint数量

由于CPU硬件支持的hw breakpoint数量非常有限,当前CPU和核心数量较多,很多时候不可能为每个CPU核心对于的per cpu变量都注册hw breakpoint,但是很多per_cpu变量的改写,甚至是读取,都限定在本CPU,而不是所有的CPU,如果是出于内核执行跟踪的目的,就没有必要把要在其它CPU上访问的per_cpu变量地址都注册在当前CPU的hw breakpoint了,这时就可以修改hw breakpoint接口register_wide_hw_breakpoint,把其中的for_each_online_cpu循环修改为仅仅处理当前CPU即可

标签:ksym,hw,per,CPU,hardware,breakpoint,cpu,内核模块
From: https://www.cnblogs.com/linhaostudy/p/18385479

相关文章

  • 如何使用hardware breakpoint
    要使用内核的硬件断点(hardwarebreakpoint)来定位内核模块中的内存访问问题,你可以通过以下步骤进行设置和调试。1.确定要监控的内存地址首先,你需要确定你想要监控的内存地址。这可以是某个变量的地址或者某个内存区域的开始地址。内核模块的内存访问问题通常涉及访问越界、未初......
  • [SCSS] Media breakpoint util mixin
    $breakpoints:('phone':(320px,480px),'pad':(481px,768px),'notebook':(769px,1024px),'desktop':(1025px,1200px),'tv':1201px,)@mixinrespond-to($breakname){$bp:map-g......
  • [oeasy]python0030_动态控制断点_breakpoints_debug_调试
     030_动态控制断点_breakpoints_debug_调试290播放·0赞同视频​设置断点_break_point_continue_运行到断点......
  • linux内核模块 字符设备驱动模板
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、linux内核模块是什么?二、代码示例总结前言提示:这里可以添加本文要记录的大概内容:内核版本5.10.92linux内核模块字符设备驱动模板cdev注册字符设备,创建一个/dev/下设备节点和/sy......
  • [oeasy]python029_ until_直接跳转到_unt_breakpoint_断点函数
     029调试中的跳转与断点228播放·0赞同视频​until_直接跳转到_unt_breakpoint_断点函数......
  • 内核模块高级-多文件编译、加载、参数传递、模块依赖
    多文件编译    对于比较复杂的驱动程序,常常会把它的功能进行拆分,由不同的文件实现,这样也能进行并行开发,缩短开发周期。多文件编译的简单例子如下:mod.c://mod.c#include<linux/init.h>#include<linux/module.h>#include"ext.h"//其他文件的头文件ext.hstatic......
  • NVIDIA全面转向开源GPU内核模块
      每周跟踪AI热点新闻动向和震撼发展想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领域的领跑者。点击订阅,与未来同行!订阅:https://......
  • 嵌入式Linux中内核模块的基本框架
    在Linux系统中,驱动程序属于内核态程序,可以认为它是介于操作系统和硬件实体之间的一层,对上负责与操作系统交流,对下负责控制硬件设备。即,驱动程序对操作系统通过软件接口进行沟通,对芯片硬件通过读写寄存器进行控制。Linux系统的驱动由内核模块(LoadableKernelModule,简称LKM)的形式......
  • 删除不必要的内核模块
    目录一.系统环境二.前言三.内核模块简介四.删除不必要的内核模块五.总结一.系统环境本文主要基于Kubernetes1.22.2和Linux操作系统Ubuntu18.04。服务器版本docker软件版本Kubernetes(k8s)集群版本kube-bench版本CPU架构Ubuntu18.04.5LTSDockerversion20.10.1......
  • 内核模块makefile
    obj-m:=hds.o #根据make的自动推导原则,make会自动将源程序hds.c编译成目标程序hds.o。#所有在配置文件中标记为-m的模块将被编译成可动态加载进内核的模块。即后缀为.ko的文件。CURRENT_PATH:=$(shellpwd) #参数化,将模块源码路径保存在CURRENT_PATH中LINUX_KERNEL:=$(......