请阅读【ARM Linux 系统稳定性分析专栏导读】
1.1 gdb 调试回顾
在GNU调试器(GDB)中,有许多命令可以帮助我们调试应用程序。gdb
: 这是一个强大的Unix下的程序调试工具。以下是使用gdb的一个简单示例:
$ gdb ./test
在这个例子中,我们启动了gdb
并将我们的程序test
作为参数传递。
可执行程序 test
是由下面代码使用gcc -g -O0 test.c -o test
编译出来:
#include<stdio.h>
#include<stdlib.h>
static int bar(void)
{
char *p = NULL;
printf("I am bar,I will core dump\n");
printf("%s",p);
*p =0x0;
return 0;
}
static int foo(void)
{
int i ;
printf("I am foo,I will call bar\n");
bar();
return 0;
}
int main(void)
{
printf("I am main, I wll can foo\n");
foo();
return 0;
}
1.1.1 gdb list 命令介绍
llist: llist
命令用于显示当前源代码的行列表,包括当前行以及周围的几行代码。这对于查看代码的上下文非常有用。
例如,你可以使用llist命令来显示当前行及周围的10
行代码:
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...
(gdb) list 10
5 {
6 char *p = NULL;
7
8 printf("I am bar,I will core dump\n");
9 printf("%s", p);
10
11 *p = 0x0;
12
13 return 0;
14 }
(gdb)
这将显示源代码的当前行周围的文本。
1.2 反汇编命令 dis 介绍
dis/disassemble: 这个命令用于查看汇编代码。例如,我们可以使用以下命令查看当前函数的汇编代码:
(gdb) disassemble
或者查看指定函数的汇编代码:
[11:01:22]sam@codingcos-sam-laptop (*^~^*) ~/test> gdb test
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...
(gdb) dis foo
Bad breakpoint number 'foo'
(gdb)
从上面的信息可以看到gdb并没有对函数 foo
进行反汇编,而是报出错误:“Bad breakpoint number ‘foo’”,甚是疑惑!!!, 网上搜了一大圈也没找到原因!!
后来发现是在使用gdb
时没有设置断点导致的,如果按照下面方式,则可以进行反汇编
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...
(gdb) b foo
Breakpoint 1 at 0x11bd: file test.c, line 19.
(gdb) dis foo
Bad breakpoint number 'foo'
(gdb) disassemble foo
Dump of assembler code for function foo:
0x00000000000011b5 <+0>: endbr64
0x00000000000011b9 <+4>: push %rbp
0x00000000000011ba <+5>: mov %rsp,%rbp
0x00000000000011bd <+8>: lea 0xe5f(%rip),%rax # 0x2023
0x00000000000011c4 <+15>: mov %rax,%rdi
0x00000000000011c7 <+18>: call 0x1060 <puts@plt>
0x00000000000011cc <+23>: call 0x1169 <bar>
0x00000000000011d1 <+28>: mov $0x0,%eax
0x00000000000011d6 <+33>: pop %rbp
0x00000000000011d7 <+34>: ret
End of assembler dump.
但是目前还不清楚为何使用 dis
命令不生效。
如下是使用 arm gdb 的反汇编示例(前提要有arm gcc 编译出来的 .o
文件):
arm-none-eabi-gdb ./build/bsp/sam/sam_demo/common/soc.o
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi".
Reading symbols from ./build/bsp/sam/sam_demo/common/soc.o...
(gdb) b reboot
Breakpoint 1 at 0x214: file /mnt/user_home/sam/rt-thread/bsp/sam/sam_demo/common/soc.c, line 36.
(gdb) disassemble reboot
Dump of assembler code for function reboot:
0x00000208 <+0>: push {r7}
0x0000020a <+2>: sub sp, #20
0x0000020c <+4>: add r7, sp, #0
0x0000020e <+6>: mov r3, r0
0x00000210 <+8>: str r1, [r7, #0]
0x00000212 <+10>: strb r3, [r7, #7]
0x00000214 <+12>: ldr r3, [pc, #24] ; (0x230 <reboot+40>)
0x00000216 <+14>: str r3, [r7, #12]
0x00000218 <+16>: dmb sy
0x0000021c <+20>: ldr r2, [pc, #20] ; (0x234 <reboot+44>)
0x0000021e <+22>: ldr r3, [r7, #12]
0x00000220 <+24>: str r3, [r2, #0]
0x00000222 <+26>: nop
0x00000224 <+28>: adds r7, #20
0x00000226 <+30>: mov sp, r7
0x00000228 <+32>: ldr.w r7, [sp], #4
0x0000022c <+36>: bx lr
0x0000022e <+38>: nop
0x00000230 <+40>: lsls r3, r4, #12
0x00000232 <+42>: movs r0, #33 ; 0x21
0x00000234 <+44>: asrs r0, r0, #2
0x00000236 <+46>: mov r1, r0
End of assembler dump.
(gdb)
另外一种查看汇编代码的方式是使用 x
命令,如下显示 pc
开始的 3
条指令:
Breakpoint 1, foo () at test.c:19
19 printf("I am foo,I will call bar\n");
(gdb) x/3i $pc
=> 0x5555555551bd <foo+8>: lea 0xe5f(%rip),%rax # 0x555555556023
0x5555555551c4 <foo+15>: mov %rax,%rdi
0x5555555551c7 <foo+18>: call 0x555555555060 <puts@plt>
(gdb)
arm gdb 反汇编示例:
查看0x0
地址开始后面的10
条汇编:
arm-none-eabi-gdb ./build/bsp/sam/sam_demo/common/soc.o
...
(gdb) x/3i 0x0
0x0 <__NVIC_SetPriority>: push {r7}
0x2 <__NVIC_SetPriority+2>: sub sp, #12
0x4 <__NVIC_SetPriority+4>: add r7, sp, #0
(gdb) x/10i 0x00000000
0x0 <__NVIC_SetPriority>: push {r7}
0x2 <__NVIC_SetPriority+2>: sub sp, #12
0x4 <__NVIC_SetPriority+4>: add r7, sp, #0
0x6 <__NVIC_SetPriority+6>: mov r3, r0
0x8 <__NVIC_SetPriority+8>: str r1, [r7, #0]
0xa <__NVIC_SetPriority+10>: strh r3, [r7, #6]
0xc <__NVIC_SetPriority+12>: ldrsh.w r3, [r7, #6]
0x10 <__NVIC_SetPriority+16>: cmp r3, #0
0x12 <__NVIC_SetPriority+18>: blt.n 0x2a <__NVIC_SetPriority+42>
0x14 <__NVIC_SetPriority+20>: ldr r3, [r7, #0]
(gdb)
1.2.1 如何设置 gdb 汇编代码的格式
GDB 主要支持两种汇编代码格式:
-
AT&T
风格:这是GDB的默认汇编代码格式,是在Unix和GNU系统中常见的格式。在AT&T
风格的汇编代码中,操作数的顺序是“源,目标”,立即数和绝对地址值以美元符号"$"
作为前缀,寄存器名称以百分号"%"
作为前缀。 -
Intel
风格:这是在Intel文档和Windows环境中常见的格式。在Intel风格的汇编代码中,操作数的顺序是“目标,源”,立即数和绝对地址值没有特殊的前缀,寄存器名称也没有特殊的前缀。
可以使用 show disassembly-flavor
命令查看当前的汇编代码风格。例如:
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...
(gdb) dis foo
Bad breakpoint number 'foo'
(gdb) show disassembly-flavor
The disassembly flavor is "att".
(gdb)
可以看到默认是 AT&T风格。
如果你想要改变汇编代码风格,你可以使用 set disassembly-flavor
命令来设置新的风格。例如,如果你想要设置成Intel风格,你可以这样做:文章来源:https://www.toymoban.com/news/detail-670611.html
(gdb) set disassembly-flavor intel
如果你想要设置成AT&T风格,你可以这样做:文章来源地址https://www.toymoban.com/news/detail-670611.html
(gdb) set disassembly-flavor att
到了这里,关于ARM Linux 系统稳定性分析入门及渐进 13 -- gdb 反汇编 disassemble 命令详细介绍及举例】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!