Ex4:複習C語言中的pointer,並確認了解pointer.c的每一個位址與現象。
Ans:Too easy to describe... :P
Ex5:如果bootloader的link address設定錯誤(不是0x7c00),第1行會出錯的指令為何?
Ans:boot/boot.S的"ljmp $PROT_MODE_CSEG, $protcseg",因為ljmp會將絕對位址載入。(先出現的jnz不會出錯是因為jnz是相對跳轉,透過gdb與boot.asm便可發現jnz後的相對位址都是一致的)。
Ex6:分別在BIOS進入到bootloader時與bootloader進入到kernel時觀察0x100000的前8個word,說明為何在這兩個時間點,同樣的記憶體位置的值會不同?
Ans:因為bootloader會根據kernel image所指定的位置(ELF program header中的LMA)將kernel的每個segment載入記憶體,所以新的值是kernel image的text segment。
Ex7:追蹤JOS kernel,觀察0x100000與0xf0100000兩處的記憶體。如果mapping沒有建立正確,哪條指令會出錯?
Ans:kernel/entry.S中:
mov $relocated, %eax
jmp *%eax
relocated:
"jmp *%eax"會錯。因為link address定為0xf0100000,所以relocated的值為0xf01xxxxx,當mapping沒有正確設置,就會無法讓EIP正確地從0x1xxxxx跳轉到0xf01xxxxx。
Ex8:將八進制的顯示加進cprintf()中。
Ans:
Ex9:找出kernel在何處、如何設定stack?
Ans:在kernel/entry.S中:
...
70 # Clear the frame pointer register (EBP)
71 # so that once we get into debugging C code,
72 # stack backtraces will be terminated properly.
73 movl $0x0,%ebp # nuke frame pointer
74
75 # Set the stack pointer
76 movl $(bootstacktop),%esp
Ex11&E12:實作backtrace(),並印出相關檔案與行號。
Ans:基本上就是反覆讀取EBP與EIP,然後以debuginfo_debug()獲取相關檔案與行號的訊息,有趣的是,debugging format採用的是STABS。本來要自己寫的,但看到HawxChen已經寫好了,而且沒有幾行程式,就不作重複的工嘍~
Ans:Too easy to describe... :P
Ex5:如果bootloader的link address設定錯誤(不是0x7c00),第1行會出錯的指令為何?
Ans:boot/boot.S的"ljmp $PROT_MODE_CSEG, $protcseg",因為ljmp會將絕對位址載入。(先出現的jnz不會出錯是因為jnz是相對跳轉,透過gdb與boot.asm便可發現jnz後的相對位址都是一致的)。
Ex6:分別在BIOS進入到bootloader時與bootloader進入到kernel時觀察0x100000的前8個word,說明為何在這兩個時間點,同樣的記憶體位置的值會不同?
Ans:因為bootloader會根據kernel image所指定的位置(ELF program header中的LMA)將kernel的每個segment載入記憶體,所以新的值是kernel image的text segment。
Ex7:追蹤JOS kernel,觀察0x100000與0xf0100000兩處的記憶體。如果mapping沒有建立正確,哪條指令會出錯?
Ans:kernel/entry.S中:
mov $relocated, %eax
jmp *%eax
relocated:
"jmp *%eax"會錯。因為link address定為0xf0100000,所以relocated的值為0xf01xxxxx,當mapping沒有正確設置,就會無法讓EIP正確地從0x1xxxxx跳轉到0xf01xxxxx。
Ex8:將八進制的顯示加進cprintf()中。
Ans:
- //in lib/printfmt.c
- void
- vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap)
- {
- ...
- // (unsigned) octal
- case 'o':
- // Replace this with your code.
- num = getint(&ap, lflag);
- base = 8;
- goto number;
- ...
- }
Ex9:找出kernel在何處、如何設定stack?
Ans:在kernel/entry.S中:
...
70 # Clear the frame pointer register (EBP)
71 # so that once we get into debugging C code,
72 # stack backtraces will be terminated properly.
73 movl $0x0,%ebp # nuke frame pointer
74
75 # Set the stack pointer
76 movl $(bootstacktop),%esp
...
95 ###################################################################
96 # boot stack
97 ###################################################################
98 .p2align PGSHIFT # force page alignment
99 .globl bootstack
100 bootstack:
101 .space KSTKSIZE
102 .globl bootstacktop
103 bootstacktop:
我們可以看到,kernel將stack top(esp)設在bootstacktop,大小為KSTKSIZE(在data section bootstack ~ bootstacktop),x86的stack增長時會從bootstacktop往下遞減位址。
Ex10:熟悉x86的calling convention。
Ans:呼叫函式時,會先將caller-saved registers推入stack,接著是參數依右至左依序推入,然後再推入EIP,進入function後,推入EBP,然後再讓EBP指到目前ESP。function中必須適當保護callee-saved registers,返回時,依序恢復EBP與EIP,並將回傳值放在EAX。可參考這篇圖文並茂的文章。
Ex11&E12:實作backtrace(),並印出相關檔案與行號。
Ans:基本上就是反覆讀取EBP與EIP,然後以debuginfo_debug()獲取相關檔案與行號的訊息,有趣的是,debugging format採用的是STABS。本來要自己寫的,但看到HawxChen已經寫好了,而且沒有幾行程式,就不作重複的工嘍~
留言
張貼留言