기호 확인

기호 문제는 다양한 방법으로 표시할 수 있습니다. 스택 추적에 잘못된 정보가 표시되거나 스택에 있는 함수의 이름을 식별하지 못할 수 있습니다. 또는 디버거 명령이 모듈, 함수, 변수, 구조 또는 데이터 형식의 이름을 이해하지 못했을 수 있습니다.

디버거가 기호를 올바르게 로드하지 않는 것으로 의심되는 경우 이 문제를 조사하기 위해 수행할 수 있는 몇 가지 단계가 있습니다.

먼저 lm(로드된 모듈 나열) 명령을 사용하여 기호 정보가 포함된 로드된 모듈 목록을 표시합니다. 이 명령의 가장 유용한 형식은 다음과 같습니다.

0:000> lml 

WinDbg를 사용하는 경우 디버그 | 모듈 메뉴 명령을 사용하면 이 정보도 볼 수 있습니다.

이러한 디스플레이에서 볼 수 있는 메모 또는 약어에 특히 주의하세요. 이에 대한 해석은 기호 상태 약어를 참조하세요.

적절한 기호 파일이 표시되지 않는 경우 가장 먼저 수행할 작업은 기호 경로를 검사 것입니다.

0:000> .sympath
Current Symbol Path is: d:\MyInstallation\i386\symbols\retail

기호 경로가 잘못된 경우 수정합니다. 커널 디버거를 사용하는 경우 로컬 %WINDIR%이 기호 경로에 없는지 확인합니다.

그런 다음 , .reload(모듈 다시 로드) 명령을 사용하여 기호를 다시 로드합니다.

0:000> .reload ModuleName 

기호 경로가 올바른 경우 dbghelp가 로드하는 기호 파일을 볼 수 있도록 노이즈 모드를 활성화해야 합니다. 그런 다음 모듈을 다시 로드합니다. 노이즈 모드를 활성화하는 방법에 대한 자세한 내용은 기호 옵션 설정을 참조하세요.

다음은 Microsoft Windows 기호의 "노이즈" 다시 로드의 예입니다.

kd> !sym noisy
kd> .reload nt
 1: Kernel Version 2081 MP Checked
 2: Kernel base = 0x80400000 PsLoadedModuleList = 0x80506fa0
 3: DBGHELP: FindExecutableImageEx-> Looking for D:\MyInstallation\i386\ntkrnlmp.exe...mismatched timestamp
 4: DBGHELP: No image file available for ntkrnlmp.exe
 5: DBGHELP: FindDebugInfoFileEx-> Looking for
 6: d:\MyInstallation\i386\symbols\retail\symbols\exe\ntkrnlmp.dbg... no file
 7: DBGHELP: FindDebugInfoFileEx-> Looking for
 8: d:\MyInstallation\i386\symbols\retail\symbols\exe\ntkrnlmp.pdb... no file
 9: DBGHELP: FindDebugInfoFileEx-> Looking for d:\MyInstallation\i386\symbols\retail\exe\ntkrnlmp.dbg... OK
10: DBGHELP: LocatePDB-> Looking for d:\MyInstallation\i386\symbols\retail\exe\ntkrnlmp.pdb... OK
11: *** WARNING: symbols checksum and timestamp is wrong 0x0036a4ea 0x00361a83 for ntkrnlmp.exe

기호 처리기는 먼저 로드하려는 모듈(줄 3과 4)과 일치하는 이미지를 찾습니다. 이미지 자체가 항상 필요한 것은 아니지만 잘못된 이미지 자체가 있으면 기호 처리기가 실패하는 경우가 많습니다. 이러한 줄은 디버거가 D:\MyInstallation\i386\ntkrnlmp.exe이미지를 찾았지만 시간 날짜 스탬프가 일치하지 않음을 보여 줍니다. 시간 날짜 스탬프가 일치하지 않아 검색이 계속됩니다. 다음으로 디버거는 로드된 이미지와 일치하는 .dbg 파일 및 .pdb 파일을 찾습니다. 6~10줄에 있습니다. 줄 11은 기호가 로드되었지만 이미지의 시간 날짜 스탬프가 일치하지 않음을 나타냅니다(즉, 기호가 잘못됨).

기호 검색에 치명적인 오류가 발생한 경우 양식의 메시지가 표시됩니다.

ImgHlpFindDebugInfo(00000000, module.dll, c:\MyDir;c:\SomeDir, 0823345, 0) failed

파일 시스템 오류, 네트워크 오류 및 손상된 .dbg 파일과 같은 항목으로 인해 발생할 수 있습니다.

기호 로드 오류 진단

시끄러운 모드에서 디버거는 기호 파일을 로드할 수 없는 경우 오류 코드를 출력할 수 있습니다. .dbg 파일에 대한 오류 코드는 winerror.h에 나열됩니다. .pdb 오류 코드는 다른 원본에서 제공되며 가장 일반적인 오류는 일반 영어 텍스트로 인쇄됩니다.

winerror.h의 .dbg 파일에 대한 몇 가지 일반적인 오류 코드는 다음과 같습니다.

0xB
ERROR_BAD_FORMAT

0x3
ERROR_PATH_NOT_FOUND

0x35
ERROR_BAD_NETPATH

네트워킹 오류로 인해 기호 파일을 로드할 수 없습니다. ERROR_BAD_FORMAT 또는 ERROR_BAD_NETPATH 표시되고 네트워크의 다른 컴퓨터에서 기호를 로드하는 경우 기호 파일을 호스트 컴퓨터에 복사하여 기호 경로에 넣습니다. 그런 다음 기호를 다시 로드합니다.

검색 경로 및 기호 확인

Let "c:\MyDir; c:\SomeDir"은 기호 경로를 나타냅니다. 디버그 정보는 어디에서 찾아야 하나요?

Windows 무료 빌드와 같은 디버그 정보가 이진 파일이 제거된 경우 먼저 다음 위치에서 .dbg 파일을 찾습니다.

c:\MyDir\symbols\exe\ntoskrnl.dbg
c:\SomeDir\symbols\exe\ntoskrnl.dbg
c:\MyDir\exe\ntoskrnl.dbg
c:\SomeDir\exe\ntoskrnl.dbg
c:\MyDir\ntoskrnl.dbg
c:\SomeDir\ntoskrnl.dbg
current-working-directory\ntoskrnl.dbg

다음으로, 다음 위치에서 .pdb 파일을 찾습니다.

c:\MyDir\symbols\exe\ntoskrnl.pdb
c:\MyDir\exe\ntoskrnl.pdb
c:\MyDir\ntoskrnl.pdb
c:\SomeDir\symbols\exe\ntoskrnl.pdb
c:\SomeDir\exe\ntoskrnl.pdb
c:\SomeDir\ntoskrnl.pdb
current-working-directory\ntoskrnl.pdb

.dbg 파일을 검색할 때 디버거는 MyDir 및 SomeDir 디렉터리를 검색하지만 .pdb 검색에서는 검색하지 않습니다.

Windows XP 이상 버전의 Windows는 .dbg 기호 파일을 사용하지 않습니다. 자세한 내용은 기호 및 기호 파일을 참조하세요.

일치하지 않는 빌드

자주 업데이트되는 컴퓨터의 디버깅 실패에서 가장 일반적인 문제 중 하나는 다른 빌드의 기호가 일치하지 않는 것입니다. 이 문제의 일반적인 원인은 잘못된 빌드의 기호를 가리키고, 해당 기호 없이 비공개로 빌드된 이진 파일을 사용하고, 다중 프로세서 컴퓨터에서 HAL(유니프로세서 하드웨어 추상화 수준) 및 커널 기호를 사용하는 것입니다. 처음 두 항목은 단순히 이진 파일과 기호를 일치시키는 문제입니다. 세 번째 는 hal*.dbg 및 ntkrnlmp.dbg의 이름을 hal.dbg 및 ntoskrnl.dbg로 변경하여 수정할 수 있습니다.

대상 컴퓨터에 설치된 Windows 빌드를 확인하려면 꼭짓점(대상 컴퓨터 버전 표시) 명령을 사용합니다.

kd> vertarget 
Windows XP Kernel Version 2505 UP Free x86 compatible
Built by: 2505.main.010626-1514
Kernel base = 0x804d0000 PsLoadedModuleList = 0x80548748
Debug session time: Mon Jul 02 14:41:11 2001
System Uptime: 0 days 0:04:53 

기호 테스트

기호를 테스트하는 것이 더 어렵습니다. 디버거에서 스택 추적을 확인하고 디버그 출력이 올바른지 확인하는 작업이 포함됩니다. 다음은 시도할 한 가지 예입니다.

kd> u videoprt!videoportfindadapter2
Loading symbols for 0xf2860000     videoprt.sys ->   videoprt.sys

VIDEOPRT!VideoPortFindAdapter2:
f2856f42 55               push    ebp
f2856f43 8bec             mov     ebp,esp
f2856f45 81ecb8010000     sub     esp,0x1b8
f2856f4b 8b4518           mov     eax,[ebp+0x18]
f2856f4e 53               push    ebx
f2856f4f 8365f400         and     dword ptr [ebp-0xc],0x
f2856f53 8065ff00         and     byte ptr [ebp-0x1],0x0
f2856f57 56               push    esi

u 명령은 videoprt.sys videoportfindadapter 문자열의 어셈블을 해제합니다. 밀어넣기 및 mov와 같은 일반적인 스택 명령이 스택에 표시되므로 디버거에서 기호가 올바르습니다. 대부분의 함수는 기본 포인터(ebp) 또는 스택 포인터(esp)를 사용하여 추가, 하위 또는 푸시 작업으로 시작합니다.

기호가 제대로 작동하지 않는 경우 일반적으로 분명합니다. 함수가 Glintmp 옆에 나열되지 않으므로 Glintmp.sys 이 예제에는 기호가 없습니다.

kd> kb
Loading symbols for 0xf28d0000     videoprt.sys ->   videoprt.sys
Loading symbols for 0xf9cdd000      glintmp.sys ->   glintmp.sys
*** ERROR: Symbols could not be loaded for glintmp.sys
ChildEBP RetAddr  Args to Child
f29bf1b0 8045b5fa 00000001 0000a100 00000030 ntoskrnl!RtlpBreakWithStatusInstruction
f29bf1b0 8044904e 00000001 0000a100 00000030 ntoskrnl!KeUpdateSystemTime+0x13e
f29bf234 f28d1955 f9b7d000 ffafb2dc f9b7d000 ntoskrnl!READ_REGISTER_ULONG+0x6
f29bf248 f9cde411 f9b7d000 f29bf2b0 f9ba0060 VIDEOPRT!VideoPortReadRegisterUlong+0x27
00000002 00000000 00000000 00000000 00000000 glintMP+0x1411 [No function listed.] 

이 스택 추적에 대해 잘못된 빌드 기호가 로드되었습니다. 처음 두 호출에 대해 나열된 함수가 없는지 확인합니다. 이 스택 추적은 win32k.sys 그리기 사각형의 문제처럼 보입니다.

1: kd> 
1: kd> kb                      [Local        9:50 AM]
Loading symbols for 0xf22b0000       agpcpq.sys ->   agpcpq.sys
*** WARNING: symbols checksum is wrong 0x0000735a 0x00000000 for agpcpq.sys
*** ERROR: Symbols could not be loaded for agpcpq.sys
Loading symbols for 0xa0000000       win32k.sys ->   win32k.sys
*** WARNING: symbols checksum is wrong 0x00191a41 0x001995a9 for win32k.sys
ChildEBP RetAddr  Args to Child
be682b18 f22b372b 82707128 f21c1ffc 826a70f8 agpCPQ+0x125b [No function listed.]
be682b4c a0140dd4 826a72f0 e11410a8 a0139605 agpCPQ+0x372b [No function listed.]
be682b80 a00f5646 e1145100 e1cee560 e1cee560 win32k!vPatCpyRect1_6x6+0x20b
00000001 00000000 00000000 00000000 00000000 win32k!RemoteRedrawRectangle+0x32 

올바른 스택 추적은 다음과 같습니다. 문제는 정말 AGP440.sys. 스택 추적에 표시되는 첫 번째 항목은 일반적으로 오류가 발생합니다. win32k.sys 사각형 오류가 사라졌습니다.

1: kd> kb                      [Local        9:49 AM]
ChildEBP RetAddr  Args to Child
be682b18 f22b372b 82707128 f21c1ffc 826a70f8 agpCPQ!AgpReleaseMemory+0x88
be682b30 f20a385c 82703638 e183ec68 00000000 agpCPQ!AgpInterfaceReleaseMemory+0x8b
be682b4c a0140dd4 826a72f0 e11410a8 a0139605 VIDEOPRT!AgpReleasePhysical+0x44
be682b58 a0139605 e1cee560 e11410a8 a00e5f0a win32k!OsAGPFree+0x14
be682b64 a00e5f0a e1cee560 e11410a8 e1cee560 win32k!AGPFree+0xd
be682b80 a00f5646 e1145100 e1cee560 e1cee560 win32k!HeapVidMemFini+0x49
be682b9c a00f5c20 e1cee008 e1cee008 be682c0c win32k!vDdDisableDriver+0x3a
be682bac a00da510 e1cee008 00000000 be682c0c win32k!vDdDisableDirectDraw+0x2d
be682bc4 a00da787 00000000 e1843df8 e1843de8 win32k!PDEVOBJ__vDisableSurface+0x27
be682bec a00d59fb 00000000 e1843de8 00000000 win32k!PDEVOBJ__vUnreferencePdev+0x204
be682c04 a00d7421 e1cee008 82566a98 00000001 win32k!DrvDestroyMDEV+0x30
be682ce0 a00a9e7f e1843e10 e184a008 00000000 win32k!DrvChangeDisplaySettings+0x8b3
be682d20 a008b543 00000000 00000000 00000000 win32k!xxxUserChangeDisplaySettings+0x106
be682d48 8045d119 00000000 00000000 00000000 win32k!NtUserChangeDisplaySettings+0x48
be682d48 77e63660 00000000 00000000 00000000 ntkrnlmp!KiSystemService+0xc9 

유용한 명령 및 확장

다음 명령 및 확장은 기호 문제를 추적하는 데 유용할 수 있습니다.

lm(로드된 모듈 나열)
모든 모듈을 나열하고 이러한 모듈에 있는 모든 기호의 로드 상태 제공합니다.

!dh image-header-base
image-header-base에서 시작하는 로드된 이미지에 대한 헤더 정보를 표시합니다.

.reload /n
모든 커널 기호를 다시 로드합니다.

.reload [image-name]
(CDB 또는 WinDbg만 해당) 이미지 이미지 이름에 대한 기호를 다시 로드합니다. image-name을 지정하지 않으면 모든 이미지에 대한 기호를 다시 로드합니다. 기호 경로가 변경된 후 기호를 다시 로드해야 합니다.

!sym noisy
기호 로드에 대해 자세한 정보 표시 모드를 켭니다. 모듈 로드에 대한 정보를 가져오는 데 사용할 수 있습니다. 자세한 내용은 기호 옵션 설정을 참조하세요 .

.sympath [new-symbol-path]
새 기호 경로를 설정하거나 현재 기호 경로를 표시합니다. 자세한 내용은 기호 경로를 참조하세요.

커널 기호가 올바르지만 전체 스택을 가져오지 않는 경우 다음 명령도 유용할 수 있습니다.

X*!
그러면 현재 기호가 로드된 모듈이 나열됩니다. 커널 기호가 올바른 경우에 유용합니다.

.reload /user
그러면 모든 사용자 모드 기호가 다시 로드됩니다. 한 프로세스가 실행되는 동안 기호가 로드되고 나중에 다른 프로세스에서 중단이 발생한 경우 커널 디버깅을 수행하는 동안 이 작업이 필요합니다. 이 경우 이 명령을 실행하지 않으면 새 프로세스의 사용자 모드 기호가 로드되지 않습니다.

X wdmaud!*start\*
그러면 이름이 "start" 문자열을 포함하는 wdmaud 모듈의 기호만 나열됩니다. 이는 wdmaud에 있는 모든 기호를 강제로 다시 로드할 수 있다는 장점이 있지만,에 "start"가 있는 기호만 표시합니다. 즉, 목록이 짧아지지만 항상 "start"가 포함된 일부 기호가 있으므로 부하가 발생했음을 확인합니다.)

기호를 확인하는 다른 유용한 기술 중 하나는 코드 언셈블입니다. 대부분의 함수는 기본 포인터(ebp) 또는 스택 포인터(esp 또는 sp)를 사용하여 추가, 하위 또는 푸시 작업으로 시작합니다. 스택의 일부 함수(오프셋 0부터)를 언어셈블(U 함수)하여 기호를 확인합니다.

네트워크 및 포트 문제

기호 파일 및 디버거에 연결하는 동안 문제가 발생합니다. 다음은 문제가 발생할 경우 유의해야 할 몇 가지 사항입니다.

  • 테스트 시스템에서 디버그 케이블이 연결된 COM 포트를 확인합니다.

  • 테스트 시스템의 boot.ini 설정을 확인합니다. /debug 스위치를 찾고 전송 속도 및 COM 포트 설정을 검사.

  • 네트워크를 통해 기호 파일에 액세스하는 경우 네트워크 문제가 디버깅을 방해할 수 있습니다.

  • 이름이 같은 .dll 및 .sys 파일(예: mga64.sys 및 mga64.dll)은 기호 트리의 적절한 디렉터리로 분리되지 않은 경우 디버거를 혼동합니다.

  • 커널 디버거는 빌드 기호 파일을 프라이빗 기호 파일로 바꾸는 것을 항상 좋아하지는 않습니다. 기호 경로를 두 번 검사 잘못된 동작 기호에서 .reloadFileName을 수행합니다. !dlls 명령은 경우에 따라 유용합니다.

질문 및 오해

Q: 기호를 성공적으로 로드했지만 스택이 잘못된 것 같습니다. 디버거가 끊어졌나요?

A: 반드시. 문제의 가장 가능성이 높은 원인은 잘못된 기호가 있다는 것입니다. 이 섹션에 설명된 단계를 진행하여 유효한 기호를 로드했는지 여부를 확인합니다. 일부 항목이 작동하기 때문에 유효한 기호가 있다고 가정하지 마십시오. 예를 들어 dd nt!ntbuildnumber 또는 u nt! 잘못된 기호가 있는 KeInitializeProcess 입니다. 위에서 설명한 절차를 사용하여 올바른지 확인합니다.

Q: 디버거가 여전히 잘못된 기호로 작동합니까?

A: 그렇기도 하고 그렇지 않기도 하고. 종종 엄격하게 일치하지 않는 기호로 도망 갈 수 있습니다. 예를 들어 이전 Windows 빌드의 기호는 경우에 따라 작동하는 경우가 많지만 언제 작동하는지와 작동하지 않을 때에 대한 규칙은 없습니다.

Q: 커널 디버거에서 중지되었으며 사용자 모드 프로세스에 대한 기호를 보려고 합니다. 이 작업을 수행할 수 있나요?

A: 주로. 커널 디버거가 각 프로세스에 대한 모듈 로드를 추적하기에 충분한 정보를 유지하지 못하지만 적절한 해결 방법이 있기 때문에 이 시나리오에 대한 지원이 부족합니다. 사용자 모드 모듈에 대한 기호를 로드하려면 .reload -user 명령을 실행합니다. 그러면 현재 컨텍스트에 대한 사용자 모드 모듈이 로드됩니다.

Q: 다음 메시지는 무엇을 의미하나요?

*** WARNING: symbols checksum and timestamp is wrong 0x0036d6bf 0x0036ab55 for ntkrnlmp.exe

A: 이는 ntkrnlmp.exe 대한 기호가 잘못됨을 의미합니다.