哪些软件分析工具需要使用到pdb符号文件?

目录

1、什么是pdb文件?pdb文件有哪些用途?

2、pdb文件的时间戳与pdb文件名称

3、常用软件分析工具有哪些?

4、使用Windbg调试器查看函数调用堆栈时需要加载pdb文件

4.1、给Windbg设置pdb文件路径

4.2、为什么要设置系统库pdb文件下载服务器地址?

5、使用IDA反汇编工具查看二进制文件的汇编代码时需要加载pdb文件

6、使用Process Explorer查看线程的函数调用堆栈时需要加载pdb文件

7、使用Process Monitor查看函数调用堆栈时需要使用到pdb文件

8、API Monitor可以查看函数调用堆栈,但不支持加载pdb文件

9、最后


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具案例集锦(专栏文章正在更新中...)https://blog.csdn.net/chenlycly/article/details/131405795       日常工作中分析C++软件问题时,有些分析工具是可以查看发生问题时的线程函数调用堆栈,比如Windbg、IDA、Process Explorer/Process Hacker、Process Monitor和API Monitor等。如果要在函数调用堆栈中能看到具体的函数名,甚至代码的行号,则需要加载pdb符号文件。今天我们就来详细讲讲哪些分析工具需要加载pdb符号文件。

1、什么是pdb文件?pdb文件有哪些用途?

       PDB - Program Databse File,程序数据库文件,存放了二进制文件中所有函数及变量的符号,还有一些调试用的信息,要查看完整的函数调用堆栈信息及变量信息,都需要用到pdb文件。pdb文件是在编译C++工程代码时产生的,它是与对应的exe或dll模块一起生成的。

       在Visual Studio中,不管是Debug还是Release下,默认都会生成pdb文件,默认配置如下所示:

本地程序之所以能调试,是因为其二进制文件在本地编译生成时会自动写入对应的pdb文件的绝对路径,而pdb文件中存放着用于调试的各种调试信息。启动调试时调试器会根据二进制文件中记录的pdb文件路径去尝试加载pdb文件,加载成功后,就能获取pdb文件中的调试信息,这样就可以调试了。

如果手动将对应目录中的pdb文件删除,在没有重新生成的情况下,程序肯定是无法调试的!

2、pdb文件的时间戳与pdb文件名称

        在使用pdb文件时,有两点需要注意一下,一个是pdb文件的时间戳,一个是pdb文件的名称。

        加载pdb文件时会严格校验pdb文件的时间戳(就是生成pdb文件的时间),必须要和二进制文件完全一致。即使是同样的代码,没有修改任何代码,在不同时间点编译生成的pdb文件,也是不能交叉使用的。

       pdb文件的名称必须和工程的名称一致,否则也是无法加载的。比如某个工程名称为videocodec_hp.vcxproj,生成的pdb文件的名称默认应为videocodec_hp.pdb(不区分大小写的),但在执行文件拷贝时将文件名称改成videocodec.pdb,这种情况下Windbg也是无法加载的。必须手动将pdb文件的名称改成Visual Studio工程文件的名称后,pdb文件才能正常加载。这个问题我们遇到过几次,就是因为pdb文件名称与工程名称不一致导致pdb加载不起来的。

3、常用软件分析工具有哪些?

       在日常工作中,常用的软件分析工具有PE工具、Dependency Walker、GDIView、Process Explorer、Process Monitor、API Monitor、Clumsy、DebugDiag、Windbg、IDA等,关于这些工具的详细介绍与说明,可以参见我之前写的文章:

C++软件开发值得推荐的十大高效软件分析工具https://blog.csdn.net/chenlycly/article/details/127608247这些工具中不是都要使用pdb,一般可以查看函数调用堆栈的,都要使用到pdb文件。Process Explorer、Process Monitor、DebugDiag、Windbg和IDA需要使用到,下面就来详细讲述一下。

4、使用Windbg调试器查看函数调用堆栈时需要加载pdb文件

       Windbg分析软件异常有两种方式,一种是静态分析dump文件,一种是动态调试目标进程。一般都需要在Windbg中查看发生异常时的函数调用堆栈,然后将函数调用堆栈与C++源码对照起来看,去分析软件异常。

       但光看到函数调用堆栈是不够的,需要在堆栈中看到具体的函数名,甚至代码行号,这样才好去分析问题。如果没有pdb文件,则堆栈中显示的是相对模块(起始地址)的偏移,或者相对于模块导出函数的偏移(模块的导出函数符号是公开的,外部是可见的),一般看不到真实具体的函数名。要看到包含具体函数名和代码行号的函数调用堆栈,则需要加载相关dll或exe二进制文件的pdb符号文件。通过pdb文件中包含的函数及变量的符号,去显示更为详细的函数调用堆栈。

4.1、给Windbg设置pdb文件路径

       在未加载pdb文件之前,通过查看函数调用堆栈中的模块名称,然后使用lm命令去查看模块的生成时间戳去找对应时间点的pdb文件。要让Windbg加载pdb文件,则需要将pdb文件所在的路径设置到Windbg中。可以将多个模块的pdb文件统一拷贝到本机的某个文件夹中,然后在Windbg菜单栏中点击File -> Symbol File Path...,会打开设置pdb文件路径的窗口:

将pdb文件路径设置给Windbg。

        一般我们设置如下格式的pdb文件路径组合:

C:\Users\Administrator\Desktop\pdbdir;srv*f:\mss0616*http://msdl.microsoft.com/download/symbols

这个一长串组合路径主要由下面两个路径构成:(多个路径之间使用分号隔开)

1)应用程序库的pdb文件路径(非系统库):
C:\Users\Administrator\Desktop\pdbdir。我们将相关开发模块的pdb文件集中拷贝到该路径中,然后将路径设置进来。多个pdb文件也可以放在不同路径下,可以设置多个路径,路径之间使用分号隔开。
2)Windows系统库的pdb文件在线下载地址
srv*f:\mss0616*http://msdl.microsoft.com/download/symbols,其中http://msdl.microsoft.com/download/symbols,是微软提供的在线系统pdb文件下载服务器。如果设置了该地址,Windbg会自动连接该服务器,去自动下载与当前dump文件中用到的系统库版本一致的pdb文件。另外,f:\mss0616路径是从微软pdb文件服务器上下载下来的pdb文件的存放路径。

4.2、为什么要设置系统库pdb文件下载服务器地址?

       设置系统库的pdb文件下载服务器地址,是为了让Windbg自动去下载Windows系统库的pdb文件,并自动将系统库的pdb文件加载进去。加载系统库的pdb符号库文件之后,不仅能看到具体的系统接口的调用,甚至还可以看到更多行的函数调用:

看到的可能是更多的系统层函数的调用记录,也可能是更多的应用层函数的调用记录。有时能直接从具体的系统函数调用接口中能得到一定的线索。另外,看到更多行的函数调用,可能更有利于快速定位发生崩溃的具体位置。

       关于设置系统库pdb下载地址去看到更多函数调用堆栈的典型问题实例,可以参见我之前写的一篇文章:
播放WebRTC开源库回调出来的视频码流时遇到的内存越界问题排查https://blog.csdn.net/chenlycly/article/details/131222627       此外,这里有个细节需要注意一下,有时微软这个服务器会有连接不上或卡顿的情况,会直接导致Windbg卡顿,这个问题我们之前遇到过很多次。所以遇到Windbg严重卡顿的时候,可以先将该服务器下载地址删除掉。但有时我们需要设置该在线地址,因为有时我们想去看到底是调用了系统库中的哪个接口触发的崩溃。

5、使用IDA反汇编工具查看二进制文件的汇编代码时需要加载pdb文件

       有时我们需要使用IDA反汇编工具去查看二进制文件的汇编代码上下文,去辅助分析C++软件异常问题。在分析问题时,要看懂汇编代码的片段或者上下文,需要将汇编代码和程序源码对应起来,但直接查看汇编很难和程序关联起来。所以在查看汇编代码时,需要和C++源码对照着看,即通过源码去辅助汇编代码的阅读。但C++代码在编译时,Release下编译器会对代码进行优化,有些代码会被优化掉,所以C++源码很难完全和汇编代码对应起来。

关于编译器优化的例子,比如C++源码中有个函数调用(调用了某个函数),编译器在编译时为了避免函数调用的开销(传递的参数要入栈出栈,要保护现场和恢复现场),直接将函数调用给优化掉,使用几句汇编代码将函数调用替换掉了。

       正因为汇编代码很难完全和C++源码对应起来,我们希望借助其他信息去将对应关系找出来。如果没有pdb文件,IDA中显示的汇编代码看不到具体的函数及变量信息,一般较难去直接阅读汇编代码上下文,是需要很强的汇编功底才行。

       如果IDA加载了当前二进制文件的pdb文件后,汇编代码中会显示具体的函数及变量信息,还会在汇编代码中额外添加一些注释,比如:

有了这些信息,阅读汇编代码上下文会显得容易很多,能够较容易地将汇编代码与C++源码对应起来。如果有pdb文件,只要将pdb文件放在二进制文件的同级目录中,这样在Windbg打开二进制文件时会自动到二进制文件所在的目录中去搜索,搜索到即会自动去加载pdb文件。

       也可以到IDA的安装路径下找到cfg文件夹,在该文件夹中找到pdb.cfg配置文件,在配置文件中设置pdb路径,不过这个操作略显麻烦,没有直接放到安装路径下简单。

6、使用Process Explorer查看线程的函数调用堆栈时需要加载pdb文件

       在使用Process Explorer工具排查程序CPU占用高的问题时,在Process Explorer显示的进程列表中双击目标进程,在打开的进程属性窗口中点击Threads标签页,切换到进程的线程列表页面,就能看到进程中的所有线程信息,找到那个CPU占用高的线程:

双击查看该线程的函数调用堆栈,然后根据函数调用堆栈去查看C++源码,去分析为什么会占用较高的CPU。如果没有pdb文件,显示出来的函数调用堆栈中看不到具体的函数名,看不到具体的函数名就没法去做跟踪分析了

       此时如何去查看相关模块的pdb文件呢?此时没用Windbg,所以没法使用Windb的lm命令去查看二进制模块的时间戳,那如何获取去获取二进制文件的时间戳呢?直接查看文件属性中的修改时间是不靠谱的,它只代表系统中该文件的修改时间,和文件的编译生成时间没关系的。其实很简单,我们只要下载个PE工具,然后将二进制文件拖入到PE工具中即可查看文件的生成时间戳,如下所示:

然后通过该时间戳找到二进制模块对应时间点的pdb文件。

        只要将pdb文件放在对应模块所在的文件夹中,Process Explorer就会自动去搜索加载的。当然也可以在Process Explorer中配置pdb文件的路径,点击Process Explorer菜单栏中的Options -> Configure Symbols...,打开如下的配置窗口:

配置pdb文件的路径即可。

7、使用Process Monitor查看函数调用堆栈时需要使用到pdb文件

        Process Monitor主要用来监测目标进程的注册表活动和文件活动的,如果监测到要监测的条目,双击即可查看执行注册表或文件操作的函数调用堆栈,通过函数调用堆栈就可以知道是哪个函数操作了注册表或文件了。

       涉及到显示线程的函数调用堆栈,就需要pdb文件,否则函数调用堆栈中就看不到具体的函数名,看不到具体的函数就较难定位问题的。与Process Explorer工具类似,pdb文件可以直接放置在二进制模块所在的文件夹中,Process Monitor会自动去搜索并加载。

       Process Monitor中也支持设置pdb文件路径,点击Process Monitor菜单栏中的Options -> Configure Symbols...,打开配置pdb文件路径的窗口,如下所示:

默认已经将微软系统库pdb下载地址设置进去了,如果要新增路径,以分号隔开就好了。

8、API Monitor可以查看函数调用堆栈,但不支持加载pdb文件

       API Monitor主要用来监测目标进程对系统API函数或者第三方库接口的调用情况。在监测到调用记录时,在call stack窗口中会显示所在线程的调用堆栈,默认只显示5条:

可以点击API Monitor菜单栏中的Tools -> Options...,在打开的Options配置窗口中点击Monitoring按钮,进入对应的标签页,如下所示:

在页面中可以配置显示函数调用堆栈的条目个数,好像最多只显示15个。

       有函数调用堆栈的地方,为了查看更详细的函数调用堆栈,需要pdb文件,但不幸的是,API Monitor不支持加载pdb文件,所以也就没有设置pdb文件路径的入口。其实这类监测接口调用的场景,函数调用堆栈的作用不大,我们只关注是否调用了接口,调用接口时传递了哪些参数。

9、最后

       本文详细介绍了Windbg、IDA、Process Explorer和Process Monitor等工具使用pdb的场景,希望能给大家提供一些借鉴和参考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/36861.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot家具商城系统

开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven…

vuepress - - - 首页底部版权信息加a标签超链接跳转或备案信息跳转链接

修改前 默认的底部版权信息只能填写纯文本,加不了超链接跳转等。 对应\docs\README.md内容: 修改后 修改后,点击Zichen跳转会打开新的网页。 看官网例子 底部添加了备案号跳转链接。 找到官网的github部署的文件。点导航栏中的“指…

【从零开始学习CSS | 第一篇】选择器介绍

目录 前言: 选择器介绍: 各类选择器: 总结: 前言: 本文以及后续几篇文章我们将会集中介绍CSS中的常见选择器,选择器的出现可以让我们实现对具体的元素标签进行定制,因此我们要掌握好各类选择…

js逆向补环境-调试工具vscode与nodejs使用之无环境联调

目录 一、啊哈一、Nodejs安装1、nodejs最新版本的安装(windows)2、旧版nodejs更新成最新版本(windows)3、nodejs安装(linux) 二、vscode安装使用(windows)1、下载安装vscode2、vscode运行插件Code Runner安…

Docker 安装与基本使用

一、简介 Docker 官方文档、Docker 中文文档,更新会落后于官方文档 什么是 Docker ? Docker 是一个应用打包、分发、部署的工具,也可以把它理解为一个轻量的虚拟机,它只虚拟软件需要的运行环境,多余的一点都不要,而普…

【C++】list模拟实现

🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。 🚁 个人主页:不 良 🔥 系列专栏:🛸C 🛹Linux 📕 学习格言:博观而约取&#xff0…

LVS负载均衡集群之LVS-DR部署

目录 一、lVS-DR集群概述 二、LVS-DR数据包流向分析 四、LVS-DR特性 五、DR模式 LVS负载均衡群集部 5.0配置虚拟 IP 地址(VIP 192.168.14.180) 5.1.配置负载调度器(192.168.14.101) 5.2部署共享存储(NFS服务器:192.168.14.10…

6.2Java EE——Spring的入门程序

下面通过一个简单的入门程序演示Spring框架的使用,要求在控制台打印“张三,欢迎来到Spring”,实现步骤具体如下。 1、在IDEA中创建名称为chapter06的Maven项目,然后在pom.xml文件中加载需使用到的Spring四个基础包以及Spring依赖…

etcd的使用

什么是etcd ETCD是一个分布式、可靠的key-value存储的分布式系统,用于存储分布式系统中的关键数据;当然,它不仅仅用于存储,还提供配置共享及服务发现;基于Go语言实现 。 etcd的特点 完全复制:集群中的每…

基于springboot+Redis的前后端分离项目之分布式锁(四)-【黑马点评】

🎁🎁资源文件分享 链接:https://pan.baidu.com/s/1189u6u4icQYHg_9_7ovWmA?pwdeh11 提取码:eh11 分布式锁 分布式锁1 、基本原理和实现方式对比2 、Redis分布式锁的实现核心思路3 、实现分布式锁版本一4 、Redis分布式锁误删情况…

Linux进程信号

文章目录: 信号入门从生活角度看信号技术应用角度看信号使用 kill -l 命令查看系统定义的信号列表信号处理常见方式概览 产生信号通过终端按键产生信号核心转储(core dump)的作用调用系统函数向进程发信号由软件条件产生信号硬件异常产生信号…

0305kali linux配置运行-docker-macos aarm64

文章目录 1 下载运行2 配置2.1 配置系统环境2.2 配置SSH服务2.3 安装工具 3 问题总结结语 1 下载运行 拉取kali linux镜像 docker pull kalilinux/kali-rolling该镜像为“纯净版”系统,没有任何工具,体积小。下面当我们运行起来之后,到容器中…

Android Java代码与JNI交互 JNI访问Java构造方法(九)

🔥 Android Studio 版本 🔥 🔥 创建包含JNI的类 JNIConstructorClass.java 🔥 package com.cmake.ndk1.jni;import com.cmake.ndk1.model.Animal;public class JNIConstructorClass {static {System.loadLibrary("constructor-class-lib");}public native…

Visual studio 2015下载安装以及缺包提示的处理方法

最近要加入的比赛团队需要用到Visual studio 2015,百度后找到很多资源,自己也转到了百度网盘。中英文都有,需要的可以下载。 链接:https://pan.baidu.com/s/12gpVwXfQxfdkXub-IwhWFw?pwds325 提取码:s325 --来自百…

为什么需要多语言并行机器翻译?

随着全球化的加速和不同语言之间的交流需求不断增长,多语言机器翻译(Multilingual Parallel Machine Translation)成为一个备受关注的领域。传统上,机器翻译系统主要集中于一对特定语言之间的翻译,但这种单一语言对的模…

【观察者模式】 ——每天一点小知识

💧 观察者模式 \color{#FF1493}{观察者模式} 观察者模式💧 🌷 仰望天空,妳我亦是行人.✨ 🦄 个人主页——微风撞见云的博客🎐 🐳 《数据结构与算法》专栏的文章图文并茂🦕…

uniapp 打包安卓apk (原生App)云打包

uniapp 打包安卓apk (原生App)云打包 hbuilder中操作 项目的一些配置appid DCloud appid 用途/作用/使用说明: https://ask.dcloud.net.cn/article/35907 右键我们项目目录-》发行-》原生APP-云打包 说明: 1. 打包安卓,只选择安卓打包项&…

基于pyqt和卷积网络CNN的中文汉字识别

直接上效果演示图: 通过点击按钮可以实现在画板上写汉字识别和加载图片识别两个功能。 视频演示和demo仓库地址在b站视频001期: 到此一游7758258的个人空间-到此一游7758258个人主页-哔哩哔哩视频 所有代码展示: 十分的简洁,主…

jni编程(windows+JDK11+clion)

JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植。 一、java代码 package org.example;public class Main {static {System.load("");}public static void main(String[] args) {Syste…

医学图像处理——读取和解读NII文件

一 预备知识 NII文件的存储格式网上有很多资料,在此只做一点简单的描述。nii是一种文件格式,它存储的是在空间中占有一定体积的小方块的物理位置和该位置对应的像素值。这个小方块我们也称之为体素(voxel)。存储的形式是一个三维数组(3D array)&#xf…