2010-04-06 34 views
6

我正在做一些實驗,希望能夠看到系統調用期間保存在堆棧中的內容(用戶登陸過程的保存狀態)。根據http://lxr.linux.no/#linux+v2.6.30.1/arch/x86/kernel/entry_32.S,它顯示寄存器的各種值保存在堆棧指針的特定偏移處。這是我一直在試圖用它來檢查哪些內容保存在棧上的代碼(這是我創建了一個自定義的系統調用):如何確定保存在堆棧上的值?

asm("movl 0x1C(%esp), %ecx"); 
asm("movl %%ecx, %0" : "=r" (value)); 

其中value是一個unsigned long。

截至目前,這個值不是預期的值(它顯示0爲ds的用戶值保存)。

我正確訪問堆棧指針的偏移量嗎?

另一種可能性是我可以使用諸如GDB的調試器來檢查內核中的堆棧內容嗎?我沒有太多廣泛的用於調試,也不知道如何在內核中調試代碼。任何幫助深表感謝。

回答

0

請記住,x86_64代碼通常會在寄存器中傳遞值(因爲它有很多),因此堆棧上沒有任何東西。檢查gcc中間輸出(-S IIRC)並在組件中查找push

我不熟悉調試內核代碼,但gdb交互式地檢查堆棧肯定更好。

4

行內組裝比看起來更棘手。試圖在短期內支付GCC的關注:

  1. 如果它修改處理器寄存器,有必要把這些寄存器撞名單上。重要的是要注意,clobber列表必須包含所有寄存器,您直接更改(讀取明確)或間接(讀取隱含地);爲了加強(1),條件操作和數學操作也會改變寄存器,更常見的狀態標誌(零,進位,溢出等),所以你必須通過將「cc」添加到clobber列表來通知它;
  2. 添加「內存」如果它修改不同的(隨機讀取)內存位置;
  3. 添加易失性關鍵字如果它修改了輸入/輸出參數中未提及的內存;

然後,你的代碼變成:是撞名單上,因爲GCC已經知道它將會改變

asm("movl 0x1C(%%esp), %0;" 
    : "=r" (value) 
    : /* no inputs :) */ 
    /* no modified registers */ 
); 

輸出參數不是必需的。

另外,因爲所有你想要的是ESP寄存器的值,就可以避免所有的痛苦這樣做:

register int esp asm("esp"); 
esp += 0x1C; 

它可能不是解決你的問題,但它要走的路。作爲參考,請檢查this,thisthis

5

無需內聯彙編。保存的狀態entry_32.S推到了一個系統調用堆棧佈局爲一個struct pt_regs,你可以得到一個指向它像這樣(你需要和/或<asm/processor.h>直接或間接地包括<asm/ptrace.h>):

struct pt_regs *regs = task_pt_regs(current);