利用Tracing阅读Chromium代码

Chromium中的Tracing工具可以记录每个函数的执行时间,是用来诊断浏览器性能问题的工具。它还有一个意想不到的用处,就是帮我们理解Chromium的代码,因为Tracing会把调用过的函数按照时间轴输出出来,通过Tracing的图形化界面,可以很清楚的明白对象函数之间的调用关系。 components/tracing/tracing_switches.cc代码文件的注释很清楚了介绍了Tracing命令行参数的用法: trace-config-file。这个开关指定Tracing命令行的配置文件,Tracing既可以通过命令行字符串设置配置,也可以通过加载一个配置文件来设置配置。 trace-shutdown。记录浏览器关闭时候到的Tracing信息。 trace-shutdown-file。把trace-shutdown记录的信息保存到一个指定的文件中。 trace-startup。记录浏览器启动时候的Tracing信息。 trace-startup-file。把trace-startup记录的信息保存到一个指定的文件中。 trace-startup-duration。设置trace-startup记录的秒数。 另外在trace-startup、trace-shutdown里面可以设置记录的Tracing类别,比如–trace-startup=base,net,就只会记录base和net类别的Tracing。 比如把以下命令行参数传递给浏览器: 它会记录浏览器启动的时候的Tracing信息,包含browser、content、input、renderer、renderer_host、startup、ui类别,记录10秒的数据,并把数据保存到tracing.json文件中。 然后浏览器地址栏中输入chrome://tracing/,点击左上角的Load按钮,加载我们生成的tracing.json数据文件,然后浏览器就会把数据以图形的样式展现给我们,如下图所示: 图中清楚显示了浏览器启动时做的各种初始化的工作,以及各种工作的先后次序。 Tracing中的数据是根据代码中的TRACE_EVENT宏收集到的: 我们也可以增进自己的数据,宏的第一个参数是类别。 ... Read More | Share it now!

DbgHelp教程4——Minidump自定义信息

MiniDumpWriteDump的MINIDUMP_TYPE可以控制往dump里面写入什么信息。不过MINIDUMP_TYPE只是一些固定的类型信息,比如内存、句柄、进程、线程信息,有时候为了定位问题,我们想收集一些其他的数据,然后写入到dump里面。恰好PMINIDUMP_USER_STREAM_INFORMATION参数可以做这个事情。 注意:自定义信息的MINIDUMP_USER_STREAM_INFORMATION的MINIDUMP_USER_STREAM的Type值必须大于MINIDUMP_STREAM_TYPE::LastReservedStream,因为之前这些值都是保留的标准类型。 可惜的是Windbg不能直接读取MINIDUMP_USER_STREAM_INFORMATION的信息,我们只好通过MiniDumpReadDumpStream接口去读取dump里面的数据。 根据MINIDUMP_STREAM_TYPE的描述,我们还可以从dump文件里面读取一些预置的信息,比如线程列表、模块列表、内存列表、异常信息、系统信息、句柄信息、函数表信息、等等。   ... Read More | Share it now!

DbgHelp教程3——Minidump

Minidump文件用来事后调试。DbgHelp库提供写Minidump的MiniDumpWriteDump方法。其实不光是程序崩溃的时候可以写dump,运行的任何时候都可以写个dump。 虽然名称是MiniDump,但有可能写的dump文件比FullDump都大,因为dump里面包含的信息不一样。MiniDumpWriteDump包含了一个MINIDUMP_TYPE参数,指定了dump类型: MiniDumpNormal。默认类型,只有当前线程的调用栈 MiniDumpWithDataSegs。所有加载模块的数据段 MiniDumpWithFullMemory。进程所有可达的内存,这个生成的dump文件非常大 MiniDumpWithHandleData。包含句柄信息 以下就是一个生成dump的例子: 往往我们希望在程序发生未处理的异常导致崩溃的时候来生成dump,因此我们可以注册这些这些异常的处理回调函数,在回调函数里面生成dump。 最常用的是SetUnhandledExceptionFilter函数,当程序发生未处理的SEH异常的时候,就会回调注册的处理函数。还有_set_invalid_parameter_handler函数,它可以注册CRT检测到的无效参数异常处理函数。_set_purecall_handler它可以注册纯虚函数调用异常处理函数。更多的异常函数,可以参考http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus。 chromium里面的崩溃收集系统使用的Breakpad,跨平台,设计精良。有空写一些文章来介绍。 ... Read More | Share it now!

DbgHelp教程2——栈回溯

调试的时候经常用到栈回溯来定位问题。获得栈回溯并不难,直接通过CaptureStackBackTrace这个API就可以获得。另外可以可以通过DbgHelp库里面的StackWalk64函数获得。 用CaptureStackBackTrace获取调用栈很简单: StackWalk64的方法稍微复杂一点,首先要获得CONTEXT。获取CONTEXT有两种办法,一是通过内联汇编获取: 另外一种是调用RtlCaptureContext获取: 获取到CONTEXT之后就用StackWalk64遍历调用栈: 我们获得的调用栈都只是一些栈帧地址,如果要知道明确的函数名,还需要把地址翻译成符号名,封了一个PrintCallStackBackTrace,就是把栈帧地址翻译成可读的符号地址:   ... Read More | Share it now!

DbgHelp教程1——初始化

以下是初始化DbgHelp最简单的代码: SymSetOptions函数是设置DbgHelper的功能选项,具体用法见https://msdn.microsoft.com/en-us/library/windows/desktop/ms681366(v=vs.85).aspx。 SymSetOptions参数为0的时候,表示所有的选项都关闭,一下是常见的选项解释: SYMOPT_ALLOW_ZERO_ADDRESS。允许符号没有地址。默认的DbgHelp会过滤掉没有地址的符号。 SYMOPT_CASE_INSENSITIVE。所有的搜索符号不区分大小写。 SYMOPT_DEBUG。通过OutputDebugString或者SymRegisterCallbackProc64... Read More | Share it now!