带libc源码gdb动态调试(导入glibc库使得可执行文件动态调试时可看见调用库函数源码)

本文主要是介绍带libc源码gdb动态调试(导入glibc库使得可执行文件动态调试时可看见调用库函数源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 参考部分
  • 查看源码是否编译时有-g
  • 调试信息和符号表
  • 在 gdb 中加载 debug 文件/符号表
    • 将 debug 文件放入 ".debug" 文件夹
    • 通过 gdb 命令 set debug-file-directory directories
  • GCC的gcc和g++区别
  • 指定gcc/g++,glibc的版本进行编译
    • 指定gcc/g++的版本
    • 指定glibc的和ld版本
  • apt安装后软件所在路径
  • gdb寻找单独的debug文件的路径
  • gdb带源码调试libc(gdb寻找源码的路径)

参考部分

gdb带源码调试libc
查看编译是否是debug模式

使用gcc生成动态库及使用动态库的方法

查看源码是否编译时有-g

-g编译的可执行性程序多了很多.debug开头的段
而没有加-g的没有

在这里插入图片描述

调试信息和符号表

这里说的调试信息指的是 debug_* 相关信息,符号表是指 symtab 和 dynsym。gdb 对这两种信息进行解析和加工,得到的信息在 gdb 内部统称为符号表。

调试信息需要带上 -g 编译选项才能产生。

其实符号表包括 symtab 和 dynsym 两种。在没有 -g 编译也会产生,在重定位过程中需要处理。

  • symtab 包括两种类型符号:全局符号和本地静态符号。
  • dynsym 仅仅包加载动态库所需要的符号。

在 gdb 中加载 debug 文件/符号表

参考链接
在使用 GDB 调试的时候就不容易看到 libc 中的各种结构。所以我们需要加载符号表来方便调试。

Ubuntu 的软件维护者在编译对应的 ELF 文件时,会将符号表与 ELF 文件分离,将符号表命名为 “*-dbg.deb”。这样我们就可以通过手动下载符号表来方便调试。

如果是使用 “glibc all in one” 下载的 libc,会在 libc 等库放置的位置使用 “.debug” 文件夹存放好了 libc 的符号表,使用 gdb 可以自动加载。但是碰到 “glibc all in one” 没有的 libc 版本时就需要手动下载 debug 文件,并手动加载了。

将 debug 文件放入 “.debug” 文件夹

在放置 libc 的目录下新建 ".debug"文件夹,将 debug 文件放入其中即可。

通过 gdb 命令 set debug-file-directory directories

我们需要将 libc 等库的 debug 文件放入对应文件夹,并通过 set debug-file-directory $directories 命令将文件夹设为分离的 debug 文件目录,就可以让 gdb 加载 debug 文件。

GCC的gcc和g++区别

GCC:GNU Compiler Collection(GUN 编译器集合),它可以编译C、C++、JAV、Fortran、Pascal、Object-C、Ada等语言。

gcc是GCC中的GUN C Compiler(C 编译器)

g++是GCC中的GUN C++ Compiler(C++编译器)

一个有趣的事实就是,就本质而言,gcc和g++并不是编译器,也不是编译器的集合,它们只是一种驱动器,根据参数中要编译的文件的类型,调用对应的GUN编译器而已,比如,用gcc编译一个c文件的话,会有以下几个步骤:

Step1:Call a preprocessor, like cpp.

Step2:Call an actual compiler, like cc or cc1.

Step3:Call an assembler, like as.

Step4:Call a linker, like ld

由于编译器是可以更换的,所以gcc不仅仅可以编译C文件

所以,更准确的说法是:gcc调用了C compiler,而g++调用了C++ compiler

指定gcc/g++,glibc的版本进行编译

不同版本的GCC实现了不同版本的c和c++标准库。这对代码的兼容性有一定影响。每个版本的gcc和标准库版本的对应关系可以在官方文档中找到。使用不同版本的标准库可能会导致代码编译和运行的行为发生不同,甚至会报错。因此,在编写代码时应该了解所使用的标准库版本,并避免使用已经废弃或不再维护的标准库。

指定gcc/g++的版本

export CC=gcc的路径
export CXX=g++的路径

指定glibc的和ld版本

通过设置环境变量LD_LIBRARY_PATH增加默认库文件搜索路径,会优先匹配我们提供目录中的libc

通过gcc 的-L参数指定glibc库(libc.so)的路径

在gcc的编译参数中指定 -Wl,–dynamic-linker=glibc中动态链接器的路径,如下:

-Wl,--dynamic-linker=/动态连接器的路径/ld-linux-x86-64.so.2

apt安装后软件所在路径

参考链接

dpkg -L +软件包的名字,可以知道这个软件包包含了哪些文件, 这个方法可以列出所有安装后留在系统里的文件,查询系统中已安装的软件包所安装的位置.
系统安装软件一般在/usr/share,可执行的文件在/usr/bin,配置文件可能安装到了/etc下等。
在这里插入图片描述

文档一般在 /usr/share

可执行文件 /usr/bin

配置文件 /etc

lib文件 /usr/lib

gdb寻找单独的debug文件的路径

参考链接

gdb寻找单独的debug文件的路径是:

  1. 当前文件所在的目录。
  2. 当前文件所在目录下的.debug目录。
  3. debug-file-directory设置的目录下,寻找当前可执行程序的调试信息会根据文件所在的实际路径组合去寻找。(比如debug-file-directory设置的目录为/usr/lib/debug, 一个可执行文件所在的目录是/home/test/example,那么gdb就回去/usr/lib/debug/home/test/下去寻找example.debug文件)如果是要寻找动态库文件(.so)的调试信息,则会使用ldd所显示的目录。可以直接使用debug-file-directory目录+ldd显示目录进行拼接即可。(比如debug-file-directory设置的目录为/usr/lib/debug,ldd显示出来的liba.so的路径是/home/zy/debuginfo/fff/liba.so,gdb就会去/usr/lib/debug/home/zy/debuginfo/fff目录下去读取liba.so所对应的debuginfo文件)
set debug-file-directory directories
Set the directories which GDB searches for separate debugging information files to directory. Multiple path components can be set concatenating them by a path separator.show debug-file-directory
Show the directories GDB searches for separate debugging information files.

如前所述,如果将debuginfo文件直接放到/usr/lib/debug目录(或者通过set-debug-file-directory命令设置的根目录)下,也是可以的,但文件目录的组织结构必须和运行时的目录组织结构一样,这个地方有一个需要注意的地方,特别是对于so文件,在debug-root-directory目录下寻找对应的debuginfo文件时,和文件实际所在的位置不一定完全一致,而要看连接器能够找到的路径,即ldd所显示的路径。gdb是会到debug-root-directory/$LDD显示的目录下去寻找对应的debuginfo文件。而ldd显示出来的路径,可能是一个绝对路径,也可能是一个相对路径,者取决于你的操作系统中所设置的一些so查找路径,比如LD_LIBRARY_PATH设置为一个相对路径还是一个绝对路径,对于gdb来说,去debug-root-directory目录下寻找的路径也不一样。gdb会拿ldd显示出来的路径直接和debug-root-directory拼接一下。比如我当前的LD_LIBRARY_PATH设置为./fff,那么gdb就会去/usr/lib/debug/./fff目录下去读取liba.so所对应的debuginfo文件,因为ldd现实出来的liba.so的路径是./fff/liba.so。

gdb带源码调试libc(gdb寻找源码的路径)

在使用gcc编译时,如果采用带-g选项编译,即可在二进制文件中附加调试信息以便gdb进行源码级别的调试。如果二进制中存在调试信息,会去相关目录寻找源码,GDB首先在编译时目录中搜索,如果失败则在当前目录中搜索,即$cdir:$cwd,其中$cdir指的是编译时目录(compilation directory),$cwd指的是当前工作目录(current working directory)。如果找到了源码文件则可以使用gdb的list命令来查看源码。
通过在ubuntu中安装带调试信息的libc,并下载libc源码,即可配置gdb跟入libc的库函数后进行源码级别的调试

不过如果我们gdb在默认寻找的目录中找不到源码文件,则无法进行源码调试。如果源码在其他目录可以在gdb中用directory或dir命令指定,或者在启动gdb时用-d参数指定,一样可以看到源码。

libc6-dbg是一个包含C标准库调试符号的调试信息包

 sudo apt install libc6-dbg  sudo apt install libc6-dbg:i386

libc6-dev :当前gcc编译链接时使用的版本的libc库源码

  1. 首先修改/etc/apt/sources.list,将deb-src配置开启
  2. 更新sudo apt update
  3. 使用apt source下载源码apt source libc6-dev

然后在调试时用directory把目录指向对应子文件夹就可以了,比如我要调试malloc:

 gdb -q ./可执行性文件 -d 下载的libc库源码文件夹路径/malloc

或者是在gdb中直接用directory

directory   下载的libc库源码文件夹路径/malloc

这篇关于带libc源码gdb动态调试(导入glibc库使得可执行文件动态调试时可看见调用库函数源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/657846

相关文章

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

Python数据处理之导入导出Excel数据方式

《Python数据处理之导入导出Excel数据方式》Python是Excel数据处理的绝佳工具,通过Pandas和Openpyxl等库可以实现数据的导入、导出和自动化处理,从基础的数据读取和清洗到复杂... 目录python导入导出Excel数据开启数据之旅:为什么Python是Excel数据处理的最佳拍档

Idea调用WebService的关键步骤和注意事项

《Idea调用WebService的关键步骤和注意事项》:本文主要介绍如何在Idea中调用WebService,包括理解WebService的基本概念、获取WSDL文件、阅读和理解WSDL文件、选... 目录前言一、理解WebService的基本概念二、获取WSDL文件三、阅读和理解WSDL文件四、选择对接

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

javafx 如何将项目打包为 Windows 的可执行文件exe

《javafx如何将项目打包为Windows的可执行文件exe》文章介绍了三种将JavaFX项目打包为.exe文件的方法:方法1使用jpackage(适用于JDK14及以上版本),方法2使用La... 目录方法 1:使用 jpackage(适用于 JDK 14 及更高版本)方法 2:使用 Launch4j(

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

java如何调用kettle设置变量和参数

《java如何调用kettle设置变量和参数》文章简要介绍了如何在Java中调用Kettle,并重点讨论了变量和参数的区别,以及在Java代码中如何正确设置和使用这些变量,避免覆盖Kettle中已设置... 目录Java调用kettle设置变量和参数java代码中变量会覆盖kettle里面设置的变量总结ja