選擇要移除的公用符號
PDBCopy 提供 -f 和 -F 選項,讓您可以從等量符號檔中移除任意的公用符號集,只保留您的物件需要存取的符號,才能執行其偵錯。
PDBCopy 的常見用法是建立特殊版本的符號檔,以供 Microsoft 在其線上當機分析 (OCA) 程式中使用。 OCA 可以將特定函式指定為 插入式,這表示如果在堆疊追蹤上找到函式,則會忽略它。 如果函式只是執行任何重大計算的包裝函式或「傳遞」函式,通常會宣告為插入。 如果在失敗分析的堆疊上找到這類函式,可以假設此函式本身不是錯誤,而且最多會傳遞從先前堆疊上常式收到的無效或損毀資料。 藉由忽略這類函式,OCA 可以更妥善地判斷錯誤或損毀的實際原因。
當然,您想要宣告「inert」 的任何函式都必須包含在 OCA 所使用的符號檔的公用符號資料表中。 不過,這些不是唯一需要包含的函式,如下列範例所示。
假設您撰寫 Windows 驅動程式,並使用 PDBCopy 從其符號檔中移除所有公用符號,但 FunctionOne 和 FunctionSix除外,兩個插入函式除外。 您的期望是,如果在當機後在堆疊上找到 FunctionOne 或 FunctionSix ,OCA 將會忽略它們。 如果驅動程式的任何其他部分位於堆疊上,Microsoft 會提供對應的記憶體位址,而且您可以使用 位址來偵錯驅動程式。
不過,讓我們假設您的驅動程式佔用下列配置中的記憶體:
位址 | 記憶體的內容 |
---|---|
0x1000 |
模組的基底位址 |
0x2000 |
FunctionOne的開頭 |
0x203F |
FunctionOne結尾 |
0x3000 |
FunctionSix的開頭 |
0x305F |
FunctionSix結尾 |
0x7FFF |
記憶體中模組的結尾 |
如果偵錯工具在堆疊上找到位址,它會選取下一個較低位址的符號。 由於公用符號資料表包含每個符號的位址,但沒有大小資訊,因此偵錯工具無法得知位址是否實際落在任何特定符號的界限內。
因此,如果在位址0x2031發生錯誤,Microsoft OCA 所執行的偵錯工具會正確地將錯誤識別為在 FunctionOne內。 由於這是插入函式,偵錯工具會繼續逐步執行堆疊,以找出損毀的原因。
不過,如果在0x2052發生錯誤,偵錯工具仍會將此位址與 FunctionOne相符,即使它超出此函式的實際結尾 (0x203F) 也是如此。
因此,您不僅必須在移除符號檔中包含您想要公開的函式,還必須包含緊接在這些函式後面的符號。 在此範例中,您想要公開FunctionOne、FunctionTwo、FunctionSix 和 FunctionSeven:
位址 | 記憶體的內容 |
---|---|
0x1000 |
模組的基底位址 |
0x2000 |
FunctionOne的開頭 |
0x203F |
FunctionOne結尾 |
0x2040 |
FunctionTwo的開頭 |
0x3000 |
FunctionSix的開頭 |
0x305F |
FunctionSix結尾 |
0x3060 |
FunctionSeven的開頭 |
0x7FFF |
記憶體中模組的結尾 |
如果您在等量符號檔中包含這四個函式,則 Microsoft OCA 分析不會誤將位址視為 FunctionOne的一部分0x2052。 在此範例中,它會假設此位址是 FunctionTwo的一部分,但這並不重要,因為您尚未向 OCA 註冊 FunctionTwo 作為插入函式。 重要的是,位址0x2052被辨識為不落在插入函式內,因此 OCA 會將它辨識為驅動程式內的有意義錯誤,並通知您錯誤。
如果您不想在每個插入函式之後公開函式的名稱,您可以將不重要的函式插入程式碼中,並遵循每個插入函式,讓這些函式的名稱可以包含在公用符號檔中。 請務必確認這些新增的函式確實會遵循二進位位址空間中的插入函式,因為某些優化常式可能會改變此情況,甚至完全移除某些函式。