[OS64][027]源码调试:程序4-11 调试过程 objdump bochs: info cpu、print-stack、sreg、breakpoint

[OS64][025]源码阅读:程序4-11:运行结果,数据结构,第一个进程init_task_union

https://www.jianshu.com/p/b30fb97a1dc4

[OS64][026]源码阅读:程序4-11 程序执行过程示意图

https://www.jianshu.com/p/9bcc6d573978

程序4-11 调试过程

  • 反汇编源码 objdump -D system
[anno@localhost kernel]$ objdump -D system > system.txt
  • 使用标号名/函数名快速锁定汇编源码,将其与C源码进行对应,从system.txt文件读取线性地址,将其转换成物理地址,就可以在bochs虚拟机里设置断点b 物理地址进行调试
    switch_to.PNG

一、在什么时候寄存器RSP的值被设置成了第一个进程的栈基地址

  • 第一个进程的栈空间,本质来源于全局变量联合体init_task_union其中的数组字段,这个全局变量位于整个内核的.data.init_task段内
  • 这里可以看到标号_stack_start处就是 就是数值 第一个进程栈空间栈基地址处
ENTRY(_stack_start)
    .quad   init_task_union + 32768
  • 在源码文件 head.S可以看到代码的布局,其中movq _stack_start(%rip), %rsp设置寄存器的RSP值成了第一个进程的栈空间的基地址
#include "linkage.h"

.section .text
ENTRY(_start)
. . .
    mov $0x7E00,    %esp

//=======   load GDTR
//=======   load    IDTR
//=======   load    cr3
//=======   64-bit mode code

switch_seg:
    .quad   entry64

entry64:
. . .
    movq    _stack_start(%rip), %rsp        
    /* rsp address */

setup_IDT:                          
. . .

rp_sidt:
. . .

setup_TSS64:
. . .

go_to_kernel:
    .quad   Start_Kernel

  • 在反汇编文件里可以查出语句所在的线性地址0xffff800000100065
ffff800000100052 :

ffff800000100065:   48 8b 25 49 01 00 00    mov    0x149(%rip),%rsp        # ffff8000001001b5 <_stack_start>
  • 设置断点 ,查看运行前后的RSP,发现从0x7E00变成了0x120000
 b 0x100065
 c
(0) Breakpoint 3, 0xffff800000100065 in ?? ()
Next at t=59413777
(0) [0x000000100065] 0008:ffff800000100065 
(unk. ctxt): mov rsp, qword ptr ds:[rip+329] ; 488b2549010000

 info cpu
CPU0:
rsp: 00000000_00007e00

 s

 info cpu
CPU0:
rsp: ffff8000_00120000

二、何时才将寄存器RSP的值设置成第二个进程的栈基地址

  • 刚进入switch_to(宏)的时候,寄存器RSP的值是rsp: ffff8000_0011ff58
 info cpu
CPU0:
rax: ffff8000_00118000 rcx: 00000000_00000000
rdx: ffff8000_00200000 rbx: ffff8000_0010d700
rsp: ffff8000_0011ff58 rbp: ffff8000_0011ffa8
rsi: ffff8000_00200000 rdi: ffff8000_00118000
r8 : 00000000_00ffffff r9 : 00000000_00000000
r10: ffff8000_00007c00 r11: ffff8000_00007c00
r12: ffff8000_00200058 r13: ffff8000_00200058
r14: ffff8000_0010d700 r15: 00000000_00000000
rip: ffff8000_0010b5b2

  • 执行完 movq %2, %%rsp之后,寄存器的RSP存入第二个进程的RSP0,成为rsp: ffff8000_00207f40
 s
Next at t=62987240
(0) [0x00000010b5b8] 0008:ffff80000010b5b8 
(unk. ctxt): mov rsp, qword ptr ds:[r12+16] ; 498b642410

 s
Next at t=62987241
(0) [0x00000010b5bd] 0008:ffff80000010b5bd 
(unk. ctxt): lea rax, qword ptr ds:[rip+13] ; 488d050d000000

 info cpu
CPU0:
rax: ffff8000_00118000 rcx: 00000000_00000000
rdx: ffff8000_00200000 rbx: ffff8000_0010d700
rsp: ffff8000_00207f40 rbp: ffff8000_0011ffa8
rsi: ffff8000_00200000 rdi: ffff8000_00118000
r8 : 00000000_00ffffff r9 : 00000000_00000000
r10: ffff8000_00007c00 r11: ffff8000_00007c00
r12: ffff8000_00200058 r13: ffff8000_00200058
r14: ffff8000_0010d700 r15: 00000000_00000000
rip: ffff8000_0010b5bd

  • 执行完pushq %3
 s
Next at t=62987243
(0) [0x00000010b5c8] 0008:ffff80000010b5c8 
(unk. ctxt): push qword ptr ds:[r13+8] ; 41ff7508

 info cpu
CPU0:
rax: ffff8000_0010b5d1 rcx: 00000000_00000000
rdx: ffff8000_00200000 rbx: ffff8000_0010d700
rsp: ffff8000_00207f40 rbp: ffff8000_0011ffa8
rsi: ffff8000_00200000 rdi: ffff8000_00118000
r8 : 00000000_00ffffff r9 : 00000000_00000000
r10: ffff8000_00007c00 r11: ffff8000_00007c00
r12: ffff8000_00200058 r13: ffff8000_00200058
r14: ffff8000_0010d700 r15: 00000000_00000000
rip: ffff8000_0010b5c8


 s
Next at t=62987244
(0) [0x00000010b5cc] 0008:ffff80000010b5cc (unk. ctxt): jmp .-1138 (0xffff80000010b15f) ; e98efbffff

 info cpu
CPU0:
rax: ffff8000_0010b5d1 rcx: 00000000_00000000
rdx: ffff8000_00200000 rbx: ffff8000_0010d700
rsp: ffff8000_00207f38 rbp: ffff8000_0011ffa8
rsi: ffff8000_00200000 rdi: ffff8000_00118000
r8 : 00000000_00ffffff r9 : 00000000_00000000
r10: ffff8000_00007c00 r11: ffff8000_00007c00
r12: ffff8000_00200058 r13: ffff8000_00200058
r14: ffff8000_0010d700 r15: 00000000_00000000
rip: ffff8000_0010b5cc

  • 查看当前的栈内容,栈顶[0xffff8000:0x0010b06b]
 print-stack
Stack address size 8
 | STACK 0xffff800000207f38 [0xffff8000:0x0010b06b]
 | STACK 0xffff800000207f40 [0x00000000:0x00000000]
 | STACK 0xffff800000207f48 [0x00000000:0x00000000]
 | STACK 0xffff800000207f50 [0x00000000:0x00000000]
. . . 
  • [0xffff8000:0x0010b06b]kernel_thread_func的入口地址,这就是为什么函数__switch_to执行完后会跳转到kernel_thread_func执行的原因
ffff80000010b06b :
ffff80000010b06b:   41 5f                   pop    %r15
ffff80000010b06d:   41 5e                   pop    %r14
. . .
  • 直接设置断点到函数__switch_toretq处,可见当前处于内核代码段cs:0x0008 Code segment,而retq指令可以视为等价于IP=0x0010b06b(kernel_thread_func)
 b 0x10b2ed
 c

(0) Breakpoint 3, 0xffff80000010b2ed in ?? ()
Next at t=63156040
(0) [0x00000010b2ed] 0008:ffff80000010b2ed (unk. ctxt): ret                       ; c3

 sreg
cs:0x0008, dh=0x00209900, dl=0x00000000, valid=1
    Code segment, base=0x00000000, limit=0x00000000, Execute-Only, Non-Conforming, Accessed, 64-bit
ss:0x0010, dh=0x00009300, dl=0x00000000, valid=1
    Data segment, base=0x00000000, limit=0x00000000, Read/Write, Accessed

  • 接着进行单步执行,就进入了函数10b06b ,当前rip的数值就可以验证这一点
 s
Next at t=63156041
(0) [0x00000010b06b] 0008:ffff80000010b06b 
(unk. ctxt): pop r15                   ; 415f

 info cpu
CPU0:
rsp: ffff8000_00207f40 
rip: ffff8000_0010b06b

你可能感兴趣的:([OS64][027]源码调试:程序4-11 调试过程 objdump bochs: info cpu、print-stack、sreg、breakpoint)