zoukankan      html  css  js  c++  java
  • gdb list命令查看源码 break设置断点可以通过源码也可以根据汇编代码地址设置

    【打印调用栈】

    (gdb) bt
     #0  epoll_wait () at bionic/libc/arch-arm/syscalls/epoll_wait.S:10
     #1  0x401275ea in android::Looper::pollInner (this=this@entry=0x747fd3f0, timeoutMillis=<optimized out>, timeoutMillis@entry=85688516) at system/core/libutils/Looper.cpp:223
     #2  0x40127814 in android::Looper::pollOnce (this=0x747fd3f0, timeoutMillis=85688516, outFd=outFd@entry=0x0, outEvents=outEvents@entry=0x0, outData=outData@entry=0x0)     at system/core/libutils/Looper.cpp:191
     #3  0x401d13dc in pollOnce (timeoutMillis=<optimized out>, this=<optimized out>) at system/core/include/utils/Looper.h:176
     #4  android::NativeMessageQueue::pollOnce (this=0x747fef58, env=0x4151dfa8, timeoutMillis=<optimized out>) at frameworks/base/core/jni/android_os_MessageQueue.cpp:97
     #5  0x4153d310 in dvmPlatformInvoke () at dalvik/vm/arch/arm/CallEABI.S:258
     #6  0x4156d8de in dvmCallJNIMethod (args=0x6d5a5e18, pResult=0x4151f568, method=0x6d60e2d8, self=0x4151f558) at dalvik/vm/Jni.cpp:1159
     #7  0x41546724 in dalvik_mterp () at dalvik/vm/mterp/out/InterpAsm-armv7-a-neon.S:16240

    【切换到调用栈的第n层】

     (gdb) f 11
     #11 0x41587ff6 in Dalvik_java_lang_reflect_Method_invokeNative (args=<optimized out>, pResult=0x4151f568) at dalvik/vm/native/java_lang_reflect_Method.cpp:101
    101                    noAccessCheck);

    【显示汇编代码】

     (gdb) disassemble 
     Dump of assembler code for function Dalvik_java_lang_reflect_Method_invokeNative(u4 const*, JValue*):
        0x41587f7c <+0>:    stmdb    sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, r10, r11, lr}
        0x41587f80 <+4>:    add.w    r4, r0, #12
        0x41587f84 <+8>:    ldmia.w    r4, {r4, r8, r9}
        0x41587f88 <+12>:    mov    r5, r0
        0x41587f8a <+14>:    mov    r11, r1
        0x41587f8c <+16>:    ldr    r6, [r0, #4]
        0x41587f8e <+18>:    ldr    r7, [r0, #8]
        0x41587f90 <+20>:    ldr.w    r10, [r0, #28]
        0x41587f94 <+24>:    ldr    r1, [r5, #24]
        0x41587f96 <+26>:    mov    r0, r4
        0x41587f98 <+28>:    bl    0x4158e828 <dvmSlotToMethod(ClassObject*, int)>
        0x41587f9c <+32>:    ldr    r3, [r0, #4]
        ...
    
    (gdb) disassemble 0x401b406c
     Dump of assembler code for function _JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...):
        0x401b4058 <+0>:    push    {r2, r3}
        0x401b405a <+2>:    push    {r0, r1, r4, lr}
        0x401b405c <+4>:    add    r3, sp, #16
        0x401b405e <+6>:    ldr    r4, [r0, #0]
        0x401b4060 <+8>:    ldr.w    r2, [r3], #4
        0x401b4064 <+12>:    ldr.w    r4, [r4, #568]    ; 0x238
        0x401b4068 <+16>:    str    r3, [sp, #4]
        0x401b406a <+18>:    blx    r4
        0x401b406c <+20>:    ldmia.w    sp!, {r2, r3, r4, lr}
        0x401b4070 <+24>:    add    sp, #8
        0x401b4072 <+26>:    bx    lr
     End of assembler dump.

    【查看当前的寄存器值】

     (gdb) info reg
     r0             0x0    0
     r1             0x4151dfa8    1095884712
     r2             0x10    16
     r3             0x0    0
     r4             0x4175c138    1098236216
     r5             0x6d68eeb8    1835593400
     r6             0x0    0
     r7             0x42dc4350    1121731408
     r8             0x42dc4278    1121731192
     r9             0x416f12a8    1097798312
     r10            0x0    0
     r11            0x4151f568    1095890280
     r12            0xbe88e2d8    3196642008
     sp             0xbe88e6c0    0xbe88e6c0
     lr             0x41587ff7    1096318967
     pc             0x41587ff6    0x41587ff6 <Dalvik_java_lang_reflect_Method_invokeNative(u4 const*, JValue*)+122>
     cpsr           0x200f0030    537854000

    【显示当前进程的所有线程】

     (gdb) info thread
       Id   Target Id         Frame 
       15   LWP 1992          epoll_wait () at bionic/libc/arch-arm/syscalls/epoll_wait.S:10
       14   LWP 2076          epoll_wait () at bionic/libc/arch-arm/syscalls/epoll_wait.S:10
       13   LWP 1815          __futex_syscall3 () at bionic/libc/arch-arm/bionic/futex_arm.S:39
       12   LWP 1814          recvmsg () at bionic/libc/arch-arm/syscalls/recvmsg.S:9
       11   LWP 1808          __futex_syscall3 () at bionic/libc/arch-arm/bionic/futex_arm.S:39
       10   LWP 1817          __futex_syscall3 () at bionic/libc/arch-arm/bionic/futex_arm.S:39
       9    LWP 1813          __rt_sigtimedwait () at bionic/libc/arch-arm/syscalls/__rt_sigtimedwait.S:10
       8    LWP 1819          __futex_syscall3 () at bionic/libc/arch-arm/bionic/futex_arm.S:39
       7    LWP 2062          __futex_syscall3 () at bionic/libc/arch-arm/bionic/futex_arm.S:39
       6    LWP 1818          __futex_syscall3 () at bionic/libc/arch-arm/bionic/futex_arm.S:39
       5    LWP 1826          __ioctl () at bionic/libc/arch-arm/syscalls/__ioctl.S:9
       4    LWP 2320          __ioctl () at bionic/libc/arch-arm/syscalls/__ioctl.S:9
       3    LWP 2210          epoll_wait () at bionic/libc/arch-arm/syscalls/epoll_wait.S:10
       2    LWP 1824          __ioctl () at bionic/libc/arch-arm/syscalls/__ioctl.S:9
     * 1    LWP 1804          epoll_wait () at bionic/libc/arch-arm/syscalls/epoll_wait.S:10

    【切换线程】

     (gdb) t 9
     [Switching to thread 9 (LWP 1813)]
     #0  __rt_sigtimedwait () at bionic/libc/arch-arm/syscalls/__rt_sigtimedwait.S:10
     10        mov     r7, ip
    
     (gdb) bt
     #0  __rt_sigtimedwait () at bionic/libc/arch-arm/syscalls/__rt_sigtimedwait.S:10
     #1  0x400b039c in sigwait (set=<optimized out>, sig=0x7194ad48) at bionic/libc/bionic/sigwait.cpp:43
     #2  0x415716ca in signalCatcherThreadStart (arg=<optimized out>) at dalvik/vm/SignalCatcher.cpp:287
     #3  0x41574176 in internalThreadStart (arg=0x747fd9d8) at dalvik/vm/Thread.cpp:1746
     ...

    【查看内存值】

     (gdb) x /32wx 0x7194ad48
     0x7194ad48:    0x00000004    0x6fbf3830    0x415dabd8    0x41573619
     0x7194ad58:    0x41700880    0x42dc0768    0x00000005    0x00000001
     0x7194ad68:    0x00000001    0x00000000    0x6fbf3830    0x747fd9d8
     0x7194ad78:    0x415dabd8    0xbe88e598    0x747fd9d8    0x41574129
     0x7194ad88:    0x7184d000    0x415db07c    0x400e92ec    0x41574177
     0x7194ad98:    0x747fd9d8    0x00010002    0x747fd9f8    0x41700880
     0x7194ada8:    0x7194add0    0x747f85a8    0x41574129    0x400aa1d4
     0x7194adb8:    0x747fd9d8    0x747f85a8    0x7194add0    0x00000001
     
     (gdb) x /20c 0xbe88eb48
     0xbe88eb48:    47 '/'    115 's'    98 'b'    105 'i'    110 'n'    58 ':'    47 '/'    118 'v'
     0xbe88eb50:    101 'e'    110 'n'    100 'd'    111 'o'    114 'r'    47 '/'    98 'b'    105 'i'
     0xbe88eb58:    110 'n'    58 ':'    47 '/'    115 's'

    【显示符号】

     (gdb) p *(Method*)0x6d682328
     $1 = {clazz = 0x41755dc0, accessFlags = 9, methodIndex = 0, registersSize = 6, outsSize = 3, insSize = 1, name = 0x6f8c1862 <Address 0x6f8c1862 out of bounds>, prototype = {dexFile = 0x6d5aac48,  protoIdx = 3750}, shorty = 
    0x6f88be67 <Address 0x6f88be67 out of bounds>, insns = 0x6f745d98, jniArgInfo = 0, nativeFunc = 0x0, fastJni = false, noRef = false, shouldTrace = false,  registerMap = 0x71a557d8, inProfile = false} 

    【若干配置】

    set print pretty on     :结构体显示的漂亮一些
    set print union          :设置显示结构体时,是否显式其内的联合体数据。
    set print vtbl             :当此选项打开时,GDB将用比较规整的格式来显示虚函数表时。其默认是关闭的。
    例如:

     (gdb)  set print pretty on
    
     (gdb) p *(Method*)0x6d682328
     $2 = {
       clazz = 0x41755dc0, 
       accessFlags = 9, 
       methodIndex = 0, 
       registersSize = 6, 
       outsSize = 3, 
       insSize = 1, 
       name = 0x6f8c1862 <Address 0x6f8c1862 out of bounds>, 
       prototype = {
         dexFile = 0x6d5aac48, 
         protoIdx = 3750
       }, 
       shorty = 0x6f88be67 <Address 0x6f88be67 out of bounds>, 
       insns = 0x6f745d98, 
       jniArgInfo = 0, 
       nativeFunc = 0x0, 
       fastJni = false, 
       noRef = false, 
       shouldTrace = false, 
       registerMap = 0x71a557d8, 
       inProfile = false
     }
    【C++中命名空间显示错误问题】
    (gdb)  p *(art::ScopedObjectAccess *) 0xbe81e618
    A syntax error in expression, near `) 0xbe81e618'.
    解决方案:用单引号''将类型名扩起来,如:
    (gdb) p *('art::ScopedObjectAccess' *) 0xbe81e618
    $19 = {
      <art::ScopedObjectAccessUnchecked> = {
        <art::ScopedObjectAccessAlreadyRunnable> = {
          self_ = 0xb4f07800,
          env_ = 0xb4f512b0,
          vm_ = 0xb4f5c280
        },
        members of art::ScopedObjectAccessUnchecked:
        tsc_ = {
          self_ = 0xb4f07800,
          thread_state_ = art::kRunnable,
          old_thread_state_ = art::kNative,
           expected_has_no_thread_ = false
        }
      }, <No data fields>}
    【如何获取类成员在类中的偏移】
    (gdb) p &(('art::ScopedObjectAccess' *)0)->tsc_.expected_has_no_thread_ 
    $26 = (const bool *) 0x18
    
    (gdb) p &(('art::ScopedObjectAccess' *)0)->env_
    $27 = (art::JNIEnvExt * const *) 0x4
    
    (gdb) p &((struct task_struct *)0)->prio
     $1 = (int *) 0x30 

    【如何获取类的大小】

     (gdb) p (('art::ScopedObjectAccess' *)0)+1
    $33 = (art::ScopedObjectAccess *) 0x1c

    【设置代码搜索路径】

    (gdb) directory ~/disk/android/
    Source directories searched: /home/disk/android:$cdir:$cwd
    (gdb) list 67 } 68 69 // Uncompress an encoded reference from its bit representation. 70 MirrorType* UnCompress() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 71 uintptr_t as_bits = kPoisonReferences ? -reference_ : reference_; 72 return reinterpret_cast<MirrorType*>(as_bits); 73 } 74 75 friend class Object; 76

    【查找内存值】

    (gdb) find /w  /20 0x41f7f0, 0x41f8f0, 0x3f800000

    0x41f7f0~0x41f8f0范围内的内存中,查询0x3f800000,步长为word,最多查找20个。

    【打印数组】

    (gdb) p je_arenas
    $0 = (arena_t **) 0x7f93f0a280
    
    (gdb) p * (arena_t **) 0x7f93f0a280@10
    $1 = {0x7f93e02200, 0x7f93f12280, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}

    编译程序时需要加上-g,之后才能用gdb进行调试:gcc -g main.c -o main

    gdb中命令:

    回车键:重复上一命令

    (gdb)help:查看命令帮助,具体命令查询在gdb中输入help + 命令,简写h

    (gdb)run:重新开始运行文件(run-text:加载文本文件,run-bin:加载二进制文件),简写r

    (gdb)start:单步执行,运行程序,停在第一执行语句

    (gdb)list:查看原代码(list-n,从第n行开始查看代码。list+ 函数名:查看具体函数),简写l

    (gdb)set:设置变量的值

    (gdb)next:单步调试(逐过程,函数直接执行),简写n

    (gdb)step:单步调试(逐语句:跳入自定义函数内部执行),简写s

    (gdb)backtrace:查看函数的调用的栈帧和层级关系,简写bt

    (gdb)frame:切换函数的栈帧,简写f

    (gdb)info:查看函数内部局部变量的数值,简写i

    (gdb)finish:结束当前函数,返回到函数调用点

    (gdb)continue:继续运行,简写c

    (gdb)print:打印值及地址,简写p

    (gdb)quit:退出gdb,简写q

    (gdb)break+num:在第num行设置断点,简写b

    (gdb)info breakpoints:查看当前设置的所有断点

    (gdb)delete breakpoints num:删除第num个断点,简写d

    (gdb)display:追踪查看具体变量值

    (gdb)undisplay:取消追踪观察变量

    (gdb)watch:被设置观察点的变量发生修改时,打印显示

    (gdb)i watch:显示观察点

    (gdb)enable breakpoints:启用断点

    (gdb)disable breakpoints:禁用断点

    (gdb)x:查看内存x/20xw 显示20个单元,16进制,4字节每单元

    (gdb)run argv[1] argv[2]:调试时命令行传参

    (gdb)set follow-fork-mode child#Makefile项目管理:选择跟踪父子进程(fork())

       core文件:先用$ ulimit -c 1024 开启core,当程序出错会自动生成core文件。调试时 gdb a.out core

    使用gdb添加断点的几种方式

    设置断点有很多方式。下面我们举例说明下常用的几种方式。

    通过行号设置断点

    格式:

    break [行号]

    break 行号,断点设置在该行开始处,注意:该行代码未被执行

    如果你的程序是用c或者c++写的,那么你可以使用“文件名:行号”的形式设置断点。示例如下:

    //test.c
    #include <stdio.h>
     
    void judge_sd(int num){
    
    	if ((num & 1) == 0){
    		printf("%d is even
    ",num);
    		return;
    	}else{
    		printf("%d is odd
    ",num);
    		return;
    	}
    }
     
    int main(int argc, char const *argv[]){
    	
    
    	judge_sd(0);
    	judge_sd(1);
    	judge_sd(4);
    
    	return 0;
    }
    
    

    编译:

    gcc -g test.c -o test
    
    • 1

    在这里插入图片描述
    gdb test
    在这里插入图片描述
    break 文件名 : 行号,适用于有多个源文件的情况。

    示例中的(gdb) b test.c:18是设置了断点。断点的位置是test.c文件的18行。使用r命令执行脚本时,当运行到18行时就会暂停。注意:该行代码未被执行

    通过函数设置断点

    格式:

    break [函数名]

    break 函数名,断点设置在该函数的开始处,断点所在行未被执行:

    同样可以将断点设置在函数处:

    b judge_sd

    在这里插入图片描述
    设置条件断点

    如果按上面的方法设置断点后,每次执行到断点位置都会暂停。有时候非常讨厌。我们只想在指定条件下才暂停。这时候根据条件设置断点就有了用武之地。设置条件断点的形式,就是在设置断点的基本形式后面增加 if条件。示例如下:

    break test.c:6 if num>0
    
    • 1

    在这里插入图片描述

    当在num>0时,程序将会在第6行断住。

    查看断点

    语法:

    info breakpoints

    可以使用info breakpoints查看断点的情况。包含都设置了那些断点,断点被命中的次数等信息。示例如下:

    在这里插入图片描述它将会列出所有已设置的断点,每一个断点都有一个标号,用来代表这个断点。

    删除断点

    语法:

    delete breakpoint

    对于无用的断点我们可以删除。删除的命令格式为 delete breakpoint 断点编号。info breakpoint命令显示结果中的num列就是编号。删除断点的示例如下:

    在这里插入图片描述
    查看源码

    断点设置完后,当程序运行到断点处就会暂停。暂停的时候,我们可以查看断点附近的代码。查看代码的子命令是list,缩写形式为l。

    在这里插入图片描述
    指定行号查看代码

    语法:

    list first,last

    例如,要列出6到21行之间的源码:
    在这里插入图片描述
    列出指定文件的源码

    前面执行l命令时,默认列出test.c的源码,如果想要看指定文件的源码呢?可以

    list 【文件名加行号或函数名】

    在这里插入图片描述
    总结

    本文介绍了GDB调试中的断点设置、源码查看。断点设置可以便于我们后期观察变量,堆栈等信息,为进一步的定位与调试做准备。源码查看可以通过指定行号或者方法名来查看相关代码。

    1. 普通断点

    根据代码行数设置断点是最常见的一种方式,在debug程序运行前就可以进行断点的配置。如:

    (gdb) b src/main.cpp:127
    

    当程序执行到main.cpp文件的第127行时就会出发断点。

    2. 条件断点

    顾名思义,这种断点是当满足一定条件时才会触发,比较适合进行异常排查。设置方式(gdb)break line-or-function if (condition), 如:

    (gdb) b src/main.cpp:127 if cnt==10
    

    3. 数据断点

    就是根据地址来进行设置断点,只能是在debug程序运行之后设置,因为只有运行后,你才能很方便地获知变量的地址。当该地址上的内容发生改变时就会触发断点。
    设置数据断点有两种方式,一种是直接指出地址值,如:

    (gdb) b *0x400522
    

    注意必须加*号。而获取地址值的方法是,先设置普通断点,在断点处print &变量名 就能获取该变量的地址。
    另一种当然就是直接设置变量名了,如:

    (gdb) b &变量名
    

    4. 函数断点

    这种断点是当程序执行到某个程序时就会触发断点。设置方式如:

    (gdb) b funcName
    

    但是函数断点并不是对所有函数都有效,比如优化后的静态函数和inline函数等,可能就无法触发断点。

    5. 监视

    设置监视也必须是在程序运行后才行。如:

    (gdb) watch *地址    # 当地址所指内容发送变化时断点
    (gdb) watch var    #当var值变化时,断点
    (gdb) watch (condition)    #当条件符合时,断点
    

    监视也被称为硬件断点。可以监测栈变量和堆变量值的变化,当被监测变量值发生变化时,程序被停住。

  • 相关阅读:
    【算法学习笔记】76.DFS 回溯检测 SJTU OJ 1229 mine
    【算法学习笔记】75. 动态规划 棋盘型 期望计算 1390 畅畅的牙签盒(改)
    【算法学习笔记】74. 枚举 状态压缩 填充方案 SJTU OJ 1391 畅畅的牙签袋(改)
    【算法学习笔记】73.数学规律题 SJTU OJ 1058 小M的机器人
    【算法学习笔记】72.LCS 最大公公子序列 动态规划 SJTU OJ 1065 小M的生物实验1
    【算法学习笔记】71.动态规划 双重条件 SJTU OJ 1124 我把助教团的平均智商拉低了
    【算法学习笔记】70.回文序列 动态规划 SJTU OJ 1066 小M家的牛们
    【算法学习笔记】69. 枚举法 字典序处理 SJTU OJ 1047 The Clocks
    【算法学习笔记】68.枚举 SJTU OJ 1272 写数游戏
    【算法学习笔记】67.状态压缩 DP SJTU OJ 1383 畅畅的牙签袋
  • 原文地址:https://www.cnblogs.com/bonelee/p/13759115.html
Copyright © 2011-2022 走看看