GDB를 사용하여 프로그램을 디버깅하는 동안 IA32_FS_BASE 및 IA32_GS_BASE와 같은 x86-64 모델 관련 레지스터를 읽을 수있는 방법이 있습니까?GDB를 사용하여 MSR 읽기
인텔 Pintool과 같은 동적 인스 트루먼 테이션 패키지를 사용하는 솔루션은 그리 바람직하지 않지만 모두 만족 스럽습니다.
GDB를 사용하여 프로그램을 디버깅하는 동안 IA32_FS_BASE 및 IA32_GS_BASE와 같은 x86-64 모델 관련 레지스터를 읽을 수있는 방법이 있습니까?GDB를 사용하여 MSR 읽기
인텔 Pintool과 같은 동적 인스 트루먼 테이션 패키지를 사용하는 솔루션은 그리 바람직하지 않지만 모두 만족 스럽습니다.
당신은 당신의 코드를 변경하지 않으려면 (또는 코드를 사용할 수없는 경우)의 다음과 같은 방법으로 답을 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
명령어 인 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)