极端搞笑的调试方式

调试kernel是一件很费劲的事情。
我找到了三种方法:
1、用hlt指令。
loop: hlt
jmp loop
一但执行到这样的代码,vmware就会告诉说CPU已经被挂起。(真实环境中现象就 是死机)
通过这样的方式一点点的找到出错的代码
2、用0xB8000这块内存
0xB8000是BIOS保留的,指向屏幕。反正往这里写什么字符进去,屏幕上就能显示 什么。
于是我在我的代码中就插了很多这样的莫名其妙的代码 (VIDEO=0xB8000)
movb TMPL__XXXX_BODY_XXXX#39;c',VIDEO
movb $7,VIDEO+1
3、用gdb
只需要在vmx文件中加这么两行:
debugStub.listen.guest64 = "TRUE"
debugStub.listen.guest64.remote = "TRUE"
在vmware里运行的东西都可以拿gdb去调试。不过呢,要区分是32位还是64位的。 比如我在这里说我的guest os是64位的,但是当它真正进入64位模式之前,我用 gdb是连不上的。操作系统启动的时候,是从16位-〉32位—〉64位这样一步步走来 的。我希望在它开始执行64位代码的地方加个断点。于是我就放了个int 3在那 里。可是不管用。可能是因为之前我已经禁用中断了,idt还没设置,所以还不能 启用中断。一遇到int3,机器立马重启了。
于是我想,在main函数的开始执行个sleep(100000)也好啊。可是我压根不知道怎 么初始化rtc,更不要说实现这么复杂的函数了。
然后,我想了个很搞笑的下断点的方式。

void kmain(uint64_t magic,struct grub_multiboot_info* info) 
{ 
for(int i=0;i<10000000 ;++i){ 
    for(int j=0;j<100000000;++j){ 
        if(j<0) goto begin; 
      __asm ("nop"); 
    } 
  } 
  begin: 
  //.... 
}

果然,它停下来了。
那个if(j<0) goto begin也是个很搞笑的东西。
我本来是这么写的

volatile int g=0; 
for(int i=0;i<10000000 && g==0;++i){ 
    for(int j=0;j<100000000 && g==0;++j){ 
      __asm ("nop"); 
    } 
  }

gdb断下来后,set g=1,然后往下走。但是发现不管用。还是等于0。依然跳不出来。
接着我就改成这样

for(int i=0;i<10000000 && i>=0;++i){ 
    for(int j=0;j<100000000 && i>=0;++j){ 
      __asm ("nop"); 
    } 
  }

(gdb) set i=-1
Ambiguous set command "i=-1":
我不知道为什么。
但是set j=-1 可以用。
于是就加了一个goto 用来跳出双层循环。
囧一个。

pmap初始化的代码中有这样一句我没看明白

/\* And recursively map PML4 to itself in order to get PTmap \*/
((pdp\_entry\_t \*)KPML4phys)[PML4PML4I] = KPML4phys;
((pdp\_entry\_t \*)KPML4phys)[PML4PML4I] |= PG\_RW | PG\_V | PG\_U;

其中,PML4PML4I=512/2=256.也就是说,KPML4phys有一个0xffff80******这样的地址?它的4级页表的表项指向的依然是4级页表,相当的诡异啊。

此博客中的热门博文

少写代码,多读别人写的代码

在windows下使用llvm+clang

tensorflow distributed runtime初窥