WinDbg: як встановити точку зупинки прикладної прогрими в режимі ядра

Коли налагодження программи йде в режимі ядра налагоджувач (WinDbg в даному випадку) працює у глобальній області видимості і грубо кажучи не розрізнює процеси. Тому і не можливо в такому режимі просто так встановити точку зупинки (breakpoint).

Тим не менш це можливо з певними додатковими діями.

Спочатку знайдемо ідентифікатор процеса який нас цікавить:

kd>!process 0 0 notepad.exe
PROCESS 8fa35c80  SessionId: 0  Cid: 07b8    Peb: 7fe37000  ParentCid: 0354

Далі переключимося у процес і виконаємо одну команду щоб налагоджувач зупинився саме у нашому процесі:

kd>.process /i 8fa35c80

kd>g

kd>!process –1 0

Тепер можна встановити точку зупинки в поточному процесі:

kd>.reload /user

kd>bp /p 8fa35c80 USER32!GetMessageW

Зауваження: Точку зупинки звісно можна встановити і в режимі ядра, але там не можливо її встановити для конкретного процеса. Наприклад:

kd>bp USER32!GetMessageW

встановить точку зупинки для будь-якого процесу що викликає GetMessage.

J. Robbins. Debugging Applications (2000)

 

Ну власне все що треба знати про дебагінг у Windows. Вірніше не те щоб зовсім усе, але доволі багато.

 

ASSERT’и, принципи роботи дебагера, Visual Studio, асемблер x86, креші, тулзи, бібліотеки і сорци, сорци…

http://search.barnesandnoble.com/books/product.aspx?isbn=9780735608863

 

http://www.amazon.com/Debugging-Applications-DV-MPS-Programming-Robbins/dp/0735608865/ref=sr_1_1?ie=UTF8&qid=1297124400&sr=8-1

Дизасеблер: створення/знищення фрейму SEH

Створення фрейму (початок блоку __try) виглядає так:

1 push 004060d0h // data value... 2 push 004014a0h // ...and function pointer (__except_handler3) 3 mov eax, fs:[0] // accessing TIB - adding a node to the top... 4 push eax // ...of the cjain 5 mov dword ptr fs:[0], esp // where actual node is

Цей код може бути оптимізовано і в результаті перемішано з іншим кодом:

1 mov eax, fs:[0] 2 push ebp 3 mov ebp, esp 4 push 0ffh 5 push 77f3d1e8h 6 push __except_handler3 7 push eax 8 mov eax, [BaseStaticServerData] 9 mov dword ptr fs:[0], esp

Знищення фрейму компілюється у такий код:

1 mov ecx, dword ptr [ebp-10h] 2 mov dword ptr fs:[0], ecx

Дизасемблер: локальні змінні та аргументи функції

Локальні змінні і аргументи функцій розміщуються у стеку (якщо звісно не задіяно якусь оптимізацію):

1 void f(int *p1, int *p2) 2 { 3 // standard function prolog 4 // push ebp 5 // mov ebp, esp 6 // sub esp, 8 <-- 2 local variables, 4 bytes each 7 8 int i1 = 3; 9 // mov dword ptr [ebp-8], 3 10 11 int i2 = 0x42; 12 // mov dword ptr [ebp-4], 42h 13 14 i1 = *p1; 15 // mov eax, dword ptr [ebp+8] 16 // mov ecx, dword ptr [eax] 17 // mov dword ptr[ebp-8], ecx 18 19 i2 = *p2; 20 // mov eax, dword ptr [ebp+0ch] 21 // mov ecx, dword ptr [eax] 22 // mov dword ptr[ebp-4], ecx 23 24 // standard epilogue 25 // mov esp, ebp 26 // pop ebp 27 // ret 28 }

Crash: як знайти функцію за .map-файлом

Нехай адреса крешу буде CA. У загальному вигляді алгоритм виглядає так:

  1. Необхідно мати .map-файл, якщо його ще нема то створити. Для цього треба вибрати опцію Line Numbers Only для Debug Info у властивостях проекту. Також треба вказати ключі /MAPINFO:LINES та /MAPINFO:EXPORTS для лінкера. Проект треба перебілдити (вірніше перезібрати).
  2. У .map-файлі треба знайти Preferred load address (PLA).
  3. Далі знаходимо колонку Rva+Base і в ній шукаємо найбільшу адресу яка менша за адресу креша. Таким чином знаходимо ім’я файлу і методу де стався креш.
  4. У секції Line numbers для знайденого файлу шукаємо номер рядка найближчий до значення CA-PLA-0x1000.

Статті по темі:

 Timestamp is 4d2cf75d (Tue Jan 11 16:35:41 2011)

 Preferred load address is 00400000

Start         Length     Name                   Class
0001:00000000 00010000H .textbss                DATA
0002:00000000 000065ceH .text                   CODE
0002:000065d0 00001259H .text$x                 CODE
0003:00000000 00000104H .CRT$XCA                DATA
0003:00000104 00000104H .CRT$XCAA               DATA

  Address         Publics by Value              Rva+Base       Lib:Object

0000:00000000       ___safe_se_handler_count   00000000     <absolute>
0000:00000000       ___safe_se_handler_table   00000000     <absolute>
0000:00000000       ___ImageBase               00400000     <linker-defined>
0001:00000000       __enc$textbss$begin        00401000     <linker-defined>
0001:00010000       __enc$textbss$end          00411000     <linker-defined>
0002:00000740       _main                      00411740 f   test.obj
0002:00000790       ?test_string_assign@@YAXXZ 00411790 f   test.obj
0002:00000940       ??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBDI@Z 00411940 f i test.obj
0002:00000a10       ??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ 00411a10 f i test.obj

Visual Studio: відображення типів користувача в дебагері

Щоб дебагер студії міг красиво показати значення об’єктів типу треба додати його опис/форматування в файл AUTOEXP.DAT.

 

Формат наступний: 

type=[text]<member[,format]>…

Field

Description

type

Type name. For  template can be followed by <*> to encompass all derived types.

text

Any

member

Data member or expression.

format

See Formatting Symbols for Watch Window

e.g. _PROC_INFO=hProc=<hProc,X> hThread=<hThread,X>

 

Тобто символи <> треба вводити.

Visual Studio: Watch Window Pseudo registers

Watch Window Pseudo registers

Pseudo register

Description

@ERR

Last error value (GetLastError result)

@TIB

Thread information block for current thread

@CLK

Clock register

Trick: enter @CLK and @CLK=0.the second zeroes out the timer after continuing debugging.

@EAX, @EBX, @ECX, @EDX, @ESI, @EDI, @EIP, @ESP, @EBP, @EFL

CPU registers

@CS, @DS, @ES, @SS, @FS, @GS

CPU segment registers

@ST0, @ST1, @ST2, @ST3, @ST4, @ST5, @ST6, @ST7

CPU floating-point registers

Visual Studio: Formatting Symbols for Watch Window Memory Dump

Formatting Symbols for Watch Window Memory Dump

Stmbol

Description

ma

64 ASCII characters

m, mb

16 bytes in hex followed by 16 ASCII chars

mw

8 words

md

4 dwords

Mq

4 qwords

mu

2-byte characters (Unicode)

#

Expands a pointer to the specified number of values

Visual Studio: форматуючі символи для вікна Watch

Formatting Symbols for Watch Window

Symbol

Description

Sample

Displays

d, i

Signed decimal int

(int)0xF000F064,d

-268373915

u

Unsigned decimal int

0x0065,u

101

o

Unsigned octal decimal

0xF065,o

0170145

x, X

Hexidecimal integer

61541,x

0x0000F065

l, h

Long or short prefix for d, I, u, o, x, X

0x0042406042,hx

0x0c22

f

Signed float

3./2,f

1.500000

e

Signed float, scientific notation

3./2,e

1.500000e+00

g

Signed float or signed scientific, which one is shorter

3./2,g

1.5

c

char

0x0065,c

‘e’

s

string

szHiWorlds,z

“Hello world”

su

Unicode string

szWHiWorlds,su

“Hello world”

st

Unicode or ANSI string, dependint on settings in autoext.dat

   

hr

HRESULT or Win32 error code

0,hr

S_OK

wc

Window class flag

0x0040,wc

WC_DEFAULTCHAR

wm

Windows message

0x0010,wm

WM_CLOSE