• GDB调试技巧汇总


    利用gdb追踪性能瓶颈

    Linux上可以使用perf快速定位耗时的函数,其实gdb利用采样也能做到:程序运行一阵子,我CTRL+C一次获得此时的调用栈,次数多了最耗时的函数自然就暴露出来了。下面是bash脚本,需要运行一阵子后自己统计次数最多的函数。
    
    • 1
    #!/bin/bash
    
    if test $# -ne 1; then
        echo "Usage: `basename $0 .sh` " 1>&2
        exit 1
    fi
    
    if test ! -r /proc/$1; then
        echo "Process $1 not found." 1>&2
        exit 1
    fi
    
    PROCESS_LINE=`ps -p $1|wc -l`
    while [ "$PROCESS_LINE" == "2" ]; do
            PROCESS_PS=`ps -p $1|wc -l`
            if [ "$PROCESS_LINE" != "2" ]
            then
                    break
            fi
    
            gdb -p $1  \
            -ex "set pagination off" \
            -ex "set logging on" \
            -ex "where" \
            -ex "detach" \
            -ex "quit"| grep '^#0'
    
            sleep 5;
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    为release程序添加符号定义

    有时拿到客户core dump,如果通过自己算结构的偏移去找某个字段的值很麻烦,有没有办法引入这些符号的定义哪?还真有,下面是个例子
    
    • 1
    // sample.c
    #include "sample.h"
    struct sample foo; //把所有有用的struct都放进来!
    gcc -g -c sample.c
    (gdb) add-symbol-file sample.o 0
    add symbol table from file "sample.o" at    .text_addr = 0x0
    (gdb) p (struct sample *)0x7fffffffd6b0
    $1 = (struct sample *) 0x7fffffffd6b0
    (gdb) p *$1
    $2 = {i = 42, less = 0x7fffffffd6b0, more = 0x7fffffffd6b0}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    连续打印链表

    In GDB, the value of $ is the value returned from the previous command.
    (gdb) p mgmt_thread_data.next_thread
    $67 = (struct k_thread *) 0x2000188c 
    (gdb) p $.next_thread
    $68 = (struct k_thread *) 0x200022ac 
    (gdb) 
    $69 = (struct k_thread *) 0x2000a120 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    显示内存布局

    (gdb)info proc mappings   
    有一个shell command功能与之类似:pmap -d pid
    
    • 1
    • 2

    显示当前调试文件的路径

    (gdb)info source
    
    • 1

    可视化调试

    CTRL+x and a
    winheight src+N  调整src窗口大小
    
    • 1
    • 2

    在GDB中执行shell命令

    (gdb)shell [shell-command]
      eg. (gdb) shell ls
    
    • 1
    • 2

    像shell管道一样连接不同的命令

    直接管道连接gdb命令和shell命令并不支持,如下会报错:
    (gdb) where|grep libc
    A syntax error in expression, near `|grep libc'.
    (gdb) pipe where|grep libc
    Undefined command: "pipe".  Try "help".
    办法是基于gdb对Python的接口写一个Python脚本:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    from __future__ import print_function
    
    import gdb
    import string
    import subprocess
    import sys
    
    #please refer to doc https://sourceware.org/gdb/onlinedocs/gdb/Python-API.html#Python-API
    class ShellPipe (gdb.Command):
        "Command to pipe gdb internal command output to external commands."
    
        def __init__(self):
            super (ShellPipe, self).__init__("shell-pipe",
                    gdb.COMMAND_DATA,
                    gdb.COMPLETE_NONE, True)
            gdb.execute("alias -a sp = shell-pipe", True)
    
        def invoke(self, arg, from_tty):
            arg = arg.strip()
            if arg == "":
                print("Argument required (gdb_command_and_args | externalcommand..).")
                return
    
            gdb_command, shell_commands = None, None
    
            if '|' in arg:
                gdb_command, shell_commands = arg.split("|")  #, maxsplit=1)
                gdb_command, shell_commands = gdb_command.strip(), shell_commands.strip()
            else:
                gdb_command = arg
    
            # Collect the output and feed it through the pipe
            output = gdb.execute(gdb_command, True, True)
            if shell_commands:
                shell_process = subprocess.Popen(shell_commands, stdin=subprocess.PIPE, shell=True)
                shell_process.communicate(output.encode('utf-8'))
            else:
                sys.stdout.write(output)
    
    ShellPipe()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    使用举例:
    (gdb) source 上面的文件
    (gdb) shell-pipe where|grep libc
    #0  0x00007f30626175f3 in __msgrcv_nocancel () from /usr/lib64/libc.so.6
    
    • 1
    • 2
    • 3
    • 4

    打印数组中连续的多个项

    (gdb) 数组@个数
    比如:arr@5
    
    • 1
    • 2

    查找内存

    (gdb) p /x "HELLO"
    $5 = {0x48, 0x45, 0x4c, 0x4c, 0x4f, 0x0}
    (gdb) find /b start_addr, end_addr, 0x48, 0x45, 0x4c, 0x4c, 0x4f   查找"HELLO"
    (gdb)  find /w 0x1be4d80a, +10, 842121264      在[0x1be4d80a,0x1be4d80a+10)中查找int 842121264
    
    • 1
    • 2
    • 3
    • 4

    回退执行

    需求:回到刚刚运行的代码再执行一遍
    This is yet another use case for Reverse Debugging.
    1. You should start process record and replay at some point:
    (gdb) record
    2. When you want to see last executed lines you can go backwards like this:
    (gdb) reverse-step 3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    反汇编

    (gdb) disass 函数
    (gdb) layout asm
    
    • 1
    • 2

    列出信号处理函数

    有时想知道当前怎么处理信号的,又不想从代码里找,有个gdb脚本可以用
    http://palves.net/list-active-signal-handlers-with-gdb/
    (gdb) info signal-dispositions 2 5
    Number  Name       Description               Disposition
    2       SIGINT     Interrupt                 rl_signal_handler in section .text of build/gdb/gdb
    5       SIGTRAP    Trace/breakpoint trap     SIG_DFL
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    gdb中定义宏

    (gdb) macro define offsetof(t, f) &((t *) 0)->f
    
    • 1
  • 相关阅读:
    6.9平衡二叉树(LC110-E)
    linux权限管理之SetUID&SetGID
    盘点国产ChatGPT十大模型
    JavaWeb基础第二章(Maven项目与MyBatis 的快速入门与配置)
    易观之星 | “2022年度用户推荐数字应用”投票通道开启
    清洗文本高频词、情感分析、情感分类、主题建模挖掘主题
    简单介绍下主数据管理(MDM)工具的发展趋势
    电巢:继腾讯与联通混改后,又有两家企业官宣,科技巨头与国企混改,意味着什么?
    sql优化实操
    税收学专业论文应该怎样选择题目能更好的完成毕业论文?
  • 原文地址:https://blog.csdn.net/zhaiminlove/article/details/125991417