LIST_ENTRY に関するデバッグコマンド
LIST_ENTRY に関するデバッグ方法
この資料では LIST_ENTRY の仕組みと利用方法 で作成したプログラムを利用して、 LIST_ENTRY に関するデバッグ方法、デバッグコマンドを紹介します。
デバッガで LIST_ENTRY をどのようにたどって、 どのように元のデータを確認できるか示します。
以下のデバッグログでは、listtest.exe をスタートした後、 listtest!PrintAllItems にブレークポイントを設定しています。 このブレークポイントがヒットしたところでは、既に LIST_ENTRY にデータがぶら下がっているはずですから、そこでデータを見てみましょう。
尚、リストヘッドはわざとらしく (笑)、LIST_ENTRY g_MyListdata グローバル変数に置いてますから、 dl コマンドで簡単に出力できます。
>c:\debuggers\cdb listtest Microsoft (R) Windows Debugger Version 6.11.0001.404 X86 Copyright (c) Microsoft Corporation. All rights reserved. CommandLine: listtest Symbol search path is: srv*C:\websymbols*http://msdl.microsoft.com/download/symbols Executable search path is: ModLoad: 00400000 00423000 listtest.exe ModLoad: 77290000 773b7000 ntdll.dll ModLoad: 75d50000 75e2c000 C:\Windows\system32\kernel32.dll (1b4.ea0): Break instruction exception - code 80000003 (first chance) eax=00000000 ebx=00000000 ecx=0012faf8 edx=772f5e74 esi=fffffffe edi=772dc19e eip=772d8b2e esp=0012fb10 ebp=0012fb40 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 ntdll!DbgBreakPoint: 772d8b2e cc int 3 0:000> x listtest!Print* 00401110 listtest!PrintAllItems (void) 0040ae02 listtest!printf (char *) 0040aee3 listtest!printf_s (char *) 0:000> bp listtest!PrintAllItems 0:000> g --- Add Three Items --- Adding: Outlook Adding: Excel Adding: Word Breakpoint 0 hit eax=00221458 ebx=7ffdd000 ecx=00221688 edx=00420f40 esi=00000000 edi=00000000 eip=00401110 esp=0012ff3c ebp=0012ff40 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 listtest!PrintAllItems: 00401110 55 push ebp 0:000> x listtest!g_* 004215a0 listtest!g_pfnRtlGenRandom = 0x57490b77 00420f40 listtest!g_MyListdata = struct _LIST_ENTRY [ 0x221688 - 0x221228 ] 0:000> dl listtest!g_MyListdata 00420f40 00221688 00221228 00000000 00000000 00221688 00221458 00420f40 00000000 006f0057 00221458 00221228 00221688 00000000 00780045 00221228 00420f40 00221458 00000000 0075004f 0:000> dt listtest!_MY_LISTDATA +0x000 data1 : Uint4B +0x004 data2 : Uint4B +0x008 linkField : _LIST_ENTRY +0x010 data3 : Uint4B +0x014 szName : [256] Wchar +0x214 data4 : Uint4B 0:000> dt listtest!_MY_LISTDATA 00221688-0x8 +0x000 data1 : 0 +0x004 data2 : 0 +0x008 linkField : _LIST_ENTRY [ 0x221458 - 0x420f40 ] +0x010 data3 : 0 +0x014 szName : [256] "Word" +0x214 data4 : 0 0:000> dt listtest!_MY_LISTDATA 00221458-0x8 +0x000 data1 : 0 +0x004 data2 : 0 +0x008 linkField : _LIST_ENTRY [ 0x221228 - 0x221688 ] +0x010 data3 : 0 +0x014 szName : [256] "Excel" +0x214 data4 : 0 0:000> dt listtest!_MY_LISTDATA 00221228-0x8 +0x000 data1 : 0 +0x004 data2 : 0 +0x008 linkField : _LIST_ENTRY [ 0x420f40 - 0x221458 ] +0x010 data3 : 0 +0x014 szName : [256] "Outlook" +0x214 data4 : 0 0:000>
上記では dt listtest!_MY_LISTDATA で MY_LISTDATA の内容を確認することで、 LIST_ENTRY が MY_LISTDATA の先頭から 0x008 のオフセットにあることを確認しています。
従って、逆に LIST_ENTRY の場所から MY_LISTDATA の先頭を求めるには、 LIST_ENTRY のアドレスから -0x008 としています。
!list コマンドの活用
さらに、上記の内容を !list コマンドで自動化すると、次のようになります。(コマンドは実際は一行)
0:000> dd listtest!g_MyListdata l2 00420f40 00221688 00221228 0:000> !list "-t ntdll!_LIST_ENTRY.Flink -e -x \"dt listtest!_MY_LISTDATA @$extret-0x8\" 00221688" dt listtest!_MY_LISTDATA @$extret-0x8 +0x000 data1 : 0 +0x004 data2 : 0 +0x008 linkField : _LIST_ENTRY [ 0x221458 - 0x420f40 ] +0x010 data3 : 0 +0x014 szName : [256] "Word" +0x214 data4 : 0 dt listtest!_MY_LISTDATA @$extret-0x8 +0x000 data1 : 0 +0x004 data2 : 0 +0x008 linkField : _LIST_ENTRY [ 0x221228 - 0x221688 ] +0x010 data3 : 0 +0x014 szName : [256] "Excel" +0x214 data4 : 0 dt listtest!_MY_LISTDATA @$extret-0x8 +0x000 data1 : 0 +0x004 data2 : 0 +0x008 linkField : _LIST_ENTRY [ 0x420f40 - 0x221458 ] +0x010 data3 : 0 +0x014 szName : [256] "Outlook" +0x214 data4 : 0 0:000>