[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 调试过程
[anno@localhost kernel]$ objdump -D system > system.txt
- 使用标号名/函数名快速锁定汇编源码,将其与C源码进行对应,从system.txt文件读取线性地址,将其转换成物理地址,就可以在bochs虚拟机里设置断点
b 物理地址
进行调试
一、在什么时候寄存器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 <entry64>:
ffff800000100065: 48 8b 25 49 01 00 00 mov 0x149(%rip),%rsp # ffff8000001001b5 <_stack_start>
- 设置断点 ,查看运行前后的
RSP
,发现从0x7E00
变成了0x120000
<bochs:8> b 0x100065
<bochs:9> c
(0) Breakpoint 3, 0xffff800000100065 in ?? ()
Next at t=59413777
(0) [0x000000100065] 0008:ffff800000100065
(unk. ctxt): mov rsp, qword ptr ds:[rip+329] ; 488b2549010000
<bochs:10> info cpu
CPU0:
rsp: 00000000_00007e00
<bochs:11> s
<bochs:12> info cpu
CPU0:
rsp: ffff8000_00120000
二、何时才将寄存器RSP的值设置成第二个进程的栈基地址
- 刚进入
switch_to(宏)
的时候,寄存器RSP
的值是rsp: ffff8000_0011ff58
<bochs:7> 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
<bochs:10> s
Next at t=62987240
(0) [0x00000010b5b8] 0008:ffff80000010b5b8
(unk. ctxt): mov rsp, qword ptr ds:[r12+16] ; 498b642410
<bochs:11> s
Next at t=62987241
(0) [0x00000010b5bd] 0008:ffff80000010b5bd
(unk. ctxt): lea rax, qword ptr ds:[rip+13] ; 488d050d000000
<bochs:12> 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
<bochs:14> s
Next at t=62987243
(0) [0x00000010b5c8] 0008:ffff80000010b5c8
(unk. ctxt): push qword ptr ds:[r13+8] ; 41ff7508
<bochs:15> 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
<bochs:16> s
Next at t=62987244
(0) [0x00000010b5cc] 0008:ffff80000010b5cc (unk. ctxt): jmp .-1138 (0xffff80000010b15f) ; e98efbffff
<bochs:17> 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]
<bochs:18> 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 <kernel_thread_func>:
ffff80000010b06b: 41 5f pop %r15
ffff80000010b06d: 41 5e pop %r14
. . .
- 直接设置断点到函数
__switch_to
的retq
处,可见当前处于内核代码段cs:0x0008 Code segment
,而retq指令可以视为等价于IP=0x0010b06b(kernel_thread_func)
<bochs:19> b 0x10b2ed
<bochs:20> c
(0) Breakpoint 3, 0xffff80000010b2ed in ?? ()
Next at t=63156040
(0) [0x00000010b2ed] 0008:ffff80000010b2ed (unk. ctxt): ret ; c3
<bochs:22> 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 <kernel_thread_func>
,当前rip
的数值就可以验证这一点
<bochs:23> s
Next at t=63156041
(0) [0x00000010b06b] 0008:ffff80000010b06b
(unk. ctxt): pop r15 ; 415f
<bochs:24> info cpu
CPU0:
rsp: ffff8000_00207f40
rip: ffff8000_0010b06b