gdb 设置一个函数, 出现4个断点的原因

简介: 今天在vmlinux上设置断点的时候出现4个地址, 超乎认知了, 仔细得看了一下原因 ``` (gdb) b sched_clock Breakpoint 1 at 0xffffffff8101cf00: sched_clock. (4 locations) (gdb) i b Num Type Disp Enb Address What

今天在vmlinux上设置断点的时候出现4个地址, 超乎认知了, 仔细得看了一下原因

(gdb) b sched_clock
Breakpoint 1 at 0xffffffff8101cf00: sched_clock. (4 locations)
(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   <MULTIPLE>         
1.1                         y     0xffffffff8101cf00 in sched_clock at arch/x86/kernel/tsc.c:75
1.2                         y     0xffffffff8101d4fd in tsc_save_sched_clock_state at arch/x86/include/asm/paravirt.h:192
1.3                         y     0xffffffff8101d555 in tsc_restore_sched_clock_state at arch/x86/include/asm/paravirt.h:192
1.4                         y     0xffffffff810b5c30 in sched_clock at kernel/sched/clock.c:71

仔细得看了一下第一个断点, 正常

unsigned long long sched_clock(void)
{
    return paravirt_sched_clock();
}
(gdb) disassemble sched_clock
Dump of assembler code for function sched_clock:
   0xffffffff8101cf00 <+0>:     push   %rbp
   0xffffffff8101cf01 <+1>:     mov    %rsp,%rbp
-------------------------------------------------------------------------------
   0xffffffff8101cf04 <+4>:     callq  *0xffffffff81a463c0
-------------------------------------------------------------------------------
   0xffffffff8101cf0b <+11>:    pop    %rbp
   0xffffffff8101cf0c <+12>:    retq   
End of assembler dump.

看第二个使用的地方tsc_save_sched_clock_state

void tsc_save_sched_clock_state(void)
{
    if (!sched_clock_stable())
        return;

    cyc2ns_suspend = sched_clock();
}

(gdb) disassemble tsc_save_sched_clock_state 
Dump of assembler code for function tsc_save_sched_clock_state:
   0xffffffff8101d4f0 <+0>:     push   %rbp
   0xffffffff8101d4f1 <+1>:     mov    %rsp,%rbp
   0xffffffff8101d4f4 <+4>:     callq  0xffffffff810b5d30 <sched_clock_stable>
   0xffffffff8101d4f9 <+9>:     test   %eax,%eax
   0xffffffff8101d4fb <+11>:    je     0xffffffff8101d50b <tsc_save_sched_clock_state+27>
------------------------------------------------------------------------------
   0xffffffff8101d4fd <+13>:    callq  *0xffffffff81a463c0
------------------------------------------------------------------------------
   0xffffffff8101d504 <+20>:    mov    %rax,0xd1c935(%rip)        # 0xffffffff81d39e40 <cyc2ns_suspend>
   0xffffffff8101d50b <+27>:    pop    %rbp
   0xffffffff8101d50c <+28>:    retq   
End of assembler dump.

可以看到函数tsc_save_sched_clock_state在调用sched_clock的时候, 因为tsc_save_sched_clock_state和sched_clock在同一个c文件里面, 就直接把函数sched_clock的肉嵌入进来了, 没有直接调用sched_clock, 为了和c语言的逻辑保持一致, 所以这些地方都需要被打上断点

第三个tsc_restore_sched_clock_state和第二个是一样的

第4个的代码是这样的

unsigned long long __attribute__((weak)) sched_clock(void)
{
    return (unsigned long long)(jiffies - INITIAL_JIFFIES)
                    * (NSEC_PER_SEC / HZ);
}

是个弱符号, 但是从以前的知识来说, 弱符号在编译的时候会被强符号干掉, 在从o文件连接成elf文件的时候就没了, 为什么这个时候又出现了呢

readelf -s vmlinux |grep sched_clock\$
  9679: ffffffff819e8690    16 OBJECT  LOCAL  DEFAULT    8 __ksymtab_sched_clock
  9680: ffffffff819fc66a    12 OBJECT  LOCAL  DEFAULT   11 __kstrtab_sched_clock
  9681: ffffffff819f7ac0     8 OBJECT  LOCAL  DEFAULT   10 __kcrctab_sched_clock
 66460: ffffffff8101ce80   123 FUNC    GLOBAL DEFAULT    1 native_sched_clock
 67482: 000000003a26ed11     0 NOTYPE  GLOBAL DEFAULT  ABS __crc_sched_clock
 72418: ffffffff8101cf00    13 FUNC    GLOBAL DEFAULT    1 sched_clock

可以看到其实符号表里面只有一个sched_clock符号, 从地址上可以确定是gdb中的第一个符号, 那么这些信息存在哪里呢

一个有可能的猜想就是在debug section里面

把vmlinux的debug section去掉看看

$strip --strip-debug vmlinux.cp

gdb vmlinux.cp

(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0xffffffff8101cf04 <sched_clock+4>

可以只剩一个了, 所以原因是vmlinux中的debug section的信息符号了符号表的信息, 这样看起来, 在gdb vmlinux的时候, 去掉debug section的时候, 有些函数调用信息会丢失, 光依赖符号表也不准确

相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
1月前
|
NoSQL
GDB调试学习(二):断点
GDB调试学习(二):断点
47 0
|
1月前
|
NoSQL 算法 Shell
【C/C++ 调试 GDB指南 】详解 gdb 断点的设置方式
【C/C++ 调试 GDB指南 】详解 gdb 断点的设置方式
47 2
|
NoSQL Linux 网络安全
【Linux C】GCC编译 && GDB调试 从入门到放弃 (gcc调试选项详解、gdb调试、条件断点、远程调试、脚本化调试)(二)
阅读本文可能需要一些基础,比如:C语言基础、Linux基础操作、vim、防火墙等。篇幅有限,本文讲的“比较浅显”。 通过本文你将学会: gcc编译 gdb调试
|
NoSQL IDE Linux
【Linux C】GCC编译 && GDB调试 从入门到放弃 (gcc调试选项详解、gdb调试、条件断点、远程调试、脚本化调试)(一)
阅读本文可能需要一些基础,比如:C语言基础、Linux基础操作、vim、防火墙等。篇幅有限,本文讲的“比较浅显”。 通过本文你将学会: gcc编译 gdb调试
|
NoSQL
快速学会图数据库 GDB设置白名单的方法
创建GDB实例后,您需要设置GDB实例的白名单,以允许外部设备访问GDB实例。默认的白名单只包含本地IP地址127.0.0.1,表示任何其他设备都无法访问该GDB实例。
542 0
|
NoSQL Python
gdb kernel debug的进程断点
gdb调试kernel的时候, 如果设置通用函数断点, 比如vfs_read, 就会遇到一堆撞到断点的地方, 比如tty输入一个字符, 就是vfs_read, 没办法调试具体的某一个进程 一种办法就是条件断点, 其实不是很好用, 比如用pid, 但是有时候这个进程还没启动, 比如task的comm来判定, 但是kernel中是不支持strcmp来判断字符串是否相等, 因为需要跑函数 g
10921 0
|
机器学习/深度学习 NoSQL
gdb反汇编详解C函数底层实现笔记(程序堆栈、内存分配)
以下是在读《深入理解计算机系统》前面的章节“程序的机器级表示”时,自己动手在linux上使用了gdb对一个简单的C程序进行反汇编,通过不懈的努力终于查清楚弄明白了绝大多数的语句。
1085 0
|
NoSQL 程序员 iOS开发
GDB秘技--调试时执行代码中的特定函数
        在使用GDB调试程序时,有时遇到看到数据不知所云,必须对照定义才能看懂, 有时还要做些运算才能看出来,这样效率显然不高. 如果需要查看一个变量类的当前值,简单的数据类型还好说,如果遇到一些枚举型的变量或特殊条件,想要看到清晰的数据输出,就会比较繁琐.
1168 0