zoukankan      html  css  js  c++  java
  • Ftrace hook的使用方法,利用Ftrace写一个memory debug程序

    1. 背景

    Ftrace利用汇编时,在每个函数的入口处放一个mcont函数来monitor代码行为,利用这一个特性,可以写一个程序来监控每个函数执行后,系统的memory状态的功能。

    2.代码

    这里主要是检查0x90000000 ~ 90200000中间2M内存的每个page的0x520处memory的值。

    #include <linux/stacktrace.h>
    #include <linux/ftrace.h>
    #include <linux/module.h>
    #include <linux/sysctl.h>
    #include <linux/init.h>
    #include <asm/setup.h>
    
    #include <linux/memblock.h>
    #include <linux/pfn.h>
    #include <linux/err.h>
    #include <linux/io.h>
    #include <asm/memory.h>
    
    #include <linux/kernel.h>
    #include <linux/export.h>
    #include <linux/kexec.h>
    #include <linux/smp.h>
    #include <linux/utsname.h>
    
    #include <linux/slab.h>
    #include <linux/sched/task_stack.h>
    #include <linux/stacktrace.h>
    
    #define MAX_STACK_TRACE_DEPTH 64
    
    static unsigned long memory_monitor_addr = 0;
    static unsigned long memory_monitor_size = 0;
    
    static int _kprint_stack(struct task_struct *task, int saved)
    {
        struct stack_trace trace;
        unsigned long *entries;
        int err;
    
        entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL);
        if (!entries)
            return –ENOMEM;
    
        trace.nr_entries = 0;
        trace.max_entries = MAX_STACK_TRACE_DEPTH;
        trace.entries = entries;
        trace.skip = 0;
        if (!err) {
            unsigned int i;
            save_stack_trace_tsk(task,&trace);
            for (i = 0; i < trace.nr_entries; i ++) {
                pr_cont(“[<%px>] %pS
    ”, (void*)entries[i], (void*)entries[i]);
                if (saved)
                    backup_stacktrace[checked_cnt][i] = entries[i];
                   }
    }
    kfree(entries);
    return err;
    }
    
    static unsigned long end_pfn = 0;
    static unsigned long start_pfn = 0;
    static void funcpoint_trace_call(unsigned long ip, unsigned long parent_ip, struct ftrace_pos *op, struct pt_regs *pt_regs)
    {
        void *va_pos;
        unsigned long cur_pfn;
        unsigned long mem_data;
    
        if (strncmp(current->comm, “PCM_OfflineDete”, sizeof(“PCM_OfflineDete”)))
            return;
    
        if (start_pfn == 0 || end_pfn == 0)
            return;
    
        for (cur_pfn = start_pfn; cur_pfn < end_pfn; cur_pfn ++) {
            va_pos = __va(PFN_PHYS(cur_pfn) + 0x520);
            mem_data = *(uint64_t*)va_pos >> 40;
            if (mem_data==0xb0ffff || mem_data==0xb0cccc || mem_data==0xb00000){
                pr_emerg(“address[%px]=%lx, CPU=%d
    ”, __pa(va_pos),*(uint64_t*)va_pos, smp_processor_id());
                pr_emerg(“----current process stack----
    ”);
                _kprint_stack(current,0);
                dump_stack();    
            }
    }
    return;
    }
    
    static struct ftrace_ops funcpoint_trace_ops __read_mostly =
    {
        .func = funcpoint_trace_call,
        .flags = FTRACE_OPS_FL_RECURSION_SAFE,
    }
    
    static int __init get_funcpoint_monitor_range(char *str)
    {
        unsigned long addr, size;
    
        pr_info(“%s(%s)
    ”, __func__, str);
        if (!str)
            return 0;
        size = memparse(str, &str);
        if (*str != ‘@’)
            return 0;
        addr = memparse(str + 1, &str);
    
        if (addr == 0 || size == 0){
            pr_info (“memory monitor is disable, addr=%#x, size=%#x
    ”, addr, size);
            return 0;
    }
    pr_info (“memory monitor is enable, addr=%#x, size=%#x
    ”, addr, size);
    memory_monitor_addr = addr;
    memory_monitor_size = size;
    return 0;
    }
    early_param(“funcpoint_memory_range”, get_funcpoint_monitor_range);
    
    static int __init func_tracepoint_init(void)
    {
        if (memory_monitor_addr == 0 || memory_monitor_size == 0)
            return 0;
        start_pfn = PHYS_PFN(memory_monitor_addr);
        end_pfn = PHYS_PFN(memory_monitor_addr + memory_monitor_size);
        pr_info(“funcpoint_memory_range: start_pfn=%#x, end_pfn=%#x.
    ”,start_pfn,end_pfn);
        register_ftrace_function(&funcpoint_trace_ops);
        return 0;
    }
    device_initcall(func_tracepoint_init);

    3.运行结果

    使用后,如果这里的memory状态发生变化,就可以打印出对应的调用栈了。

  • 相关阅读:
    Java的HashMap
    为什么 char c = 'A';c += 32; 结果输出的是 'a'?
    java中整数的常量优化机制
    IDEA2019版中文汉化包
    asp.net项目协作开发时,常常要忽略版本控制的目录
    SQLServer同步数据到ElasticSearch
    为什么不建议在微信小程序的TarBar上检查统一登录后跳转页面
    nginx的热备方式
    HTTP 和FTP 状态信息总结(留着自己用)
    Web Api 简介
  • 原文地址:https://www.cnblogs.com/smilingsusu/p/14594225.html
Copyright © 2011-2022 走看看