使用Bochs和GDB对内核进行源代码级调试
使用Bochs和GDB对内核进行源代码级调试
Written by YY
Wednesday, 21 April 2010 12:49
1. 安装 Bochs编译 Bochs 要加入 --enable-gdb-stub 选项:
$ ./configure --enable-gdb-stub
$ make
$ sudo make install
2. 生成内核修改 Makefile
将 CFLAGS 加入 -g 选项,以便加入调试符号
CFLAGS = -I include/ -I include/sys/ -c -g -fno-builtin -Wall由于加了调试符号之后 kernel.bin 太大,所以将其 strip 之后在拷贝入磁盘映像
将
sudo cp -fv kernel.bin /mnt/floppy
改为:
strip kernel.bin -o kernel.bin.stripped
sudo cp -fv kernel.bin.stripped /mnt/floppy/kernel.bin
如此一来,在 bochs 虚拟机里面执行的 kernel.bin 是 strip 之后的,过会儿用来交给 gdb 的 kernel.bin 是带调试符号的。
编译内核
$ make image
3. 启动 Orange'S修改 bochsrc
加入这么一行:
gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0 运行
$ bochs -q -f bochsrc.gdb # 注意必须用加入了--enable-gdb-stub 编译选项的bochs
4. 用 gdb 调试打开另一控制台,运行 gdb
$ gdb
在 gdb 中调试
(gdb) file kernel.bin ←注意这里的 kernel.bin 必须是加入了 -g 编译选项的带调试符号的内核
Reading symbols from /home/forrest/local/src/osfs/oranges/phases/chapter11/a/kernel.bin...done. (gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x0000fff0 in ?? ()
(gdb) b start.c:26
Breakpoint 1 at 0x14a6: file kernel/start.c, line 26.
(gdb) c
Continuing.
Breakpoint 1, cstart () at kernel/start.c:26
26 disp_str("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n-----\"cstart\" begins-----\n"); (gdb) n
29 memcpy( &gdt, /* New GDT */
(gdb)
.gdbinit
由于每次都需要执行 file kernel.bin 和 target remote localhost:1234 两个命令,所以可以建立一个 .gdbinit 文件,比如:
$ vi .gdbinit
file kernel.bin
target remote localhost:1234
set disassembly-flavor intel
b start.c:26
b kernel/main.c:183
这样下次直接执行 gdb 这个文件里的命令即可自动执行。
.gdbinit 可以做许多事,比如上例中就加了俩断点。
在 .gdbinit 中自定义函数
在 .gdbinit 中可添加自定义函数,比如:
define lsproc
set $count = 16
set $idx = 0
printf "The first %d TASKS/PROCS:\n",$count
while($idx < $count)
if(proc_table[$idx].p_flags != 0x20)
if($idx < 5)
printf "[%2d] TASK: %8s",$idx,proc_table[$idx].name
printf "\t p_flags: %8Xh\n",proc_table[$idx].p_flags
else
printf "[%2d] PROC: %8s",$idx,proc_table[$idx].name
printf "\t p_flags: %8Xh\n",proc_table[$idx].p_flags
end
end
set $idx++
end
end
这样在 gdb 中执行一个 lsproc,便可打印出所有进程的信息,巨方便:
(gdb) lsproc
The first 16 TASKS/PROCS:
[ 0] TASK: TTY p_flags: 4h
[ 1] TASK: SYS p_flags: 4h
[ 2] TASK: HD p_flags: 4h
[ 3] TASK: FS p_flags: 4h
[ 4] TASK: MM p_flags: 4h
[ 5] PROC: INIT p_flags: Ch
[ 6] PROC: TestA p_flags: 0h
[ 7] PROC: TestB p_flags: 0h
[ 8] PROC: TestC p_flags: 0h
[ 9] PROC: INIT_9 p_flags: 4h
[10] PROC: INIT_10 p_flags: 4h
利用gdb调试core文件
利用gdb调试core文件 什么是core dump core dump又叫核心转储, 当程序运行过程中发生异常, 程序异常退出时, 由操作系统把程序当前的内存状况存储在一个core文件中, 叫core dump。(linux中如果内存越界会收到SIGSEGV信号,然后就会core dump) 在程序运行的过程中,有的时候我们会遇到Segment fault(段错误)这样的错误。这种看起来比较困难,因为没有任何的栈、trace信息输出。该种类型的错误往往与指针操作相关。往往可以通过这样的方式进行定位。 造成segment fault,产生core dump的可能原因 1、内存访问越界 a) 由于使用错误的下标,导致数组访问越界 b) 搜索字符串时,依靠字符串结束符来判断字符串是否结束,但是字符串没有正常的使用结束符 c) 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字符串操作函数,将目标字符串读/写爆。应该使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防止读写越界。 2、多线程程序使用了线程不安全的函数。 3、多线程读写的数据未加锁保护。 对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成core dump 4、非法指针 a) 使用空指针 b) 随意使用指针转换。一个指向一段内存的指针,除非确定这段内存原先就分配为某种结构或类型,或者这种结构或类型的数组,否则不要将它转换为这种结构或类型的指针,而应该将这段内存拷贝到一个这种结构或类型中,再访问这个结构或类型。这是因为如果这段内
实例—使用gdb调试器
2.4 实例—使用gdb调试器 1.编写实例程序gcctest.c,见2.2小节的开头部分 2.编译 3.启动GDB,执行程序 启动gdb,进入gdb调试环境,可以使用gdb的命令对程序进行调试。 [root@localhost gdbtest txt]# gdb //启动gdb GNU gdb Fedora (6.8-27.el5) Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later
国嵌视频教程下载
嵌入式Linux视频教程 相关搜索:简体中文, 学习方法, 视频教程, 普通话, 嵌入式 中文名: 嵌入式Linux视频教程 资源格式: 光盘镜像 学校: 成都国嵌嵌入式培训中心版本: 成都国嵌嵌入式培训中心的基于广州友善之发行日期: 2010年 地区: 大陆 对白语言: 普通话 文字语言: 简体中文 视频光盘目录结构 国嵌视频1.iso -学习方法与课程体系介绍(学前必看) -学习方法介绍.avi -国嵌嵌入式课程体系.pdf -嵌入式Linux学习方法.pdf -国嵌课程1-嵌入式入门体验班(上) -第1天(嵌入式系统概述) -国嵌体验入门班-1-1(嵌入式系统概述).avi -国嵌体验入门班-1-2(ARM概述).avi -国嵌体验入门班-1-3(嵌入式Linux概述).avi -国嵌体验入门班-1-4(2440开发板介绍).avi -国嵌体验入门班-1-5(软硬件环境搭建).avi -第2天(开发板快乐体验) -国嵌体验入门班-2-1(开发板系统安装).avi -国嵌体验入门班-2-1(开发板系统安装-Jlink方式).avi -国嵌体验入门班-2-1(开发板系统安装-并口方式).avi -国嵌体验入门班-2-2(裸机程序体验).avi -国嵌体验入门班-2-3(QT系统体验).avi -国嵌体验入门班-2-4(Android系统体验).avi 国嵌视频2.iso
-国嵌课程1-嵌入式入门体验班(下) -第3天(Linux系统体验) -国嵌体验入门班-3-1(Linux定制安装).avi -国嵌体验入门班-3-2(Linux命令).avi -国嵌体验入门班-3-3(VI使用).avi -国嵌体验入门班-3-4(Linux系统管理).avi -国嵌体验入门班-3-5(Shell编程).avi -国嵌体验入门班-3-6(Qcd功能演示).avi -国嵌体验入门班-3-7(必修实验).avi -国嵌课程2-嵌入式Linux应用开发班 -第1天(编程基础) -国嵌应用班-1-1(GCC程序编译).avi -国嵌应用班-1-2(GDB程序调试).avi -国嵌应用班-1-3(makefile工程管理).avi -国嵌应用班-1-4(必修实验).avi -第2天(文件时间编程) -国嵌应用班-2-1(系统调用方式访问文件).avi -国嵌应用班-2-2(库函数访问文件).avi -国嵌应用班-2-3(时间编程).avi -国嵌应用班-2-4(必修实验).avi -第3天(多进程程序设计) -国嵌应用班-3-1(进程控制原理).avi -国嵌应用班-3-2(进程控制程序设计).avi -国嵌应用班-3-3(必修实验).avi -第4天(进程间通讯) -国嵌应用班-4-1(进程间通讯概述).avi -国嵌应用班-4-2(管道通讯).avi -国嵌应用班-4-3(信号通讯).avi -国嵌应用班-4-4(共享内存通讯).avi -国嵌应用班-4-5(必修实验).avi -第5天(进程间通讯) -国嵌应用班-5-1(消息队列).avi
gdb单步调试(中)
一、设置断点(BreakPoint ) 我们用break 命令来设置断点。正面有几点设置断点的方法: break
gbd调试
用GDB调试程序 GDB概述 ———— GDB 是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在 UN IX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。 一般来说,GDB主要帮忙你完成下面四个方面的功能: 1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。 2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式) 3、当程序被停住时,可以检查此时你的程序中所发生的事。 4、动态的改变你程序的执行环境。 从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过在细节上,你会发现GDB这个调试工具的强大,大家可能比较习惯了图形化的调试工具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。让我们一一看来。 一个调试示例 —————— 源程序:tst.c
1 #include
GDB调试精粹及使用实例
GDB调试精粹及使用实例 一:列文件清单 1. List (gdb) list line1,line2 二:执行程序 要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和>)和外壳通配符(*、?、[、])在内。 如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。 利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。 (gdb)set args –b –x (gdb) show args backtrace命令为堆栈提供向后跟踪功能。 Backtrace 命令产生一张列表,包含着从最近的过程开始的所以有效过程和调用这些过程的参数。 三:显示数据 利用print 命令可以检查各个变量的值。 (gdb) print p (p为变量名) whatis 命令可以显示某个变量的类型 (gdb) whatis p type = int * print 是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。表达式除了包含你程序中的变量外,还可以包含以下内容: l 对程序中函数的调用 (gdb) print find_entry(1,0) l 数据结构和其他复杂对象 (gdb) print *table_start $8={e=reference=’\000’,location=0x0,next=0x0} l 值的历史成分 (gdb)print $1 ($1为历史记录变量,在以后可以直接引用 $1 的值) l 人为数组 人为数组提供了一种去显示存储器块(数组节或动态分配的存储区)内容的方法。早期的调试程序没有很好的方法将任意的指针换成一个数组。就像对待参数一样,让我们查看内存中在变量h后面的10个整数,一个动态数组的语法如下所示: base@length 因此,要想显示在h后面的10个元素,可以使用h@10: (gdb)print h@10 $13=(-1,345,23,-234,0,0,0,98,345,10)
GDB调试及实例
GDB调试及实例 一:列文件清单 1.List (gdb) list line1,line2 二:执行程序 要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和>)和外壳通配符(*、?、[、])在内。 如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。 利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。 (gdb)set args –b –x (gdb) show args backtrace命令为堆栈提供向后跟踪功能。 Backtrace 命令产生一张列表,包含着从最近的过程开始的所以有效过程和调用这些过程的参数。 三:显示数据 利用print 命令可以检查各个变量的值。 (gdb) print p (p为变量名) whatis 命令可以显示某个变量的类型 (gdb) whatis p type = int * print 是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。表达式除了包含你程序中的变量外,还可以包含以下内容: l 对程序中函数的调用 (gdb) print find_entry(1,0) l 数据结构和其他复杂对象 (gdb) print *table_start $8={e=reference=’\000’,location=0x0,next=0x0} l 值的历史成分 (gdb)print $1 ($1为历史记录变量,在以后可以直接引用$1 的值) l 人为数组 人为数组提供了一种去显示存储器块(数组节或动态分配的存储区)内容的方法。早期的调试程序没有很好的方法将任意的指针换成一个数组。就像对待参数一样,让我们查看内存中在变量h后面的10个整数,一个动态数组的语法如下所示: base@length 因此,要想显示在h后面的10个元素,可以使用h@10: (gdb)print h@10 $13=(-1,345,23,-234,0,0,0,98,345,10)
使用QEMU+GDB调试Linux内核
使用QEMU调试Linux内核 一.使用QEMU安装Ubuntu10.04 1.安装qemu ubuntu下使用sudo apt-get install 安装的qemu版本是0.12.3,该版本中存在bug,使得无法在断点处停下;因此需要在qemu官方网站https://www.360docs.net/doc/5111246151.html,/Download上下载最新的版本qemu-0.12.5.tar.gz的源代码包自己进行编译安装: ●Sudo apt-get install zlib1g-dev libsdl-dev ●解压源代码后,进入源代码所在目录执行./confingure ●执行make ●执行sudo make install 2.创建QEMU格式的硬盘 qemu-img create –f qcow2name.img size 例如:qemu-img create –f qcow2 ubuntu10.04.img 4GB 3.在创建的硬盘上安装操作系统 qemu–hdaname.img–cdrom ~/Download/ubuntu10.04.iso –boot d 说明:使用hda指定硬盘镜像,使用CDROM选定光驱。-boot d 指从cdrom启动,-boot a是软盘,-boot c 是硬盘;使用qemu或qemu-system-x86_64(64为机子),有时安装系统会很慢,这是可以考虑使用kvm来代替。 例如:kvm–hda ubuntu10.04.img –cdrom ./ubuntu-10.04.iso -boot
d 4.从已经装好操作系统的硬盘启动 qemu–hda ubuntu10.04.img 5.在64位的主机上要使用qemu-system-x86_64命令来代替qemu 二.自己编译内核 现将Linux的编译调节过程简述为: 1. 下载自己要调试的Linux内核的源代码,这个可以从Linux内 核的官方网站上得到:https://www.360docs.net/doc/5111246151.html, 2. 编译内核最主要的便是配置文件.config,为了能够准确的得到 结果(第一次不要求编译时间),将本机的config文件直接拷 贝到解压后的源代码中。 3.然后进行make操作,结束后将产生的bzImage文件拷到boot 目录下,重启,选择自己编译的内核,这样一般不会出问题,但时间较慢,大约编译一次需要40分钟。 3.1以前编译内核是为调试内核服务的,现在做华为的项目, 发现需要在实际的机器上运行自己编译的内核,参考网站: https://www.360docs.net/doc/5111246151.html,/tips/compiling-linux-kernel-26.html 4.为了降低编译时间,就需要对配置文件进行裁剪,在配置文件 中有好多是本机不需要的模块,参考: https://www.360docs.net/doc/5111246151.html,/Linux/kernel_options.html。另外调试内 核与模块无关,所以辨识为M的直接可以不选。 5.剪裁的时候采用“逐步瘦身”法,先剪裁掉某个或某几个模块, 然后在进行编译,若没错,在进行模块裁剪,这样可以最大程
如何在Linux中使用gdb调试C程序
如何在Linux中使用gdb调试C程序 无论多么有经验的程序员,开发的任何软件都不可能完全没有bug。因此,排查及修复bug 成为软件开发周期中最重要的任务之一。有许多办法可以排查bug(测试、代码自审等等),但是还有一些专用软件(称为调试器)可以帮助准确定位问题的所在,以便进行修复。 如果你是C/C++ 程序员,或者使用Fortran 和Modula-2 编程语言开发软件,那么你将会很乐意知道有这么一款优秀的调试器- GDB - 可以帮你更轻松地调试代码bug 以及其它问题。在这篇文章中,我们将讨论一下GDB 调试器的基础知识,包括它提供的一些有用的功能/选项。 在我们开始之前,值得一提的是,文章中的所有说明和示例都已经在Ubuntu 14.04 LTS 中测试过。教程中的示例代码都是 C 语言写的;使用的shell 为bash(4.3.11);GDB 版本为7.7.1。 GDB 调试器基础 通俗的讲,GDB 可以让你看到程序在执行过程时的内部流程,并帮你明确问题的所在。我们将在下一节通过一个有效的示例来讨论GDB 调试器的用法,但在此之前,我们先来探讨一些之后对你有帮助的基本要点。 首先,为了能够顺利使用类似GDB 这样的调试器,你必须以指定的方式编译程序,让编译器产生调试器所需的调试信息。例如,在使用gcc 编译器(我们将在本教程之后的章节用它来编译C 程序示例)编译代码的时候,你需要使用 -g 命令行选项。 IT网,http://it 想要了解gcc 编译器手册页中关于 -g 命令行选项相关的内容,请看这里。 下一步,确保在你的系统中已经安装GDB 调试器。如果没有安装,而且你使用的是基于Debian 的系统(如Ubuntu),那么你就可以使用以下命令轻松安装该工具: sudo apt-get install gdb 在其他发行版上的安装方法,请看这里。 现在,当你按照上述的方式编译完程序(gcc -g 命令行选项),同时也已经安装好GDB 调
用GDB调试程序--调试器GDB常用功能
一,GDB调试器简介 GDB是Linux下的常用调试器,主要用于调试源代码、调试运行中的进程和查看core dump文件。Linux下的调试器主要有gdb、cgdb、ddd、eclipse。GDB调试器的运行速度快、能够进行源代码同步显示。 使用-tui 选项开启gdb命令输入和源代码的分屏显示,tui即Terminal User Interface。 二,GDB常用调试命令 a)调试可执行文件 以源代码为/home/zebra/目录下的test.c文件产生的可执行文件test为例(可执行文件使用gcc进行编译,并使用-g选项以产生调试信息),进行命令的说明(详细源代码参见第三部分:三,调试实例分析 )。 gdb调试源代码流程: 1,开启gdb程序,即运行如下命令:gdb -q (-q用以使得gdb不输出gdb程序的版本等信息)2,指定调试的二进制文件:file test 3,list查看源代码 4,设定断点breakpoint main breakpoint sub 上述分别在main函数和sub函数处设定了断点。 断点可以设置在任意已知源代码文件的某一行,某一个函数,同时可以指定是设置在哪个/哪些线程上(见下边描述)。 5,运行可执行文件: run 6,这样程序会运行到断点处停止下来,gdb会打印当前断点的信息。 7,使用s 或者n进行单步调试。 s即step,n即next都是执行一条语句,然后停下来。 如果想执行一条汇编语句,则可以使用si ,ni,即step instruction,next instruction。 8,bt命令查看当前的调用栈,bt即backtrace。 9,info frame查看函数帧信息。 10,frame n 进入某个函数帧(编号为n) 11,info 命令可以对当前的函数帧的寄存器、局部变量、函数的参数进行查看。 info register;info local;info args。 12,disassemble对当前函数对应的二进制进行反汇编。 13,x/nfu address 查看内存其中address是内存开始的地址,从该地址向高地址增加, x是examinate的缩写,n表示重复次数,f表示输出格式,u表示内存大小的单位(默认是字,即4个字节)。 一般我都用x/nx address,即打印n个从address开始的内存,每个是4字节,以十六进制打印。14,continue,执行至该函数退出 15,info threads,显示当前可调试的所有线程 16,thread
linux下的静态库与动态库的区别,Gdb调试段错误,自动生成Makefile
linux下的静态库与动态库的区别 1.什么是库 在windows平台和linux平台下都大量存在着库。 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。 由于windows和linux的本质不同,因此二者库的二进制是不兼容的。 2.库的种类 linux下的库有两种:静态库和共享库(动态库)。 二者的不同点在于代码被载入的时刻不同。 静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。 共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。 3.库存在的意义 库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。 共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。 4.库文件是如何产生的在linux下 静态库的后缀是.a,它的产生分两步 Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表 Step 2.ar命令将很多.o转换成.a,成文静态库 动态库的后缀是.so,它由gcc加特定参数编译产生。 例如: $ gcc -fPIC -c *.c $ gcc -shared -Wl,-soname, libfoo.so.1 -o libfoo.so.1.0 *. 5.库文件是如何命名的,有没有什么规范 在linux下,库文件一般放在/usr/lib /lib下, 静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称 动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号,minor是副版本号 6.如何知道一个可执行程序依赖哪些库 ldd命令可以查看一个可执行程序依赖的共享库, 例如# ldd /bin/lnlibc.so.6 => /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2 => /lib/ld- linux.so.2 (0×40000000) 可以看到ln命令依赖于libc库和ld-linux库 Gdb调试段错误 1.段错误是什么
GDB基本命令
1. 本文介绍使用gdb调试程序的常用命令。 主要内容: [简介] [举例] [其他] [简介] ============= GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。同时GDB也具有例如ddd这样的图形化的调试端。 一般来说,GDB主要完成下面四个方面的功能: (1)启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。 (2)可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式) (3)当程序被停住时,可以检查此时你的程序中所发生的事。 (4)动态的改变你程序的执行环境。 [举例] ============= *启动gdb $gdb 这样可以和gdb进行交互了。 *启动gdb,并且分屏显示源代码: $gdb -tui 这样,使用了'-tui'选项,启动可以直接将屏幕分成两个部分,上面显示源代码,比用list方便多了。这时候使用上下方向键可以查看源代码,想要命令行使用上下键就用[Ctrl]n和[Ctrl]p. *启动gdb调试指定程序app: $gdb app 这样就在启动gdb之后直接载入了app可执行程序,需要注意的是,载入的app程序必须在编译的
时候有gdb调试选项,例如'gcc -g app app.c',注意,如果修改了程序的源代码,但是没有编译,那么在gdb中显示的会是改动后的源代码,但是运行的是改动前的程序,这样会导致跟踪错乱的。 *启动程序之后,再用gdb调试: $gdb
LINUX gdb调试命令手册
常用的gdb命令 backtrace 显示程序中的当前位置和表示如何到达当前位置的栈跟踪(同义词:where)breakpoint 在程序中设置一个断点 cd 改变当前工作目录 clear 删除刚才停止处的断点 commands 命中断点时,列出将要执行的命令 continue 从断点开始继续执行 delete 删除一个断点或监测点;也可与其他命令一起使用 display 程序停止时显示变量和表达时 down 下移栈帧,使得另一个函数成为当前函数 frame 选择下一条continue命令的帧 info 显示与该程序有关的各种信息 jump 在源程序中的另一点开始运行 kill 异常终止在gdb 控制下运行的程序 list 列出相应于正在执行的程序的原文件内容 next 执行下一个源程序行,从而执行其整体中的一个函数 print 显示变量或表达式的值 pwd 显示当前工作目录 pype 显示一个数据结构(如一个结构或C++类)的内容 quit 退出gdb reverse-search 在源文件中反向搜索正规表达式 run 执行该程序 search 在源文件中搜索正规表达式 set variable 给变量赋值 signal 将一个信号发送到正在运行的进程 step 执行下一个源程序行,必要时进入下一个函数 undisplay display命令的反命令,不要显示表达式 until 结束当前循环 up 上移栈帧,使另一函数成为当前函数 watch 在程序中设置一个监测点(即数据断点) whatis 显示变量或函数类型
GDB命令分类详解 一:列文件清单 (2) 二:执行程序 (2) 三:显示数据 (2) 四:断点(breakpoint) (3) 五.断点的管理 (3) 六.变量的检查和赋值 (4) 七.单步执行 (4) 八.函数的调用 (4) 九.机器语言工具 (4) 十.信号 (4) 十一.原文件的搜索 (5) 十二. UNIX接口 (5) 十三. 命令的历史 (5) 十四. GDB帮助 (5) 十五. GDB多线程 (6) 十六. GDB使用范例 (7) 一:列文件清单 1.List (gdb) list line1,line2 二:执行程序 要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和>)和外壳通配符(*、?、[、])在内。 如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。 利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。 (gdb)set args –b –x (gdb) show args backtrace命令为堆栈提供向后跟踪功能。 Backtrace 命令产生一张列表,包含着从最近的过程开始的所以有效过程和调用这些过程的参数。 三:显示数据 利用print 命令可以检查各个变量的值。 (gdb) print p (p为变量名) whatis命令可以显示某个变量的类型 (gdb) whatis p type = int * print 是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。表达式除了包含你程序中的变量外,还可以包含以下内容:
用 GDB 调试程序
用 GDB 调试程序 用 gdb 调试 GCC 程序 Linux 包含了一个叫 gdb 的 GNU 调试程序. gdb 是一个用来调试 C 和 C++ 程序的强力调试器. 它使你能在程序运行时观察程序的内部结构和内存的使用情况. 以下是 gdb 所提供的一些功能: ?它使你能监视你程序中变量的值. ?它使你能设置断点以使程序在指定的代码行上停止执行. ?它使你能一行行的执行你的代码. 在命令行上键入 gdb 并按回车键就可以运行 gdb 了, 如果一切正常的话, gdb 将被启动并且你将在屏幕上看到类似的内容: GDB is free software and you are welcome to distribute copies of it under certain conditions; type "show copying" to see the conditions. There is absolutely no warranty for GDB; type "show warranty" for details. GDB 4.14 (i486-slakware-linux), Copyright 1995 Free Software Foundation, Inc. (gdb) 当你启动 gdb 后, 你能在命令行上指定很多的选项. 你也可以以下面的方式来运行 gdb : gdb
gdb汇编跟踪调试与objdump查看汇编代码
gdb汇编跟踪调试与objdump查看汇编代码 使用objdump生成可读性好的汇编代码 g++ -g3 secret.cpp -o secret objdump -SIz secret -j .text > secret.s man objdump ================ 常用命令: 如何跳出for 循环 -- until 行号 如何在多重循环中监视某变量变化情况 -- watch + until 打印数组a的前10个元素 -- p o GDB 反汇编命令 set disassembly-flavor 设置ATT或INTEL格式 set disassemble-next-line 设置下一步是否显示汇编码 disas function_name 反汇编函数function_name info line function_name 查看function_name 开始和结束地址 如果调试一个stripped 的程序,就只有依赖地址了: b *0x00401365 设置断点,这个地址与没有stripped的程序相同 watch *(int*)0x00401369 设置硬件断点 ni -- 下一条指令,n 命令是无法使用的。 si -- 单步指令,s 命令也是无法使用的。 disas start_addr,end_addr 反汇编[start_addr,end_addr]之间的指令 x /3i $pc 查看eip 开始的三条指令 o 没有调试符号的实例 假设 gcc t.c (gdb) b *0x401365 Breakpoint 1 at 0x401365 (gdb) r Starting program: F:\work/a.exe [New Thread 1752.0x560] Breakpoint 1, 0x00401365 in ?? () (gdb) disas /r 0x401365,0x401370 Dump of assembler code from 0x401365to 0x401370: => 0x00401365: c7 44 24 1c 44 13 40 00 movl $0x401344,0x1c(%esp) 0x0040136d: 8b 44 241c mov 0x1c(%esp),%eax End of assembler dump. (gdb) p /x *(int*)0x401365 $1 = 0x1c2444c7
使用 GDB 调试多进程程序的子程序
GDB 是 linux 系统上常用的 c/c++ 调试工具,功能十分强大。对于较为复杂的系统,比如多进程系统,如何使用 GDB 调试呢?考虑下面这个三进程系统: 进程 Proc2 是 Proc1 的子进程,Proc3 又是 Proc2 的子进程。如何使用 GDB 调试 proc2 或者 proc3 呢? 实际上,GDB 没有对多进程程序调试提供直接支持。例如,使用GDB调试某个进程,如果该进程fork了子进程,GDB会继续调试该进程,子进程会不受干扰地运行下去。如果你事先在子进程代码里设定了断点,子进程会收到SIGTRAP 信号并终止。那么该如何调试子进程呢?其实我们可以利用GDB的特点或者其他一些辅助手段来达到目的。此外,GDB 也在较新内核上加入一些多进程调试支持。 接下来我们详细介绍几种方法,分别是 follow-fork-mode 方法,attach 子进程方法和 GDB wrapper 方法。 follow-fork-mode 在2.5.60版Linux内核及以后,GDB对使用fork/vfork创建子进程的程序提供了follow-fork-mode选项来支持多进程调试。 follow-fork-mode的用法为: set follow-fork-mode [parent|child] ?parent: fork之后继续调试父进程,子进程不受影响。 ?child: fork之后调试子进程,父进程不受影响。 因此如果需要调试子进程,在启动gdb后: (gdb) set follow-fork-mode child 并在子进程代码设置断点。 此外还有detach-on-fork参数,指示GDB在fork之后是否断开(detach)某个进程的调试,或者都交由GDB控制:
gdb+gdbserver安装及调试(总结)
Ubuntu下gdb+gdbserver安装及调试 1、g db+gdbserver介绍 1.1、说明 远程调试(即gdb+gdbserver)环境由宿主机GDB和目标机调试stub共同构成,两者通过串口或TCP连接。使用 GDB标准程串行协议协同工作,实现对目标机上的系统内核和上层应用的监控和调试功能。调试stub是嵌入式系统中的一段代码,作为宿主机GDB和目标机调试程序间的一个媒介而存在。 就目前而言,嵌入式Linux系统中,主要有三种远程调试方法,分别适用于不同场合的调试工作:用ROM Monitor调试目标机程序、用KGDB调试系统内核和用gdbserver调试用户空间程序。这三种调试方法的区别主要在于,目标机远程调试stub 的存在形式的不同,而其设计思路和实现方法则是大致相同的。而我们最常用的是调试应用程序。就是采用gdb+gdbserver的方式进行调试。 1.2、功能 一般来说,GDB可以帮你办以下几件事: 1、启动程序,可以按照用户自定义的要求随心所欲的运行程序。 2、可让被调试的程序在用户所指定的调置的断点处停住。 3、当程序被停住时,可以检查此时用户的程序中所发生的事。 1.3、优点 在很多情况下,用户需要对一个应用程序进行反复调试,特别是复杂的程序。采用GDB方法调试,由于嵌入式系统资源有限性,一般不能直接在目标系统上进行调试,所以通常采用gdb+gdbserver的方式进行调试。 2、安装包下载 嵌入式Linux的GDB调试环境由宿主机host和目标机(开发板)target两部分组成,arm-linux-gdb安装运行于宿主机,gdbserver安装运行于目标机,但
GDB调试之跨平台驱动调试
GDB调试之跨平台代码调试 一个问题引发的思考: 问题描述:使用交叉编译工具(mips64-nlm-linux-gcc) 将某一段程序编译为目标开发板上所可以使用的可执行程序后,在目标开发板上报了如下的错误: 乍一看很明显的是oops(kernel panic)了 那么我们应该如何去定位这种问题并解决呢?那就当然要用到我们的GDB了!不过是需要支持mips架构的gdb而已 一、gdb跨平台环境搭建 首先我们可以使用如下命令来查看Debian中对于体系架构的一张描述表 cat /usr/share/dpkg/archtable #
x86_64-kfreebsd-gnu kfreebsd-amd64 对于我们当前来说:我们仅仅需要 x86_64-linux-gnu amd64 mips-linux-gnu mips 明确了我们的需求,就开始生成我们自己的编译器了! 1、创建一个目录并且下载gdb源码到此目录 目录自己选择(此处为opt) //注意需要切换root mkdir /opt/build-gdb apt-get source gdb 2、根据需求配置我们的configure ./configure --enable-targets=x86_64-linux-gnu,mips-linux-gnu 3、编译 make 4、将生成的gdb复制到/usr/sbin下 cp gdb/gdb /usr/sbin/gdb-all 以上操作就可以完成跨平台gdb调试的基本安装! 二、如何使用 我们回到我们的问题的最开始: 如何定位? 1、gdb-all vmlinux (这个为开发板上所使用的vmlinx) 2、设置目标架构 set architecture mips:isa64r2 3、定位错误 info line *0x我们上述oops的epc地址 info line *0xffffffff804c120c 定位结果:第293行 Line 293 of "drivers/tl_modules/xlp_module/command_kernel/command_kernel.c" starts at address 0xffffffff804c1204