EXDI XML 구성 파일
이 항목에서는 EXDI XML 구성 파일을 사용하여 고급 옵션을 구성하는 방법에 대해 설명합니다. WinDbg 사용자 인터페이스를 사용하여 EXDI를 구성하는 방법에 대한 일반적인 내용은 EXDI 디버거 전송 구성을 참조 하세요. 가장 일반적인 설정은 사용자 인터페이스에서 사용할 수 있습니다. 이 방법은 여기에 설명된 EXDI XML 구성 파일을 수동으로 편집하는 보다 쉬운 방법입니다.
EXDI(확장 디버깅 인터페이스)는 소프트웨어 디버거와 디버깅 대상 간의 적응 계층입니다. Windows용 디버깅 도구는 Windows 버전 22000부터 EXDI를 사용하여 커널 디버깅을 지원합니다.
참고 항목
EXDI는 특정 환경에 대한 고급 특수한 형태의 디버깅입니다. 표준 KDNET 연결을 사용하는 것이 더 쉽게 구성할 수 있으며 권장됩니다. 네트워크 디버깅을 자동으로 설정하려면 KDNET 네트워크 커널 디버깅 자동 설정을 참조 하세요.
EXDI 구성 XML 파일을 사용하여 고급 옵션 구성
EXDI GDB COM 서버(ExdiGdbSrv.dll)에서 사용하는 두 개의 필수 xml 파일이 있습니다.
exdiConfigData.xml - 이 파일에는 GDB 서버 클라이언트가 HW 디버거 GDB 서버 대상을 사용하여 성공적으로 GDB 세션을 설정하는 데 필요한 기본 구성 데이터가 포함되어 있으므로 파일 위치가 EXDI_GDBSRV_XML_CONFIG_FILE 환경 변수에 의해 설정되지 않은 경우 GDB 서버 클라이언트가 실행되지 않습니다. 각 xml 태그를 사용하면 특정 GDB 서버 기능 집합을 구성할 수 있습니다. XML에서 수정할 수 있는 특성 목록과 샘플 XML은 아래를 참조하세요.
Systemregister.xml - 이 파일에는 시스템 레지스터와 레지스터에 액세스하는 데 사용되는 코드 간의 매핑이 포함되어 있습니다. 액세스 코드는 GDB 서버에서 xml 파일에서 제공되지 않고 디버거가 액세스 코드를 통해 각 시스템 레지스터에 액세스하기 때문에 필요합니다. 환경 변수
EXDI_SYSTEM_REGISTERS_MAP_XML_FILE
를 통해 파일을 설정하지 않으면 ExdiGdbSrv.dll 계속 작동하지만 디버거는 rdmsr 또는 wrmsr 명령을 통해 시스템 레지스터에 액세스할 수 없습니다. 이러한 레지스터 목록은 GDB 서버 하드웨어 디버거에서 지원해야 합니다(특정 시스템 레지스터 이름은 시스템 xml 파일에 전송된 레지스터 목록에 있어야 함).
EXDI UI 및 XML 구성 파일
WinDbg의 EXDI UI는 XML 파일 매개 변수를 사용하고 IP:포트 값과 같은 UI 필수 매개 변수에서 병합합니다. 기본 XML 파일 매개 변수를 수정해야 하는 경우 명령줄에서 매개 PathToSrvCfgFiles=<path to the modified exdiconfigdata.xml file>
변수를 사용하여 WinDbgNext 애플리케이션을 시작합니다.
대상 아키텍처
EXDI UI 대상 아키텍처 필드 값은 Windows OS 대상 아키텍처를 설명하는 대상 설명 XML 파일을 구현하지 않는 GDB 서버 스텁에 대해서만 대상에서 실행되는 Windows OS와 일치해야 합니다. 이 target.xml 파일 정보는 GDB 클라이언트와 GDB 서버 스텁 간의 GDB-RSP 프로토콜 핸드셰이크 중에 GDB 서버 스텁에서 전송됩니다.
Windbg-ExdiGdbSrv는 사용자가 EXDI UI에서 잘못된 대상 아키텍처 필드 입력 값을 설정하는 경우에도 올바른 대상 OS 아키텍처를 설정할 수 있습니다. 대상 OS 아키텍처는 GDB 서버 핸드셰이크의 target.xml 파일을 포함하는 GDB 서버에서 제공하는 target.xml 설명 파일에서 가져와서 구성됩니다. 대상 아키텍처를 확인하려면 유효 머신 .effmach 디버거 명령을 사용합니다.
GDBServer 태그 및 특성
다음 표에서는 파일에 정의된 GDBServer 태그 및 특성에 대해 exdiConfigData.xml
설명합니다.
매개 변수 | 설명 |
---|---|
ExdiTargets | exdiConfigData.xml 파일에는 현재 ExdiGdbSrv.dll 지원되는 모든 GDB 서버가 포함되어 있으므로 ExdiGgbSrv.dll GDB 서버 대상과의 GDB 연결을 설정하는 데 사용할 특정 GDB 서버 대상 구성을 지정합니다(이 파일은 특정 GDB 서버와 ExdiGdbSrv.dll 사용하기 전에 채워야 함). |
CurrentTarget | GDB 서버 대상의 이름을 지정합니다(예: 이 특성 값은 exdiConfigData.xml 파일에 포함된 태그 중 <ExdiTarget Name= 하나의 이름 값과 일치해야 합니다. |
ExdiTarget | 각 GDB 서버 대상 구성 요소에 포함된 모든 구성 데이터에 대한 시작 태그입니다. |
속성 | GDB 서버의 이름을 지정합니다(예: QEMU, BMC-OpenOCD, Trace32, VMWare). |
agentNamePacket | GDB 서버 HW 디버거에서 인식할 수 있는 GDB 클라이언트의 이름입니다. GDB 서버 HW 디버거에서 특정 GDB 클라이언트에 대해 자신을 구성하는 데 사용할 수 있습니다(예: Trace32 GDB 서버는 "QMS.windbg" 이름을 보내서 windbg-GDB 클라이언트를 식별한 다음 MS GDB 서버 클라이언트(exdiGdbSrv.dll)에 대해서만 지원되는 사용자 지정된 GDB 메모리 패킷을 사용하도록 설정 ExdiGdbSrv.dll해야 합니다. |
ExdiGdbServerConfigData | ExdiGdbSrv.dll 구성 요소 관련 구성 매개 변수를 지정합니다. |
uuid | 는 ExdiGdbSrv.dll 구성 요소의 UUI를 지정합니다. |
displayCommPackets | '예'인 경우 플래그를 지정하면 명령 로그 창에 RSP 프로토콜 통신 문자가 표시됩니다. '아니요'이면 요청-응답 쌍 텍스트만 표시합니다. |
enableThrowExceptionOnMemoryErrors | GDB 오류 응답 패킷(E0x)이 있는 경우 GDB 서버 클라이언트에서 이 특성을 확인하여 클라이언트가 예외를 throw하고 메모리 읽기를 중지해야 하는지 여부를 확인합니다. |
qSupportedPacket | 이렇게 하면 GDB 클라이언트가 xml 대상 설명 파일 다음에 GDB 서버 HW 디버거가 전송해야 하는 xml 레지스터 아키텍처 파일을 요청하도록 구성할 수 있습니다(기본적으로 클라이언트는 클라이언트에서 지원하는 아키텍처를 GDB 서버에 알릴 것이며, 현재 클라이언트는 x64 아키텍처를 지원합니다). |
ExdiGdbServerTargetData | GdbServer 세션에서 디버그하는 하드웨어 대상과 관련된 매개 변수를 지정합니다. |
targetArchitecture | 대상 하드웨어 아키텍처를 포함하는 문자열입니다. 가능한 값: X86, X64, ARM, ARM64. 현재 exdiGdbSrv.dll X86 및 ARM만 지원합니다. |
targetFamily | 대상 하드웨어 패밀리를 포함하는 문자열입니다. 가능한 값: ProcessorFamilyX86, ProcessorFamilyX64, ProcessorFamilyARM, ProcessorFamilyARM64. |
numberOfCores | 대상이 지원하는 프로세서 코어 수입니다. 이 매개 변수는 다중 Gdbserver 세션(T32-GdbServer 세션)을 사용할 때 유효성이 검사됩니다. 아래 'MultiCoreGdbServerSessions' 특성은 '예'로 설정해야 합니다. |
EnableSseContext | 'yes'인 경우 플래그를 지정하면 'g' 컨텍스트 RSP 패킷에 부동 소수점 레지스터 값이 포함됩니다. 이 매개 변수는 Intel 제품군 대상에만 적합합니다. |
heuristicScanSize | 이렇게 하면 지정된 크기로 스캔된 메모리 프로브를 줄이도록 디버거 엔진의 빠른 추론 알고리즘이 구성됩니다. 특성 값 이 지정되지 않은 경우(또는 "0"), 디버거 엔진은 빠른 추론을 사용하지 않고 PE DOS 서명을 찾는 전체 메모리를 검사하는 레거시 추론으로 대체됩니다. 일반적인 검사 크기 값은 0xfffe(NT에 가장 적합) 또는 0xffe(사전 NT 앱의 경우)입니다. |
targetDescriptionFile | 는 GDB 서버가 각 개별 xml 파일을 보내기 전에 대상 설명 헤더 파일을 보내는지 지정합니다. 이 필드는 비어 있으면 GDB 서버 클라이언트가 xml 아키텍처 시스템 레지스터를 요청하지 않습니다(예: 별도의 xml 파일에서 아키텍처 레지스터 전송을 지원하지 않는 Trace32 GDBs 서버). |
GdbServerConnectionParameters | GdbServer 세션 매개 변수를 지정합니다. 이러한 매개 변수는 ExdiGdbSrv.dll 구성 요소와 GdbServer 간의 RSP GdbServer 세션을 제어하는 데 사용됩니다. |
MultiCoreGdbServerSessions | 플래그가 '예'이면 다중 코어 GdbServer 세션(T32-GdbServer 백 엔드에서 사용되는 세션)이 있습니다. '아니요'이면 GdbServer의 인스턴스 하나만 통신합니다. |
MaximumGdbServerPacketLength | 이는 한 패킷에 대해 지원되는 최대 GdbServer 길이입니다. |
MaximumConnectAttempts | 최대 연결 시도입니다. GdbServer에 대한 RSP 연결을 설정하려고 할 때 ExdiGdbSrv.dll 사용됩니다. |
SendPacketTimeout | RSP 전송 시간 제한입니다. |
ReceivePacketTimeout | RSP 수신 시간 제한입니다. |
HostNameAndPort | 형식<hostname/ip address:Port number> 의 연결 문자열. 둘 이상의 GdbServer 연결 문자열 있을 수 있습니다(예: T32 다중 코어 GdbServer 세션). 연결 문자열 수는 코어 수와 일치해야 합니다. |
ExdiGdbServerMemoryCommands | 다양한 예외 CPU 수준에서 시스템 레지스터 값 또는 읽기/쓰기 액세스 메모리를 얻기 위해 GDB 메모리 명령을 실행하는 다양한 방법을 지정합니다(예: BMC-OpenOCD는 "aarch64 mrs nsec/sec <access code> " 사용자 지정 명령을 통해 CP15 레지스터에 대한 액세스를 제공합니다). |
GdbSpecialMemoryCommand | "예"이면 GDB 서버는 사용자 지정된 메모리 명령을 지원합니다(예: 시스템 레지스터, Trace32 GDB 서버에 대해 설정해야 함). |
PhysicalMemory | "예"이면 GDB 서버는 실제 메모리를 읽기 위한 사용자 지정된 명령을 지원합니다(Trace32 GDB 서버에 대해 설정됨). |
SupervisorMemory | "yes"이면 GDB 서버는 감독자 메모리를 읽기 위한 사용자 지정된 명령을 지원합니다(Trace32 GDB 서버에 대해 설정됨). |
SpecialMemoryRegister | "예"이면 GDB 서버는 시스템 레지스터를 읽기 위한 사용자 지정된 명령을 지원합니다(Trace32 GDB 서버에 대해 설정됨). |
SystemRegistersGdbMonitor | "예"이면 GDB 서버는 GDB 모니터 명령을 통해 사용자 지정된 명령을 지원합니다(BMC Open-OCD에 대해 설정됨). |
SystemRegisterDecoding | "예"이면 GDB 클라이언트는 GDB 모니터 명령을 보내기 전에 액세스 코드 디코딩을 허용합니다. |
ExdiGdbServerRegisters | 특정 아키텍처 레지스터 코어 집합을 지정합니다. |
아키텍처 | 정의된 레지스터 집합의 CPU 아키텍처입니다. |
FeatureNameSupported | xml 시스템 레지스터 설명 파일에서 제공하는 시스템 레지스터 그룹의 이름입니다. GDB 서버에서 보낸 xml 파일의 일부인 시스템 레지스터 xml 그룹을 식별해야 합니다. |
SystemRegistersStart | 이는 코어 레지스터 집합의 일부로 보고되는 첫 번째 시스템 레지스터(낮은 레지스터 번호/순서)를 식별하기 위한 것입니다(예: X64에서 QEMU는 x64 시스템 레지스터 집합을 구분된 xml 대상 설명 파일로 보고하지 않으므로 시스템 regs는 핵심 레지스터의 일부임). |
SystemRegistersEnd | 핵심 레지스터 집합의 일부로 보고되는 마지막 시스템 레지스터(높은 레지스터 번호/순서)를 식별하기 위한 것입니다. |
속성 | 레지스터의 이름입니다. |
순서 | 레지스터 배열의 인덱스를 식별하는 숫자입니다. 이 번호는 GDB 클라이언트 및 서버 집합/쿼리(p<number>”/”q<number> ) 등록 패킷에서 사용됩니다. |
크기 | 레지스터 크기(바이트)입니다. |
샘플 exdiConfigData.xml 파일
<ExdiTargets CurrentTarget = "QEMU">
<!-- QEMU SW simulator GDB server configuration -->
<ExdiTargets CurrentTarget="QEMU">
<!-- QEMU SW simulator GDB server configuration -->
<ExdiTarget Name="QEMU">
<ExdiGdbServerConfigData agentNamePacket="" uuid="72d4aeda-9723-4972-b89a-679ac79810ef" displayCommPackets="yes" debuggerSessionByCore="no" enableThrowExceptionOnMemoryErrors="yes" qSupportedPacket="qSupported:xmlRegisters=aarch64,i386">
<ExdiGdbServerTargetData targetArchitecture="ARM64" targetFamily="ProcessorFamilyARM64" numberOfCores="1" EnableSseContext="no" heuristicScanSize="0xfffe" targetDescriptionFile="target.xml"/>
<GdbServerConnectionParameters MultiCoreGdbServerSessions="no" MaximumGdbServerPacketLength="1024" MaximumConnectAttempts="3" SendPacketTimeout="100" ReceivePacketTimeout="3000">
<Value HostNameAndPort="LocalHost:1234"/>
</GdbServerConnectionParameters>
<ExdiGdbServerMemoryCommands GdbSpecialMemoryCommand="no" PhysicalMemory="no" SupervisorMemory="no" HypervisorMemory="no" SpecialMemoryRegister="no" SystemRegistersGdbMonitor="no" SystemRegisterDecoding="no"> </ExdiGdbServerMemoryCommands>
<ExdiGdbServerRegisters Architecture = "ARM64" FeatureNameSupported = "sys">
<Entry Name ="X0" Order = "0" Size = "8" />
<Entry Name ="X1" Order = "1" Size = "8" />
<Entry Name ="X2" Order = "2" Size = "8" />
<Entry Name ="X3" Order = "3" Size = "8" />
<Entry Name ="X4" Order = "4" Size = "8" />
<Entry Name ="X5" Order = "5" Size = "8" />
<Entry Name ="X6" Order = "6" Size = "8" />
<Entry Name ="X7" Order = "7" Size = "8" />
<Entry Name ="X8" Order = "8" Size = "8" />
<Entry Name ="X9" Order = "9" Size = "8" />
<Entry Name ="X10" Order = "a" Size = "8" />
<Entry Name ="X11" Order = "b" Size = "8" />
<Entry Name ="X12" Order = "c" Size = "8" />
<Entry Name ="X13" Order = "d" Size = "8" />
<Entry Name ="X14" Order = "e" Size = "8" />
<Entry Name ="X15" Order = "f" Size = "8" />
<Entry Name ="X16" Order = "10" Size = "8" />
<Entry Name ="X17" Order = "11" Size = "8" />
<Entry Name ="X18" Order = "12" Size = "8" />
<Entry Name ="X19" Order = "13" Size = "8" />
<Entry Name ="X20" Order = "14" Size = "8" />
<Entry Name ="X21" Order = "15" Size = "8" />
<Entry Name ="X22" Order = "16" Size = "8" />
<Entry Name ="X23" Order = "17" Size = "8" />
<Entry Name ="X24" Order = "18" Size = "8" />
<Entry Name ="X25" Order = "19" Size = "8" />
<Entry Name ="X26" Order = "1a" Size = "8" />
<Entry Name ="X27" Order = "1b" Size = "8" />
<Entry Name ="X28" Order = "1c" Size = "8" />
<Entry Name ="fp" Order = "1d" Size = "8" />
<Entry Name ="lr" Order = "1e" Size = "8" />
<Entry Name ="sp" Order = "1f" Size = "8" />
<Entry Name ="pc" Order = "20" Size = "8" />
<Entry Name ="cpsr" Order = "21" Size = "8" />
<Entry Name ="V0" Order = "22" Size = "16" />
<Entry Name ="V1" Order = "23" Size = "16" />
<Entry Name ="V2" Order = "24" Size = "16" />
<Entry Name ="V3" Order = "25" Size = "16" />
<Entry Name ="V4" Order = "26" Size = "16" />
<Entry Name ="V5" Order = "27" Size = "16" />
<Entry Name ="V6" Order = "28" Size = "16" />
<Entry Name ="V7" Order = "29" Size = "16" />
<Entry Name ="V8" Order = "2a" Size = "16" />
<Entry Name ="V9" Order = "2b" Size = "16" />
<Entry Name ="V10" Order = "2c" Size = "16" />
<Entry Name ="V11" Order = "2d" Size = "16" />
<Entry Name ="V12" Order = "2e" Size = "16" />
<Entry Name ="V13" Order = "2f" Size = "16" />
<Entry Name ="V14" Order = "30" Size = "16" />
<Entry Name ="V15" Order = "31" Size = "16" />
<Entry Name ="V16" Order = "32" Size = "16" />
<Entry Name ="V17" Order = "33" Size = "16" />
<Entry Name ="V18" Order = "34" Size = "16" />
<Entry Name ="V19" Order = "35" Size = "16" />
<Entry Name ="V20" Order = "36" Size = "16" />
<Entry Name ="V21" Order = "37" Size = "16" />
<Entry Name ="V22" Order = "38" Size = "16" />
<Entry Name ="V23" Order = "39" Size = "16" />
<Entry Name ="V24" Order = "3a" Size = "16" />
<Entry Name ="V25" Order = "3b" Size = "16" />
<Entry Name ="V26" Order = "3c" Size = "16" />
<Entry Name ="V27" Order = "3d" Size = "16" />
<Entry Name ="V28" Order = "3e" Size = "16" />
<Entry Name ="V29" Order = "3f" Size = "16" />
<Entry Name ="V30" Order = "3f" Size = "16" />
<Entry Name ="V31" Order = "3f" Size = "16" />
<Entry Name ="fpsr" Order = "40" Size = "4" />
<Entry Name ="fpcr" Order = "41" Size = "4" />
</ExdiGdbServerRegisters>
<!-- x64 GDB server core resgisters -->
<ExdiGdbServerRegisters Architecture = "X64" FeatureNameSupported = "sys" SystemRegistersStart = "18" SystemRegistersEnd = "20" >
<Entry Name ="rax" Order = "0" Size ="8" />
<Entry Name ="rbx" Order = "1" Size ="8" />
<Entry Name ="rcx" Order = "2" Size ="8" />
<Entry Name ="rdx" Order = "3" Size ="8" />
<Entry Name ="rsi" Order = "4" Size ="8" />
<Entry Name ="rdi" Order = "5" Size ="8" />
<Entry Name ="rbp" Order = "6" Size ="8" />
<Entry Name ="rsp" Order = "7" Size ="8" />
<Entry Name ="r8" Order = "8" Size ="8" />
<Entry Name ="r9" Order = "9" Size ="8" />
<Entry Name ="r10" Order = "a" Size ="8" />
<Entry Name ="r11" Order = "b" Size ="8" />
<Entry Name ="r12" Order = "c" Size ="8" />
<Entry Name ="r13" Order = "d" Size ="8" />
<Entry Name ="r14" Order = "e" Size ="8" />
<Entry Name ="r15" Order = "f" Size ="8" />
<Entry Name ="rip" Order = "10" Size ="8" />
<!-- <flags id="x64_eflags" size="4">
<field name="" start="22" end="31"/>
<field name="ID" start="21" end="21"/>
<field name="VIP" start="20" end="20"/>
<field name="VIF" start="19" end="19"/>
<field name="AC" start="18" end="18"/>
<field name="VM" start="17" end="17"/>
<field name="RF" start="16" end="16"/>
<field name="" start="15" end="15"/>
<field name="NT" start="14" end="14"/>
<field name="IOPL" start="12" end="13"/>
<field name="OF" start="11" end="11"/>
<field name="DF" start="10" end="10"/>
<field name="IF" start="9" end="9"/>
<field name="TF" start="8" end="8"/>
<field name="SF" start="7" end="7"/>
<field name="ZF" start="6" end="6"/>
<field name="" start="5" end="5"/>
<field name="AF" start="4" end="4"/>
<field name="" start="3" end="3"/>
<field name="PF" start="2" end="2"/>
<field name="" start="1" end="1"/>
<field name="CF" start="0" end="0"/>
</flags> -->
<Entry Name ="eflags" Order = "11" Size ="4" />
<!-- Segment registers -->
<Entry Name ="cs" Order = "12" Size ="4" />
<Entry Name ="ss" Order = "13" Size ="4" />
<Entry Name ="ds" Order = "14" Size ="4" />
<Entry Name ="es" Order = "15" Size ="4" />
<Entry Name ="fs" Order = "16" Size ="4" />
<Entry Name ="gs" Order = "17" Size ="4" />
<!-- Segment descriptor caches and TLS base MSRs -->
<!--Entry Name ="cs_base" Order = "18" Size="8"/
<Entry Name ="ss_base" Order = "18" Size ="8" />
<Entry Name ="ds_base" Order = "19" Size ="8" />
<Entry Name ="es_base" Order = "1a" Size ="8" /> -->
<Entry Name ="fs_base" Order = "18" Size ="8" />
<Entry Name ="gs_base" Order = "19" Size ="8" />
<Entry Name ="k_gs_base" Order = "1a" Size ="8" />
<!-- Control registers -->
<!-- the cr0 register format fields:
<flags id="x64_cr0" size="8">
<field name="PG" start="31" end="31"/>
<field name="CD" start="30" end="30"/>
<field name="NW" start="29" end="29"/>
<field name="AM" start="18" end="18"/>
<field name="WP" start="16" end="16"/>
<field name="NE" start="5" end="5"/>
<field name="ET" start="4" end="4"/>
<field name="TS" start="3" end="3"/>
<field name="EM" start="2" end="2"/>
<field name="MP" start="1" end="1"/>
<field name="PE" start="0" end="0"/>
</flags> -->
<Entry Name ="cr0" Order = "1b" Size ="8" />
<Entry Name ="cr2" Order = "1c" Size ="8" />
<!-- the cr3 register format fields:
<flags id="x64_cr3" size="8">
<field name="PDBR" start="12" end="63"/>
<field name="PCID" start="0" end="11"/>
</flags> -->
<Entry Name ="cr3" Order = "1d" Size ="8" />
<!-- the cr4 register format fields:
<flags id="x64_cr4" size="8">
<field name="PKE" start="22" end="22"/>
<field name="SMAP" start="21" end="21"/>
<field name="SMEP" start="20" end="20"/>
<field name="OSXSAVE" start="18" end="18"/>
<field name="PCIDE" start="17" end="17"/>
<field name="FSGSBASE" start="16" end="16"/>
<field name="SMXE" start="14" end="14"/>
<field name="VMXE" start="13" end="13"/>
<field name="LA57" start="12" end="12"/>
<field name="UMIP" start="11" end="11"/>
<field name="OSXMMEXCPT" start="10" end="10"/>
<field name="OSFXSR" start="9" end="9"/>
<field name="PCE" start="8" end="8"/>
<field name="PGE" start="7" end="7"/>
<field name="MCE" start="6" end="6"/>
<field name="PAE" start="5" end="5"/>
<field name="PSE" start="4" end="4"/>
<field name="DE" start="3" end="3"/>
<field name="TSD" start="2" end="2"/>
<field name="PVI" start="1" end="1"/>
<field name="VME" start="0" end="0"/>
</flags> -->
<Entry Name ="cr4" Order = "1e" Size ="8" />
<Entry Name ="cr8" Order = "1f" Size ="8" />
<!-- the efer register format fields:
<flags id="x64_efer" size="8">
<field name="TCE" start="15" end="15"/>
<field name="FFXSR" start="14" end="14"/>
<field name="LMSLE" start="13" end="13"/>
<field name="SVME" start="12" end="12"/>
<field name="NXE" start="11" end="11"/>
<field name="LMA" start="10" end="10"/>
<field name="LME" start="8" end="8"/>
<field name="SCE" start="0" end="0"/>
</flags> -->
<Entry Name ="efer" Order = "20" Size ="8"/>
<!-- x87 FPU -->
<Entry Name ="st0" Order = "21" Size ="10" />
<Entry Name ="st1" Order = "22" Size ="10" />
<Entry Name ="st2" Order = "23" Size ="10" />
<Entry Name ="st3" Order = "24" Size ="10" />
<Entry Name ="st4" Order = "25" Size ="10" />
<Entry Name ="st5" Order = "26" Size ="10" />
<Entry Name ="st6" Order = "27" Size ="10" />
<Entry Name ="st7" Order = "28" Size ="10" />
<Entry Name ="fctrl" Order = "29" Size ="4" />
<Entry Name ="fstat" Order = "2a" Size ="4" />
<Entry Name ="ftag" Order = "2b" Size ="4" />
<Entry Name ="fiseg" Order = "2c" Size ="4" />
<Entry Name ="fioff" Order = "2d" Size ="4" />
<Entry Name ="foseg" Order = "2e" Size ="4" />
<Entry Name ="fooff" Order = "2f" Size ="4" />
<Entry Name ="fop" Order = "30" Size ="4" />
<Entry Name ="xmm0" Order = "31" Size ="16" />
<Entry Name ="xmm1" Order = "32" Size ="16" />
<Entry Name ="xmm2" Order = "33" Size ="16" />
<Entry Name ="xmm3" Order = "34" Size ="16" />
<Entry Name ="xmm4" Order = "35" Size ="16" />
<Entry Name ="xmm5" Order = "36" Size ="16" />
<Entry Name ="xmm6" Order = "37" Size ="16" />
<Entry Name ="xmm7" Order = "38" Size ="16" />
<Entry Name ="xmm8" Order = "39" Size ="16" />
<Entry Name ="xmm9" Order = "3a" Size ="16" />
<Entry Name ="xmm10" Order = "3b" Size ="16" />
<Entry Name ="xmm11" Order = "3c" Size ="16" />
<Entry Name ="xmm12" Order = "3d" Size ="16" />
<Entry Name ="xmm13" Order = "3e" Size ="16" />
<Entry Name ="xmm14" Order = "3f" Size ="16" />
<Entry Name ="xmm15" Order = "40" Size ="16" />
<!-- the mxcsr register format fields:
<flags id="x64_mxcsr" size="4">
<field name="IE" start="0" end="0"/>
<field name="DE" start="1" end="1"/>
<field name="ZE" start="2" end="2"/>
<field name="OE" start="3" end="3"/>
<field name="UE" start="4" end="4"/>
<field name="PE" start="5" end="5"/>
<field name="DAZ" start="6" end="6"/>
<field name="IM" start="7" end="7"/>
<field name="DM" start="8" end="8"/>
<field name="ZM" start="9" end="9"/>
<field name="OM" start="10" end="10"/>
<field name="UM" start="11" end="11"/>
<field name="PM" start="12" end="12"/>
<field name="FZ" start="15" end="15"/>
</flags> -->
<Entry Name ="mxcsr" Order = "41" Size ="4" />
</ExdiGdbServerRegisters>
</ExdiGdbServerConfigData>
</ExdiTarget>
</ExdiTargets>
</ExdiTargets>
EXDI PowerShell 스크립트 예제
이 샘플 PowerShell 스크립트는 EXDI를 설치한 다음 디버거를 시작합니다. Start-ExdiDebugger.ps1 스크립트는 필요한 경우 ExdiGdbSrv.dll 설치하고, xml 설정 파일을 구성하고, dllhost.exe 프로세스 실행을 확인하고, 디버거를 시작하여 이미 실행 중인 gdb 서버 하드웨어 디버깅 대상에 연결합니다.
WinDBg에서 사용할 수 있는 사용자 인터페이스를 사용하는 경우 ExdiGdbSrv.dll 이미 설치되어 있으며 이 스크립트는 관련이 없습니다. 기본 제공 사용자 인터페이스 사용에 대한 자세한 내용은 EXDI 디버거 전송 구성을 참조 하세요.
시작 스크립트를 호출하는 예제입니다.
PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64
필요한 경우 빌드된 파일을 지정할 수도 있습니다.
PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files"
Start-ExdiDebugger.ps1에는 다음과 같은 설정 옵션이 있습니다.
매개 변수 | 설명 |
---|---|
ExdiTarget | 연결할 대상의 유형입니다. 이는 설정 xml 파일의 특정 섹션에 해당합니다. |
HostName | gdb 서버 세션을 호스팅하는 컴퓨터의 IP 주소 또는 호스트 이름(기본값은 "LocalHost") |
GdbPort | gdb 서버가 수신 대기 중인 포트입니다. |
아키텍처 | 하드웨어 디버깅 대상의 아키텍처(이 매개 변수는 xml 설정 파일의 ArchitectureFamily 매개 변수도 의미) |
ExdiDropPath | ExdiGdbSrv.dll, exdiConfigData.xml 및 systemregisters.xml 파일의 위치입니다. ExdiGdbSrv.dll 설치되지 않았거나 잘못 설치된 경우에만 복사됩니다. |
ExtraDebuggerArgs | 디버거 명령줄에 전달할 추가 인수 |
PreNTAppDebugging | heuristicScanSize의 값을 0xfffe(NT에 가장 적합)에서 0xffe(사전 NT 앱의 경우)로 변경합니다. |
DontTryDllHostCleanup | dllhost.exe ExdiGdbSrv.dll 기존 실행 중인 인스턴스를 확인하려면 권한 상승이 필요합니다. 이 스위치를 제공하면 디버거가 제대로 작동하지 않을 수 있지만 권한 상승 없이 스크립트를 실행할 수 있습니다. |
패킷을 표시할 수 있도록 하려면 displayCommPackets의 값을 예로 설정합니다.
[pscustomobject]@{ Path = 'displayCommPackets' ; value = "yes" }
.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files"
자세한 설정 옵션은 코드 주석을 참조하세요.
<#
.Synopsis
Installs and launches exdi debugger (automating xml file editing)
.Description
This script will install ExdiGdbSrv.dll if required, configure the xml settings
files, check for running dllhost.exe processes, and launch the debugger to connect to
an already running gdb server hardware debugging target.
.Parameter ExdiTarget
Type of target to connect to. This corresponds to a specific section in the settings xml file
.Parameter HostName
IP address or hostname of the computer hosting the gdb server session (defaults to "LocalHost")
.Parameter GdbPort
Port that the gdb server is listening on.
.Parameter Architecture
Architecture of the hardware debugging target (this parameter also implies the ArchitectureFamily
parameter in the xml settings file)
.Parameter ExdiDropPath
Location of the ExdiGdbSrv.dll, exdiConfigData.xml, and systemregisters.xml files. These will
only be copied if ExdiGdbSrv.dll is not installed or is installed incorrectly.
.Parameter ExtraDebuggerArgs
Extra arguments to pass on the debugger command line
.Parameter PreNTAppDebugging
Changes the value of the heuristicScanSize from 0xfffe (best for NT) to 0xffe (for pre-NT Apps)
.Parameter DontTryDllHostCleanup
Checking for existing running instances of ExdiGdbSrv.dll in dllhost.exe requires elevation.
Providing this switch will allow the script to run without elevation (although the debugger may not
function correctly).
.Example
>---------------- (first run) ------------<
.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files"
.Example
PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64
#>
[CmdletBinding()]
param
(
[ValidateSet("QEMU")]
[string]
$ExdiTarget = "QEMU",
[string]
$HostName = "LocalHost",
[Parameter(Mandatory=$true)]
[Int]
$GdbPort,
[Parameter(Mandatory=$true)]
[string]
[ValidateSet("x86", "x64", "arm64")]
$Architecture,
[string]
$ExdiDropPath,
[string]
$DebuggerPath,
[string[]]
$ExtraDebuggerArgs = @(),
[switch]
$PreNTAppDebugging,
[switch]
$DontTryDllHostCleanup
)
$ErrorActionPreference = "Stop"
#region Functions
Function Test-Admin
{
([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]"Administrator")
}
Function Find-PathToWindbgX
{
$InternalWindbgXPath = "$env:LOCALAPPDATA\DBG\UI\WindbgX.exe"
$ExternalWindbgXPath = "$env:LOCALAPPDATA\Microsoft\WindowsApps\WinDbgX.exe"
if (Test-Path $InternalWindbgXPath -PathType Leaf)
{
return $InternalWindbgXPath
}
elseif (Test-Path $ExternalWindbgXPath -PathType Leaf)
{
return $ExternalWindbgXPath
}
}
Function Test-ParameterValidation
{
$CommandName = $PSCmdlet.MyInvocation.InvocationName
$ParameterList = (Get-Command -Name $CommandName).Parameters
foreach ($Parameter in $ParameterList) {
Get-Variable -Name $Parameter.Values.Name -ErrorAction SilentlyContinue | Out-String | Write-Verbose
}
if (-not $DebuggerPath)
{
throw "WindbgX is not installed"
}
elseif (-not (Test-Path $DebuggerPath -PathType Leaf))
{
throw "DebuggerPath param ($DebuggerPath) does not point to a debugger."
}
# Searching for loaded instances of ExdiGdbSrv.dll in dllhost.exe requires elevation
if (-not $DontTryDllHostCleanup -and
-not $(Test-Admin))
{
throw "Searching for loaded instances of ExdiGdbSrv.dll in dllhost.exe requires elevation. Run with the -DontTryDllHostCleanup parameter to skip this check (debugger session init may fail)."
}
}
Function Get-ExdiInstallPath
{
Get-ItemPropertyValue -Path "Registry::HKEY_CLASSES_ROOT\CLSID\{29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014}\InProcServer32" -Name "(default)" -ErrorAction SilentlyContinue
}
Function Test-ExdiServerInstalled
{
# Check registration of exdi server class
if ($(Get-ExdiInstallPath) -ne $null -and $(Test-Path "$(Get-ExdiInstallPath)"))
{
Write-Verbose "Exdi server is installed. Checking installation..."
$ExdiInstallDir = [System.IO.Path]::GetDirectoryName($(Get-ExdiInstallPath))
if (-not (Test-Path $ExdiInstallDir))
{
Write-Host "Currently Registered exdi server does not exist. Reinstalling..."
return $false
}
elseif (-not ((Test-Path "$ExdiInstallDir\exdiConfigData.xml") -and (Test-Path "$ExdiInstallDir\systemregisters.xml")))
{
Write-Host "Currently Registered exdi server does not have required xml settings files. Reinstalling..."
return $false
}
else
{
Write-Verbose "Exdi server is insalled correctly. Skipping installation..."
return $true
}
}
else
{
Write-Host "Exdi server is not installed. Installing..."
return $false
}
}
Function Install-ExdiServer
{
[CmdletBinding()]
param
(
[string] $InstallFrom,
[string] $InstallTo
)
if (-not $(Test-Admin))
{
throw "Script needs to be run as an Admin to install exdi software."
}
New-Item -ItemType Directory $InstallTo -ErrorAction SilentlyContinue | Write-Verbose
Copy-Item -Path "$InstallFrom\ExdiGdbSrv.dll" -Destination $InstallTo -ErrorAction stop | Write-Verbose
Copy-Item -Path "$InstallFrom\exdiConfigData.xml" -Destination $InstallTo -ErrorAction stop | Write-Verbose
Copy-Item -Path "$InstallFrom\systemregisters.xml" -Destination $InstallTo -ErrorAction stop | Write-Verbose
regsvr32 /s "$InstallTo\ExdiGdbSrv.dll"
if ($(Get-ExdiInstallPath) -eq $null)
{
throw "Unable to install exdi server"
}
}
Function Edit-ExdiConfigFile
{
[CmdletBinding()]
param
(
[string] $ExdiFilePath,
[string] $ExdiTargetType,
[PSCustomObject[]] $XmlSettingPathValueList
)
# Edit exdiConfigData.xml
[xml]$exdiConfigXml = Get-Content "$ExdiFilePath"
# Set current target
$exdiConfigXml.ExdiTargets.CurrentTarget = $ExdiTarget
# set HostNameAndPort
$ExdiTargetXmlNode = $exdiConfigXml.SelectSingleNode("//ExdiTargets/ExdiTarget[@Name='$ExdiTarget']/ExdiGdbServerConfigData")
foreach ($XmlSettingPathValue in $XmlSettingPathValueList)
{
Write-Verbose "Processing $XmlSettingPathValue"
if ($XmlSettingPathValue.Value -eq $null)
{
continue
}
$PathParts = $XmlSettingPathValue.Path.Split(".")
$curNode = $ExdiTargetXmlNode
if ($PathParts.Count -gt 1)
{
foreach ($PathPart in $PathParts[0..($PathParts.Count-2)])
{
Write-Verbose $PathPart
$curNode = $curNode.($PathPart)
}
}
$curNode.($PathParts[-1]) = $XmlSettingPathValue.Value
}
$exdiConfigXml.Save("$ExdiFilePath")
}
Function Stop-ExdiContainingDllHosts
{
$DllHostPids = Get-Process dllhost | ForEach-Object { $_.Id }
foreach ($DllHostPid in $DllHostPids)
{
$DllHostExdiDlls = Get-Process -Id $DllHostPid -Module | Where-Object { $_.FileName -like "*ExdiGdbSrv.dll" }
if ($DllHostExdiDlls.Count -ne 0)
{
Write-Verbose "Killing dllhost.exe with pid $DllHostPid (Contained instance of ExdiGdbSrv.dll)"
Stop-Process -Id $DllHostPid -Force
}
}
}
#endregion
#region Script
# Apply defaults for $DebuggerPath before Parameter validation
if (-not $DebuggerPath)
{
$DebuggerPath = Find-PathToWindbgX
}
Test-ParameterValidation
# look clean up dllhost.exe early since it can hold a lock on files which
# need to be overwritten
if (-not $DontTryDllHostCleanup)
{
Stop-ExdiContainingDllHosts
}
if (-not $(Test-ExdiServerInstalled))
{
if (-not $ExdiDropPath)
{
throw "ExdiServer is not installed and -ExdiDropPath is not valid"
}
$ExdiInstallDir = Join-Path -Path "$([System.IO.Path]::GetDirectoryName($DebuggerPath))" -ChildPath "exdi"
Install-ExdiServer -InstallFrom "$ExdiDropPath" -InstallTo "$ExdiInstallDir"
}
$SystemRegistersFilepath = Join-Path -Path "$([System.IO.Path]::GetDirectoryName($(Get-ExdiInstallPath)))" -ChildPath "systemregisters.xml"
$ExdiConfigFilepath = Join-Path -Path "$([System.IO.Path]::GetDirectoryName($(Get-ExdiInstallPath)))" -ChildPath "exdiConfigData.xml"
# Calculate implied parameters
$HeuristicScanSize = if ($PreNTAppDebugging) { "0xffe" } else { "0xfffe" }
$ArchitectureFamily = switch($Architecture)
{
x64 { "ProcessorFamilyx64" }
x86 { "ProcessorFamilyx86" }
arm64 { "ProcessorFamilyARM64" }
}
# Path is evaluated relative to the relevant ExdiTarget's ExdiGdbServerConfigData node in the xml schema
$SettingsToChange = @(
[pscustomobject]@{ Path = 'GdbServerConnectionParameters.Value.HostNameAndPort' ; Value = "${HostName}:$GdbPort" },
[pscustomobject]@{ Path = 'ExdiGdbServerTargetData.targetArchitecture' ; Value = "$Architecture" },
[pscustomobject]@{ Path = 'ExdiGdbServerTargetData.targetFamily' ; Value = "$ArchitectureFamily" },
[pscustomobject]@{ Path = 'ExdiGdbServerTargetData.heuristicScanSize' ; Value = "$HeuristicScanSize" },
[pscustomobject]@{ Path = 'displayCommPackets' ; value = "no" }
)
Edit-ExdiConfigFile -ExdiFilePath "$ExdiConfigFilepath" -ExdiTargetType "$ExdiTarget" -XmlSettingPathValueList $SettingsToChange
# Set env vars for debugger
[System.Environment]::SetEnvironmentVariable('EXDI_GDBSRV_XML_CONFIG_FILE',"$ExdiConfigFilepath")
[System.Environment]::SetEnvironmentVariable('EXDI_SYSTEM_REGISTERS_MAP_XML_FILE',"$SystemRegistersFilepath")
$DebuggerArgs = @("-v", "-kx exdi:CLSID={29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014},Kd=Guess,DataBreaks=Exdi")
Write-Verbose "DebuggerPath = $DebuggerPath"
Start-Process -FilePath "$DebuggerPath" -ArgumentList ($DebuggerArgs + $ExtraDebuggerArgs)
#endregion