Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 3개 있습니다.)
(시리즈 글이 6개 있습니다.)
Linux: 26. .NET Core 응용 프로그램을 위한 메모리 덤프 방법
; https://www.sysnet.pe.kr/2/0/12078

Linux: 27. linux - lldb를 이용한 .NET Core 응용 프로그램의 메모리 덤프 분석 방법
; https://www.sysnet.pe.kr/2/0/12083

.NET Framework: 2053. 리눅스 환경의 .NET Core 3/5+ 메모리 덤프를 분석하는 방법 - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/13135

.NET Framework: 2054. .NET Core/5+ SDK 설치 없이 dotnet-dump 사용하는 방법
; https://www.sysnet.pe.kr/2/0/13136

.NET Framework: 2055. 리눅스 환경의 .NET Core 3/5+ 메모리 덤프로부터 닷넷 모듈을 추출하는 방법
; https://www.sysnet.pe.kr/2/0/13137

.NET Framework: 2057. 리눅스 환경의 .NET Core 3/5+ 메모리 덤프로부터 모든 닷넷 모듈을 추출하는 방법
; https://www.sysnet.pe.kr/2/0/13139




리눅스 환경의 .NET Core 3/5+ 메모리 덤프로부터 모든 닷넷 모듈을 추출하는 방법

지난 글을 통해 개별 모듈을 파일로 저장하는 방법을 설명했으니,

리눅스 환경의 .NET Core 3/5+ 메모리 덤프로부터 닷넷 모듈을 추출하는 방법
; https://www.sysnet.pe.kr/2/0/13137

이제 순서에 따라 ^^ .NET Framework에서 그랬던 것처럼 모든 닷넷 모듈을 파일로 자동 저장하는 방법을,

windbg - 풀 덤프에 포함된 모든 닷넷 모듈을 파일로 저장하는 방법
; https://www.sysnet.pe.kr/2/0/11297

알아보겠습니다. ^^




windbg의 경우, plug-in 규약이 잘 돼 있어 파이썬 스크립트를 쓸 수 있는 pykd 확장이 있었고, 그것의 힘을 빌려 메모리 덤프에 포함된 모든 닷넷 모듈을 자동으로 추출하는데 그다지 어려움이 없었습니다.

반면, dotnet-dump는 아직 딱히 확장 기술이 없는 것 같습니다. 더군다나, windbg의 ".writemem" 같은 명령어도 제공하지 않으므로 이러한 과정을 매끄럽게 할 수 있는 방법이 없습니다. 그리고 이 와중에 예전에 살펴봤던 ClrMD가 눈에 들어오는군요. ^^

.NET 스레드 콜 스택 덤프 (7) - ClrMD(Microsoft.Diagnostics.Runtime)를 이용한 방법
; https://www.sysnet.pe.kr/2/0/11043

ClrMD를 이용해 메모리 덤프 파일로부터 특정 인스턴스를 참조하고 있는 소유자 확인
; https://www.sysnet.pe.kr/2/0/11809

자, 그럼 우선 우리가 해야 할 것은 닷넷 모듈을 찾는 것입니다.

// Install-Package Microsoft.Diagnostics.Runtime

// nuget - Microsoft.Diagnostics.Runtime 
// ; https://www.nuget.org/packages/Microsoft.Diagnostics.Runtime/

using Microsoft.Diagnostics.Runtime;

string dumpFilePath = @"C:\temp\core_20221007_000149.dmp";

using (DataTarget target = DataTarget.LoadDump(dumpFilePath))
{
    foreach (var module in target.EnumerateModules())
    {
        if (module.IsManaged == false)
        {
            continue;
        }

        Console.WriteLine($"{module.ImageBase:x} {module.ImageSize:x} {module.IsManaged} {module.FileName}");
    }    
}

출력 결과를 보면,

...[생략]...
7faa1c093000 64000 True /app/System.Configuration.ConfigurationManager.dll
7fb6d0020000 42000 True /app/log4net.dll
7fb6d7c20000 55200 True /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.22/System.Net.WebClient.dll
...[생략]...

지난 글에 설명한 lm과 clrmodules의 결과와 비교해 또 다른 값이 나오고 있습니다. 다행히 ImageBase 주소는 같고, 단지 ImageSize가 경우에 따라 lm 출력보다 큰 값을 보입니다. (값이 크니 차라리 다행입니다.)

그럼, 이제 게임 끝이군요. 주소와 크기를 구했으니, 그에 해당하는 바이트 스트림을 구해 파일로 출력하기만 하면 됩니다. 아래는 그 모든 코드를 다 합친 결과입니다.

using Microsoft.Diagnostics.Runtime;

string dumpFilePath = @"C:\temp\core_20221007_000149.dmp";
string outputDir = @"C:\temp\output";

using (DataTarget target = DataTarget.LoadDump(dumpFilePath))
{
    foreach (var module in target.EnumerateModules())
    {
        if (module.IsManaged == false)
        {
            continue;
        }

        Console.WriteLine($"{module.ImageBase:x} {module.ImageSize:x} {module.IsManaged} {module.FileName}");
        Span<byte> buffer = new byte[module.ImageSize];
        target.DataReader.Read(module.ImageBase, buffer);

        string fileName = Path.GetFileName(module.FileName);
        string outputFilePath = Path.Combine(outputDir, fileName);

        File.WriteAllBytes(outputFilePath, buffer.ToArray());
    }    
}

(첨부 파일은 이 글의 예제 코드를 포함합니다.)




참고로, dotnet-dump의 확장이 없는 것을 아쉬운 대로 redirection을 이용해 우회하는 방법이 있습니다.

How can we script dotnet dump analyze commands?
; https://stackoverflow.com/questions/71803641/how-can-we-script-dotnet-dump-analyze-commands

가령, 닷넷 모듈 주소를 구하는 결과를 다음과 같은 식으로 얻는 것도 가능합니다.

c:\temp> type cmds.txt
clrmodules
quit

c:\temp> dotnet-dump analyze core_20221007_000149.dmp < cmds.txt > output.txt

그럼, output.txt에는 대충 다음과 같은 출력을 얻을 수 있겠고!

Loading core dump: core_20221007_000149.dmp ...
Ready to process analysis commands. Type 'help' to list available commands or 'help [command]' to get detailed help on a command.
Type 'quit' or 'exit' to exit the session.
<END_COMMAND_OUTPUT>
> clrmodules
...[생략]...
00007FAA1C093000 00060A68 /app/System.Configuration.ConfigurationManager.dll
00007FB6D0020000 0003F000 /app/log4net.dll
00007FB6D7C20000 00055200 /usr/share/dotnet/shared/Microsoft.NETCore.App/3.1.22/System.Net.WebClient.dll
...[생략]...




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 10/20/2022]

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

비밀번호

댓글 작성자
 




... 121  122  123  124  125  126  127  128  129  130  131  132  [133]  134  135  ...
NoWriterDateCnt.TitleFile(s)
1764정성태9/30/201423760오류 유형: 243. 파일 삭제가 안 되는 경우 - The action can't be comleted because the file is open in System
1763정성태9/30/201425283.NET Framework: 468. PDB 파일을 연동해 소스 코드 라인 정보를 알아내는 방법파일 다운로드1
1762정성태9/30/201426142.NET Framework: 467. 닷넷에서 EIP/RIP 레지스터 값을 구하는 방법 [1]파일 다운로드1
1761정성태9/29/201423278.NET Framework: 466. 윈도우 운영체제의 보안 그룹 이름 및 설명 문자열을 바꾸는 방법파일 다운로드1
1760정성태9/28/201421251.NET Framework: 465. ICorProfilerInfo::GetILToNativeMapping 메서드가 0x80131358을 반환하는 경우
1759정성태9/27/201432557개발 환경 구성: 240. Visual C++ / x64 환경에서 inline-assembly를 매크로 어셈블리로 대체하는 방법파일 다운로드1
1758정성태9/23/201439154개발 환경 구성: 239. 원격 데스크톱 접속(RDP)을 기존의 콘솔 모드처럼 사용하는 방법 [1]
1757정성태9/23/201419785오류 유형: 242. Lync로 모임 참여 시 소리만 들리지 않는 경우 - 두 번째 이야기
1756정성태9/23/201428906기타: 48. NVidia 제품의 과다한 디스크 사용 [2]
1755정성태9/22/201435730오류 유형: 241. Unity Web Player를 설치해도 여전히 설치하라는 화면이 나오는 경우 [4]
1754정성태9/22/201426096VC++: 80. 내 컴퓨터에서 C++ AMP 코드가 실행이 될까요? [1]
1753정성태9/22/201421874오류 유형: 240. Lync로 세미나 참여 시 소리만 들리지 않는 경우 [1]
1752정성태9/21/201441989Windows: 100. 윈도우 8 - RDP 연결을 이용해 VNC처럼 사용자 로그온 화면을 공유하는 방법 [5]
1751정성태9/20/201440089.NET Framework: 464. 프로세스 간 통신 시 소켓 필요 없이 간단하게 Pipe를 열어 통신하는 방법 [1]파일 다운로드1
1750정성태9/20/201425347.NET Framework: 463. PInvoke 호출을 이용한 비동기 파일 작업파일 다운로드1
1749정성태9/20/201425083.NET Framework: 462. 커널 객체를 위한 null DACL 생성 방법파일 다운로드1
1748정성태9/19/201426626개발 환경 구성: 238. [Synergy] 여러 컴퓨터에서 키보드, 마우스 공유
1747정성태9/19/201429959오류 유형: 239. psexec 실행 오류 - The system cannot find the file specified.
1746정성태9/18/201426886.NET Framework: 461. .NET EXE 파일을 닷넷 프레임워크 버전에 상관없이 실행할 수 있을까요? - 두 번째 이야기 [6]파일 다운로드1
1745정성태9/17/201424415개발 환경 구성: 237. 리눅스 Integration Services 버전 업그레이드 하는 방법 [1]
1744정성태9/17/201432310.NET Framework: 460. GetTickCount / GetTickCount64와 0x7FFE0000 주솟값 [4]파일 다운로드1
1743정성태9/16/201422089오류 유형: 238. 설치 오류 - Failed to get size of pseudo bundle
1742정성태8/27/201428450개발 환경 구성: 236. Hyper-V에 설치한 리눅스 VM의 VHD 크기 늘리는 방법 [2]
1741정성태8/26/201422552.NET Framework: 459. GetModuleHandleEx로 알아보는 .NET 메서드의 DLL 모듈 관계파일 다운로드1
1740정성태8/25/201433955.NET Framework: 458. 닷넷 GC가 순환 참조를 해제할 수 있을까요? [2]파일 다운로드1
1739정성태8/24/201427802.NET Framework: 457. 교착상태(Dead-lock) 해결 방법 - Lock Leveling [2]파일 다운로드1
... 121  122  123  124  125  126  127  128  129  130  131  132  [133]  134  135  ...