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
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的時候, 有些函數調用信息會丟失, 光依賴符號表也不準確
最後更新:2017-05-20 09:31:18