次の方法で共有


EXDI を使用した QEMU カーネルモード デバッグのセットアップ

このトピックでは、Windows デバッガーで EXDI を使用して QEMU カーネル モード デバッグを設定する方法について説明します。

EXDI 接続の構成およびトラブルシューティングのセットアップに関する一般的な情報については 「EXDI デバッガー トランスポートの構成」を参照してください。

仮想化およびマシン エミュレーション ソフトウェアである QEMU を使用して、ホストとして機能する他のオペレーティング システム (Linux など) に接続できます。 QEMU 自体は、x64 や Arm64 などの多数のアーキテクチャで実行できます。 ExdiGdb デバッグ サーバーは、他のプロセッサもサポートしています。たとえば、WinDbg を使用して x64 で実行されている QEMU をデバッグし、Arm64 をエミュレートすることができます。 EXDI を使用すると、OS が読み込まれる前であっても、ブート プロセスの早い段階で VM を HW デバッグすることもできます。

Note

EXDI は、特定の環境向けの高度で特殊な形式のデバッグです。 標準の KDNET 接続を使用するほうが構成が容易であり、推奨されます。 ネットワーク デバッグを自動的にセットアップするには、「KDNET ネットワーク カーネル デバッグの自動セットアップ」を参照してください。

EXDI COM サーバー

EXDI は、ハードウェア デバッガ (JTAG ベース、GdbServer ベースなど) のサポートを追加することで WinDbg を拡張できるインターフェイスです。 次の図は、EXDI-GdbServer の役割を示しています。

上に WinDbg-DbgEng がある EXDI-GdbServer、EXDI インターフェイス、GDB サーバーと通信する EXDI COM サーバーの役割を示すスタック図。

重要

EXDI は KDNET プロトコルを使用しないため、接続されたデバッガーでは、PC 上で実行されている内容に関する情報が大幅に少なく、多くのコマンドで動作が異なるか、まったく機能しない可能性があります。 デバッグ対象のコードのプライベート シンボルにアクセスすることで、デバッガーがターゲット システムのコード実行について、より詳細に把握するのに役立ちます。 詳細については、「パブリック シンボルとプライベート シンボル」を参照してください。

QEMU 上の Windows イメージへのデバッガー接続をセットアップする

これらの手順では、Windows 上でも実行されている Windbg クライアント (EXDI COM サーバーを使用) に GDB サーバーを公開する Windows x64 仮想マシンにアタッチする方法について説明します。 WinDbg ExdiGdbSrv.dll (GDB サーバー クライアント) と QEMU GDB サーバーの間の GdbServer RSP セッションが使用されます。

  1. Windows に QEMU をダウンロードしてインストールします。
  2. デバッグに必要なネットワークと BIOS/UEFI 設定を使用して起動するように、ターゲット QEMU 仮想 Windows イメージを構成します。
  3. 起動スクリプトを使用して QEMU 環境を起動します。
  4. QEMU で GdbServer を起動します。
  5. ネットワーク接続を確認し、ターゲット イメージの IP アドレスを見つけて記録します。 (HOST IP default address of LocalHost, and port of 1234).
  6. Windows デバッグ ツールをホスト システムにダウンロードしてインストールします。
  7. コマンド ラインまたは UI を使用して WinDbg を起動し、EXDI サーバーに接続します。
  8. WinDbg を使用して、ターゲット QEMU Windows イメージをデバッグします。

QEMU オープン ソース コンピューター エミュレーター

QEMU は、動的翻訳を引き起こす汎用のオープン ソースのマシン エミュレーターおよび仮想化器です。 QEMU をマシン エミュレータとして使用する場合、あるプロセッサー (Arm64など) 用に作成された OS とプログラムを別のマシン (x64 PC) で実行できます。 さまざまな OS (Windows/Linux/Mac) の仮想マシン イメージを実行/ホストすることもできます。

QEMU は KVM などの他のハイパーバイザーで動作し、仮想化に CPU 拡張機能 (HVM) を使用できます。 QEMU がバーチャライザーとして使用される場合、QEMU はゲスト コードをホスト CPU 上で直接実行することにより、ネイティブに近いパフォーマンスを実現します。 QEMU は、OS ハイパーバイザー機能を利用して、CPU および MMU エミュレーションを実際のハードウェアにオフロードできます。

QEMU をダウンロードしてインストールする

このウォークスルーでは、Windows x64 用 QEMU が、Windows デバッガーも実行される x64 PC にインストールされます。

QEMU ダウンロード ページから QEMU をダウンロードします。 https://www.qemu.org/download/

QEMU のインストールについては、QEMU のドキュメントを参照してください。 https://www.qemu.org/documentation/

ターゲット仮想ディスクの構成

デバッグするソフトウェアが含まれる仮想ディスク イメージを検索または作成します。

この例では、Windows x64 VHDX 仮想マシンのディスク イメージが使用されます。 Windows 仮想マシン イメージの詳細については、「Windows 10 で Hyper-V を使用して仮想マシンを作成する」を参照してください。

VirtIO ドライバーを Windows イメージに挿入する

ネットワーク機能と適切なストレージ デバイスのパフォーマンスを可能にするには、VirtIO ドライバーを Windows 仮想マシンのディスク イメージに挿入またはインストールします。 VirtIO ドライバーは、ここで入手できます。 https://github.com/virtio-win/kvm-guest-drivers-windows

VirtIO は、仮想マシンがブロック デバイス、ネットワーク アダプター、コンソールなどの抽象化されたハードウェアにアクセスできるようにする標準化されたインターフェイスです。 VirtIO は、QEMU のような仮想化環境のハードウェア デバイスの抽象化レイヤーとして機能します。

Windows イメージに VirtIO ドライバーを挿入するには、次の手順に従います。

  1. フォルダー内の VirtIo ドライバーを抽出します (例: C:\VirtIo_Drivers)。
  2. エクスプローラーで VHDX をダブルクリックして、Windows x64 仮想マシンを含む VHDX をマウントします (diskpart も使用できます)。 Windows では、"L:" などの特定の文字を使用して VHDX がマウントされます
  3. Dism: dism /image:L: /Add-Driver /driver:C:\VirtIo_Drivers を使用してマウントされたイメージにドライバーを挿入する DISM の詳細については、「 DISM の概要を参照してください。
  4. プロセスが完了したら、イメージのマウントを解除し、VHDX から QEMU への変換に進むことができます。

VHDX から QEMU への変換

この手順は必須ではありませんが、VHDX の代わりにネイティブ QEMU QCOW イメージを使用するとパフォーマンスが向上するため、この手順をお勧めします。

次の qemu-img.exe コマンドを使用して、vhdx を変換します。 このユーティリティは、QEMU をインストールした場所 (例:C:\Program Files\qemu ) にあります。

C:\Program Files\qemu> qemu-img convert -c -p -O qcow2 MyVHDXFile.vhdx MyQEMUFile.qcow2 

UEFIファームウェアをダウンロードする

最良の結果を得るには、UEFI ファームウェア ファイル (OVMF.fd) をダウンロードまたはコンパイルします。 ファームウェアが必要なのは、そうでない場合、デフォルトで QEMU が古い BIOS システムをエミュレートするためです。

UEFI ファームウェアのソースの 1 つは、Open Clear Linux プロジェクトです。 https://clearlinux.org/

UEFI OVMF.fdファイルの例はここから入手できます。 https://github.com/clearlinux/common/tree/master/OVMF.fd

ダウンロードしたファイルの内容を C:\Program Files\qemu\Firmwareで解凍します。

Intel AMD64 以外のプラットフォームの場合は、EDK2 からファームウェアをコンパイルする必要があります。 詳細については、https://github.com/tianocore/tianocore.github.io/wiki/How-to-build-OVMFを参照してください。

QEMU 起動スクリプトの構成

QEMU で構成ファイルを作成します。 たとえば、QEMU ルート ディレクトリの下に StartQEMUx64Windows.bat ファイルを作成します。 以下のファイル例を参照してください。

QEMU 起動スクリプトを使用して QEMU を起動します

QEMU 起動スクリプトを実行して QEMU を起動します。

c:\Program Files\qemu\StartQEMUx64Windows.bat

ファイアウォール防御プロンプトが表示された場合は、ホスト デバッガー マシンの Windows ファイアウォールを介して Windbg を有効にするために、アプリにすべての種類のネットワークに対するすべての権限を付与します。

3 つのオプションがすべてチェックされた [Windows Defender ファイアウォール] ダイアログ ボックス。

Windows 仮想マシンが QEMU 環境で起動されると、QEMU UI が表示されます。

ビュー メニュー オプションが表示されている QEMU のスクリーンショット。

CTRL+ALT+数字キーの組み合わせを使用して、QEMU モニター コンソールに移動します。 このモニターは、View->compatmonitor を使用しても利用できます。

QEMU でフロントエンド GDB サーバーを起動するためにgdbserverを入力します。

QEMU が表示するはずです Waiting for gdb connection on device ‘tcp::1234’

CTRL+ALT+1 キーの組み合わせを使用してメイン ウィンドウに戻ります。

ヒント: GDB コンソール ウィンドウでは、エミュレーションをすばやく再起動するための system_reset コマンドがサポートされています。 GDB コンソール コマンドの一覧に「 help 」と入力します。

QEMU x64 Windows VM 起動スクリプトのサンプル

AMD64 仮想マシンに使用できる QEMU 構成スクリプトの例を次に示します。 DISK および CDROM ファイルを指すリンクを PC 上の場所に置き換えます。

    REM
    REM  This script is used to run a Windows x64 VM on QEMU that is hosted by a Windows x64 host system
    REM  The Host system is a PC with Intel(R) Xeon(R) CPU.
    REM
    set EXECUTABLE=qemu-system-x86_64
    set MACHINE=-m 6G -smp 4

    REM No acceleration
    REM generic cpu emulation.
    REM to find out which CPU types are supported by the QEMU version on your system, then run:
    REM	 qemu-system-x86_64.exe -cpu help
    REM the see if your host system CPU is listed
    REM

    set CPU=-machine q35 

    REM Enables x64 UEFI-BIOS that will be used by QEMU :
    set BIOS=-bios "C:\Program Files\qemu\Firmware\OVMF.fd"

    REM  Use regular GFX simulation
    set GFX=-device ramfb -device VGA 
    set USB_CTRL=-device usb-ehci,id=usbctrl
    set KEYB_MOUSE=-device usb-kbd -device usb-tablet

    REM # The following line enable the full-speed HD controller (requires separate driver)
    REM # Following line uses the AHCI controller for the Virtual Hard Disk:
    set DRIVE0=-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0

    REM
    REM This will set the Windows VM x64 disk image that will be launched by QEMU
    REM The disk image is in the qcow2 format accepted by QEMU.
    REM You get the .qcow2 image, once you get the VHDX Windows VM x64 image 
    REM and apply the script to inject the virtio x64 drivers and then run the 
    REM the QEMU tool to convert the .VHDX image to .qcow2 format
    REM 	i.e. 
    REM	qemu-img convert -c -p -O qcow2 Windows_VM_VHDX_with_injected_drivers_file.vhdx file.qcow2
    REM file : points to the specified qcow2 image path.
    REM
    set DISK0=-drive id=disk,file="C:\Program Files\qemu\MyQEMUFile.qcow2",if=none

    REM
    REM for kdnet on, then best option:
    REM   NETWORK0="-netdev user,id=net0,hostfwd=tcp::53389-:3389,hostfwd=tcp::50001-:50001 -device virtio-net,netdev=net0,disable-legacy=on"
    REM
    REM Create a mapping for the RDP service from port 3389 to 3589.
    REM
    set NETHOST=-netdev user,id=net0,hostfwd=tcp::3589-:3389
    set NETGUEST=-device e1000,netdev=net0

    REM # The following line should enable the Daemon (instead of interactive)
    set DAEMON=-daemonize"
    %EXECUTABLE% %MACHINE% %CPU% %BIOS% %GFX% %USB_CTRL% %DRIVE0% %DISK0% %NETHOST% %NETGUEST%

ネットワーク接続

ローカル ホスト

GDB サーバーが正常に起動した場合は、GDB サーバーがリッスンするポート番号が表示され、このポートを使用してホスト デバッガー IP:Port ペアをセットアップする必要があります。

ホスト デバッガーが QEMU ゲストをホストするコンピューターと同じコンピューターにある場合、Localhost 識別子は IP:Port ペアで使用されます。 この例では、同じ PC 上のサーバーデバッガーとホスト デバッガーを使用して、 LocalHost:1234 が使用されます。

リモート ホスト

リモート PC で作業している場合は、Windows IP アドレスを見つけます (デバッガー ホスト セッションが QEMU VM と同じ Windows マシンに配置されない場合)。

ターゲット QEMU IP <address>:<port number> は EXDI UI で構成されます。

QEMU コンソール (compatmonitor0) で次のコマンドを実行すると、ネットワークと接続ステータスに関する情報を表示できます。

info network
info usernet

QEMU ネットワーキングの詳細については、次を参照してください。 https://wiki.qemu.org/Documentation/Networking

Windows デバッグ ツールをホスト システムにダウンロードしてインストールします。

ホスト システムに Windows デバッグ ツールをインストールします。 デバッガー ツールのダウンロードとインストールについては、「Windows 用デバッグ ツール」を参照してください。

ホスト システムで WinDbg を起動します。

ここで説明するシナリオでは、EXDI UI で接続する次のオプションを設定します。

ターゲットの種類 - QEMU

ターゲット アーキテクチャ - x64

ターゲット OS - Windows

画像スキャンヒューリスティック サイズ - 0xFFE - NT

Gdb サーバーとポート - LocalHost:1234

接続の中断 - yes

Windbg EXDI カーネル接続 UI。IP アドレスとポート アドレスを含む接続オプションが表示されます。

EXDI UI の使用をお勧めしますが、ここに示すようなコマンド ライン オプションを使用して WinDbg を起動することもできます。

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

コマンド ラインを使用する場合、IP アドレスとポートは exdiConfigData.xml ファイルを使用して構成されます。 詳細については、EXDI XML 構成ファイルを参照してください。

追加の出力を表示するには、-v:verbose セッションを使用できます。 WinDbg オプションの一般的な情報については、「WinDbg コマンド ライン オプション」を参照してください。

デバッガーが起動し、QEMU GdbServer に接続する必要があります。

ウィンドウ タイトルに EXDI CLSID が表示されているメインの WinDbg セッション。

デバッガーに、成功した EXDI トランスポートの初期化が表示されます。

EXDI: DbgCoInitialize returned 0x00000001
EXDI: CoCreateInstance() returned 0x00000000
EXDI: QueryInterface(IExdiServer3) returned 0x00000000
Target command response: QEMU
exdiCmd: The function: 'ExdiDbgType' was completed.
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

EXDIGdbServer コンソール パケット ウィンドウでは、[詳細オプション] の下で *"Show 通信パケット ログ がオンに設定されている場合、EXDI 接続の状態に関する情報を表示することもできます。 詳細については、「EXDI デバッガー トランスポートの構成」のトラブルシューティング情報を参照してください。

WinDbg を使用してターゲット QEMU Windows イメージをデバッグする

dbgeng.dll はヒューリスティック アルゴリズムを使用して、break コマンドが発生した時点の NT ベース ロード アドレスの場所を見つけます。 プライベート シンボルを使用できない場合、このプロセスは失敗します。

これは、多くの接続シーケンスでは、break が期待どおりに機能しないことを意味します。 手動でコードを一時停止すると、その時点で Windows が実行していたランダムな場所になります。 ターゲット コードのシンボルを使用できない可能性があるため、シンボルを使用してブレークポイントを設定することが困難な場合があります。

使用可能なデバッガー メモリ アクセス コマンド

メモリに直接アクセスする次のようなコマンドは機能します。

k、kb、kc、kd、kp、kP、kv (スタック バックトレースの表示)

r (レジスタ)

d、da、db、dc、dd、dD、df、dp、dq、du、dw (メモリの表示)

u (逆アセンブル)

コードをステップ実行することもできます。

p(ステップ)

デバッグしたいコードを見つけるために使用できるコマンドもあります。

s (メモリの検索)

.imgscan (イメージ ヘッダーの検索)

従来の KDNET ベースのカーネル デバッグとは異なり、シンボルに基づいてブレークポイントを設定できない場合があるため、Imgscan は EDXI デバッグで役立ちます。 目的のターゲット イメージの場所を特定することで、その場所を使用してメモリ アクセス ブレークポイントを簡単に設定できるようになります。

.exdicmd (EXDI コマンド)

.exdicmd は、アクティブな EXDI デバッグ接続を使用して、EXDI コマンドをターゲット システムに送信します。 詳細については、「.exdicmd (EXDI コマンド)」を参照してください。

トラブルシューティング

EXDI デバッガー トランスポートの構成」のトラブルシューティング情報を参照してください。

関連項目

EXDI デバッガー トランスポートの構成

EXDI XML 構成ファイル

.exdicmd (EXDI コマンド)

KDNET ネットワーク カーネル デバッグの自動設定

KDNET ネットワーク カーネル デバッグの手動設定