Microsoft MVP성태의 닷넷 이야기
디버깅 기술: 1. 디버깅 방법 - CLR 프로파일러 [링크 복사], [링크+제목 복사],
조회: 28046
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 2개 있습니다.)

저 같은 경우, 해당 응용 프로그램을 개발하기 쉬운지, 어려운지에 대한 기준으로 얼마나 쉽게 "디버거" 환경에서 구동시킬 수 있느냐로 판단합니다. 쉽게 말해서, IDE 환경에서 "F5"를 통한 디버깅이 되느냐/안되느냐에 따른 것인데요.

그러한 디버깅이 다소 어려운 Windows Shell, ISAPI Filter, API 후킹 등은 "어려운 분야"라고 저는 판단합니다. 사실 어려운 분야죠. ^^; 어려울수록 디버깅은 더욱 힘들어지는 것이 정석인가 봅니다.

다행스러운 것은, 최근 들어 전체적으로 개발환경이 .NET으로 넘어오면서, "F5 디버깅"의 영역이 넓어지고 있다는 것입니다. 단적인 예로, ASP.NET 디버깅이 그렇죠.



이런저런 이유로, 어떤 응용 프로그램을 개발할 때에 저는 최대한 "F5 디버깅"이 가능하게 하려고 노력을 합니다. 이번 글은, 최근에 제가 노력했었던 "F5 디버깅" 환경 구성 중에서 "CLR 프로파일러"를 위한 것을 설명하겠습니다.

CLR 프로파일러 자체는 Unamaged C/C++로 개발이 되고, Managed 환경으로부터의 접점을 Environment Variable을 통해서 하고 있습니다. 얼핏 디버깅 방법이 실행 중에 attach 시키는 것뿐이 없는 것 같은데요. 그런 식으로 디버깅하는 것과 "F5 디버깅"의 생산성 차이는 엄청나기 때문에 조금 살펴보게 되었습니다.

일단, 시작 예제 프로젝트는 7차 MMS 모임 때 발표 자료였던 "High-Level .NET Profiling API"를 이용한 프로젝트로 하겠습니다.어차피 Low-Level CLR Profiling API도 마찬가지일거라 봅니다. 관련 자료는 다음의 URL에서 찾아 볼 수 있습니다.

.NET Profiling
Write Profilers With Ease Using High-Level Wrapper Classes
; https://docs.microsoft.com/en-us/archive/msdn-magazine/2006/april/write-profilers-with-ease-using-high-level-wrapper-classes

이제부터, .NET Profiler 프로젝트를 위한 디버깅 환경 설정을 설명해 보겠습니다.

1. 우선, 프로젝트 설정 / "General" 범주에서 "Output Directory"를 CLR Profiling 대상이 되는 .NET 프로그램이 있는 폴더로 지정합니다. 당연하겠지요. ^^

다음은 실제 예제 프로젝트의 솔루션 구조와, 대상 Output Directory에 모여진 파일들의 모습입니다.
Output Directory

2. "Debugging" 범주에서 아래와 같이 적절한 값으로 Command, Working Directory, Debugger Type을 지정합니다. Command Arguments가 있는 경우에는 역시 입력해 주면 되겠고, 각자 자신이 맞는 환경에 맞게 값을 채워주시면 됩니다. 주의할 것은 Working Directory도 반드시 명시를 해주셔야 합니다.

  Command : .NET 프로파일링 대상이 되는 EXE 프로그램 경로
  Working Directory : 대상 EXE 프로그램이 있는 디렉터리
  Debugger Type : 반드시 Native Only 값을 주어야 합니다. Mixed 방식을 주면 CLR로부터의 Call back API들에서 Break Point가 동작하지 않습니다.

프로젝트 설정 화면

3. 이미 말씀드린 것처럼, CLR Profiling의 동작 방식은 CLR이 로딩시에 환경 변수에 특정 변수로 등록된 COM 개체의 CLSID를 얻어서 해당 COM 개체를 활성화시킨 다음 정해진 interface 규칙에 맞게 callback을 해주는 구조입니다. 따라서, "F5 디버깅"을 위해서는 해당 디버깅 세션 동안에 유효할 수 있는 환경 변수 설정을 적절하게 해주어야 합니다. 사실 VS.NET 2003까지는 디버깅 세션에 환경 변수를 설정할 수 있는 방법이 없었습니다. "My Computer"의 전역 환경 설정 변수를 이용할 수도 있었겠지만, 그런 경우 전체 응용 프로그램 모두에 프로파일링 API가 동작하게 되는 부작용이 있으므로 사용하기에는 현실성이 없어 보입니다.

다행히도, VS.NET 2005에서는 디버깅 세션에 환경 변수를 설정할 수 있는 방법을 명시적으로 제공하고 있습니다. 아래의 화면에서 보는 것처럼, CLR 프로파일링 동작을 위한 환경 변수를 설정해 주시면 됩니다.

환경 변수 설정

4. 자, 이제 모든 준비는 끝났습니다. 평상시처럼, 자신이 구현한 CLR 프로파일러 내부의 로직에 break point를 설정한 후, "F5" 키를 누르면 아래 화면과 같이 정상적으로 디버깅이 가능한 것을 볼 수 있습니다.

CLR 프로파일러 디버깅 화면 **** 첨부 파일은 이 글에서 설명한 예제 프로젝트입니다.
[연관 글]






[최초 등록일: ]
[최종 수정일: 6/25/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2012-09-20 12시39분
본문과는 상관없지만! 프로파일러와 관련이 있어서 기록을 남깁니다.

ICorProfilerInfo2::DoStackSnapshot 호출의 반환값(hr)으로 E_INVALIDARG (-2147024809, 0x80070057) 값이 나왔다면? DoStackSnapshot API가 동작하기 위해서는 ICorProfilerInfo2::SetEventMask에 COR_PRF_ENABLE_STACK_SNAPSHOT 옵션을 주어야 하기 때문입니다.
정성태

... 61  62  63  64  65  66  67  68  69  70  71  72  [73]  74  75  ...
NoWriterDateCnt.TitleFile(s)
12111정성태1/12/202020549디버깅 기술: 155. C# - KernelMemoryIO 드라이버를 이용해 실행 프로그램을 숨기는 방법(DKOM: Direct Kernel Object Modification) [16]파일 다운로드1
12110정성태1/11/202019875디버깅 기술: 154. Patch Guard로 인해 블루 스크린(BSOD)가 발생하는 사례 [5]파일 다운로드1
12109정성태1/10/202016595오류 유형: 588. Driver 프로젝트 빌드 오류 - Inf2Cat error -2: "Inf2Cat, signability test failed."
12108정성태1/10/202017428오류 유형: 587. Kernel Driver 시작 시 127(The specified procedure could not be found.) 오류 메시지 발생
12107정성태1/10/202018614.NET Framework: 877. C# - 프로세스의 모든 핸들을 열람 - 두 번째 이야기
12106정성태1/8/202019653VC++: 136. C++ - OSR Driver Loader와 같은 Legacy 커널 드라이버 설치 프로그램 제작 [1]
12105정성태1/8/202018143디버깅 기술: 153. C# - PEB를 조작해 로드된 DLL을 숨기는 방법
12104정성태1/7/202019361DDK: 9. 커널 메모리를 읽고 쓰는 NT Legacy driver와 C# 클라이언트 프로그램 [4]
12103정성태1/7/202022494DDK: 8. Visual Studio 2019 + WDK Legacy Driver 제작- Hello World 예제 [1]파일 다운로드2
12102정성태1/6/202018819디버깅 기술: 152. User 권한(Ring 3)의 프로그램에서 _ETHREAD 주소(및 커널 메모리를 읽을 수 있다면 _EPROCESS 주소) 구하는 방법
12101정성태1/5/202019090.NET Framework: 876. C# - PEB(Process Environment Block)를 통해 로드된 모듈 목록 열람
12100정성태1/3/202016563.NET Framework: 875. .NET 3.5 이하에서 IntPtr.Add 사용
12099정성태1/3/202019439디버깅 기술: 151. Windows 10 - Process Explorer로 확인한 Handle 정보를 windbg에서 조회 [1]
12098정성태1/2/202019184.NET Framework: 874. C# - 커널 구조체의 Offset 값을 하드 코딩하지 않고 사용하는 방법 [3]
12097정성태1/2/202017244디버깅 기술: 150. windbg - Wow64, x86, x64에서의 커널 구조체(예: TEB) 구조체 확인
12096정성태12/30/201919898디버깅 기술: 149. C# - DbgEng.dll을 이용한 간단한 디버거 제작 [1]
12095정성태12/27/201921618VC++: 135. C++ - string_view의 동작 방식
12094정성태12/26/201919354.NET Framework: 873. C# - 코드를 통해 PDB 심벌 파일 다운로드 방법
12093정성태12/26/201918931.NET Framework: 872. C# - 로딩된 Native DLL의 export 함수 목록 출력파일 다운로드1
12092정성태12/25/201917675디버깅 기술: 148. cdb.exe를 이용해 (ntdll.dll 등에 정의된) 커널 구조체 출력하는 방법
12091정성태12/25/201919983디버깅 기술: 147. pdb 파일을 다운로드하기 위한 symchk.exe 실행에 필요한 최소 파일 [1]
12090정성태12/24/201920099.NET Framework: 871. .NET AnyCPU로 빌드된 PE 헤더의 로딩 전/후 차이점 [1]파일 다운로드1
12089정성태12/23/201919051디버깅 기술: 146. gflags와 _CrtIsMemoryBlock을 이용한 Heap 메모리 손상 여부 체크
12088정성태12/23/201917991Linux: 28. Linux - 윈도우의 "Run as different user" 기능을 shell에서 실행하는 방법
12087정성태12/21/201918462디버깅 기술: 145. windbg/sos - Dictionary의 entries 배열 내용을 모두 덤프하는 방법 (do_hashtable.py) [1]
12086정성태12/20/201920992디버깅 기술: 144. windbg - Marshal.FreeHGlobal에서 발생한 덤프 분석 사례
... 61  62  63  64  65  66  67  68  69  70  71  72  [73]  74  75  ...