本文共 6628 字,大约阅读时间需要 22 分钟。
很多文章写调试qemu都是从start_kernel开始的,那么start_kernel之前的函数如何调试呢。尤其是 startup_64
即使打上了断点也无法跟踪。 原因是 startup_64 在 vmlinux 里面对应的是链接地址。7262499 ffffffff81000000 <_text>:7262500 ffffffff81000000: 48 8d 2d f9 ff ff ff lea -0x7(%rip),%rbp # ffffffff81000000 <_text>
而实际上 startup_64 执行的时候, 页表还没有建立, 使用的虚拟地址跟物理地址是1:1对应的, 也就是其执行的时候, 虚拟地址和物理地址是相等的。
那么怎么找到其开始运行的时候的物理地址呢?rlk@ubuntu:runninglinuxkernel_4.0_x86$ cat .config | grep CONFIG_RELOCATABLECONFIG_RELOCATABLE=yrlk@ubuntu:runninglinuxkernel_4.0_x86$ cat .config | grep CONFIG_PHYSICAL_STARTCONFIG_PHYSICAL_START=0x1000000rlk@ubuntu:runninglinuxkernel_4.0_x86$ rlk@ubuntu:kernel$ vi vmlinux.ldsSECTIONS{ . = (0xffffffff80000000 + ALIGN(0x1000000, 0x200000)); phys_startup_64 = startup_64 - 0xffffffff80000000;}
调试代码对应的汇编语言如下
7262497 Disassembly of section .text: 7262498 7262499 ffffffff81000000 <_text>: 7262500 ffffffff81000000: 48 8d 2d f9 ff ff ff lea -0x7(%rip),%rbp # ffffffff81000000 <_text> 7262501 ffffffff81000007: 48 81 ed 00 00 00 01 sub $0x1000000,%rbp 7262502 ffffffff8100000e: 48 89 e8 mov %rbp,%rax 7262503 ffffffff81000011: 25 ff ff 1f 00 and $0x1fffff,%eax 7262504 ffffffff81000016: 85 c0 test %eax,%eax 7262505 ffffffff81000018: 0f 85 a7 01 00 00 jne ffffffff810001c57262506 ffffffff8100001e: 48 8d 05 db ff ff ff lea -0x25(%rip),%rax # ffffffff81000000 <_text> 7262507 ffffffff81000025: 48 c1 e8 2e shr $0x2e,%rax 7262508 ffffffff81000029: 0f 85 96 01 00 00 jne ffffffff810001c5 7262509 ffffffff8100002f: 48 01 2d c2 7f f4 00 add %rbp,0xf47fc2(%rip) # ffffffff81f47ff8 7262510 ffffffff81000036: 48 01 2d b3 ff e0 00 add %rbp,0xe0ffb3(%rip) # ffffffff81e0fff0 7262511 ffffffff8100003d: 48 01 2d b4 ff e0 00 add %rbp,0xe0ffb4(%rip) # ffffffff81e0fff8 7262512 ffffffff81000044: 48 01 2d 85 1f e1 00 add %rbp,0xe11f85(%rip) # ffffffff81e11fd0 7262513 ffffffff8100004b: 48 8d 3d ae ff ff ff lea -0x52(%rip),%rdi # ffffffff81000000 <_text>
所以打断点要基于物理地址打断点:
(gdb) target remote localhost:1234Remote debugging using localhost:12340x000000000000fff0 in scsi_format_log ()(gdb) b *0x1000000 // 其中, 0x1000000 是 startup_64 运行时的虚拟地址。给地址打断点, 前面需要加上 *Breakpoint 1 at 0x1000000(gdb) cContinuing.Breakpoint 1, 0x0000000001000000 in ?? ()(gdb) info reg // 打印寄存器rax 0x1000000 16777216rbx 0x1f19000 32608256rcx 0x780 1920rdx 0x3d5 981rsi 0x140a0 82080rdi 0x3d5 981rbp 0x1000000 0x1000000rsp 0x23fa540 0x23fa540r8 0x4e1580 5117312r9 0x14d9000 21860352r10 0xd 13r11 0xa 10r12 0x0 0r13 0x0 0r14 0x0 0r15 0x0 0rip 0x1000000 0x1000000eflags 0x2 [ IOPL=0 ]cs 0x10 16ss 0x0 0ds 0x0 0es 0x0 0fs 0x0 0gs 0x0 0fs_base 0x0 0gs_base 0x0 0k_gs_base 0x0 0cr0 0x80000011 [ PG ET PE ]cr2 0x0 0cr3 0x23fb000 [ PDBR=1 PCID=0 ]cr4 0x20 [ PAE ]cr8 0x0 0efer 0x500 [ LMA LME ]mxcsr 0x1f80 [ IM DM ZM OM UM PM ](gdb) n Cannot find bounds of current function(gdb) sCannot find bounds of current function(gdb) b *0x1000007Breakpoint 2 at 0x1000007(gdb) cContinuing.Breakpoint 2, 0x0000000001000007 in ?? ()(gdb) info regrax 0x1000000 16777216rbx 0x1f19000 32608256rcx 0x780 1920rdx 0x3d5 981rsi 0x140a0 82080rdi 0x3d5 981rbp 0x1000000 0x1000000rsp 0x23fa540 0x23fa540r8 0x4e1580 5117312r9 0x14d9000 21860352r10 0xd 13r11 0xa 10r12 0x0 0r13 0x0 0r14 0x0 0r15 0x0 0rip 0x1000007 0x1000007eflags 0x2 [ IOPL=0 ]cs 0x10 16ss 0x0 0ds 0x0 0es 0x0 0fs 0x0 0gs 0x0 0fs_base 0x0 0gs_base 0x0 0k_gs_base 0x0 0(gdb) b *0x100001eBreakpoint 3 at 0x100001e(gdb) cContinuing.Breakpoint 3, 0x000000000100001e in ?? ()(gdb) info regrax 0x0 0 // 这条语句讲rax清零 ffffffff81000011: 25 ff ff 1f 00 and $0x1fffff,%eaxrbx 0x1f19000 32608256rcx 0x780 1920rdx 0x3d5 981rsi 0x140a0 82080rdi 0x3d5 981rbp 0x0 0x0rsp 0x23fa540 0x23fa540r8 0x4e1580 5117312r9 0x14d9000 21860352r10 0xd 13r11 0xa 10r12 0x0 0r13 0x0 0r14 0x0 0r15 0x0 0rip 0x100001e 0x100001eeflags 0x46 [ IOPL=0 ZF PF ]cs 0x10 16ss 0x0 0ds 0x0 0es 0x0 0fs 0x0 0gs 0x0 0fs_base 0x0 0gs_base 0x0 0k_gs_base 0x0 0cr0 0x80000011 [ PG ET PE ]cr2 0x0 0cr3 0x23fb000 [ PDBR=1 PCID=0 ]cr4 0x20 [ PAE ]cr8 0x0 0efer 0x500 [ LMA LME ](gdb) b *0x1000025Breakpoint 4 at 0x1000025(gdb) c Continuing.Breakpoint 4, 0x0000000001000025 in ?? ()(gdb) info regrax 0x1000000 16777216 // ffffffff8100001e: 48 8d 05 db ff ff ff lea -0x25(%rip),%rax # ffffffff81000000 <_text>rbx 0x1f19000 32608256rcx 0x780 1920rdx 0x3d5 981rsi 0x140a0 82080rdi 0x3d5 981rbp 0x0 0x0 rsp 0x23fa540 0x23fa540r8 0x4e1580 5117312r9 0x14d9000 21860352r10 0xd 13r11 0xa 10r12 0x0 0r13 0x0 0r14 0x0 0r15 0x0 0rip 0x1000025 0x1000025eflags 0x46 [ IOPL=0 ZF PF ]
转载地址:http://zdlji.baihongyu.com/