EnglishFrenchGermanItalianPortugueseSpanish

Адрес модуля в WinDbg

Довольно часто я сталкиваюсь с тем, что необходимо получить имя модуля по какому-либо адресу внутри него. Например, для того, чтобы загрузить символы этого модуля. Отладчик использует отложенную загрузку символов (deferred symbol loading или lazy symbol loading) и выражается она в том, что символы подгружаются только тогда, когда они нужны. Делается это специально, иначе программист устанет ждать, когда же загрузятся все символы. Я, кстати, не знаю в чем смысл «когда они нужны». Эта тайна доступна лишь программистам WinDbg.

И так часто бывает, что по команде lm видны лишь несколько модулей ядра:

kd> lm

start end module name
8181c000 81bd5000 nt (pdb symbols) c:\symserver\ntkrpamp.pdb\37D328E3BAE5460F8E662756ED80951D2\ntkrpamp.pdb

Unloaded modules:
85b4a000 85b57000 crashdmp.sys
85b57000 85b61000 dump_storport.sys
85b61000 85b7b000 dump_LSI_SCSI.sys
85b7b000 85b8c000 dump_dumpfve.sys

Рассмотрим типичную ситуацию, в которой необходимо получить имя модуля по адресу в его образе:

kd> !devstack \Device\Harddisk0\DR0

!DevObj !DrvObj !DevExt ObjectName
84680d20 \Driver\partmgr 84680dd8
> 8457d1e0 \Driver\disk 8457d298 DR0
83d03708 \Driver\LSI_SCSI 83d037c0 0000004b

!DevNode 83d031d0 :

DeviceInst is «SCSI\Disk&Ven_VMware_&Prod_VMware_Virtual_S\4&2b9256da&0&000000″

ServiceName is «disk»

kd> !devobj 83d03708
Device object (83d03708) is for:
0000004b \Driver\LSI_SCSI DriverObject 833bbb98
Current Irp 00000000 RefCount 0 Type 00000007 Flags 00001050
Dacl 87c8f334 DevExt 83d037c0 DevObjExt 83d03a38 DevNode 83d031d0
ExtensionFlags (0×00000800)
Unknown flags 0×00000800
AttachedDevice (Upper) 8457d1e0 \Driver\disk
Device queue is not busy.

kd> !drvobj 833bbb98 2
Driver object (833bbb98) is for:
\Driver\LSI_SCSI
DriverEntry: 81fec005
DriverStartIo: 00000000
DriverUnload: 807b9a50
AddDevice: 807b379c

Dispatch routines:

[00] IRP_MJ_CREATE 807e460a +0x807e460a
[01] IRP_MJ_CREATE_NAMED_PIPE 81841fef nt!IopInvalidDeviceRequest
[02] IRP_MJ_CLOSE 807e4565 +0x807e4565
[03] IRP_MJ_READ 81841fef nt!IopInvalidDeviceRequest
[04] IRP_MJ_WRITE 81841fef nt!IopInvalidDeviceRequest
[05] IRP_MJ_QUERY_INFORMATION 81841fef nt!IopInvalidDeviceRequest
[06] IRP_MJ_SET_INFORMATION 81841fef nt!IopInvalidDeviceRequest
[07] IRP_MJ_QUERY_EA 81841fef nt!IopInvalidDeviceRequest
[08] IRP_MJ_SET_EA 81841fef nt!IopInvalidDeviceRequest
[09] IRP_MJ_FLUSH_BUFFERS 81841fef nt!IopInvalidDeviceRequest
[0a] IRP_MJ_QUERY_VOLUME_INFORMATION 81841fef nt!IopInvalidDeviceRequest
[0b] IRP_MJ_SET_VOLUME_INFORMATION 81841fef nt!IopInvalidDeviceRequest
[0c] IRP_MJ_DIRECTORY_CONTROL 81841fef nt!IopInvalidDeviceRequest
[0d] IRP_MJ_FILE_SYSTEM_CONTROL 81841fef nt!IopInvalidDeviceRequest
[0e] IRP_MJ_DEVICE_CONTROL 807e46cb +0x807e46cb
[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL 807b3ee3 +0x807b3ee3
[10] IRP_MJ_SHUTDOWN 81841fef nt!IopInvalidDeviceRequest
[11] IRP_MJ_LOCK_CONTROL 81841fef nt!IopInvalidDeviceRequest
[12] IRP_MJ_CLEANUP 81841fef nt!IopInvalidDeviceRequest
[13] IRP_MJ_CREATE_MAILSLOT 81841fef nt!IopInvalidDeviceRequest
[14] IRP_MJ_QUERY_SECURITY 81841fef nt!IopInvalidDeviceRequest
[15] IRP_MJ_SET_SECURITY 81841fef nt!IopInvalidDeviceRequest
[16] IRP_MJ_POWER 807b998f +0x807b998f
[17] IRP_MJ_SYSTEM_CONTROL 807e48fe +0x807e48fe
[18] IRP_MJ_DEVICE_CHANGE 81841fef nt!IopInvalidDeviceRequest
[19] IRP_MJ_QUERY_QUOTA 81841fef nt!IopInvalidDeviceRequest
[1a] IRP_MJ_SET_QUOTA 81841fef nt!IopInvalidDeviceRequest
[1b] IRP_MJ_PNP 807e629c +0x807e629c

kd> lma 0x807e46cb

start end module name

Команда lm с параметром a Address должна вывести имя модуля, в котором содержится данный адрес, но символы не загружены и список модулей практически пуст. Как вариант – это загрузить все символы для всех модулей ядра, но, не загружая их.

kd> .reload /n /s
Connected to Windows Server 2008/Windows Vista 6001 x86 compatible target at (Fri Nov 20 15:54:17.231 2009 (GMT+3)), ptr64 FALSE
Loading Kernel Symbols
………………………………………………………
……………………………………………………….
…..
Loading unloaded module list
….
kd> lm
start    end        module name
8060e000 80616000   kdcom      (deferred)
80616000 80676000   mcupdate_GenuineIntel   (deferred)
80676000 80687000   PSHED      (deferred)
80687000 8068f000   BOOTVID    (deferred)
8068f000 806d0000   CLFS       (deferred)
806d0000 807b0000   CI         (deferred)
807b0000 807f1000   storport   (deferred)
8181c000 81bd5000   nt         (pdb symbols)          c:\symserver\ntkrpamp.pdb\37D328E3BAE5460F8E662756ED80951D2\ntkrpamp.pdb
81bd5000 81c08000   hal        (deferred)
81e0e000 81e8a000   Wdf01000   (deferred)
81e8a000 81e97000   WDFLDR     (deferred)

Unloaded modules:
85b4a000 85b57000   crashdmp.sys
85b57000 85b61000   dump_storport.sys
85b61000 85b7b000   dump_LSI_SCSI.sys
85b7b000 85b8c000   dump_dumpfve.sys

Как мы видим, информация о модулях обновилась, а загрузка символов все еще отложена. Теперь попробуем еще раз воспользоваться командой lm:

kd> lma 0x807e46cb
start    end        module name
807b0000 807f1000   storport   (deferred)

Вот мы и получили имя модуля и можем подгрузить только его символы.

Альтернативный вариант – воспользоваться скриптовым языком отладчика и перечислить все модули ядра:

$$ pointer to modules list
r $t0 = nt!PsLoadedModuleList
 
	.echo "Section             Start               End                 Name"
 
.for ( r $t1 = poi(@$t0);
       (@$t1 != 0) & (@$t1 != @$t0);
       r $t1 = poi(@$t1) )
{
    r? $t2 = #CONTAINING_RECORD( @$t1, nt!_LDR_DATA_TABLE_ENTRY, InLoadOrderLinks );
    as /x ${/v:$Section} @$t2
 
    $$  Get image name into $DriverName
    as /msu ${/v:$DriverName} @@c++(&@$t2->BaseDllName)
    $$  Get image base into $Start
    as /x ${/v:$Start} @@c++(@$t2->DllBase)
    $$  Get image base + image size into $End
    as /x ${/v:$End} ( @@c++(@$t2->DllBase) + @@c++(@$t2->SizeOfImage) )
 
    .block
    {
        .echo ${$Section}: ${$Start}: ${$End}: ${$DriverName}
    }
 
    ad ${/v:$End}
    ad ${/v:$Start}
    ad ${/v:$DriverName}
    ad ${/v:$Section}
}

kd> $$>a< c:\dbg_get_kernel_modules.txt
Section Start End Name
0xffffffff82f69ba0: 0xffffffff8181c000: 0xffffffff81bd5000: ntoskrnl.exe
0xffffffff82f69b30: 0xffffffff81bd5000: 0xffffffff81c08000: hal.dll
0xffffffff82f69ab8: 0xffffffff8060e000: 0xffffffff80616000: kdcom.dll
0xffffffff82f69a40: 0xffffffff80616000: 0xffffffff80676000: mcupdate.dll
0xffffffff82f699c8: 0xffffffff80676000: 0xffffffff80687000: PSHED.dll
0xffffffff82f69950: 0xffffffff80687000: 0xffffffff8068f000: BOOTVID.dll
0xffffffff82f698e0: 0xffffffff8068f000: 0xffffffff806d0000: CLFS.SYS
0xffffffff82f69870: 0xffffffff806d0000: 0xffffffff807b0000: CI.dll
0xffffffff82f697f8: 0xffffffff81e0e000: 0xffffffff81e8a000: Wdf01000.sys
0xffffffff82f69780: 0xffffffff81e8a000: 0xffffffff81e97000: WDFLDR.SYS
0xffffffff82f69710: 0xffffffff81e97000: 0xffffffff81edd000: acpi.sys
0xffffffff82f69698: 0xffffffff81edd000: 0xffffffff81ee6000: WMILIB.SYS
0xffffffff82f69620: 0xffffffff81ee6000: 0xffffffff81eee000: msisadrv.sys
0xffffffff82f695b0: 0xffffffff81eee000: 0xffffffff81f15000: pci.sys
0xffffffff82f69538: 0xffffffff81f15000: 0xffffffff81f24000: partmgr.sys
0xffffffff82f694c0: 0xffffffff81f24000: 0xffffffff81f27000: compbatt.sys
0xffffffff82f69448: 0xffffffff81f27000: 0xffffffff81f31000: BATTC.SYS
0xffffffff82f693d0: 0xffffffff81f31000: 0xffffffff81f40000: volmgr.sys
0xffffffff82f69358: 0xffffffff81f40000: 0xffffffff81f8a000: volmgrx.sys
0xffffffff82f692e0: 0xffffffff81f8a000: 0xffffffff81f91000: intelide.sys
0xffffffff82f69268: 0xffffffff81f91000: 0xffffffff81f9f000: PCIIDEX.SYS
0xffffffff82f691f0: 0xffffffff81f9f000: 0xffffffff81faf000: mountmgr.sys
0xffffffff82f69178: 0xffffffff81faf000: 0xffffffff81fb7000: atapi.sys
0xffffffff82f69100: 0xffffffff81fb7000: 0xffffffff81fd5000: ataport.SYS
0xffffffff82f69088: 0xffffffff81fd5000: 0xffffffff81fef000: lsi_scsi.sys
0xffffffff82f6ff90: 0xffffffff807b0000: 0xffffffff807f1000: storport.sys

Читайте также:

Share

8 comments to Адрес модуля в WinDbg

  • Митя

    > Я, кстати, не знаю в чем смысл «когда они нужны».
    «Они нужны» имеется ввиду они нужны пользователю, когда он явно пишет что-то вроде
    ? module_name!some_symbol. В этом случае module_name «нужен» и символы будут загружены. Эта фича связана с с опцией Debug -> Resolve Unqualified Symbols из WinDbg — если опция отмечена, то даже если не указывать имя модуля, а просто указать символ, который находится в модуле и при этом нет коллизий, то опять же символы нужного модуля будут загружены. Видимо список самих символов без ассоциаций хранится даже, если фактически символы не загружены (deffered).

    К слову сказать, чтобы символы не были отложены у windbg есть опция комм. строки -slags. Например,
    windbg -sflags 0×30333 -k com:pipe,port=\\.\pipe\com_1
    — эта команда отменяет deffered loading.

    Такие же опции, но с другим написанием есть у kd, cdb и ntsd.

    • SWW

      Насколько я замечал, WinDbg не всегда подгружает символы, хотя обращение к ним происходит (команда x, например, или в Disasm Window). Вот поэтому я и написал, что не понимаю смысл «когда они нужны».

      • Митя

        Ну я то не просто так написал. Прежде чем написать — проверил. Проверь и ты.

        • SWW

          Ну, конечно же, я проверял. Например, если у меня сейчас не подгружены символы atapi, то !drvobj \Driver\atapi 2″ никаких символов не подгружает. А также:

          lkd> x atapi!*
          ^ Couldn’t resolve ‘x atapi’
          lkd> x ataport!*
          ^ Couldn’t resolve ‘x ataport’

          Простой пойми, что я не знаю имя символа, который мне нужен. Вот и как тут быть?

  • Митя

    Ммм, странно, вот что я воспроизвел (у меня Windows 7):

    kd> lmsm
    start end module name
    f974e000 f977bf80 ACPI (deferred)
    f7a63000 f7a84b80 afd (deferred)
    f98dd000 f98e7580 agp440 (deferred)
    f96e0000 f96f7900 atapi (deferred)
    f9f81000 f9f81c00 audstub (deferred)

    804d7000 806cfd00 nt (pdb symbols) c:\symbols\ntkrnlpa.pdb\30B5FB31AE7E4ACAABA750AA241FF3311\ntkrnlpa.pdb

    Unloaded modules:
    f997d000 f9986000 HIDCLASS.SYS
    f7b1e000 f7b21000 hidusb.sys
    f9c6d000 f9c75000 usbccgp.sys

    kd> x atapi!*
    f96f45fa atapi!IdePortDetectAlias = no type information
    f96eb5f4 atapi!_imp___allmul = no type information
    f96f33ba atapi!IdePortGetFlushCommand = no type information
    f96e7098 atapi!IdeProcessCompletedRequest = no type information
    f96eb574 atapi!_imp__IoCreateDevice = no type information

    kd> lmsm
    start end module name
    f974e000 f977bf80 ACPI (deferred)
    f7a63000 f7a84b80 afd (deferred)
    f98dd000 f98e7580 agp440 (deferred)
    f96e0000 f96f7900 atapi (pdb symbols) c:\symbols\atapi.pdb\3379CE3C730640ADA2AEC243E90016481\atapi.pdb

    При этом:
    kd> version

    Microsoft (R) Windows Debugger Version 6.11.0001.404 AMD64

  • Митя

    Нет, я до этого релоад сделал

    • Митя

      Ну вообще получается именно так. Модуль не виден потому, что его нет в списке модулей windbg. Прежде чем вводить x atapi!* надо загрузить список модулей(.reload), и уже тот же atapi будет известен. Но при этом во всех этих модулях (кроме тех к которым уже обращались и nt) символы не будут загружены, они загружается «когда они нужны», т.е. при обращении.

      P.S. И о чем же вы с Доктором в курилке говорили =)

      P.P.S Заходил на мобильную версию твоего блога — жмал ссылку на комментарии к этому посту — 404 =(

Leave a Reply

  

  

  

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">