1. 程式人生 > >從零開始搭建環境編寫作業系統 AT&T GCC (七)GDB除錯和-monitor

從零開始搭建環境編寫作業系統 AT&T GCC (七)GDB除錯和-monitor

  一直有個小教程沒有寫給大家,那就是使用GDB除錯和-monitor除錯,借這次程式碼整理,跟大家說一下怎麼用。這裡我使用到了objdump工具,gdb除錯工具,這些工具都可以直接apt-get獲得。當然我還用到了qemu的自帶除錯功能-monitor
  這一節就是把system資料夾下lds檔案的. = 0x8200;刪掉,這是個歷史遺留問題哈哈,剛開始寫的時候加上了這行程式碼,導致了後來寫程式眾多不便,於是決定刪掉他,這一節不感興趣的可以直接跳過了。
一、修改system資料夾
  1、開啟lds檔案,刪掉 . = 0x8200; 這個歷史遺留問題
  2、開啟system.s 進行如下修改,我們看看程式還能不能正常執行。

########################################start 32
############set GDT
    movl    gdt_base+0x8200,    %eax################修改

############0# empty GDT
    movl    $0x00000000,   0(%eax)
    movl    $0x00000000,   4(%eax)
############1# code GDT
    movl    $0x8200ffff,   8(%eax)
    movl    $0x00409a00,   12(%eax)
############2# data GDT
movl $0x0000ffff, 16(%eax) movl $0x00cf9200, 20(%eax) ############3# stack GDT movl $0x00007a00, 24(%eax) movl $0x00409600, 28(%eax) #close interrupt cli lgdt gdt_size+0x8200 #configuration ################修改

  儲存,執行,哎呦?還不錯,至少沒有大錯誤,滑鼠和我們的文字沒有了,怎麼回事?我也不知道,debug!
  這裡寫圖片描述

二、debug過程記錄


  其實我是不太想寫這個的,因為想要把完整的debug過程記錄下來還是需要費點時間,但是為了體現一下怎麼用qemu和dbg除錯系統核心,而且這部分的教程真是少之又少,所以還是狠狠心寫下來吧。當然,具體DBG的所有命令解釋,-monitor的所有命令解釋,objdump的所有命令解釋我就不贅述了,這些資料網上還是有很多的,我只是記錄我的debug過程,給大家一個大體的概念。
  1、首先我注意到了滑鼠和字元同時沒有了,顯示這兩個的函式是我在另外的.c檔案中定義的,所以問題應該是出在定址上。
  2、進入系統程式碼資料夾,執行命令:objdump -D bin/system.elf ,反彙編.elf檔案。找到SysMain函式,閱讀彙編原始碼,看看問題是不是出在這裡。似乎問題不大。沒有找到問題。

 151:   e8 bb 03 00 00          call   511 <PutString>
 156:   83 c4 10                add    $0x10,%esp
 159:   83 ec 04                sub    $0x4,%esp
 15c:   6a 00                   push   $0x0
 15e:   6a 32                   push   $0x32
 160:   6a 32                   push   $0x32

  3、執行objdump -D -b binary -m i386 bin/system.bin 命令反彙編我們的raw binary檔案,額,好長,而且沒有條理,瘋了,那也得看。在2、中我們看到SysMain在0xf6處,所以直奔0xf6,找到push 0xfffffff傳參就找到我們函式呼叫位置了。傳完引數,最後call了0x511,似乎也沒有問題。完了,咋回事兒?
  4、不能就這樣放棄啊,該放大招了,開啟loader資料夾Makefile,修改如下,意思是啟動虛擬機器的時候stop
  

    qemu-system-i386 -fda $(BIN_DIR)/loader.img -boot a -gdb tcp::1234 -S -monitor stdio 
#   qemu-system-i386 -fda $(BIN_DIR)/loader.img -boot a -gdb tcp::1234 -monitor stdio 

  5、make,啊哈,虛擬機器停住了,再開啟一個控制檯,啟動gdb,執行target remote localhost:1234 連線虛擬機器,成功
  6、設定斷點 break *0x8200 ,因為我們把system載入到了這個位置執行的嘛,所以啟動system的一瞬間,我們停住它,然後在dbg中輸入命令c,continue的簡寫,讓它執行起來,然後中斷在0x8200處,完成
  7、停住了,這個時候我們啟動反彙編模式,layout asm,ip上下的程式碼就清晰可見了,注意layout asm在啟動保護模式分段之後就不能用了,因為它無視CS暫存器……
  8、用滑鼠往下翻彙編原始碼,找到ljmp,我們要在這裡再停下來,break *0x8274 再插入一個斷點,continue
  9、又停住了,下邊我們就不能再用layout asm了,所以我們先關掉它,ctrl+x 然後按a,關掉了。執行命令si,這個是執行一步彙編的意思,我們看它跳到哪裡了。
  10、我的跳到了0x79處,但是我們有段選擇子,偏移是0x8200,所以現在執行的指令應該位於0x8279處,我們再開啟一個發控制檯,objdump -D -b binary -m i386 bin/system.bin,看著我們的反彙編程式碼。這個時候0x79就應該與我們的程式碼一一對應了,看看0x79處是什麼,可能是混亂的,沒關係
  11、再在gdb中回車一下,看看執行到哪裡了,我的是0x7d
     7d: 8e d8 mov %eax,%ds
  12、最上面的指令因為對齊的原因,翻譯的不準確,就不看了,0x7d這才是我們的彙編程式碼
  13、第一個call 到了0xf6,再開啟一個控制檯,objdump -D bin/system.elf,看看0xf6是什麼,main函式,沒問題
  14、在gdb不停的回車執行si,直接回車表示執行上一條命令,現在進入了main函式依然沒有發現問題
  15、找到call 0x511,這條指令在0x151位置,因為我們知道0x511是輸出字元的函式,我們這設定一個斷點break *0x8351
  16、continue,停了下來,輸入si單步除錯,看看到哪裡去了,停住了!問題來了,為啥停住了??
  17、再檢查暫存器,擦,IDT為0x1140,又犯傻了,我們把偏移0x8200去掉後,資料段也不正確了
  
  18、把system.s進行修改,改成如下,暫時可以用了。

############2# data GDT
    movl    $0x8200ffff,   16(%eax)
    movl    $0x00cf9200,   20(%eax)

  19、背景變成這樣子了,那是因為資料段修改後視訊記憶體存放位置不正確,把所有視訊記憶體寫入的地址都減去0x8200,當然這也只是權宜之計,我們先這樣做
  這裡寫圖片描述
  20、好了,視訊記憶體恢復了正常,中斷還是不能使用,去InitIDT把 DefaultIntCallBack的-0x8200去掉,還是不能用,頻繁重啟,去檢視一下IDT暫存器的基址,居然還是0x1140,寫程式就是在慢慢犯傻的過程中改進,因為LIDT需要的是絕對地址嘛,也是佩服自己的智商,直接去void InitIDT()中,給idt+0x8200/8就好了嘛!注意是0x8200/8,因為指標每加1,是以自身大小為單位+1,我們要地址加0x8200,所以要除以自身單位。修改後的InitIDT()
  

    for (i=1;i<0x30;i++)
    {
        idt[i].offset1 = (short)((int)(void*)(DefaultIntCallBack));
        idt[i].selector = 0x0008;
        idt[i].no_use = 0x8e00;
        idt[i].offset2 = (short)(((int)(void*)(DefaultIntCallBack))>>16);   
    }
    FunctionLidt(0x30*8-1,idt+0x8200/8);

  這次make一下,成功!我們看到中斷函式被呼叫了,雖然不斷重啟,原因是中斷結束後需要iret,我們沒有做這個工作(偷懶的方法是在中斷最後加一個while(1)),所以我們是成功的!
  21、這次除錯就記錄到這裡了,當然如果自己會除錯核心最好了,有問題儘管問!

相關推薦

開始搭建環境編寫作業系統 AT&T GCC GDB除錯-monitor

  一直有個小教程沒有寫給大家,那就是使用GDB除錯和-monitor除錯,借這次程式碼整理,跟大家說一下怎麼用。這裡我使用到了objdump工具,gdb除錯工具,這些工具都可以直接apt-get獲得。當然我還用到了qemu的自帶除錯功能-monitor   

開始學習音視頻編程技術 開發環境搭建Qt4.86手動設置環境,主要就是設置g++qmake,比較透徹,附下載鏈接

路徑 details 分享 baidu 末尾 是我 其中 找到 source 1.先下載安裝Qt 我們使用的版本是4.8。 可以自行百度下載也可以從下面的網盤地址下載: Qt庫和編譯器下載: 鏈接:http://pan.baidu.com/s/1hrUxLIG 密碼

新公司入職,開始搭建環境

windows環境: 1.安裝chrome瀏覽器最新版,官網下載,直接安裝 2.安裝python3,百度雲盤 3.安裝Pycharm IDE,官網下載 啟用碼:https://www.jianshu.com/p/7e31bf8dbdb4 4.安裝VMware Workstatio

開始搭建遊戲伺服器》 序列化工具最優版Protostuff

前言: 之前使用protobuf工具來解析表格資料和定製網路協議,但是為了網路安全和壓縮資料大小,有時候需要對資料進行序列化,這就需要設計一個序列化工具類來完成序列化和反序列化的操作。 框架的對比: Java中幾個常用的序列化框架對比,包括:kryo、

開始搭建前後端分離的NetCore2.2EF Core CodeFirst+Autofac+Vue的專案框架之四Nlog記錄日誌至資料庫

  為什麼要進行日誌記錄呢?為什麼要存至資料庫呢?只能說日誌記錄是每個系統都應當有的。   好的日誌記錄方式可以提供我們足夠多定位問題的依據。查詢系統或軟體或專案的錯誤或異常記錄。程式在執行時就像一個機器人,我們可以從所記錄的日誌看出它正在做什麼,是不是按預期的設計在做,用來判斷執行狀態是否是正常的。   日

開始搭建前後端分離的NetCore2.2EF Core CodeFirst+Autofac+Vue的專案框架之五全域性異常處理

  在 上一篇 中講到了在NetCore專案中如何配置NLog將日誌存到資料庫,這篇中將講述如何處理自定義丟擲的異常以及未處理的異常,並通過日誌記錄下來。   為什麼要進行異常的全域性處理和記錄日誌呢?   在實際的軟體專案開發與迭代中,無論程式設計師是久經沙場的老將,還是初出茅廬的萌新,

開始搭建前後端分離的NetCore2.2EF Core CodeFirst+Autofac+Vue的專案框架之六使用過濾器進行全域性請求資料驗證

  在 上一篇 中講到了在NetCore專案中如何進行全域性異常處理,當手動丟擲或系統未處理異常出現時進行的一個攔截處理。   本節中將講到API請求模型的一個驗證,先丟擲幾個問題, 為什麼要使用模型驗證?對於我的瞭解來說,一般使用者並不會都是輸入的有效資料,這可能在應用程式中使用到這些

開始搭建前後端分離的NetCore2.2EF Core CodeFirst+Autofac+Vue的專案框架之使用JWT生成Token(個人見解)

  在 上一篇 中講到了在NetCore專案中如何進行全域性的請求模型驗證,只要在請求模型中加了驗證特性,介面使用時只用將資料拿來使用,而不用去關係資料是否符合業務需求。   這篇中將講些個人對於JWT的看法和使用,在網上也能找到很多相關資料和如何使用,基本都是直接嵌到 &nbs

開始搭建前後端分離的NetCore2.2EF Core CodeFirst+Autofac+Vue的專案框架之八MemoryCache與redis快取的使用

   1.快取概念   1.什麼是快取     這裡要講到的快取是服務端快取,簡單的說,快取就是將一些實時性不高,但訪問又十分頻繁,或者說要很長時間才能取到的資料給存在記憶體當中,當有請求時直接返回,不用經過資料庫或介面獲取。這樣就可以減輕資料庫的負擔。   2.為什麼要用快取     總的來說就是

開始搭建前後端分離的NetCore2.2EF Core CodeFirst+Autofac+Vue的專案框架之十一Swagger使用一

 一.未使用Swagger狀況   相信無論是前端開發人員還是後端開發人員,都或多或少都被介面文件折磨過,前端經常抱怨後端給的介面文件或與實際情況不一致。後端又覺得編寫及維護介面文件會耗費不少精力,經常來不及更新。 其實無論是前端呼叫後端,還是後端呼叫後端,都期望有一個好的介面文件。但是這個介面文件對於程式設

開始搭建前後端分離的NetCore2.2EF Core CodeFirst+Autofac+Vue的專案框架之十二Swagger引數使用二

  引言   在 上一篇 中提到了 Swagger 的基本使用,僅限於沒有引數,沒有驗證的那種api文件生成,那麼這篇就連線上篇繼續,在一般具有安全性、許可權等驗證的介面上,   都會在header/url中加上請求者的祕鑰、簽名等,當然也有可能新增到body等其它地方, Swashbuckle.A

開始——基於角色的權限管理01補充

itl jsp mage logs log sonar class htm -1 此博文較為詳細的介紹從零開始——基於角色的權限管理01文中的兩個部分的流程(解釋代碼)。 1)  index.jsp中提交跳轉action      action的login,獲取jsp頁面傳

開始使用CodeArt實踐最佳領域驅動開發

using emp 程序集 mman his return main 更新 物理 本章內容還在整理上傳中,你可以等全部更新完畢後再查閱也可以先預覽已上傳的內容。。。。。。 7. 應用層的命令模式   在上個章節裏我們設計並編碼了領域對象Permission,但是目前Perm

開始學大數據-Java基礎-switch語句6

大數據 Java CCIE 從零開始學大數據 我們從零開始學習大數據技術,從java基礎,到Linux技術涉獵,再深入到大數據技術的Hadoop、Spark、Storm技術,最後到大數據企業平臺的搭建,層層遞進,由點到面!希望技術大牛能過來指導學習。上一節學習了流程控制語句,本節學習switc

開始寫自己的PHP框架系列教程[App.php]

porting col config exce tro efault fig 默認 clas 從這一個文件開始以後加載的均以類加載,請註意命名空間和所在文件的路徑 APP.php的這個類所在路徑:根目錄\framework\App.php 直接上代碼 namespace

開始構建一個Reactor模式的網路庫 執行緒同步MutexCondition

最近在學習陳碩大神的muduo庫,感覺寫的很專業,以及有一些比較“高階”的技巧和設計方式,自己寫會比較困難。 於是打算自己寫一個簡化版本的Reactor模式網路庫,就取名叫mini吧,同樣只基於Linux平臺,不使用boost庫,去掉一些比較複雜的部分,只實現比較基本的功能。 寫作的過程中,參考了http

開始的畢設--HTML(超文字標記語言)1

認識style元素 要增加樣式,需要在頁面中增加一個新的element這就是,<style>元素。 <style type="text/css"> body{ background-color:#d2b48c; margin-left

開始的畢設--HTML(超文字標記語言)2

前往web 域名 域名是網站的名字,如 bupt.edu.cn 域名由一個集中的權威機構ICANN控制,以確保一次只能有一個人使用某個域名。(收費的) 如果我想獲得bupt.edu.cn的域名,是不是會得到www.bupt.edu.cn呢?看起來所有人都在使用

開始的畢設--HTML(超文字標記語言)4

HTML考古 在古老的HTML4.01和XHTML1.1頁面,它們使用了doctype放在HTML頁面的最上面,告訴瀏覽器所使用的HTML版本。 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "htt

開始構建一個Reactor模式的網路庫執行緒類Thread

執行緒類Thread是對POSIX執行緒的封裝類,因為要構建的是一個Linux環境下的多執行緒網路庫,對執行緒的封裝是很必要的。 首先是CurrentThread名稱空間,主要是獲取以及快取執行緒id: 1 #ifndef CURRENTTHREAD_H 2 #define CURRENTTHR