fix a bug, should be: Virtual Address=Physical Address+0xC0000000

This commit is contained in:
chyyuu 2014-10-25 20:15:34 +08:00
parent 5346cc9003
commit 89d28c7ba1
13 changed files with 24 additions and 24 deletions

View File

@ -58,7 +58,7 @@
输出日志到 qemu.log 文件。
其他参数说明可以参考http://bellard.org/qemu/qemu-doc.html#SEC15 。其他qemu的安装和使用的说明可以参考http://bellard.org/qemu/user-doc.html。
或者在命令行收入 qemu (没有参数) 显示帮助。
在实验中,例如 lab1可能用到的命令如
@ -68,4 +68,4 @@
qemu -S -s -hda ucore.img -monitor stdio # 用于与gdb配合进行源码调试

View File

@ -31,13 +31,13 @@ qemu中monitor的常用命令
0x000fe05b: xor %ax, %ax
step命令为单步命令即qemu执行一步能够跳过 breakpoint 断点执行。如果此时使用cont命令则qemu 运行改为连续执行。
log命令能够保存qemu模拟过程产生的信息与qemu运行参数 `-d' 相同),具体参数可以参考命令帮助。产生的日志信息保存在 “/tmp/qemu.log” 中,例如使用 'log in_asm'命令以后运行过程产生的的qemu.log 文件为:
1 ----------------
2 IN:
3 0xfffffff0: ljmp $0xf000,$0xe05b
4
4
5 ----------------
6 IN:
7 0x000fe05b: xor %ax,%ax

View File

@ -12,4 +12,4 @@
使用 diff 命令对修改后的 ucore 代码和 ucore 源码进行比较,比较之前建议使用 make clean 命令清除不必要文件。(如果有ctags 文件,需要手工清除。)
(3)应用修改:参见 patch 命令说明。

View File

@ -10,7 +10,7 @@
(gdb) file obj/kernel/kernel.elf
之后gdb就会载入这个文件中的符号信息了。
通过gdb可以对ucore代码进行调试以lab1中调试memset函数为例
(1) 运行 qemu -S -s -hda ucore.img -monitor stdio

View File

@ -7,11 +7,11 @@
target remote 127.0.0.1:1234
file obj/kernel/kernel.elf
为了让gdb在启动时执行这些命令使用下面的命令启动gdb
$ gdb -x gdbinit
如果觉得这个命令太长,可以将这个命令存入一个文件中,当作脚本来执行。
另外,如果直接使用上面的命令,那么得到的界面是一个纯命令行的界面,不够直观,就像下图这样:
@ -21,4 +21,4 @@
如果想获得上面右图那样的效果,只需要再加上参数-tui就行了比如
gdb -tui -x gdbinit

View File

@ -10,10 +10,10 @@
下面我们要求gdb将linker加载到0x6fee6180这个地址上
(gdb) add-symbol-file android_test/system/bin/linker 0x6fee6180
这样的命令默认是将代码段(.data)段的调试信息加载到0x6fee6180上当然你也可以通过“-s”这个参数来指定比如
(gdb) add-symbol-file android_test/system/bin/linker s .text 0x6fee6180
这样在执行到linker中代码时gdb就能够显示出正确的代码和调试信息出来。
这个方法在操作系统中调试动态链接器时特别有用。

View File

@ -6,4 +6,4 @@
(gdb) set arch i8086
这个方法在调试不同架构或者说不同模式的代码时还是有点用处的。

View File

@ -1,2 +1,2 @@
#### 2.4.4 结合gdb和qemu源码级调试ucore
#### 2.4.4 结合gdb和qemu源码级调试ucore

View File

@ -1,11 +1,11 @@
#### 3.2.4 ELF文件格式概述
ELF(Executable and linking format)文件格式是Linux系统下的一种常用目标文件(object file)格式,有三种主要类型:
ELF(Executable and linking format)文件格式是Linux系统下的一种常用目标文件(object file)格式,有三种主要类型:
- 用于执行的可执行文件(executable file),用于提供程序的进程映像,加载的内存执行。 这也是本实验的OS文件类型。
- 用于连接的可重定位文件(relocatable file),可与其它目标文件一起创建可执行文件和共享目标文件。
- 共享目标文件(shared object file),连接器可将它与其它可重定位文件和共享目标文件连接成其它的目标文件,动态连接器又可将它与可执行文件和其它共享目标文件结合起来创建一个进程映像。
- 用于连接的可重定位文件(relocatable file),可与其它目标文件一起创建可执行文件和共享目标文件。
- 共享目标文件(shared object file),连接器可将它与其它可重定位文件和共享目标文件连接成其它的目标文件,动态连接器又可将它与可执行文件和其它共享目标文件结合起来创建一个进程映像。
这里只分析与本实验相关的ELF可执行文件类型。ELF header在文件开始处描述了整个文件的组织。ELF的文件头包含整个执行文件的控制结构其定义在elf.h中
@ -36,8 +36,8 @@ struct proghdr {
uint type; // 段类型
uint offset; // 段相对文件头的偏移值
uint va; // 段的第一个字节将被放到内存中的虚拟地址
uint pa;
uint filesz;
uint pa;
uint filesz;
uint memsz; // 段在内存映像中占用的字节数
uint flags;
uint align;

View File

@ -4,8 +4,8 @@
栈是一个很重要的编程概念编译课和程序设计课都讲过相关内容与编译器和编程语言有紧密的联系。理解调用栈最重要的两点是栈的结构EBP寄存器的作用。一个函数调用动作可分解为零到多个PUSH指令用于参数入栈一个CALL指令。CALL指令内部其实还暗含了一个将返回地址即CALL指令下一条指令的地址压栈的动作由硬件完成。几乎所有本地编译器都会在每个函数体之前插入类似如下的汇编指令
```
pushl %ebp
movl %esp , %ebp
pushl %ebp
movl %esp , %ebp
```
这样在程序执行到一个函数的实际指令前已经有以下数据顺序入栈参数、返回地址、ebp寄存器。由此得到类似如下的栈结构参数入栈顺序跟调用方式有关这里以C语言默认的CDECL为例

View File

@ -18,7 +18,7 @@ IDT和IDTR寄存器的结构和关系如下图所示
![IDT和IDTR寄存器的结构和关系图](../lab1_figs/image007.png "IDT和IDTR寄存器的结构和关系图")
图8 IDT和IDTR寄存器的结构和关系图
在保护模式下最多会存在256个Interrupt/Exception Vectors。范围[031]内的32个向量被异常Exception和NMI使用但当前并非所有这32个向量都已经被使用有几个当前没有被使用的请不要擅自使用它们它们被保留以备将来可能增加新的Exception。范围[32255]内的向量被保留给用户定义的Interrupts。Intel没有定义也没有保留这些Interrupts。用户可以将它们用作外部I/O设备中断8259A IRQ或者系统调用System Call 、Software Interrupts等。
在保护模式下最多会存在256个Interrupt/Exception Vectors。范围[031]内的32个向量被异常Exception和NMI使用但当前并非所有这32个向量都已经被使用有几个当前没有被使用的请不要擅自使用它们它们被保留以备将来可能增加新的Exception。范围[32255]内的向量被保留给用户定义的Interrupts。Intel没有定义也没有保留这些Interrupts。用户可以将它们用作外部I/O设备中断8259A IRQ或者系统调用System Call 、Software Interrupts等。
(2) IDT gate descriptors
@ -51,7 +51,7 @@ Interrupts/Exceptions应该使用Interrupt Gate和Trap Gate它们之间的唯
- 如果存在特权级转换从内核态转换到用户态则还需要从内核栈中弹出用户态栈的ss和esp这样也意味着栈也被切换回原先使用的用户态的栈了
- 如果此次处理的是带有错误码errorCode的异常CPU在恢复先前程序的现场时并不会弹出errorCode。这一步需要通过软件完成即要求相关的中断服务例程在调用iret返回之前添加出栈代码主动弹出errorCode。
下图显示了从中断向量到GDT中相应中断服务程序起始位置的定位方式:
下图显示了从中断向量到GDT中相应中断服务程序起始位置的定位方式:
![中断向量与中断服务例程起始地址的关系](../lab1_figs/image009.png "中断向量与中断服务例程起始地址的关系")
图10 中断向量与中断服务例程起始地址的关系

View File

@ -3,7 +3,7 @@
当bootloader通过读取硬盘扇区把ucore在系统加载到内存后就转跳到ucore操作系统在内存中的入口位置kern/init.c中的kern_init函数的起始地址这样ucore就接管了整个控制权。当前的ucore功能很简单只完成基本的内存管理和外设中断管理。ucore主要完成的工作包括
- 初始化终端;
- 初始化终端;
- 显示字符串;
- 显示堆栈中的多层函数调用关系;
- 切换到保护模式,启用分段机制;

View File

@ -41,7 +41,7 @@ Virtual Address= Linear Address
改为
Virtual Address=Linear Address-0xC0000000
Virtual Address=Linear Address + 0xC0000000
由于gcc编译出的虚拟起始地址从0xC0100000开始ucore被bootloader放置在从物理地址0x100000处开始的物理内存中。所以当kern\_entry函数完成新的段映射关系后且ucore在没有建立好页映射机制前CPU按照ucore中的虚拟地址执行能够被分段机制映射到正确的物理地址上确保ucore运行正确。