Download presentation
Presentation is loading. Please wait.
Published byIrwan Suhendra Gunardi Modified 6년 전
1
윈도우 커널모드 드라이버 64비트 포팅 월간 마이크로소프트웨어 김성현
2
목차 64비트 세상 제품 포팅 계획 64비트 CPU 64비트 드라이버 빌드 DDK 예제 포팅 포팅 문제 해결
3
64비트 세상 INTEL P4 프레스캇 630 – 3GHz System Bus : 800MHz L1 Cache : 16KB
L2 Cache : 2MB 64Bit 지원( EM64T ) 하이퍼스레딩 기술 지원
4
64비트 드라이버 포팅! Why? 64비트 윈도우 정책 WOW64 64비트 드라이버 바이너리 필요!!!
32비트 APP 지원, 32비트 Driver 지원안함 WOW64 32비트 APP 에뮬레이션 레이어 32비트 APP 바이너리 그대로 수행 32비트 Driver 동작 못함 64비트 드라이버 바이너리 필요!!! 32비트, 64비트 One Source, Two Binary
5
Reserved Address Space
NT Executive Win32k.sys Kernel Mode User Mode Reserved Address Space 0x `7FFEFFFF or 0x `FFFEFFFF 64-bit ntdll.dll WoW64.dll WoW64win.dll WoW64cpu.dll 32-bit ntdll.dll 32-bit modules
6
제품 포팅 계획 32비트 APP 64비트 APP 유저모드 커널모드 64비트 Driver 64비트 Driver 방법1
(제약사항있음) 방법2
7
FileSystem Redirection
32비트 프로세스로 제품설치시 주의 32비트 APP 접근시 WOW64에서 처리 C:\Program Files => C:\Program Files(x86) C:\windows\system32 => C:\windows\syswow64 Wow64DisableWow64FsRedirection() API 로 제어가능
8
Registry Redirection 32비트 APP 접근시 WOW64에서 처리
HKLM\Software => HKLM\Software\Wow6432Node HKCR => HKCR\Wow6432Node RegOpenKeyEx(), RegCreateKeyEx() KEY_WOW64_64KEY: 64bit Registry 접근 KEY_WOW64_32KEY: 32bit Registry 접근
9
64비트 CPU 종류 AMD64 ( AMD ) IA64 ( INTEL ) EM64T ( INTEL ) 32비트 호환
Athlon64, Opteron IA64 ( INTEL ) 진보적인 아키텍쳐(RISC 기반, 32비트 호환?) Itanium, Itanium2 EM64T ( INTEL ) AMD64 Clone? 개발시 AMD64로 취급 ZEON EM64T, Pentium4 with EM64T Q) Dual P4 Hiper Threading EM64T
10
CPU별 바이너리 종류 지원 대상 CPU 생성할 바이너리 종류 AMD Opteron AMD64 바이너리 AMD Athlon64
Intel Xeon EM64T Intel Pentium 4 with EM64T Intel Itanium processors (including the Itanium2) IA64 바이너리
11
64비트 드라이버 빌드 DDK 64비트 빌드환경을 제공하는 DDK Windows Server 2003 SP1 DDK
CD 신청 Download 가능 Thanks OSR!!!
12
64비트 드라이버 빌드 32비트 드라이버 64비트 드라이버 NT4 빌드? 2K 빌드? XP 빌드?
2K3 빌드! ( XP x64 Edition 커널 )
13
64비트 드라이버 빌드 DDK 빌드 종류 용도 Windows Server 2003 Checked IA-64 Bit Build Environment IA64용 디버그버전 빌드 Windows Server 2003 Free IA-64 Bit Build Environment 릴리즈버전 빌드 Windows Server 2003 Checked x64 Build Environment AMD64, EM64T Windows Server 2003 Free x64 Build Environment IA64 define : _M_IA64, __IA64__ ; x64 define : _M_AMD64, __AMD64__
14
64비트 Windows Windows XP x64 Edition Windows XP 64bit Edition
Windows Server 2003 x64 Edition Windows Server 2003 for Itanium based system
15
인라인 어셈블리 OH NO!!! X86 instruction AMD64 instruction IA64 instruction
64비트 컴파일러는 인라인 어셈블리 미지원 원칙 : 1 C-Source Code, 3 Binary
16
AMD64 Instruction mov [rbp-0x80],rcx mov rdi,[rdi+0x18]
movzx ecx,byte ptr [rax+rdi] sub rsp,rcx and rsp,0xfffffffffffffff0 mov rdi,rsp mov rsi,[rbp+0x100] add rsi,0x28 test byte ptr [rbp+0xf0],0x1
17
IA64 Instruction addl r2=ffffffff`ffe020b8, gp ;; ld8 r2=[r2]
nop.i 0 ;; ld8 r3=[r2], 8 ;; ld8 gp=[r2] mov b6=r3, +0 nop.m 0 nop.i 0 br.cond.sptk.few b6
18
64비트 포팅 가이드라인 _WIN64 define ( _WIN32 ) __AMD64__, __IA64__ 포인터 사용 체크
sizeof(PULONG) != sizeof(ULONG) 포인터 연산 체크 32비트 + 32비트 = 64비트 0xFFFFFFFF != -1
19
64비트 포팅 가이드라인 ~((UINT64)(PAGE_SIZE-1)) == (UINT64)~(PAGE_SIZE-1) PAGE_SIZE = 0x1000UL // Unsigned Long - 32 bits PAGE_SIZE - 1 = 0x00000fff LHS expression: // Unsigned expansion(UINT64)(PAGE_SIZE -1 ) = 0x fff ~((UINT64)(PAGE_SIZE -1 )) = 0xfffffffffffff000 RHS expression: ~(PAGE_SIZE-1) = 0xfffff000 (UINT64)(~(PAGE_SIZE - 1)) = 0x fffff000 ~((UINT64)(PAGE_SIZE-1)) != (UINT64)(~(PAGE_SIZE-1))
20
드라이버 포팅 예제 NT4 DDK 샘플 64비트 빌드환경 일반샘플처럼 빌드
DDK\src\general\portio 64비트 빌드환경 Windows Server 2003 Checked IA-64(또는 x64) 실행 일반샘플처럼 빌드 생성된 Buildchk_wnet_IA64(또는 AMD64).err 확인
21
드라이버 포팅 예제
22
오류내용 1>sys\genport.c(223) : error C4312: 'type cast' : conversion from 'ULONG' to 'PVOID' of greater size 1>sys\genport.c(513) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG' 1>sys\genport.c(526) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG' 1>sys\genport.c(526) : error C4312: 'type cast' : conversion from 'unsigned long' to 'PUCHAR' of greater size 1>sys\genport.c(530) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG' 1>sys\genport.c(530) : error C4312: 'type cast' : conversion from 'unsigned long' to 'PUSHORT' of greater size 1>sys\genport.c(534) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG'
23
포인터의 타입캐스팅 데이터 타입의 크기에 대한 문제 포인터와 ULONG을 구분하지 않고 작성된 코드에 대한 문제
32비트 환경 포인터 크기: 32비트 32비트 환경 ULONG 크기: 32비트 64비트 환경 포인터 크기: 64비트 64비트 환경 ULONG 크기: 32비트 포인터와 ULONG을 구분하지 않고 작성된 코드에 대한 문제
24
포인터의 타입캐스팅 1>sys\genport.c(513) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG‘ 511 : if (nPort >= pLDI->PortCount || 512 : (nPort + DataBufferSize) > pLDI->PortCount || 513 : (((ULONG)pLDI->PortBase + nPort) & (DataBufferSize - 1)) != 0) pLDI->PortBase는 PVOID, nPort 는 ULONG 타입캐스팅이 에러?
25
포인터의 타입캐스팅 해결방법 1 ULONG_PTR ULONG 형 포인터? X 32비트 빌드시: 32비트 크기의 정수형
513 : (((ULONG_PTR)pLDI->PortBase + nPort) & (DataBufferSize - 1)) != 0) ULONG_PTR ULONG 형 포인터? X 32비트 빌드시: 32비트 크기의 정수형 64비트 빌드시: 64비트 크기의 정수형
26
포인터의 타입캐스팅 해결방법 2 PtrToUlong() 매크로
513 : ((PtrToUlong(pLDI->PortBase) + nPort) & (DataBufferSize - 1)) != 0) PtrToUlong() 매크로 #define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) ) 주의) pLDI->PortBase가 32비트로 잘림
27
포인터의 타입캐스팅 1>sys\genport.c(526) : error C4311: 'type cast' : pointer truncation from 'PVOID' to 'ULONG' 1>sys\genport.c(526) : error C4312: 'type cast' : conversion from 'unsigned long' to 'PUCHAR' of greater size 524 : case IOCTL_GPD_READ_PORT_UCHAR: 525: *(PUCHAR)pIOBuffer = READ_PORT_UCHAR( 526: (PUCHAR)((ULONG)pLDI->PortBase + nPort) ); 527: break; 한줄에 2가지 오류
28
포인터의 타입캐스팅 방법 1 방법 2 방법 2+ 신중히 결정할 것 주의) 반복되는 오류처리
(PUCHAR)((ULONG_PTR)pLDI->PortBase + nPort)); 방법 2 (PUCHAR)PtrToUlong(pLDI->PortBase) + nPort); 방법 2+ (PUCHAR)UlongToPtr(PtrToUlong(pLDI->PortBase) + nPort)); 신중히 결정할 것 주의) 반복되는 오류처리
29
타입캐스팅을 넘어서 1>sys\genport.c(223) : error C4312: 'type cast' : conversion from 'ULONG' to 'PVOID' of greater size 223 : pLocalInfo->PortBase = (PVOID)MappedAddress.LowPart; MappedAddress.LowPart 는 ULONG 타입캐스팅으로 해결? 아니면?
30
타입캐스팅을 넘어서 해결방법 1 223 : pLocalInfo->PortBase = UlongToPtr( MappedAddress.LowPart ); 해결방법 2 223 : pLocalInfo->PortBase = (PVOID)(ULONG_PTR)MappedAddress.LowPart;
31
타입캐스팅을 넘어서 해결방법 3 MappedAddress의 타입 데이터구조를 생각하자 LowPart? HighPart?
PHYSICAL_ADDRESS MappedAddress; typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
32
타입캐스팅을 넘어서 typedef union _LARGE_INTEGER { struct { ULONG LowPart;
LONG HighPart; }; } u; LONGLONG QuadPart; // 64비트!!! } LARGE_INTEGER;
33
타입캐스팅을 넘어서 해결방법 3 198: HalTranslateBusAddress( Isa, 199: 0,
223 : pLocalInfo->PortBase = (PVOID)MappedAddress.QuadPart; 198: HalTranslateBusAddress( Isa, 199: , 200: PortAddress, 201: &MemType, 202: &MappedAddress );
34
응용 프로그램과 드라이버가 공유하는 구조체 기존 32비트 응용프로그램이 사용하던 구조체를 새로 작성되는 64비트 드라이버에 전달해야 할 때 32비트 환경과 64비트 환경에서 데이터 크기가 달라지는 타입에 대한 문제
35
응용 프로그램과 드라이버가 공유하는 구조체 응용 프로그램 코드 예제 드라이버 코드 예제
GENPORT_WRITE_INPUT InputBuffer sscanf(argv[2],"%x",&InputBuffer.PortNumber); InputBuffer.LongData = (ULONG)DataValue; 드라이버 코드 예제 GENPORT_WRITE_INPUT *pInputBuffer nPortNum = pInputBuffer->PortNumber; nLongData = pInputBuffer->LongData;
36
응용 프로그램과 드라이버가 공유하는 구조체 Gpioctl.h
typedef struct _GENPORT_WRITE_INPUT { ULONG PortNumber; // Port # to write to union { // Data to be output to port ULONG LongData; USHORT ShortData; UCHAR CharData; }; } GENPORT_WRITE_INPUT;
37
응용 프로그램과 드라이버가 공유하는 구조체 32비트 APP + 64비트 DRV 32 비트 gpdwrite.exe
64 비트 genport.sys 32 비트 gpdwrite.exe GENPORT_WRITE_INPUT (ULONG 4 바이트, union 4 바이트)
38
공유 구조체 문제 32비트, 64비트에서 크기가 다른 데이터가 존재하는 경우
typedef struct _GENPORT_WRITE_INPUT { PVOID PortNumber; union { ULONG LongData; USHORT ShortData; UCHAR CharData; }; } GENPORT_WRITE_INPUT;
39
공유 구조체 문제 32비트 APP + 64비트 DRV 32 비트 gpdwrite.exe GENPORT_WRITE_INPUT
64 비트 genport.sys 32 비트 gpdwrite.exe GENPORT_WRITE_INPUT (PVOID 4 바이트, union 4 바이트) (PVOID 8 바이트,
40
공유 구조체 문제 해결 64비트 드라이버가 사용하는 32비트용 구조체 정의
typedef struct _GENPORT_WRITE_INPUT_32 { ULONG PortNumber; union { ULONG LongData; USHORT ShortData; UCHAR CharData; }; } GENPORT_WRITE_INPUT;
41
공유 구조체 문제 해결 32비트 APP + 64비트 DRV 64 비트 genport.sys 32 비트 gpdwrite.exe
GENPORT_WRITE_INPUT (PVOID 4 바이트, union 4 바이트) GENPORT_WRITE_INPUT_32 (ULONG 4 바이트,
42
IoIs32bitProcess() 시나리오 64비트 드라이버의 운명은? 32비트 기존 응용프로그램 사용
64비트 드라이버 출시 후… 64비트 응용프로그램 포팅 완료 64비트 드라이버의 운명은? 32 APP, 64 APP 모두 지원 32 APP, 64 APP 구분 필요
43
IoIs32bitProcess() 64비트 APP + 64비트 DRV 64 비트 gpdwrite.exe
GENPORT_WRITE_INPUT (PVOID 8 바이트, union 4 바이트) 64 비트 genport.sys GENPORT_WRITE_INPUT (PVOID 8 바이트, union 4 바이트)
44
IoIs32bitProcess() GENPORT_WRITE_INPUT *pInputBuffer
If (IoIs32bitProcess( Irp ) == TRUE) pInputBuffer32 = (GENPORT_WRITE_INPUT_32*) pIrp->AssociatedIrp.SystemBuffer; else pInputBuffer = (GENPORT_WRITE_INPUT*) pIrp->AssociatedIrp.SystemBuffer; switch (IoctlCode) { case IOCTL_GPD_WRITE_PORT_ULONG: nPortNum = pInputBuffer32->PortNumber; nLongData = pInputBuffer32->LongData; } Else // 64 bit nPortNum = pInputBuffer->PortNumber; nLongData = pInputBuffer->LongData;
45
IoIs32bitProcess() IOCTL Code 사용하는 방법 현재 64비트 Device Type (16)
Access (2) Custom(1) Function (11) Method (2) Device Type (16) Access (2) Custom(1) 64-Bit (1) Function (10) Method (2)
46
Quiz #pragma pack(1) typedef struct _PACK1_DATA { ULONG ul1;
UCHAR uc1; } PACK1_DATA; #pragma pack() #pragma pack(8) typedef struct _PACK8_DATA UCHAR uc8; PACK1_DATA p1d; ULONG ul8; } PACK8_DATA;
47
Quiz 32비트 환경에서 메모리 구성은? 1 2 3 uc8 ul1 uc1 ul8 uc8 ul1 uc1 ul8 uc8 ul1
padding ul1 uc1 padding ul8 uc8 ul1 uc1 padding ul8 uc8 padding ul1 uc1 ul8
48
Data Misalignment 문제 IA64에서 발생하는 문제 메모리 주소 경계에 맞지 않는 주소를 액세스할 경우
APP => 비정상종료 DRV => 블루스크린 Bug Check 0x1E: KMODE_EXCEPTION_NOT_HANDLED Parameter 1: 0x STATUS_DATATYPE_MISALIGNMENT
49
Data Misalignment 문제 #pragma pack(1)
typedef struct _GENPORT_WRITE_INPUT { BOOLEAN bTest; PVOID PortNumber; // Port # to write to union { // Data to be output to port ULONG LongData; USHORT ShortData; UCHAR CharData; }; } GENPORT_WRITE_INPUT; #pragma pack()
50
Data Misalignment 문제 1바이트 정렬된 구조체의 메모리구조 bTest GENPORT_WRITE_INPUT
PortNumber LongData
51
Data Misalignment 문제 해결
1. 예외 핸들링 2. 구조체를 정렬된 형태로 수정 3. 컴파일러에게 도움 요청
52
Data Misalignment 문제 해결
구조체 선언시 #pragma pack(1) 제거 8바이트 정렬된 구조체의 메모리구조 GENPORT_WRITE_INPUT bTest Padding PortNumber LongData
53
Data Misalignment 문제 해결
메모리 공간 절약 배치 typedef struct _GENPORT_WRITE_INPUT { PVOID PortNumber; // Port # to write to union { // Data to be output to port ULONG LongData; USHORT ShortData; UCHAR CharData; }; BOOLEAN bTest; } GENPORT_WRITE_INPUT;
54
Data Misalignment 문제 해결
8바이트 정렬하고 bTest를 맨뒤로… bTest GENPORT_WRITE_INPUT PortNumber LongData
55
Data Misalignment 문제 해결
컴파일러에게 도움 요청 죽어도 #pragma pack(1) 을 써야할 경우 32비트 응용 프로그램의 구조체를 수정하지 못할 경우 UNALIGNED 매크로 문제가 있는 코드임을 컴파일러에게 알림 1바이트씩 읽어서 조합해 주는 코드 생성 주의) 성능 저하의 우려가 있음
56
Data Misalignment 문제 해결
데이터 미정렬 예외(data misalignment exception)가 발생하는 코드 pInputBuffer->PortNumber = p; 데이터 미정렬 예외(data misalignment exception)가 발생하지 않는 코드 *(UNALIGNED PVOID) &pInputBuffer->PortNumber = p;
57
참고자료 DDK Help: 64-Bit Issues MS 사이트 64-bit Platform 드라이버 포팅 기본 가이드
64비트 개발관련 수많은 문서
58
Q & A
Similar presentations