实验XXGDB调试实验.docx
实验XX GDB调试实验【实验目的】1、熟悉GDB的各命令。2、学习 arm-linux-gdb 的使用。3、掌握嵌入式Linux的交叉调试的方法。【实验内容与步骤】1、GDB命令本节将结合一个简单的例子,向大家演示这些常用指令的具体应用。这是一个冒泡排序 算法的程序,这个例子的目的仅仅是演示,并不是实际调试。将下面的源程序存为bubble.c 文件,并编译好。include <stdio.h>#define MAX_RECORD_NUMBER 10int recordMAX_RECORD_NUMBER=12,76,48,62,94,17,37,52,69,32;void swap(int * x , int * y )int temp;temp = *x;*x = *y;*y = temp;int main()int i,j;for( i = 0 ; i < MAX_RECORD_NUMBER - 1; i+ )for( j = MAX_RECORD_NUMBER - 1; j > i; j-)if( recordj < recordj-1) swap(&recordj,&recordj-1);for( i = 0; i < MAX_RECORD_NUMBER -1; i+)printf("%d ",recordi);Lprintf("n");return 1;记得在编译时用-g开关。口: gcc -g -o bubble bubble.c。你能在当前子目录下得到一个 编译好的文件bubble。我们下面将以这个程序为例子向大家演示上面的指令在实际中的应 用。首先启动GDB,可以在启动的同时载入文件bubble,如:gdb bubble。也可以分两步进 行,先启动GDB,执行gdb,进入GDB后,再执行file bubble。这时可以用list指令列出源程序,list的使用比较简单,但其实在GDB中最不方便的就 是看源程序,主要原因是因为GDB仅是一个文本方式的调试器,无法让你用鼠标和光标键 来翻阅源程序,在这方面ddd等窗口程序有巨大的优势。我们先来查看一下当前源程序的信息,如下:(gdb) info sourceCurrent source file is bubble.cCompilation directory is /root/sampleLocated in /root/sample/bubble.cContains 32 lines.Source language is c.Compiled with DWARF 2 debugging format.Does not include preprocessor macro info.我们可以知道程序名,目录,文件大小,语言等信息。下面我们来设置断点,我们想在函数swap出设置一个断点:(gdb) br swapBreakpoint 1 at 0x80483d6: file bubble.c, line 11.br是break的简写。上面的一行是GDB告诉我们这个断点的信息,我们可以知道这个断点的断点号是1,地址是0x80483d6,它在文件bubble.c的11行。我们再在一个行号上设一个断点,(gdb) br 23Breakpoint 2 at 0x804844a: file bubble.c, line 23.我们已经设了两个断点,许多时候你会想查看一下断点的信息和状态,因此你会用到你(gdb) info br Num Type1 breakpoint2 breakpoint最常使用的info指令,info br。Disp Enb Address Whatkeep y 0x0804832e in swap at bubble.c:11keep y 0x08048390 in main at bubble.c:23用这条指令的大多数原因是想查看一下某个断点的断点号,就是第一列的数值。有时也 会看一下断点的状态是enable还是disable。以上的两个断点都是y,也就是都处于enable 状态。type列显示breakpoint,是因为info br指令同时也会显示watch的信息,因此用type 来识别是断点breakpoint还是检查点watch。如果你知道断点号,想删除断点很简单,例如想删除断点2,执行del 2就行了。在程序中,断点2本来设在循环中,那样程序会频繁断下,这也许不是我们希望的。也 许我们仅想在某个条件下让它断下,如想当j=5时。(gdb) del 2(gdb) info br Num TypeDisp Enb Address What1 breakpointkeep y 0x0804832e in swap at bubble.c:11(gdb) br 23 if j=5Breakpoint 3 at 0x8048390: file bubble.c, line 23.(gdb) info br Num TypeDisp Enb Address What1 breakpointkeep y 0x0804832e in swap at bubble.c:113 breakpointkeep y 0x08048390 in main at bubble.c:23stop only if j = 5注意现在的断点信息,虽然断点2被删除了,但新设的断点号没有使用2号,而是使用 了 3号。新设的断点是个条件断点,这从"stop only if j = 5"可以清楚的看出。现在1执行程序,输入run指令。(gdb) runStarting program: /root/sample/bubbleBreakpoint 1, swap (x=0x8049524, y=0x8049520) at bubble.c:1111 temp = *x;程序已经在断点1停了下来。当断点停下时,我们经常需要查看变量值。如查看x值。(gdb) p x$1 = (int *) 0x8049524GDB告诉我们x是一个指向整数的指针,指针值是0x80495a4。如果想查看指针指向的 值。执行:(gdb) p *x$2 = 32(gdb) p *y$3 = 69然后,单步执行t(gdb) n12 *x = *y;查看变量temp值(gdb) p temp$4 = 32(gdb) n13 *y = temp;(gdb) p *x$5 = 69现在删除断点1(gdb) del 1继续执行(gdb) contContinuing.Breakpoint 3, main () at bubble.c:2323swap(&recordj,&recordj-1);程序在断点3停下,记得断点3是个条件断点。要验证很简单,查看一下变量的值是 不是5。(gdb) p j$6 = 5我们可以查看一下全局变量record的值,(gdb) p record$7 = 12, 76, 48, 62, 94, 17, 32, 37, 52, 69也可以查看一下变量record的地址,(gdb) p &record$8 = (int (*)10) 0x8049500知道地址时,也可以x指令查看内存值。(gdb) x/4uw 0x8049500 0x8049500 <record>:12764862上面的指令查看4个4字节数,以整数方式显示。可以看到这与reocrd值是相附的。(gdb) x/4bb record 0x8049500 <record>:12000显示4个单字节数,以字节当时显示。上面的4个字节值正好是record数组第一个整 数值,因为整数是4字节,而且intel机器的数值是低字节在前。改变变量值也很简单,如果想将reocrd数组第一个值改为1,(gdb) set record0=1看一下值是否改变了。(gdb) p record$10 = 1, 76, 48, 62, 94, 17, 32, 37, 52, 69第一个值已经改成了 1。以上简单地介绍了一些常用的GDB指令,由于篇幅所限,无法涉及GDB所有指令及GDB 其它许多功能,应当自己在实践中不断地学习。Linux系统中会有详细的GDB的资料,可以 用info gdb来查阅这些资料。2、利用GDB进行远程调试完成上面的基础实验之后,应该掌握了基本的GDB命令使用,接下来的这一小节我们 将利用GDB进行远程调试。GDB远程调试并不像在本机上调试一个可执行程序那么简单, 因为需要在两台机器的连接的基础上进行调试,为了使便于理解,我们选用了较为容易的搭 建一个主机PC端的gdb和目标机端的gdbserver方式来进行实验。2.1编译GDBGDB用ARM体系的GCC编译,因为XSBase开发板上的的Xscale PXA255芯片是ARM内 核。Toolchain必须在主机平台上重新安装来编译用于ARM的GDB。2.1.1 编译 GDB Server,解压 gdb-5.3.tar.gz.root$super root# mkdir /HYPER255/temproot$super root# cp gdb-5.3.tar.gz /HYPER255/temproot$super temp# cd /HYPER255/temproot$super temp# tar xvzf gdb-5.3.tar.gz运行configure创建make文件,执行make。root$super temp# cd gdb-5.3root$super gdb-5.3# ./configure -target=arm-linux -prefix=/usr/local/arm-gdb-v root$super gdb-5.3# make root$super gdb-5.3# make install配置选项:target :选择 arm-linux 因为 XSBase255 是基于 ARM。prefix :当你执行make install时选择安装路径如果编译没有任何错误,arm-linux-gdb将生成在/usr/local/arm-gdb/bin。 Arm-linux-gdb运行在主机平台上成为GDB服务器,用来远程调试XSBase255板子。2.1.2 GDB客户机端编译 首先进入GDB目录编译root$super root# cd /HYPER255/temp/gdb-5.3root$super gdb-5.3# export PATH=$PATH:/usr/local/arm-gdb/binroot$super gdb-5.3# ./configure -target=arm-linux -host=arm-linuxtarget :选择 arm-linux 因为 Hyper255 是基于 ARM 的。host :选择 arm-linux 因为 Hyper255 是基于 ARM 的。 客户端程序在gdb/gdbserver目录下root$super gdb-5.3# cd gdb/gdbserverroot$super gdbserver# make CC=/usr/local/hybus-arm-linux-R1/bin/arm-linux-gcc 如果你按上面的编译会出现下面的错误信息。linux-arm-low.c:26: sys/reg.h: No such file or directory解决这个错误,请修改gdb/gdbserver/config.h文件。#define HAVE_SYS_REG_H 1-> /#define HAVE_SYS_REG_H 1按上述的注释“define HAVE_SYS_REG_H 1”句子。 再执行makeroot$super gdbserver# make CC=/usr/local/hybus-arm-linux-R1/bin/arm-linux-gcc 如果没有编译错误gdbserver将生成在gdb/gdbserver目录下。这个文件是GDB 客户端程序,在xsbase开发板上运行。2.2 GDB调试GDB通过以太网对XSBase255板进行调试。因此,必须使主机平台和XSBase实验平台 之间的TCP/IP协议可用。首先,检查主机平台和XSBase255实验平台之间的通信。默认xsbase的IP地址是 192.168.100.50。在这节实验中,假设主机平台的IP是192.168.100.216。root$super gdbserver# ifconfig eth0 192.168.100.2162.2.1编写需调试代码源文件名:test.c#include <stdio.h>int main()int i;double j;char *str = NULL ;for(i=0; i<5; i+)j = i/2 + i;printf("j is %f n", j);strcpy(str,"hello, world");printf("str is %s n", str);return 0;J这个程序代码是把变量i和变量i/2加到j中,然后拷贝字符串到指针变量str 并输出。下面的输出是希望得到的。j is 0.000000j is 1.500000j is 3.000000j is 4.500000j is 6.000000str is hello. world然而,它并没有得到上面的结果。用GDB调试程序。2.2.2 用 arm-linux-gcc 编译root$super temp#arm-linux-gcc -g test.c -o test2.2.3下载到目标平台下载test和gdbserver到XSBase255目标板。Zmodem和ftp都可以用来下载。例 如我们用zmodem来下载。按Ctrl+A然后再按Z键出现minicom配置窗口。mi把 4urn; ct-cfv?普州皿 nw flruKiDMiiWnmnd Snimt r vOxTHbnih <anhr «lkd hy CTRL-4Hun Pun«t Ron-ctMhr Fi>ri iw>5Dlu 1 ln 割rw"ry. .D Saikd. riIo a .Scixara Pa rarrn La r b . . . . P Giplu ra nfk/ri-Fr. .L send brak .PTerninal settings. T I ircWap on-Xof f. .I ijl!i rtol.Ri'cC'iVt JbUtfiAdil 1 LncJiMHlEhri|Up . “E“EE“EE“. rniLMlize Nbdrm tuh Nriri 1. kml Etha un/nff.M.札kClcjir EerceiiCnil lv r-i Min I 虬-口 Sa i p4»J. onirii i«r>r3i. . . _J Mil jaJ. ra id 1 . . . . .X <> i i *i It rcse irQ iQirscr ify node . .1 Ih Ip icrtcni.Zitrtfl 1 Uii:k泪Sdla-s-E F'un-eLban arlinitr for1WiLLrn by Mqurl v-an Snuurfiibire Ittl-ltti Sarrr addi Lmni: by Jukka Lahiinm by Arn& tdo Ofn'ilihn de Mi IdWTJCij按s键选择zmodem。图2可以看到主机平台的目录,从/HYPER255/temp/gdb/gdbserver中下载gdbserver。- L ,5-.L i 上-1 !±'- L- L ,5-.L i 上-1 !±'- LhET-fe Lin.-. KT/IP 3.9 Wr NZT-1.0JI?IIP. 1XFJI? : r«u i gb| cdv ha ck i ih la Si t bufap i n. 4Uiyivi IC'f: itaih i>biki l ctibT sgurpd *« i: iah I uahJ. 4lJK bLU "D#!1用同样的方法下载test,然后执行test。rootHYPER255 /root$./testj is 0.000000j is 1.000000 pc : <4009a8f8> lr : <0000845c> Not tainted j is 3.000000j is 4.000000j is 6.000000sp :bffffd4cip:bffffd5cfp :bffffd58r10:401342fcr9:40133c88r8 :000083d4r7 :00000001r6:00008280r5 :4001e724 r4 : bffffd94r3 :00000068r2:ffff7af3r1 :0000850d r0 : 00000000Flags:nzCvIRQson FIQs onModeUSER_32 Segment userControl: 397F Table: A3E54000 DAC: 00000015Segmentation faultrootHYPER255 /root$结果出现段错误,这不是我们希望得到的结果。2.2.4实现远程连接 在XSBase255板子上运行gdbserver。rootHYPER255 /root$ ./gdbserver 192.168.100.216:1234 testProcess test created; pid = 85Listening on port 1234此时,运行在开发板上的gdbserver监听在1234端口 拷贝test程序到主机平台上的/usr/local/arm-gdb/bin目录下,然后执行arm-linux-gdboroot$super temp# cp /HYPER255/test /usr/local/arm-gdb/bin root$super temp# cd /usr/local/arm-gdb/bin root$super temp # ./arm-linux-gdb test GNU gdb 6.1Copyright 2004 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and yc are welcome to change it and/or 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. This GDB was configured as "host=i686-pcTinux-gnutarget=armTinux. (gdb)连接到XSBase255开发板。(gdb) target remote 192.168.100.50:1234Remote debugging using 192.168.100.50:12340x40002980 in ?()在这里,实验平台的IP地址是192.168.100.50,端口是1234o如果连接成功的话,在XSBase255上将出现下面的信息。Remote debugging from host 192.168.100.2162.2.5远程调试完成连接以后,才开始真正的调试工作。导入symbol文件。(gdb) contContinuing.Breakpoint 1, main () at test.c:99for(i=0; i<5; i+) 用list命令查看代码的内容。 因为运行结果不是我们希望的,在第9行代码中设置一个断点来查找出错原因。(gdb) break 9Breakpoint 1 at 0x83ec: file test.c, line 9. 执行代码。(gdb) contContinuing.Breakpoint 1, main () at test.c:99for(i=0; i<5; i+)在第9行断点暂停。 用单步命令step继续执行。(gdb) step11 j = i/2 + i;(gdb) step12 printf("j is %f n", j);(gdb) step9for(i=0; i<5; i+)此时我们切换到xsbase开发板的minicom窗口下,可以看到输出变量j的值。 在下面的单步中选中变量i和j的值。(gdb) step11j = i/2 + i;I (gdb) p i$1 = 1(gdb) p j$2 = 0(gdb) step12(gdb) p j$3 = 1你会发现当i = 1时j = 1。通过调试结果分析发现j=i/2+1是不正确的。正确的表达式是 j = (double)i/2 + i。查找其他的bug,在strcpy(str,"hello, world"这行设置一个断点。(gdb) break 15Breakpoint 2 at 0x8448: file test.c, line 15.(gdb) contContinuing.Breakpoint 2, main () at test.c:1515strcpy(str,"hello, world"); 查看变量str的值,然后单步运行。(gdb) p str$4 = 0x0(gdb) stepProgram received signal SIGSEGV, Segmentation fault.0x4009a8f8 in ?()可以看到在15行有一个段错误。变量str的值是0X0。因为它没有给str变 量分配空间导致出现段错误。修正这个错误,在 15行前面添加str = (char *)calloc(1, sizeof(char)。 修正错误,退出GDB。(gdb) cContinuing.Program terminated with signal SIGSEGV, Segmentation fault.The program no longer exists.(gdb) quit 重新下载修改过后的test程序,在实验平台上运行,得到正确的结果。【实验原理】1、GDB基础GDB是GNU开源组织发布的交叉调试工具。和VC、BCB等图形界面方式的IDE的调试 不一样,GDB是在UNIX下一个强大的命令行调试工具,用来观察程序内部的运行情况。它 可以使得程序的开发者了解到程序在运行时的详细细节,从而能够很好的除去程序的错误, 达到调试的目的。英文debug的意思就是"除虫”,而GDB的全称就是Gnu DeBugger。目前 GDB支持的可以调试的语言有C,C+,Modula-2等几种语言,现在还可能可以支持Fortran 语言的调试。使用GDB可以完成以下任务: 启动你的程序,可以按照自定义的要求运行程序。 可让被调试的程序在所指定的设置的断点处停住。(断点可以是条件表达式) 当程序被停住时,可以检查此时程序中所发生的事。 动态的改变程序的执行环境。2、GDB常用命令GDB的命令很多,在此讲解一些最常用的。在讲解之前,必须提到GDB中的一个非常有 用的功能一补齐功能。它就如同Linux下SHELL中的命令补齐一样。当你输入一个命令的前几个字符,然后输入TAB键,如果没有其它命令的前几个字符与此相同,SHELL将补齐此命 令。如果有其它命令的前几个字符与此相同,你会听到一声警告声,再输入TAB键,SHELL 将所有前几个字符与此相同的命令全部列出。而GDB中的补齐功能不仅能补齐GDB命令,而 且能补齐参数。GDB程序有许多命令和参数,在此没有必要详细讲解,以下将最为常用的简要说明一下: 1)基本功能下面的所有命令除了第一条启动GDB命令是在SHELL下输入的,其余都是GDB内部的命 令。大部分GDB内部的命令都可以仅输入前几个字符,只要不与其它指令冲突。如quit可 以简写为q,因为以q打头的命令只有quit。List可以简写为1,等等。功能及命令功能及命令描述启动GDB输入GDB来启动GDB程序。如果你已经编译好一个程序,我们假设文件名为 hello,你想用GDB调试它,可以输入gdb hello来启动GDB并载入你的程序。 如果你仅仅启动了 GDB,你必须在启动后,在GDB中再载入你的程序。载入程序 file在GDB内,载入程序很简单,使用file命令。如file hello。当然,程序 的路径名要正确。退出GDB quit在GDB的命令方式下,输入quit,就可以退出GDB。也可以输入'Ctrl-d'来 退出GDB。运行程序run当你在GDB中已将要调试的程序载入后,你可以用run命令来执行。如果你 的程序需要参数,你可以在run指令后接输入参数,就象你在SHELL下执行 一个需要参数的命令一样。查看程序信息infoinfo指令用来查看程序的信息,当你用help info查看帮助的话,info指令的 参数足足占了两个屏幕,它的参数非常多,但大部分不常用。一般用info指 令最多的是用它来查看断点信息。查看断点信息info brbr是断点break的缩写,记得GDB的补齐功能吧。用这条指令,你可以得到 你所设置的所有断点的详细信息。包括断点号、类型、状态、内存地址和断 点在源程序中的位置等。查看当前源程序info source这条指令可以查看当前文件的名字、路径和所使用的程序语言等信息。查看堆栈信息info stack用这条指令你可以看清楚程序的调用层次关系。查看当前的参数info local显示被调试程序当前函数中的局部变量信息。list FUNCTION列出被调试程序某个函数list LINENUM以当前源文件的某行为中间显示一段源程序list接着前一次继续显示list-显示前一次之前的源程序ListFILENAME:FUNCTION显示另一个文件的一段程序,也可以使用list FILENAME:LINENUM2)设置断点break无论何时,只要你的程序已被载入,并且当前没有正在运行,你就能设置、修改或删除断点。设置断点的命令是break。有许多种设置断点的方法。如下:break FUNCTION在函数入口设置断点。break LINENUM在当前源文件的某一行上设置断点。break *ADDRESS 用。break .if CONDbreak FILENAME:LINENUM在另一个源文件的某一行上设置断点。在某个地址上设置断点,当你调试的程序没有源程序时,这很有条件断点;COND是一个布尔条件表达式,语法与C语言中的一 样。条件断点与一般的断点不同之处是每当程序执行到断点处, 都要计算条件表达式,如果为真,程序才会断下,否则程序会一 直执行下去。GDB给每个断点赋上一个整数数字,这个数字在操作断点时起到重要作用,它实际上就 代表相应的断点。GDB中的断点有四种状态:有效(Enabled)禁止(Disabled)一次有效(Enabled once)有效后删除(Enabled for deletion)在上面的四个状态有效和禁止都很好理解,禁止就是让断点暂时失效。一次有效就是当 程序在此断点断下后,断点状态自动变为禁止状态。有效后删除就是当程序在此断点断下后, 断点被删除。实际上,后两种状态一般不会碰到。当你设置一个断点后,它的缺省状态是有效。你可以用enable和disable指令来设置断 点的状态为有效或禁止。例如,如果你想禁止2号断点,可以用下面的指令:disable 2相应的,如果想删除2号断点,可以有下面的指令:delete 23) 设置监视点watch当你调试一个很大的程序,并且在跟踪一个关键的变量时,发现这个变量不知在哪里被 改动过,如何才能找到改动它的地方。这时你可以使用watch命令。简单地说,监视点可以 让你监视某个表达式或变量,当它被读或被写时让程序断下。watch命令的用法如下:watch EXPRESSIONwatch指令是监视被写的,当你想监视某个表达式或变量被读的话,需要使用watch指 令,具体用法是一样的。要注意的是,监视点有硬件和软件两种方式,如果可能Linux尽可 能用硬件方式,因为硬件方式在速度上要大大快于软件方式。软件方式由于要在每次执行一 条指令后都要检查所要监视的值是否被改变,因此它的执行速度会大大降低。同时它也无法 设置成被读时让程序断下,因为读操作不会改变值,所以GDB无法检测到读操作。幸运的 是,目前的PC机基本都支持硬件方式。如果你想确认一下你的机器是否支持硬件,你可以 在调试程序时用watch设置一个监视点,如果GDB向你显示:Hardware watchpoint NUM: EXPR 那么你可以放心了,你的机器支持硬件方式。4) 检查数据最常用的检查数据的方法是使用print命令。print expprint指令打印exp表达式的值。缺省情况下,表达式的值的打印格式依赖于它的数据 类型。但你可以用一个参数/F来选择输出的打印格式。F是一个代表某种格式的字母,详细 可参考输出格式一节。表达式可以是常量,变量,函数调用,条件表达式等。但不能打印宏 定义的值。表达式exp中的变量必须是全局变量或当前堆栈区可见的变量。否则GDB会显示象下面的一条信息:No symbol "variable" in current context5) 修改变量值在调试程序时,你可能想改变一个变量的值,看看在这种情况下会发生什么。用set指 令可以修改变量的值:set variable=value例如你想将一个变量tmp的值赋为10,set tmp=106) 检查内存值检查内存值的指令是x,x是eXamine的意思。用法如下:x/NFU ADDR其中N代表重复数,F代表输出格式,U代表每个数据单位的大小。U可以去如下值:b :字节(byte)h :双字节数值w :四字节数值g :八字节数值因此,上面的指令可以这样解释:从ADDR地址开始,以F格式显示N个U数值。例 如:x/4ub 0x4000会以无符号十进制整数格式(u)显示四个字节(b),0x4000,0x4001,0x4002,0x4003。输出格式:缺省情况下,输出格式依赖于它的数据类型。但你可以改变输出格式。当你 使用print命令时,可以用一个参数/F来选择输出的打印格式。F可以是以下的一些值:'x' 16进制整数格式'd'一有符号十进制整数格式'u'一无符号十进制整数格式'f'一浮点数格式7) 单步执行指令单步执行指令有两个:step和next。Step可以让你跟踪进入到一个函数种执行,而next 指令则不会进入函数。8) 继续执行指令当程序被断下后,你查看了所需的信息后,你会希望程序执行下去,输Continue,程 序会继续执行下去。9) 帮助指令help在GDB中,如果想知道一条指令的用法,最方便的方法是使用help。使用方法很简单, 在help后跟上指令名。例如,想知道list指令用法,输入:help list3、GDB远程调试功能当gdb被适当的集成到某个嵌入式系统中的时候,它的远程调试功能允许设计人员一步 一步的调试程序代码、设置断点、检验内存,并且同目标交换信息。GDB同目标板交换信息的能力相当强,胜过绝大多数的商业调试内核,甚至功能相当于某些低端仿真器。在GDB里面有一个调试目标(Target)的概念。调试目标就是你的程序所获得的执行环 境。一般的情况下,你要调试的程序和你当前所在的环境是完全一样的,那么你用file或者 core命令可以指定你的调试目标。(file命令用来指定用来调试的可执行文件,core命令用 来指定调试的时候需要导入的core dump文件)。另外一种情况就是需要在这里说明的。如 果需要调试的程序和GDB所运行的环境不同,或者说你需要调试的环境上根本无法运行起 GDB,那么就没有办法使用file或者core命令来指调试目标了。这里,就需要使用远程调试 功能,通过一台可以使用GDB的机器,通过串口的通讯协议和被调试的程序所在的机器连 接,从而调试程序。这种情况是很多的,比如说你要调试一个独立的系统,或者说是实时系 统,都需要和这个系统建立起连接才能完成整个调试过程。在GDB里面就是使用target命 令完成这项工作的。指定你需要调试的远程机器的方法是使用target remote命令,后面紧接着需要和远程 机器连接的设备,口/dev/ttyS0 (串口 1)等等。在GDB里面内嵌有串口的通信协议,并且 规范了和远程机器的调试命令的一些数据传输包的格式;在远程机器上,需要实现一个stub 文件,在这个文件里面需要提供串口连接的协议,和传送数据信息的方法。可以这样说,stub 文件代替了在本地主机上GDB串口协议的位置