perf打印调用栈的过程

perf_prepare_sample-->perf_callchain-->get_perf_callchain

上面的调用栈会使用

perf_event_output-->

0xffffffff811837f0 : perf_event_output+0x0/0x80 [kernel]
 0xffffffff81183a1f : __perf_event_overflow+0x1af/0x1d0 [kernel]
 0xffffffff81183c1a : perf_swevent_overflow+0x9a/0xc0 [kernel]
 0xffffffff81183c9d : perf_swevent_event+0x5d/0x80 [kernel]
 0xffffffff81183e5c : perf_tp_event+0x19c/0x1b0 [kernel] 这个函数第一次有了regs
 0xffffffff811620fb : perf_syscall_enter+0x1db/0x1f0 [kernel]
 0xffffffff81003b7b : syscall_trace_enter_phase2+0x1cb/0x1e0 [kernel]
 0xffffffff818245cb : tracesys_phase2+0x2d/0x8d [kernel]

对调用栈的一些理解,首先如果栈采集在用户态的话,那么肯定是没有内核栈的,但是如果是才加到内核态的话,那么可能是有用户态的栈的,但是对于系统进程来说,同样是没有用户态的栈的。怎么判断是在用户态还是内核态,是指采样点所位于的函数位置,

0xffffffff811837f0 : perf_event_output+0x0/0x80 [kernel]
 0xffffffff81183a1f : __perf_event_overflow+0x1af/0x1d0 [kernel]
 0xffffffff811844d4 : perf_event_overflow+0x14/0x20 [kernel]
 0xffffffff8100fd7e : __intel_pmu_pebs_event+0x1ee/0x240 [kernel]
 0xffffffff8100ff55 : intel_pmu_drain_pebs_nhm+0x185/0x350 [kernel]
 0xffffffff8100c549 : intel_pmu_handle_irq+0x279/0x460 [kernel]
 0xffffffff810056bd : perf_event_nmi_handler+0x2d/0x50 [kernel]
 0xffffffff810323a9 : nmi_handle+0x69/0x120 [kernel]
 0xffffffff810328e0 : default_do_nmi+0x40/0x100 [kernel]
 0xffffffff81032a82 : do_nmi+0xe2/0x130 [kernel]
 0xffffffff81826906 : nmi+0x56/0xa5 [kernel]

tracepoint事件

0xffffffff811837f0 : perf_event_output+0x0/0x80 [kernel]
 0xffffffff81183a1f : __perf_event_overflow+0x1af/0x1d0 [kernel]
 0xffffffff81183c1a : perf_swevent_overflow+0x9a/0xc0 [kernel]
 0xffffffff81183c9d : perf_swevent_event+0x5d/0x80 [kernel]
 0xffffffff81183e5c : perf_tp_event+0x19c/0x1b0 [kernel]  
 0xffffffff810a7bb6 : perf_trace_sched_switch+0x166/0x190 [kernel]    vim include/trace/perf.h +32
 0xffffffff8181fdd7 : __schedule+0x427/0xa10 [kernel]
 0xffffffff818203f5 : schedule+0x35/0x80 [kernel]
 0xffffffff818238e5 : schedule_hrtimeout_range_clock+0xc5/0x1b0 [kernel]

x86的中断寄存器

regs是在perf_fetch_caller_regs(在perf_trace_sched_switch函数中)中获取ip,cs,bp,sp是最重要的三个寄存器,其中cs寄存器来表明当前是在内核态还是用户态,ip是当前在执行的指令,bp是栈指针寄存器。这里是返回内核态, tracepoint都是返回内核态,有了cs,bp,sp就足够拿到函数的调用栈了,内核态和用户态有各自的unwind的方法。所有的tracepoint都是在内核态,

原文地址:https://www.cnblogs.com/honpey/p/9271344.html

时间: 2024-10-14 17:28:34

perf打印调用栈的过程的相关文章

在c或c+程序里打印调用栈。转

在C/C++程序里打印调用栈信息 我们知道,GDB的backtrace命令可以查看堆栈信息.但很多时候,GDB根本用不上.比如说,在线上环境中可能没有GDB,即使有,也不太可能让我们直接在上面调试.如果能让程序自己输出调用栈,那是最好不过了.本文介绍和调用椎栈相关的几个函数. NAME       backtrace, backtrace_symbols, backtrace_symbols_fd - support for application self-debugging SYNOPSIS

android native HAL程序 java程序 linux kernel打印调用栈的方法

android native HAL程序 java程序 linux kernel打印调用栈的方法 关于android java打出调用栈的方法 1)方法一:refs:frameworks/base/services/java/com/android/server/ActivityManagerService.javastartProcessLocked(){Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "amProcessStart&quo

java 中打印调用栈

source-code: public class A { public A() {} private static void printStackTrace() {         StackTraceElement[] stackElements = new Throwable().getStackTrace(); if(stackElements != null) { for(int i = 0; i < stackElements.length; i++) { System.out.pr

获取任意线程调用栈的那些事

BSBacktraceLogger 是一个轻量级的框架,可以获取任意线程的调用栈,开源在我的 GitHub,建议下载下来结合本文阅读. 我们知道 NSThread 有一个类方法 callstackSymbols 可以获取调用栈,但是它输出的是当前线程的调用栈.在利用 Runloop 检测卡顿时,子线程检测到了主线程发生卡顿,需要通过主线程的调用栈来分析具体是哪个方法导致了阻塞,这时系统提供的方法就无能为力了. 最简单.自然的想法就是利用 dispatch_async 或 performSelec

Android各种获取代码调用栈的方法[补]

打印调用栈不用说,基本上每位开发者都会用到,讨论几个方法,以前也说过,http://blog.csdn.net/freshui/article/details/9456889 再次简单整理一下吧,啰嗦就啰嗦了 :) 基本分两大类,一类是静态的,要把打印语句插入到代码中,一类是动态的,需要看的时候,查看一下,实时观测各线程调用栈情况. 静态方法 1. Java中打印调用栈 比较简单,利用Throwable,直接log中打印出来: [java] view plain copy Log.d(TAG, 

打印完整的递归调用栈

之前在写0-1背包问题的递归解法时,想要弄出完整的递归栈.尝试了使用debug工具手工追踪并画出调用栈,发现太麻烦了,又试了一下使用visual studio的code map功能,发现对于递归,它只会显示递归函数不断调用自己,并不会自动展开成为树的形式.所以我就使用了最简陋的办法,就是自己写了一个类,依赖C++的constructor和destructor来自动将栈输入到一个vector中,并且在main函数结束的地方添加一个语句将其内容输出到文件中. 这里使用了一些C++11的特性,我使用m

用递归正/逆序打印一个数组,以及调用返回的过程理解

1 #include <stdio.h> 2 /* 3 题目:用递归正/逆序打印数组的元素,以及递归调用的过程理解 4 正序打印数组解题思路:第一:数组元素是连续的.知道第一个元素的地址,就能推算出第二个元素的地址.以此类推 5 第二:数组的结束条件:i = sizeof(arr)/4 -1; 此时的值为arr[sizeof(arr)/4-1]; 6 第三:后一个元素的值的下标 = 前一个元素的值的下标+1 (通项公式) 7 */ 8 void arr1(int *p,int n,int *p

VC++ 崩溃处理以及打印调用堆栈

title: VC++ 崩溃处理以及打印调用堆栈 tags: [VC++, 结构化异常处理, 崩溃日志记录] date: 2018-08-28 20:59:54 categories: windows 高级编程 keywords: VC++, 结构化异常处理SEH, 崩溃日志记录 --- 我们在程序发布后总会面临崩溃的情况,这个时候一般很难重现或者很难定位到程序崩溃的位置,之前有方法在程序崩溃的时候记录dump文件然后通过windbg来分析.那种方法对开发人员的要求较高,它需要程序员理解内存.寄

【转】StackTraceElement获取方法调用栈的信息

本文链接:https://blog.csdn.net/hp910315/article/details/52702199 一.什么是StackTrace StackTrace(堆栈轨迹)存放的就是方法调用栈的信息,异常处理中常用的printStackTrace()实质就是打印异常调用的堆栈信息. 二.StackTraceElement介绍 StackTraceElement表示StackTrace(堆栈轨迹)中的一个方法对象,属性包括方法的类名.方法名.文件名以及调用的行数. public fi