共用方式為


設定 EXDI 調試程式傳輸

本主題描述如何使用 EXDI 設定內核模式偵錯。 擴充偵錯介面 (EXDI) 是軟體調試程式與偵錯目標之間的適應層。 從 Windows 版本 22000 開始,Windows 偵錯工具支援使用 EXDI 進行核心偵錯。

EXDI 可用來建立與 QEMU 虛擬環境的連線。 如需詳細資訊,請參閱 使用EXDI設定QEMU內核模式偵錯。

注意

EXDI 是特定環境的進階特製化偵錯形式。 使用標準 KDNET 連線更容易設定,而且建議使用。 若要自動設定網路偵錯,請參閱 自動設定 KDNET 網路核心偵錯

EXDI COM 伺服器概觀

EXDI 是一種介面,可藉由新增硬體調試程式的支持來擴充 WinDbg(例如 JTAG 型或 GdbServer 型)。 下圖說明 EXDI-GdbServer 的角色。

顯示 EXDI-GdbServer 角色的堆疊圖表,上面有 WinDbg-DbgEng、EXDI 介面,以及與 GDB 伺服器通訊的 EXDI COM 伺服器。

因為 EXDI 連線與 Windows 或目標電腦上所載入的 KDNET 通訊協定沒有任何相依性。 由於不需要這些軟體調試程式元件,因此EXDI在早期裝置啟動和偵錯OS啟動問題中很有用。

重要

由於 EXDI 不會使用 KDNET 通訊協定,因此連線的調試程式對於電腦上執行的內容明顯較少,而且許多命令的運作方式不同,或完全無法運作。 存取所偵錯程式代碼的私人符號,可協助調試程序進一步瞭解目標系統程式代碼執行。 如需詳細資訊,請參閱 公用和私人符號

EXDI 核心模式裝置需求

執行調試程式的計算機稱為 主計算機,而偵錯的計算機稱為 目標計算機

需要下列專案:

  • 在目標與主計算機上,由所需的環境所支援的網路卡,例如 QEMU。

  • 目標與主機之間的網路連線,使用 TCP/IP。

  • Windows 10 或 Windows 11 版本 22000 或更新版本。

限制

  • EXDI 硬體偵錯必須使用 XML 檔案手動設定,而且 Windows 調試程式中沒有相關的 UI。

  • 如上所述,因為EXDI不會使用 KDNET 通訊協定,因此連線的調試程式對於目標系統的資訊較少,而且調試程式的使用方式不同。 若無法存取目標程式代碼的私人符號,許多使用符號來瞭解目標系統狀態的命令將無法運作。 在此情況下,可以檢視記憶體並註冊內容和反組譯碼。 判斷執行程序代碼的位置,或執行其他常見的調試程式工作,可能非常困難且耗時,而不需要私用符號。

COM GDB 伺服器用戶端

本主題涵蓋使用實作 EXDI COM 調試程式介面的 EXDI COM GDB Server 用戶端 (ExdiGdbSrv.dll)。 您可以使用相同的 COM 介面來實作其他介面,例如適用於 JTAG-DCI 的 EXDI COM 伺服器。

並行EXDI和 KDNET 偵錯

在某些複雜的案例中,例如在早期裝置啟動中,有兩個目標裝置的聯機會很有用。 一個 EXDI 和一個 KDNET。 如果目標是 Windows OS,KDNET 軟體偵錯會設定為一般,例如連線到虛擬機。 在此設定中,這兩個並行調試程式中的任一個都可以中斷,以偵錯目標計算機上的程序代碼。

設定 EXDI 連線的程式摘要

在本主題中,我們將描述設定 EXDI 連線的程式。 如需EXDI使用案例的範例,請參閱 使用EXDI設定QEMU內核模式偵錯。

  1. 在主機系統上下載並安裝 Windows 偵錯工具。
  2. 下載、建置及註冊 EXDI 伺服器 DLL。
  3. 編輯 EXDI 組態 XML 檔案來設定連線。
  4. 使用 -kx 選項啟動 WinDbg 以連線到 EXDI 伺服器。
  5. 使用 WinDbg 對目標系統進行偵錯。

下載並安裝 Windows 偵錯工具

在主機系統上安裝 Windows 偵錯工具。 如需下載及安裝調試程式工具的資訊,請參閱 Windows 的偵錯工具。

下載、建置及註冊 EXDI 伺服器 DLL

從 Microsoft/WinDbg-Samples, GitHub https://github.com/microsoft/WinDbg-Samples下載對應的ExdiGdbSrv.dll二進位檔 (EXDI COM 伺服器用戶端) 原始程式碼

git clone https://github.com/microsoft/WinDbg-Samples

根據位於 Exdi/exdigdbsrv 的主機調試程式安裝架構,建置 VS 解決方案 (ExdiGdbSrv.sln)。

找出組建所產生的ExdiGdbSrv.dll。

將 EXDI com 伺服器 (ExdiGdbSrv.dll) 複製到主電腦,並複製到包含調試程式 .g 的目錄。 C:\Program Files (x86)\Windows Kits\10\Debuggers\x64C:\Debuggers

使用 regsvr32 在 管理員 istrator 命令提示字元中註冊 DLL。

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>regsvr32 ExdiGdbSrv.dll

RegSvr32 應該傳回訊息, DLLRegisterServer in ExdiGdbSrv.dll succeeded指出 。

此步驟只需要完成一次,但如果您變更ExdiGdbSrv.dll的位置,則必須再次註冊 COM 伺服器。

另一個選項是使用範例 PowerShell 腳本是安裝 EXDI DLL,並第一次啟動調試程式。 如需詳細資訊,請參閱 範例 EXDI PowerShell 腳本

使用 EXDI 組態 XML 檔案設定 WinDbg

找出 中的 WinDbg-Samples/Exdi/exdigdbsrv/ 兩個必要組態檔,並將其複製到安裝調試程式的本機主機調試程序計算機。

  • exdiConfigData.xml
  • systemregisters.xml

EXDI_GDBSRV_XML_CONFIG_FILE – 描述 Exdi xml 組態檔的完整路徑。

EXDI_SYSTEM_REGISTERS_MAP_XML_FILE – 描述 Exdi xml 系統快取器對應檔的完整路徑。

如需exdiConfigData.xml標籤和屬性的詳細資訊,請參閱 下面的EXDI XML 組態檔

在我們的案例中,我們會將下列值設定為零,以停用調試程式嘗試尋找 nt!kdVersionBlock。

heuristicScanSize = "0"

設定 EXDI 路徑值以參考 XML 組態檔的位置

設定環境變數EXDI_GDBSRV_XML_CONFIG_FILE,並EXDI_SYSTEM_REGISTERS_MAP_XML_FILE描述 exdi xml 組態檔的完整路徑。 請確定指定的路徑環境值可從ExdiGdbSrv.dll的位置取得。

命令提示字元

開啟命令提示字元並設定下列環境變數。

set EXDI_GDBSRV_XML_CONFIG_FILE="C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\exdiConfigData.xml"

set EXDI_SYSTEM_REGISTERS_MAP_XML_FILE="C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\systemregisters.xml"

輸入 SET 以確認指定的路徑可從ExdiGdbSrvSample.dll的位置取得

Powershell

開啟 PowerShell 提示字元並設定下列環境變數:

$env:EXDI_GDBSRV_XML_CONFIG_FILE = 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\exdiConfigData.xml'

$env:EXDI_SYSTEM_REGISTERS_MAP_XML_FILE = 'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\systemregisters.xml'

輸入 dir env: 以確認指定的路徑可從ExdiGdbSrvSample.dll的位置取得

啟動 WinDbg 並連線到 EXDI 伺服器

在設定環境變數的相同命令提示字元中,透過exdi介面啟動windbg會話(EXDI_GDBSRV_XML_CONFIG_FILE和EXDI_SYSTEM_REGISTERS_MAP_XML_FILE)。

c:\Debuggers> windbg.exe -v -kx exdi:CLSID={29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014},Kd=NtBaseAddr,DataBreaks=Exdi

若要顯示適用於診斷用途的其他輸出, 可以使用 -v: 詳細資訊會話。 如需 WinDbg 選項的一般資訊,請參閱 WinDbg 命令行選項。 如需詳細資訊,請參閱 下面的EXDI WinDbg 載入參數

調試程式會顯示成功的 EXDI 傳輸初始化。

EXDI: DbgCoInitialize returned 0x00000001
EXDI: CoCreateInstance() returned 0x00000000
EXDI: QueryInterface(IExdiServer3) returned 0x00000000
EXDI: Server::GetTargetInfo() returned 0x00000000
EXDI: Server::SetKeepaliveInterface() returned 0x00000000
EXDI: Server::GetNbCodeBpAvail() returned 0x00000000
EXDI: ExdiNotifyRunChange::Initialize() returned 0x00000000
EXDI: LiveKernelTargetInfo::Initialize() returned 0x00000000
EXDI: Target initialization succeeded
Kernel Debugger connection established

在視窗標題中顯示 EXDI CLSID 的主要 WinDbg 工作階段。

EXDIGdbServer 控制台視窗也可以顯示 EXDI 連線狀態的相關信息。 如需主控台的詳細資訊,請參閱 疑難解答

EXDI WinDbg 載入參數

下列參數會與 WinDbg 搭配使用,以啟動 EXDI 核心工作階段。

-kx: EXDI:Options

下列 EXDI 選項適用於 -kx 選項。

參數 描述
CLSID 指派給 LiveExdiGdbSrvServer 的類別標識碼(如ExdiGdbSrv.idl 檔案中所定義)。
Kd=NtBaseAddr 調試程式引擎會尋找NT基位址。
ForceX86 強制調試程式引擎使用 IeXdiX86Context3 介面來取得/設定 CPU 內容。
DataBreaks=Exdi 允許使用數據斷點。
Inproc 允許使用 inproc Exdi-Server。

使用 WinDbg 對目標系統進行偵錯

dbgeng.dll會使用啟發學習演算法來尋找發生中斷命令時 NT 基底負載位址的位置。 如果私人符號無法使用,此程式將會失敗。

這表示在許多連接順序下,中斷將無法如預期般運作。 如果您手動中斷程式代碼,則會是 Windows 當時所執行的隨機位置。 由於目標程式代碼的符號可能無法使用,因此很難使用符號來設定斷點。

直接存取記憶體的命令如下。

k, kb, kc, kd, kp, kP, kv (顯示堆棧回溯)

r (快取器)

d, da, db, dc, dd, dD, df, dp, dq, du, dw (顯示記憶體)

u (Unassemble)

您可以使用 p (Step) 逐步執行程式碼

也有一個命令可用來嘗試尋找您想要偵錯的程序代碼。

s (搜尋記憶體)

.imgscan (尋找影像標頭)

Imgscan 對於 EDXI 偵錯很有説明,因為與傳統 KDNET 核心偵錯不同,根據符號設定斷點可能無法使用。 尋找所需的目標映像,有助於使用其位置來設定記憶體取斷點。

.exdicmd (EXDI 命令)

.exdicmd 會使用作用中的 EXDI 偵錯連線,將 EXDI 命令傳送至目標系統。 如需詳細資訊,請參閱 .exdicmd (EXDI 命令)

疑難排解

使用 ExdiGdbServer 視窗的輸出來監視連接順序。

ExdiGdbServer 文字窗口,顯示長十六進位數位。

問題:錯誤:無法建立與 GbDServer 的連線。 請確認 連接字串 <hostname/ip>:portnumber

此問題可能是由下列原因所造成:

  • ExdiGdbSrv.dll無法連線到目標 GDB 伺服器。
  • GDB 伺服器尚未在目標上執行。
  • 防火牆問題,請確定這兩個IP位址都可以透過 ping、tracert 或其他工具來確認 GDB 流量可以通過防火牆。

問題:無法使用EXDI啟動核心偵錯。

此問題可能是由下列原因所造成:

  • 在主調試程式計算機上執行的另一個ExdiGdbSrv.dll實例(由 dllhost.exe 裝載)。
  • 終止裝載ExdiGdbSrv.dll之 COM 服務的額外實例。
    • 首先列出進程,使用主機計算機上的 TList 之類的公用程式。 裝載ExdiGdbSrv.dll的 DLLHost 會顯示 ExdiGdbServer

      tlist 261928 dllhost.exe ExdiGdbServer

    • kill -f XXXXX 調試程式命令提示字元中使用 ,以使用進程號碼終止進程。

問題:錯誤:無法設定 GdbServer 會話。

此問題可能是由下列原因所造成:

  • 尋找工作階段資訊時發生錯誤,例如 XML 組態檔的路徑。

問題:錯誤:未定義EXDI_GDBSRV_XML_CONFIG_FILE環境變數。

此問題可能是由下列原因所造成:

  • ExdiGdbSrv.dll未設定環境變數,或無法在環境中使用。

問題:錯誤:未定義EXDI_GDBSRV_XML_CONFIG_FILE環境變數。Exdi-GdbServer 範例目前不會繼續。請設定 Exdi xml 組態檔的完整路徑。

此問題可能是由下列原因所造成:

  • 設定EXDI_GDBSRV_XML_CONFIG_FILE環境變數。 在某些情況下,如果您按下 [確定] 按鈕,ExdiGDbSrv.dll會繼續運作,但windbg.exe會失敗查詢系統緩存器(例如透過 rdmsr/wrmsr 函式)。

問題:無法使用目標系統的錯誤案例 - 傳回的 DbgCoInitialize 0x00000001

如果未載入目標系統或無法使用,可能會傳回下列輸出。

Microsoft (R) Windows Debugger Version 10.0.20317.1 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

EXDI: DbgCoInitialize returned 0x00000001

當 ExdiGdbSrv.dll COM 伺服器無法連線到 QEMU GDServer 時,這是常見的錯誤,因此可能會因為下列原因而失敗:

  • 透過dllhost.exe程式(COM 相關)啟動 EXDI COM 伺服器(ExdiGDbSrv.dll)失敗。 若要解決此問題,請重新啟動主機調試程式計算機或註銷 Windows,然後再次登入。 如果無法運作,請在重新啟動/登入后重新註冊 EXDI COM 伺服器。

    • regsvr32.exe <full path to the ExdiGdbSrv.dll)
  • ExdiGdbSrv.dll的上一個會話仍由dllhost.exe進程裝載,因此您必須終止dllhost.exe程式。 檢查裝載ExdiGdbSrv.dll並終止相關聯 pid 之dllhost.exe的 tlist。

  • QEMU gdbserver 尚未啟動,或exdiconfigdata.xml檔案包含無效的IP:Port 值。 如果 WinDbg 工作階段在與 QEMU Windows VM 相同的主電腦中啟動,則 IP=LocalHost。

問題:無法啟動偵錯會話:FAILURE HR=0x80004005:Failed to AttachKernel。

此問題可能是由下列原因所造成:

  • 如上所述,ExdiGdbSrv.dll的上一個會話可能仍在使用中。 找出並終止相關聯的 DLL 主機,如上所述。

顯示 HR 0x80004005失敗的 WinDbg 對話方塊。

EXDI XML 組態檔

EXDI GDB COM 伺服器會取用兩個必要的 xml 檔案(ExdiGdbSrv.dll)。

  1. exdiConfigData.xml - 此檔案包含 GDB 伺服器用戶端使用 HW 調試程式 GDB 伺服器目標建立成功 GDB 工作階段所需的主要組態數據,因此如果檔案位置不是由EXDI_GDBSRV_XML_CONFIG_FILE環境變數設定,GDB 伺服器用戶端將不會執行。 每個 xml 標記都允許設定 GDB 伺服器功能的特定集合。 如需您可以在 XML 中修改的屬性清單,以及範例 XML,請參閱下方。

  2. Systemregister.xml - 此檔案包含系統快取碼之間的對應。 這是必要的,因為 XML 檔案中的 GDB 伺服器未提供存取碼,而調試程式會透過存取碼存取每個系統快取器。 如果檔案未透過環境變數 EXDI_SYSTEM_REGISTERS_MAP_XML_FILE設定,則ExdiGdbSrv.dll會繼續運作,但調試程式將無法透過 rdmsr 或 wrmsr 命令存取任何系統緩存器。 GDB 伺服器硬體除錯程式應該支援這些快取器的清單(特定系統快取器名稱應該出現在系統 xml 檔案中傳送的快取器清單中)。

GDBServer 標記和屬性

下表描述檔案中 exdiConfigData.xml 定義的 GDBServer 標記和屬性。

參數 描述
ExdiTargets 指定ExdiGgbSrv.dll將使用哪些特定 GDB 伺服器目標組態來建立與 GDB 伺服器目標的 GDB 連線,因為exdiConfigData.xml檔案包含ExdiGdbSrv.dll目前支援的所有 GDB 伺服器(此檔案必須先填入,才能搭配特定 GDB 伺服器使用ExdiGdbSrv.dll)。
CurrentTarget 指定 GDB 伺服器目標的名稱(例如,這個屬性值應該與exdiConfigData.xml檔案所包含的其中一個 <ExdiTarget Name= 標籤名稱值相符。
ExdiTarget 這是每個 GDB 伺服器目標元件所包含之所有組態數據的開始標記。
名稱 指定 GDB 伺服器的名稱(例如 QEMU、BMC-OpenOCD、Trace32、VMWare)。
agentNamePacket 這是 GDB 伺服器 HW 調試程式所辨識的 GDB 用戶端名稱。 GDB 伺服器 HW 調試程式可以使用此程式來設定特定 GDB 用戶端的本身(例如 Trace32 GDB 伺服器需要ExdiGdbSrv.dll傳送 “QMS.windbg” 名稱來識別 windbg-GDB 用戶端,然後啟用僅支援 MS GDB 伺服器用戶端的自定義 GDB 記憶體封包(exdiGdbSrv.dll)。
ExdiGdbServerConfigData 指定ExdiGdbSrv.dll元件相關的組態參數。
uuid 指定ExdiGdbSrv.dll元件的 UUI。
displayCommPackets 如果為 『yes』,則我們會在命令記錄視窗中顯示 RSP 通訊協定通訊字元。 如果為 『no』,則只會顯示要求-回應組文字。
enableThrowExceptionOnMemoryErrors 當 GDB 錯誤回應封包 (E0x) 時,GDB 伺服器用戶端會檢查此屬性,以判斷用戶端是否應該擲回例外狀況並停止讀取記憶體。
qSupportedPacket 這可讓設定 GDB 用戶端要求在 XML 目標描述檔之後,GDB 伺服器 HW 調試程式應該傳送哪些 xml 快取器架構檔案(基本上,用戶端會通知 GDB 伺服器哪些架構受到客戶端支援,目前用戶端支援 x64 架構)。
ExdiGdbServerTargetData 指定與 GdbServer 會話偵錯的硬體目標相關的參數。
targetArchitecture 包含目標硬體架構的字串。 可能的值:X86、X64、ARM、ARM64。 目前,exdiGdbSrv.dll僅支援 X86 和 ARM。
targetFamily 包含目標硬體系列的字串。 可能的值:ProcessorFamilyX86、ProcessorFamilyX64、ProcessorFamilyARM、ProcessorFamilyARM64。
numberOfCores 目標支援的處理器核心數目。 當我們使用多 Gdbserver 會話 (T32-GdbServer 會話) 時,將會驗證此參數。 下列 'MultiCoreGdbServerSessions' 屬性應設定為 'yes'。
EnableSseContext 如果為 『yes』,則 『g』 內容 RSP 封包會包含浮點緩存器值。 此參數僅適用於 Intel 系列目標。
heuristicScanSize 這會設定調試程式引擎快速啟發學習法演算法,以減少所掃描記憶體探查的大小,如果未指定屬性值(或 “0”),則調試程式引擎不會使用快速啟發學習法,並回復到掃描整個記憶體的啟發學習法,以尋找 PE DOS 簽章。
targetDescriptionFile 指定 GDB 伺服器是否在傳送每個個別的 xml 檔案之前傳送目標描述頭檔。 此欄位空白,則 GDB 伺服器用戶端不會要求 xml 架構系統快取器(例如不支援在個別 xml 檔案中傳送架構快取器的 Trace32 GB 伺服器)。
GdbServer 連線 ionParameters 指定 GdbServer 工作階段參數。 這些參數可用來控制ExdiGdbSrv.dll元件與 GdbServer 之間的 RSP GdbServer 會話。
MultiCoreGdbServerSessions 旗標 如果為 'yes',則我們將有多核心 GdbServer 會話(T32-GdbServer 後端所使用的會話)。 如果為 『no』,則我們只會與 GdbServer 的一個實例通訊。
MaximumGdbServerPacketLength 這是一個封包所支援的最大 GdbServer 長度。
Maximum 連線 Attempts 這是連線嘗試次數上限。 ExdiGdbSrv.dll嘗試建立與 GdbServer 的 RSP 連線時,會使用它。
SendPacketTimeout 這是 RSP 傳送逾時。
ReceivePacketTimeout 這是 RSP 接收逾時。
HostNameAndPort 這是格式<hostname/ip address:Port number>的 連接字串。 可以有多個 GdbServer 連接字串 (例如 T32 多核心 GdbServer 會話)。 連接字串 數目應該與核心數目相符。
ExdiGdbServerMemoryCommands 指定各種發出 GDB 記憶體命令的方式,以便取得不同例外狀況 CPU 層級的系統緩存器值或讀取/寫入存取記憶體(例如 BMC-OpenOCD 可透過 “aarch64 mrs nsec/sec <access code>” 自定義命令來存取 CP15 緩存器。
GdbSpecialMemoryCommand 如果為 「yes」,則 GDB 伺服器支援自定義的記憶體命令(例如系統快取器,這應該為 Trace32 GDB 伺服器設定)。
PhysicalMemory 如果為 「yes」,則 GDB 伺服器支援自定義命令來讀取物理記憶體(它設定為 Trace32 GDB 伺服器)。
SupervisorMemory 如果為 「yes」,則 GDB 伺服器支援自定義命令來讀取監督員記憶體(它設定為 Trace32 GDB 伺服器)。
SpecialMemoryRegister 如果為 「yes」,則 GDB 伺服器支援自訂命令來讀取系統快取器(它設定為 Trace32 GDB 伺服器)
SystemRegistersGdbMonitor 如果為 「yes」,則 GDB 伺服器會透過 GDB 監視器命令支援自定義命令(其設定為 BMC Open-OCD)。
SystemRegisterDecoding 如果為 「yes」,則 GDB 用戶端會在傳送 GDB 監視器命令之前接受譯碼。
ExdiGdbServerRegisters 指定特定的架構快取器核心集。
架構 已定義快取器集的CPU架構。
FeatureNameSupported 這是 xml 系統快取器描述檔所提供的系統快取器群組名稱。 需要識別系統註冊 xml 群組,該群組是 GDB 伺服器所傳送之 xml 檔案的一部分。
SystemRegistersStart 這是要識別作為核心緩存器集一部分回報的第一個系統緩存器(例如,在 X64 上,QEMU 不會將 x64 系統快取器集合報告為分隔的 xml 目標描述檔,因此系統 regs 是核心緩存器的一部分)。
SystemRegistersEnd 這是識別在核心緩存器集中回報的最後一個系統緩存器(高緩存器編號/順序)。
名稱 緩存器的名稱。
訂單 這是識別快取器陣列中索引的數位。 GDB 用戶端和伺服器集/查詢 (p<number>”/”q<number>) 註冊封包將會使用此數位。
大小 這是以位元組為單位的緩存器大小。

範例exdiConfigData.xml檔案

<ExdiTargets CurrentTarget = "QEMU">
<!-- QEMU SW simulator GDB server configuration -->
    <ExdiTargets CurrentTarget="QEMU">
    <!--  QEMU SW simulator GDB server configuration  -->
    <ExdiTarget Name="QEMU">
    <ExdiGdbServerConfigData agentNamePacket="" uuid="72d4aeda-9723-4972-b89a-679ac79810ef" displayCommPackets="yes" debuggerSessionByCore="no" enableThrowExceptionOnMemoryErrors="yes" qSupportedPacket="qSupported:xmlRegisters=aarch64,i386">
    <ExdiGdbServerTargetData targetArchitecture="ARM64" targetFamily="ProcessorFamilyARM64" numberOfCores="1" EnableSseContext="no" heuristicScanSize="0xfffe" targetDescriptionFile="target.xml"/>
    <GdbServerConnectionParameters MultiCoreGdbServerSessions="no" MaximumGdbServerPacketLength="1024" MaximumConnectAttempts="3" SendPacketTimeout="100" ReceivePacketTimeout="3000">
    <Value HostNameAndPort="LocalHost:1234"/>
    </GdbServerConnectionParameters>
    <ExdiGdbServerMemoryCommands GdbSpecialMemoryCommand="no" PhysicalMemory="no" SupervisorMemory="no" HypervisorMemory="no" SpecialMemoryRegister="no" SystemRegistersGdbMonitor="no" SystemRegisterDecoding="no"> </ExdiGdbServerMemoryCommands>
        <ExdiGdbServerRegisters Architecture = "ARM64" FeatureNameSupported = "sys">
            <Entry Name ="X0"  Order = "0" Size = "8" />
            <Entry Name ="X1"  Order = "1" Size = "8" />
            <Entry Name ="X2"  Order = "2" Size = "8" />
            <Entry Name ="X3"  Order = "3" Size = "8" />
            <Entry Name ="X4"  Order = "4" Size = "8" />
            <Entry Name ="X5"  Order = "5" Size = "8" />
            <Entry Name ="X6"  Order = "6" Size = "8" />
            <Entry Name ="X7"  Order = "7" Size = "8" />
            <Entry Name ="X8"  Order = "8" Size = "8" />
            <Entry Name ="X9"  Order = "9" Size = "8" />
            <Entry Name ="X10" Order = "a"  Size = "8" />
            <Entry Name ="X11" Order = "b"  Size = "8" />
            <Entry Name ="X12" Order = "c"  Size = "8" />
            <Entry Name ="X13" Order = "d"  Size = "8" />
            <Entry Name ="X14" Order = "e"  Size = "8" />
            <Entry Name ="X15" Order = "f"  Size = "8" />
            <Entry Name ="X16" Order = "10" Size = "8" />
            <Entry Name ="X17" Order = "11" Size = "8" />
            <Entry Name ="X18" Order = "12" Size = "8" />
            <Entry Name ="X19" Order = "13" Size = "8" />
            <Entry Name ="X20" Order = "14" Size = "8" />
            <Entry Name ="X21" Order = "15" Size = "8" />
            <Entry Name ="X22" Order = "16" Size = "8" />
            <Entry Name ="X23" Order = "17" Size = "8" />
            <Entry Name ="X24" Order = "18" Size = "8" />
            <Entry Name ="X25" Order = "19" Size = "8" />
            <Entry Name ="X26" Order = "1a" Size = "8" />
            <Entry Name ="X27" Order = "1b" Size = "8" />
            <Entry Name ="X28" Order = "1c" Size = "8" />
            <Entry Name ="fp"  Order = "1d" Size = "8" />
            <Entry Name ="lr"  Order = "1e" Size = "8" />
            <Entry Name ="sp"  Order = "1f" Size = "8" />
            <Entry Name ="pc"  Order = "20" Size = "8" />
            <Entry Name ="cpsr" Order = "21" Size = "8" />
            <Entry Name ="V0" Order = "22" Size = "16" />
            <Entry Name ="V1" Order = "23" Size = "16" />
            <Entry Name ="V2" Order = "24" Size = "16" />
            <Entry Name ="V3" Order = "25" Size = "16" />
            <Entry Name ="V4" Order = "26" Size = "16" />
            <Entry Name ="V5" Order = "27" Size = "16" />
            <Entry Name ="V6" Order = "28" Size = "16" />
            <Entry Name ="V7" Order = "29" Size = "16" />
            <Entry Name ="V8" Order = "2a" Size = "16" />
            <Entry Name ="V9" Order = "2b" Size = "16" />
            <Entry Name ="V10" Order = "2c" Size = "16" />
            <Entry Name ="V11" Order = "2d" Size = "16" />
            <Entry Name ="V12" Order = "2e" Size = "16" />
            <Entry Name ="V13" Order = "2f" Size = "16" />
            <Entry Name ="V14" Order = "30" Size = "16" />
            <Entry Name ="V15" Order = "31" Size = "16" />
            <Entry Name ="V16" Order = "32" Size = "16" />
            <Entry Name ="V17" Order = "33" Size = "16" />
            <Entry Name ="V18" Order = "34" Size = "16" />
            <Entry Name ="V19" Order = "35" Size = "16" />
            <Entry Name ="V20" Order = "36" Size = "16" />
            <Entry Name ="V21" Order = "37" Size = "16" />
            <Entry Name ="V22" Order = "38" Size = "16" />
            <Entry Name ="V23" Order = "39" Size = "16" />
            <Entry Name ="V24" Order = "3a" Size = "16" />
            <Entry Name ="V25" Order = "3b" Size = "16" />
            <Entry Name ="V26" Order = "3c" Size = "16" />
            <Entry Name ="V27" Order = "3d" Size = "16" />
            <Entry Name ="V28" Order = "3e" Size = "16" />
            <Entry Name ="V29" Order = "3f" Size = "16" />
            <Entry Name ="V30" Order = "3f" Size = "16" />
            <Entry Name ="V31" Order = "3f" Size = "16" />
            <Entry Name ="fpsr" Order = "40" Size = "4" />
            <Entry Name ="fpcr" Order = "41" Size = "4" />
        </ExdiGdbServerRegisters>


        <!-- x64 GDB server core resgisters -->
        <ExdiGdbServerRegisters Architecture = "X64" FeatureNameSupported = "sys" SystemRegistersStart = "18" SystemRegistersEnd = "20" >
            <Entry Name ="rax" Order = "0" Size ="8" />
            <Entry Name ="rbx" Order = "1" Size ="8" />
            <Entry Name ="rcx" Order = "2" Size ="8" />
            <Entry Name ="rdx" Order = "3" Size ="8" />
            <Entry Name ="rsi" Order = "4" Size ="8" />
            <Entry Name ="rdi" Order = "5" Size ="8" />
            <Entry Name ="rbp" Order = "6" Size ="8" />
            <Entry Name ="rsp" Order = "7" Size ="8" />
            <Entry Name ="r8"  Order = "8" Size ="8" />
            <Entry Name ="r9"  Order = "9" Size ="8" />
            <Entry Name ="r10" Order = "a" Size ="8" />
            <Entry Name ="r11" Order = "b" Size ="8" />
            <Entry Name ="r12" Order = "c" Size ="8" />
            <Entry Name ="r13" Order = "d" Size ="8" />
            <Entry Name ="r14" Order = "e" Size ="8" />
            <Entry Name ="r15" Order = "f" Size ="8" />
            <Entry Name ="rip" Order = "10" Size ="8" />
            <!-- <flags id="x64_eflags" size="4">
                <field name="" start="22" end="31"/>
                <field name="ID" start="21" end="21"/>
                <field name="VIP" start="20" end="20"/>
                <field name="VIF" start="19" end="19"/>
                <field name="AC" start="18" end="18"/>
                <field name="VM" start="17" end="17"/>
                <field name="RF" start="16" end="16"/>
                <field name="" start="15" end="15"/>
                <field name="NT" start="14" end="14"/>
                <field name="IOPL" start="12" end="13"/>
                <field name="OF" start="11" end="11"/>
                <field name="DF" start="10" end="10"/>
                <field name="IF" start="9" end="9"/>
                <field name="TF" start="8" end="8"/>
                <field name="SF" start="7" end="7"/>
                <field name="ZF" start="6" end="6"/>
                <field name="" start="5" end="5"/>
                <field name="AF" start="4" end="4"/>
                <field name="" start="3" end="3"/>
                <field name="PF" start="2" end="2"/>
                <field name="" start="1" end="1"/>
                <field name="CF" start="0" end="0"/>
            </flags> -->
            <Entry Name ="eflags" Order = "11" Size ="4" />

            <!-- Segment registers -->
            <Entry Name ="cs" Order = "12" Size ="4" />
            <Entry Name ="ss" Order = "13" Size ="4" />
            <Entry Name ="ds" Order = "14" Size ="4" />
            <Entry Name ="es" Order = "15" Size ="4" />
            <Entry Name ="fs" Order = "16" Size ="4" />
            <Entry Name ="gs" Order = "17" Size ="4" />

            <!-- Segment descriptor caches and TLS base MSRs -->
            <!--Entry Name ="cs_base" Order = "18" Size="8"/
            <Entry Name ="ss_base" Order = "18" Size ="8" />
            <Entry Name ="ds_base" Order = "19" Size ="8" />
            <Entry Name ="es_base" Order = "1a" Size ="8" /> -->
            <Entry Name ="fs_base" Order = "18" Size ="8" />
            <Entry Name ="gs_base" Order = "19" Size ="8" />
            <Entry Name ="k_gs_base" Order = "1a" Size ="8" />

            <!-- Control registers -->
            <!-- the cr0 register format fields:
            <flags id="x64_cr0" size="8">
            <field name="PG" start="31" end="31"/>
            <field name="CD" start="30" end="30"/>
            <field name="NW" start="29" end="29"/>
            <field name="AM" start="18" end="18"/>
            <field name="WP" start="16" end="16"/>
            <field name="NE" start="5" end="5"/>
            <field name="ET" start="4" end="4"/>
            <field name="TS" start="3" end="3"/>
            <field name="EM" start="2" end="2"/>
            <field name="MP" start="1" end="1"/>
            <field name="PE" start="0" end="0"/>
            </flags> -->
            <Entry Name ="cr0" Order = "1b" Size ="8" />
            <Entry Name ="cr2" Order = "1c" Size ="8" />

            <!-- the cr3 register format fields:
            <flags id="x64_cr3" size="8">
                <field name="PDBR" start="12" end="63"/>
                <field name="PCID" start="0" end="11"/>
            </flags> -->
            <Entry Name ="cr3" Order = "1d" Size ="8" />

            <!-- the cr4 register format fields:
            <flags id="x64_cr4" size="8">
                <field name="PKE" start="22" end="22"/>
                <field name="SMAP" start="21" end="21"/>
                <field name="SMEP" start="20" end="20"/>
                <field name="OSXSAVE" start="18" end="18"/>
                <field name="PCIDE" start="17" end="17"/>
                <field name="FSGSBASE" start="16" end="16"/>
                <field name="SMXE" start="14" end="14"/>
                <field name="VMXE" start="13" end="13"/>
                <field name="LA57" start="12" end="12"/>
                <field name="UMIP" start="11" end="11"/>
                <field name="OSXMMEXCPT" start="10" end="10"/>
                <field name="OSFXSR" start="9" end="9"/>
                <field name="PCE" start="8" end="8"/>
                <field name="PGE" start="7" end="7"/>
                <field name="MCE" start="6" end="6"/>
                <field name="PAE" start="5" end="5"/>
                <field name="PSE" start="4" end="4"/>
                <field name="DE" start="3" end="3"/>
                <field name="TSD" start="2" end="2"/>
                <field name="PVI" start="1" end="1"/>
                <field name="VME" start="0" end="0"/>
            </flags> -->
            <Entry Name ="cr4" Order = "1e" Size ="8" />
            <Entry Name ="cr8" Order = "1f" Size ="8" />

            <!-- the efer register format fields:
            <flags id="x64_efer" size="8">
            <field name="TCE" start="15" end="15"/>
            <field name="FFXSR" start="14" end="14"/>
            <field name="LMSLE" start="13" end="13"/>
            <field name="SVME" start="12" end="12"/>
            <field name="NXE" start="11" end="11"/>
            <field name="LMA" start="10" end="10"/>
            <field name="LME" start="8" end="8"/>
            <field name="SCE" start="0" end="0"/>
            </flags> -->
            <Entry Name ="efer" Order = "20" Size ="8"/>

            <!-- x87 FPU -->
            <Entry Name ="st0" Order = "21" Size ="10" />
            <Entry Name ="st1" Order = "22" Size ="10" />
            <Entry Name ="st2" Order = "23" Size ="10" />
            <Entry Name ="st3" Order = "24" Size ="10" />
            <Entry Name ="st4" Order = "25" Size ="10" />
            <Entry Name ="st5" Order = "26" Size ="10" />
            <Entry Name ="st6" Order = "27" Size ="10" />
            <Entry Name ="st7" Order = "28" Size ="10" />
            <Entry Name ="fctrl" Order = "29" Size ="4" />
            <Entry Name ="fstat" Order = "2a" Size ="4" />
            <Entry Name ="ftag"  Order = "2b" Size ="4" />
            <Entry Name ="fiseg" Order = "2c" Size ="4" />
            <Entry Name ="fioff" Order = "2d" Size ="4" />
            <Entry Name ="foseg" Order = "2e" Size ="4" />
            <Entry Name ="fooff" Order = "2f" Size ="4" />
            <Entry Name ="fop" Order = "30" Size ="4" />
            <Entry Name ="xmm0" Order = "31" Size ="16"  />
            <Entry Name ="xmm1" Order = "32" Size ="16"  />
            <Entry Name ="xmm2" Order = "33" Size ="16"  />
            <Entry Name ="xmm3" Order = "34" Size ="16"  />
            <Entry Name ="xmm4" Order = "35" Size ="16"  />
            <Entry Name ="xmm5" Order = "36" Size ="16"  />
            <Entry Name ="xmm6" Order = "37" Size ="16"  />
            <Entry Name ="xmm7" Order = "38" Size ="16"  />
            <Entry Name ="xmm8" Order = "39" Size ="16"  />
            <Entry Name ="xmm9" Order = "3a" Size ="16"  />
            <Entry Name ="xmm10" Order = "3b" Size ="16"  />
            <Entry Name ="xmm11" Order = "3c" Size ="16"  />
            <Entry Name ="xmm12" Order = "3d" Size ="16"  />
            <Entry Name ="xmm13" Order = "3e" Size ="16"  />
            <Entry Name ="xmm14" Order = "3f" Size ="16"  />
            <Entry Name ="xmm15" Order = "40" Size ="16"  />
            
            <!-- the mxcsr register format fields:
            <flags id="x64_mxcsr" size="4">
                <field name="IE" start="0" end="0"/>
                <field name="DE" start="1" end="1"/>
                <field name="ZE" start="2" end="2"/>
                <field name="OE" start="3" end="3"/>
                <field name="UE" start="4" end="4"/>
                <field name="PE" start="5" end="5"/>
                <field name="DAZ" start="6" end="6"/>
                <field name="IM" start="7" end="7"/>
                <field name="DM" start="8" end="8"/>
                <field name="ZM" start="9" end="9"/>
                <field name="OM" start="10" end="10"/>
                <field name="UM" start="11" end="11"/>
                <field name="PM" start="12" end="12"/>
                <field name="FZ" start="15" end="15"/>
            </flags> -->
            <Entry Name ="mxcsr" Order = "41" Size ="4" />

        </ExdiGdbServerRegisters>
    </ExdiGdbServerConfigData>
    </ExdiTarget>
    </ExdiTargets>
</ExdiTargets>

範例 EXDI PowerShell 腳本

此範例 PowerShell 腳本會安裝 EXDI,然後啟動調試程式。 Start-ExdiDebugger.ps1 腳本會視需要安裝ExdiGdbSrv.dll、設定 xml 配置檔、檢查是否執行dllhost.exe進程,以及啟動調試程式以聯機到已執行中的 gdb 伺服器硬體偵錯目標。

這是呼叫啟動腳本的範例。

PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64

您也可以視需要指定建置的檔案。

PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files"

Start-ExdiDebugger.ps1 具有下列設定選項。

參數 描述
ExdiTarget 要連線的目標類型。 這會對應至設定 xml 檔案中的特定區段
HostName 載入 gdb 伺服器工作階段之電腦的 IP 位址或主機名稱(預設為 “LocalHost” )
GdbPort gdb 伺服器正在接聽的埠。
架構 硬體偵錯目標的架構(此參數也表示 xml 設定檔中的 ArchitectureFamily 參數)
ExdiDropPath ExdiGdbSrv.dll、exdiConfigData.xml和systemregisters.xml檔案的位置。 只有在未安裝ExdiGdbSrv.dll或安裝不正確時,才會複製這些複本。
ExtraDebuggerArgs 在調試程式命令行上傳遞的額外自變數
PreNTAppDebugging 將啟發學習型ScanSize 的值從 0xfffe (最適合 NT) 變更為 0xffe (適用於預先 NT 應用程式)
DontTryDllHostCleanup 檢查dllhost.exe中現有執行中ExdiGdbSrv.dll實例需要提高許可權。 提供此參數可讓腳本在沒有提高許可權的情況下執行(雖然調試程式可能無法正常運作)。

若要啟用要顯示的封包,請將displayCommPackets的值設定為 yes。

    [pscustomobject]@{ Path = 'displayCommPackets'                                  ; value = "yes" } 
.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files"

如需更多設定選項,請參閱程式代碼批注。

<#
.Synopsis
    Installs and launches exdi debugger (automating xml file editing)

.Description
    This script will install ExdiGdbSrv.dll if required, configure the xml settings
    files, check for running dllhost.exe processes, and launch the debugger to connect to
    an already running gdb server hardware debugging target.

.Parameter ExdiTarget
    Type of target to connect to. This corresponds to a specific section in the settings xml file

.Parameter HostName
    IP address or hostname of the computer hosting the gdb server session (defaults to "LocalHost")

.Parameter GdbPort
    Port that the gdb server is listening on.

.Parameter Architecture
    Architecture of the hardware debugging target (this parameter also implies the ArchitectureFamily
    parameter in the xml settings file)

.Parameter ExdiDropPath
    Location of the ExdiGdbSrv.dll, exdiConfigData.xml, and systemregisters.xml files. These will
    only be copied if ExdiGdbSrv.dll is not installed or is installed incorrectly.

.Parameter ExtraDebuggerArgs
    Extra arguments to pass on the debugger command line

.Parameter PreNTAppDebugging
    Changes the value of the heuristicScanSize from 0xfffe (best for NT) to 0xffe (for pre-NT Apps)

.Parameter DontTryDllHostCleanup
    Checking for existing running instances of ExdiGdbSrv.dll in dllhost.exe requires elevation.
    Providing this switch will allow the script to run without elevation (although the debugger may not
    function correctly).

.Example
    >---------------- (first run) ------------<
    .\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files"

.Example
    PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64
#>

[CmdletBinding()]
param
(
    [ValidateSet("QEMU")]
    [string]
    $ExdiTarget = "QEMU",

    [string]
    $HostName = "LocalHost",

    [Parameter(Mandatory=$true)]
    [Int]
    $GdbPort,

    [Parameter(Mandatory=$true)]
    [string]
    [ValidateSet("x86", "x64", "arm64")]
    $Architecture,

    [string]
    $ExdiDropPath,

    [string]
    $DebuggerPath,

    [string[]]
    $ExtraDebuggerArgs = @(),

    [switch]
    $PreNTAppDebugging,

    [switch]
    $DontTryDllHostCleanup
)

$ErrorActionPreference = "Stop"

#region Functions

Function Test-Admin
{
    ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
}

Function Find-PathToWindbgX
{
    $InternalWindbgXPath = "$env:LOCALAPPDATA\DBG\UI\WindbgX.exe"
    $ExternalWindbgXPath = "$env:LOCALAPPDATA\Microsoft\WindowsApps\WinDbgX.exe"

    if (Test-Path $InternalWindbgXPath -PathType Leaf)
    {
        return $InternalWindbgXPath
    }
    elseif (Test-Path $ExternalWindbgXPath -PathType Leaf)
    {
        return $ExternalWindbgXPath
    }
}

Function Test-ParameterValidation
{
    $CommandName = $PSCmdlet.MyInvocation.InvocationName
    $ParameterList = (Get-Command -Name $CommandName).Parameters

    foreach ($Parameter in $ParameterList) {
        Get-Variable -Name $Parameter.Values.Name -ErrorAction SilentlyContinue | Out-String | Write-Verbose
    }

    if (-not $DebuggerPath)
    {
        throw "WindbgX is not installed"
    }
    elseif (-not (Test-Path $DebuggerPath -PathType Leaf))
    {
        throw "DebuggerPath param ($DebuggerPath) does not point to a debugger."
    }

    # Searching for loaded instances of ExdiGdbSrv.dll in dllhost.exe requires elevation
    if (-not $DontTryDllHostCleanup -and
        -not $(Test-Admin))
    {
        throw "Searching for loaded instances of ExdiGdbSrv.dll in dllhost.exe requires elevation. Run with the -DontTryDllHostCleanup parameter to skip this check (debugger session init may fail)."
    }
}

Function Get-ExdiInstallPath
{
    Get-ItemPropertyValue -Path "Registry::HKEY_CLASSES_ROOT\CLSID\{29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014}\InProcServer32" -Name "(default)" -ErrorAction SilentlyContinue
}

Function Test-ExdiServerInstalled
{
    # Check registration of exdi server class
    if ($(Get-ExdiInstallPath) -ne $null -and $(Test-Path "$(Get-ExdiInstallPath)"))
    {
        Write-Verbose "Exdi server is installed. Checking installation..."
        $ExdiInstallDir = [System.IO.Path]::GetDirectoryName($(Get-ExdiInstallPath))
        if (-not (Test-Path $ExdiInstallDir))
        {
            Write-Host "Currently Registered exdi server does not exist. Reinstalling..."
            return $false
        }
        elseif (-not ((Test-Path "$ExdiInstallDir\exdiConfigData.xml") -and (Test-Path "$ExdiInstallDir\systemregisters.xml")))
        {
            Write-Host "Currently Registered exdi server does not have required xml settings files. Reinstalling..."
            return $false
        }
        else
        {
            Write-Verbose "Exdi server is insalled correctly. Skipping installation..."
            return $true
        }
    }
    else
    {
        Write-Host "Exdi server is not installed. Installing..."
        return $false
    }
}

Function Install-ExdiServer
{
    [CmdletBinding()]
    param
    (
        [string] $InstallFrom,
        [string] $InstallTo
    )
    
    if (-not $(Test-Admin))
    {
        throw "Script needs to be run as an Admin to install exdi software."
    }

    New-Item -ItemType Directory $InstallTo -ErrorAction SilentlyContinue | Write-Verbose
    Copy-Item -Path "$InstallFrom\ExdiGdbSrv.dll" -Destination $InstallTo -ErrorAction stop | Write-Verbose
    Copy-Item -Path "$InstallFrom\exdiConfigData.xml" -Destination $InstallTo -ErrorAction stop | Write-Verbose
    Copy-Item -Path "$InstallFrom\systemregisters.xml" -Destination $InstallTo -ErrorAction stop | Write-Verbose
    regsvr32 /s "$InstallTo\ExdiGdbSrv.dll"

    if ($(Get-ExdiInstallPath) -eq $null)
    {
        throw "Unable to install exdi server"
    }
}

Function Edit-ExdiConfigFile
{
    [CmdletBinding()]
    param
    (
        [string] $ExdiFilePath,
        [string] $ExdiTargetType,
        [PSCustomObject[]] $XmlSettingPathValueList
    )
    
    # Edit exdiConfigData.xml
    [xml]$exdiConfigXml = Get-Content "$ExdiFilePath"

    # Set current target
    $exdiConfigXml.ExdiTargets.CurrentTarget = $ExdiTarget

    # set HostNameAndPort
    $ExdiTargetXmlNode = $exdiConfigXml.SelectSingleNode("//ExdiTargets/ExdiTarget[@Name='$ExdiTarget']/ExdiGdbServerConfigData")

    foreach ($XmlSettingPathValue in $XmlSettingPathValueList)
    {
        Write-Verbose "Processing $XmlSettingPathValue"
        if ($XmlSettingPathValue.Value -eq $null)
        {
            continue
        }

        $PathParts = $XmlSettingPathValue.Path.Split(".")
        $curNode = $ExdiTargetXmlNode
        if ($PathParts.Count -gt 1)
        {
            foreach ($PathPart in $PathParts[0..($PathParts.Count-2)])
            {
                Write-Verbose $PathPart
                $curNode = $curNode.($PathPart)
            }
        }
        $curNode.($PathParts[-1]) = $XmlSettingPathValue.Value
    }

    $exdiConfigXml.Save("$ExdiFilePath")
}

Function Stop-ExdiContainingDllHosts
{
    $DllHostPids = Get-Process dllhost | ForEach-Object { $_.Id }
    foreach ($DllHostPid in $DllHostPids)
    {
        $DllHostExdiDlls = Get-Process -Id $DllHostPid -Module | Where-Object { $_.FileName -like "*ExdiGdbSrv.dll" }
        if ($DllHostExdiDlls.Count -ne 0)
        {
            Write-Verbose "Killing dllhost.exe with pid $DllHostPid (Contained instance of ExdiGdbSrv.dll)"
            Stop-Process -Id $DllHostPid -Force
        }
    }
}

#endregion

#region Script

# Apply defaults for $DebuggerPath before Parameter validation
if (-not $DebuggerPath)
{
    $DebuggerPath = Find-PathToWindbgX
}

Test-ParameterValidation

# look clean up dllhost.exe early since it can hold a lock on files which
# need to be overwritten
if (-not $DontTryDllHostCleanup)
{
    Stop-ExdiContainingDllHosts
}

if (-not $(Test-ExdiServerInstalled))
{
    if (-not $ExdiDropPath)
    {
        throw "ExdiServer is not installed and -ExdiDropPath is not valid"
    }

    $ExdiInstallDir = Join-Path -Path "$([System.IO.Path]::GetDirectoryName($DebuggerPath))" -ChildPath "exdi"
    Install-ExdiServer -InstallFrom "$ExdiDropPath" -InstallTo "$ExdiInstallDir"
}

$SystemRegistersFilepath = Join-Path -Path "$([System.IO.Path]::GetDirectoryName($(Get-ExdiInstallPath)))" -ChildPath "systemregisters.xml"
$ExdiConfigFilepath      = Join-Path -Path "$([System.IO.Path]::GetDirectoryName($(Get-ExdiInstallPath)))" -ChildPath "exdiConfigData.xml"

# Calculate implied parameters
$HeuristicScanSize = if ($PreNTAppDebugging) { "0xffe" } else { "0xfffe" }
$ArchitectureFamily = switch($Architecture)
{
    x64   { "ProcessorFamilyx64" }
    x86   { "ProcessorFamilyx86" }
    arm64 { "ProcessorFamilyARM64" }
}

# Path is evaluated relative to the relevant ExdiTarget's ExdiGdbServerConfigData node in the xml schema
$SettingsToChange = @(
    [pscustomobject]@{ Path = 'GdbServerConnectionParameters.Value.HostNameAndPort' ; Value = "${HostName}:$GdbPort" },
    [pscustomobject]@{ Path = 'ExdiGdbServerTargetData.targetArchitecture'          ; Value = "$Architecture" },
    [pscustomobject]@{ Path = 'ExdiGdbServerTargetData.targetFamily'                ; Value = "$ArchitectureFamily" },
    [pscustomobject]@{ Path = 'ExdiGdbServerTargetData.heuristicScanSize'           ; Value = "$HeuristicScanSize" },
    [pscustomobject]@{ Path = 'displayCommPackets'                                  ; value = "no" }
)
Edit-ExdiConfigFile -ExdiFilePath "$ExdiConfigFilepath" -ExdiTargetType "$ExdiTarget" -XmlSettingPathValueList $SettingsToChange

# Set env vars for debugger
[System.Environment]::SetEnvironmentVariable('EXDI_GDBSRV_XML_CONFIG_FILE',"$ExdiConfigFilepath")
[System.Environment]::SetEnvironmentVariable('EXDI_SYSTEM_REGISTERS_MAP_XML_FILE',"$SystemRegistersFilepath")

$DebuggerArgs = @("-v", "-kx exdi:CLSID={29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014},Kd=Guess,DataBreaks=Exdi")
Write-Verbose "DebuggerPath = $DebuggerPath"
Start-Process -FilePath "$DebuggerPath" -ArgumentList ($DebuggerArgs + $ExtraDebuggerArgs)

#endregion

另請參閱

使用 EXDI 設定 QEMU 內核模式偵錯

.exdicmd (EXDI 命令)

自動設定 KDNET 網路核心偵錯

手動設定 KDNET 網路核心偵錯

手動設定核心模式偵錯