2014-04-15 3 views
2

GDB를 사용하여 프로그램을 디버깅하는 동안 IA32_FS_BASE 및 IA32_GS_BASE와 같은 x86-64 모델 관련 레지스터를 읽을 수있는 방법이 있습니까?GDB를 사용하여 MSR 읽기

인텔 Pintool과 같은 동적 인스 트루먼 테이션 패키지를 사용하는 솔루션은 그리 바람직하지 않지만 모두 만족 스럽습니다.

답변

2

당신은 당신의 코드를 변경하지 않으려면 (또는 코드를 사용할 수없는 경우)의 다음과 같은 방법으로 답을 amdn 비슷한 일을 할 수 있습니다. arch_prctl에 대한 호출은 스택의 빈 부분 (현재 스택 포인터 아래의 8 바이트)에 주소를 사용하는 uint64_t에 대한 포인터가 필요합니다. 호출이 반환 된 후 해당 위치에 저장된 8 바이트 값을 읽습니다.

상수 사용했을 ARCH_GET_FS = 0x1003, ARCH_GET_GS =

(gdb) p $rsp 
$1 = (void *)0x7fffffffe6f0 

(gdb) call arch_prctl(0x1003, $rsp - 0x8)  
$2 = 0 
(gdb) x /gx $rsp - 0x8 
0x7fffffffe6e8: 0x00007ffff7fe0700 => IA32_FS_BASE 

(gdb) call arch_prctl(0x1004, $rsp - 0x8) 
$3 = 0 
(gdb) x /gx $rsp - 0x8 
0x7fffffffe6e8: 0x0000000000000000 => IA32_GS_BASE 
0x1004
3

명령어 인 privileged (Ring 0)을 사용하면 x86 을 읽을 수 있습니다. 리눅스에서는 사용자 스레드가 FS_BASE와 GS_BASE를 읽기 위해 호출 할 수있는 시스템 호출이 있습니다. 라이브러리 래퍼가 없으므로 직접 호출하는 코드를 작성해야합니다.

여기 C++에서이를 수행하는 한 방법입니다, 당신은 당신의 프로그램이 전역 함수의 정의를 추가 :

이제
#include <cstdint> 
#include <asm/prctl.h> 
#include <sys/syscall.h> 
namespace x86 { 
    uint64_t fs_base() { 
     uint64_t fs_base; 
     syscall(SYS_arch_prctl,ARCH_GET_FS,&fs_base); 
     return fs_base; 
    } 
    uint64_t gs_base() { 
     uint64_t gs_base; 
     syscall(SYS_arch_prctl,ARCH_GET_GS,&gs_base); 
     return gs_base; 
    } 
} 

당신은 GDB에서이 함수를 호출하고 다음과 같이 육각 자신의 반환 값을 인쇄 할 수 있습니다

(gdb) p/x x86::fs_base() 
$1 = 0x7ffff5e01780 
(gdb) p/x x86::gs_base() 
$2 = 0x0 
(gdb) 
관련 문제