mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 07:32:23 -07:00
demon/linux: x64 register reading
This commit is contained in:
@@ -532,6 +532,174 @@ dmn_lnx_thread_from_pid(pid_t pid)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
dmn_lnx_thread_read_reg_block(DMN_LNX_Entity *thread, void *reg_block)
|
||||
{
|
||||
B32 result = 0;
|
||||
{
|
||||
REGS_RegBlockX64 *dst = (REGS_RegBlockX64 *)reg_block;
|
||||
pid_t tid = (pid_t)thread->id;
|
||||
|
||||
//- rjf: read GPR
|
||||
B32 got_gpr = 0;
|
||||
{
|
||||
DMN_LNX_UserX64 ctx = {0};
|
||||
struct iovec iov_gpr = {0};
|
||||
iov_gpr.iov_len = sizeof(ctx);
|
||||
iov_gpr.iov_base = &ctx;
|
||||
if(ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, &iov_gpr) != -1)
|
||||
{
|
||||
got_gpr = 1;
|
||||
DMN_LNX_UserRegsX64 *src = &ctx.regs;
|
||||
dst->rax.u64 = src->rax;
|
||||
dst->rcx.u64 = src->rcx;
|
||||
dst->rdx.u64 = src->rdx;
|
||||
dst->rbx.u64 = src->rbx;
|
||||
dst->rsp.u64 = src->rsp;
|
||||
dst->rbp.u64 = src->rbp;
|
||||
dst->rsi.u64 = src->rsi;
|
||||
dst->rdi.u64 = src->rdi;
|
||||
dst->r8.u64 = src->r8;
|
||||
dst->r9.u64 = src->r9;
|
||||
dst->r10.u64 = src->r10;
|
||||
dst->r11.u64 = src->r11;
|
||||
dst->r12.u64 = src->r12;
|
||||
dst->r13.u64 = src->r13;
|
||||
dst->r14.u64 = src->r14;
|
||||
dst->r15.u64 = src->r15;
|
||||
dst->cs.u16 = src->cs;
|
||||
dst->ds.u16 = src->ds;
|
||||
dst->es.u16 = src->es;
|
||||
dst->fs.u16 = src->fs;
|
||||
dst->gs.u16 = src->gs;
|
||||
dst->ss.u16 = src->ss;
|
||||
dst->fsbase.u64 = src->fsbase;
|
||||
dst->gsbase.u64 = src->gsbase;
|
||||
dst->rip.u64 = src->rip;
|
||||
dst->rflags.u64 = src->rflags;
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: read FPR
|
||||
B32 got_fpr = 0;
|
||||
if(got_gpr)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
DMN_LNX_XSave *xsave = 0;
|
||||
DMN_LNX_XSaveLegacy *xsave_legacy = 0;
|
||||
|
||||
// rjf: try xsave
|
||||
if(!xsave_legacy)
|
||||
{
|
||||
U8 xsave_buffer[KB(4)];
|
||||
struct iovec iov_xsave = {0};
|
||||
iov_xsave.iov_len = sizeof(xsave_buffer);
|
||||
iov_xsave.iov_base = xsave_buffer;
|
||||
if(ptrace(PTRACE_GETREGSET, tid, (void*)NT_X86_XSTATE, &iov_xsave) != -1)
|
||||
{
|
||||
xsave = push_array_no_zero(scratch.arena, DMN_LNX_XSave, 1);
|
||||
MemoryCopy(xsave, xsave_buffer, sizeof(*xsave));
|
||||
xsave_legacy = &xsave->legacy;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: try fxsave
|
||||
if(!xsave_legacy)
|
||||
{
|
||||
DMN_LNX_XSaveLegacy fxsave = {0};
|
||||
struct iovec iov_fxsave = {0};
|
||||
iov_fxsave.iov_len = sizeof(fxsave);
|
||||
iov_fxsave.iov_base = &fxsave;
|
||||
if(ptrace(PTRACE_GETREGSET, tid, (void *)NT_FPREGSET, &iov_fxsave) != -1)
|
||||
{
|
||||
xsave_legacy = push_array_no_zero(scratch.arena, DMN_LNX_XSaveLegacy, 1);
|
||||
MemoryCopy(xsave_legacy, &fxsave, sizeof(*xsave_legacy));
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: fill from xsave legacy
|
||||
if(xsave_legacy)
|
||||
{
|
||||
DMN_LNX_XSaveLegacy *src = xsave_legacy;
|
||||
dst->fcw.u16 = src->fcw;
|
||||
dst->fsw.u16 = src->fsw;
|
||||
dst->ftw.u16 = src->ftw; // TODO(rjf): old: fix tag word (?)
|
||||
dst->fop.u16 = src->fop;
|
||||
dst->fip.u64 = src->b64.fip;
|
||||
// TODO(rjf): these 16-bit registers do not belong in x64
|
||||
dst->fcs.u16 = 0;
|
||||
dst->fdp.u64 = src->b64.fdp;
|
||||
dst->fds.u16 = 0;
|
||||
dst->mxcsr.u32 = src->mxcsr;
|
||||
dst->mxcsr_mask.u32 = src->mxcsr_mask;
|
||||
{
|
||||
U8 *float_s = src->st_space.u8;
|
||||
REGS_Reg80 *float_d = &dst->st0;
|
||||
for(U32 n = 0; n < 8; n += 1, float_s += 16, float_d += 1)
|
||||
{
|
||||
MemoryCopy(float_d, float_s, sizeof(*float_d));
|
||||
}
|
||||
}
|
||||
{
|
||||
U8 *xmm_s = src->xmm_space.u8;
|
||||
REGS_Reg512 *xmm_d = &dst->zmm0;
|
||||
for(U32 n = 0; n < 16; n += 1, xmm_s += 16, xmm_d += 1)
|
||||
{
|
||||
MemoryCopy(xmm_d, xmm_s, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: fill from ymm registers
|
||||
// TODO(rjf): this is a lie; ymm can technically move around. study & fix.
|
||||
if(xsave)
|
||||
{
|
||||
B32 has_ymm_registers = ((xsave->header.xstate_bv & 4) != 0);
|
||||
if(has_ymm_registers)
|
||||
{
|
||||
U8 *ymm_s = (U8 *)xsave->ymmh;
|
||||
REGS_Reg512 *ymm_d = &dst->zmm0;
|
||||
for(U32 n = 0; n < 16; n += 1, ymm_s += 16, ymm_d += 1)
|
||||
{
|
||||
MemoryCopy(((U8*)ymm_d) + 16, ymm_s, 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
got_fpr = (xsave || xsave_legacy);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
//- rjf: read debug registers
|
||||
B32 got_debug = 0;
|
||||
if(got_fpr)
|
||||
{
|
||||
got_debug = 1;
|
||||
REGS_Reg64 *dr_d = &dst->dr0;
|
||||
for(U32 i = 0; i < 8; i += 1, dr_d += 1)
|
||||
{
|
||||
if(i != 4 && i != 5)
|
||||
{
|
||||
U64 offset = OffsetOf(DMN_LNX_UserX64, u_debugreg[i]);
|
||||
errno = 0;
|
||||
int peek_result = ptrace(PTRACE_PEEKUSER, tid, PtrFromInt(offset), 0);
|
||||
if(errno == 0)
|
||||
{
|
||||
dr_d->u64 = (U64)peek_result;
|
||||
}
|
||||
else
|
||||
{
|
||||
got_debug = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = got_debug;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS)
|
||||
|
||||
@@ -828,6 +996,11 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: unpack controls
|
||||
//
|
||||
DMN_LNX_Entity *single_step_thread = dmn_lnx_entity_from_handle(ctrls->single_step_thread);
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: push any deferred events
|
||||
//
|
||||
@@ -853,12 +1026,17 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
e->error_kind = DMN_ErrorKind_NotAttached;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: determine if we need to wait for new events
|
||||
//
|
||||
B32 need_wait_on_events = (evts.count == 0);
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: gather all threads which we should run
|
||||
//
|
||||
DMN_LNX_EntityNode *first_run_thread = 0;
|
||||
DMN_LNX_EntityNode *last_run_thread = 0;
|
||||
ProfScope("gather all threads which we should run")
|
||||
if(need_wait_on_events) ProfScope("gather all threads which we should run")
|
||||
{
|
||||
//- rjf: scan all processes
|
||||
for(DMN_LNX_Entity *process = dmn_lnx_state->entities_base->first;
|
||||
@@ -956,7 +1134,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
//- rjf: loop: wait for next stop, produce debug events
|
||||
//
|
||||
pid_t final_wait_pid = 0;
|
||||
for(B32 done = 0; !done;)
|
||||
if(need_wait_on_events) for(B32 done = 0; !done;)
|
||||
{
|
||||
//- rjf: wait for next event
|
||||
int status = 0;
|
||||
@@ -974,6 +1152,17 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
DMN_LNX_Entity *process = thread->parent;
|
||||
B32 thread_is_process_root = (thread->id == process->id);
|
||||
|
||||
//- rjf: unpack thread's registers
|
||||
U64 rip = 0;
|
||||
void *regs_block = 0;
|
||||
if(thread != &dmn_lnx_nil_entity)
|
||||
{
|
||||
U64 regs_block_size = regs_block_size_from_arch(thread->arch);
|
||||
regs_block = push_array(scratch.arena, U8, regs_block_size);
|
||||
dmn_lnx_thread_read_reg_block(thread, regs_block);
|
||||
rip = regs_rip_from_arch_block(thread->arch, regs_block);
|
||||
}
|
||||
|
||||
//- rjf: WIFEXITED(status) -> thread exit
|
||||
B32 thread_exit = 0;
|
||||
U64 exit_code = 0;
|
||||
@@ -1003,11 +1192,40 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
||||
}
|
||||
|
||||
//- rjf: SIGTRAP:PTRACE_EVENT_FORK, or SIGTRAP:PTRACE_EVENT_VFORK
|
||||
if(wifstopped && wstopsig == SIGTRAP &&
|
||||
B32 sigtrap_handled = 0;
|
||||
if(!sigtrap_handled && wifstopped && wstopsig == SIGTRAP &&
|
||||
(ptrace_event_code == PTRACE_EVENT_FORK ||
|
||||
ptrace_event_code == PTRACE_EVENT_VFORK))
|
||||
{
|
||||
// TODO(rjf)
|
||||
sigtrap_handled = 1;
|
||||
}
|
||||
|
||||
//- rjf: SIGTRAP
|
||||
if(!sigtrap_handled && wifstopped && wstopsig == SIGTRAP)
|
||||
{
|
||||
// rjf: this is the single step thread => this is a single step completion
|
||||
DMN_EventKind e_kind = DMN_EventKind_Trap;
|
||||
if(thread == single_step_thread)
|
||||
{
|
||||
e_kind = DMN_EventKind_SingleStep;
|
||||
}
|
||||
|
||||
// rjf: this matches a specified trap => breakpoint
|
||||
{
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
// rjf: after breakpoint -> rollback
|
||||
if(e_kind == DMN_EventKind_Breakpoint)
|
||||
{
|
||||
// TODO(rjf)
|
||||
}
|
||||
|
||||
// rjf: push event
|
||||
DMN_Event *e = dmn_event_list_push(arena, &evts);
|
||||
e->kind = e_kind;
|
||||
e->process = dmn_lnx_handle_from_entity(process);
|
||||
e->thread = dmn_lnx_handle_from_entity(thread);
|
||||
}
|
||||
|
||||
//- rjf: WSTOPSIG(status) is SIGSTOP
|
||||
@@ -1243,7 +1461,13 @@ dmn_tls_root_vaddr_from_thread(DMN_Handle handle)
|
||||
internal B32
|
||||
dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block)
|
||||
{
|
||||
return 0;
|
||||
B32 result = 0;
|
||||
DMN_AccessScope
|
||||
{
|
||||
DMN_LNX_Entity *thread = dmn_lnx_entity_from_handle(handle);
|
||||
result = dmn_lnx_thread_read_reg_block(thread, reg_block);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
|
||||
@@ -4,20 +4,195 @@
|
||||
#ifndef DEMON_CORE_LINUX_H
|
||||
#define DEMON_CORE_LINUX_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
#include <elf.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: ptrace options
|
||||
|
||||
#define DMN_LNX_PTRACE_OPTIONS (PTRACE_O_TRACEEXIT|\
|
||||
PTRACE_O_EXITKILL|\
|
||||
PTRACE_O_TRACEFORK|\
|
||||
PTRACE_O_TRACEVFORK|\
|
||||
PTRACE_O_TRACECLONE)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Register Layouts
|
||||
//
|
||||
// These are defined in <sys/user.h>, but only for one architecture at a time
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct DMN_LNX_UserRegsX64 DMN_LNX_UserRegsX64;
|
||||
struct DMN_LNX_UserRegsX64
|
||||
{
|
||||
U64 r15;
|
||||
U64 r14;
|
||||
U64 r13;
|
||||
U64 r12;
|
||||
U64 rbp;
|
||||
U64 rbx;
|
||||
U64 r11;
|
||||
U64 r10;
|
||||
U64 r9;
|
||||
U64 r8;
|
||||
U64 rax;
|
||||
U64 rcx;
|
||||
U64 rdx;
|
||||
U64 rsi;
|
||||
U64 rdi;
|
||||
U64 orig_rax;
|
||||
U64 rip;
|
||||
U64 cs;
|
||||
U64 rflags;
|
||||
U64 rsp;
|
||||
U64 ss;
|
||||
U64 fsbase;
|
||||
U64 gsbase;
|
||||
U64 ds;
|
||||
U64 es;
|
||||
U64 fs;
|
||||
U64 gs;
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_XSaveLegacy DMN_LNX_XSaveLegacy;
|
||||
struct DMN_LNX_XSaveLegacy
|
||||
{
|
||||
U16 fcw;
|
||||
U16 fsw;
|
||||
U16 ftw;
|
||||
U16 fop;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
U64 fip;
|
||||
U64 fdp;
|
||||
} b64;
|
||||
struct
|
||||
{
|
||||
U32 fip;
|
||||
U16 fcs, _pad0;
|
||||
U32 fdp;
|
||||
U16 fds, _pad1;
|
||||
} b32;
|
||||
};
|
||||
U32 mxcsr;
|
||||
U32 mxcsr_mask;
|
||||
U128 st_space;
|
||||
U256 xmm_space;
|
||||
U8 padding[96];
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_XSaveHeader DMN_LNX_XSaveHeader;
|
||||
struct DMN_LNX_XSaveHeader
|
||||
{
|
||||
U64 xstate_bv;
|
||||
U64 xcomp_bv;
|
||||
U8 reserved[48];
|
||||
};
|
||||
|
||||
// TODO(rjf):
|
||||
//
|
||||
// this one is hacked; ymmh is not gauranteed to be at a fixed location
|
||||
// and there can be more after that. Requires CPUID to be totally compliant to the standard.
|
||||
// See intel's manual on the xsave format for more info.
|
||||
//
|
||||
typedef struct DMN_LNX_XSave DMN_LNX_XSave;
|
||||
struct DMN_LNX_XSave
|
||||
{
|
||||
DMN_LNX_XSaveLegacy legacy;
|
||||
DMN_LNX_XSaveHeader header;
|
||||
U8 ymmh[256];
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_UserX64 DMN_LNX_UserX64;
|
||||
struct DMN_LNX_UserX64
|
||||
{
|
||||
DMN_LNX_UserRegsX64 regs;
|
||||
S32 u_fpvalid, _pad0;
|
||||
DMN_LNX_XSaveLegacy i387;
|
||||
U64 u_tsize, u_dsize, u_ssize, start_code, start_stack;
|
||||
U64 signal;
|
||||
S32 reserved, _pad1;
|
||||
U64 u_ar0, u_fpstate;
|
||||
U64 magic;
|
||||
U8 u_comm[32];
|
||||
U64 u_debugreg[8];
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_UserRegsX86 DMN_LNX_UserRegsX86;
|
||||
struct DMN_LNX_UserRegsX86
|
||||
{
|
||||
U32 ebx;
|
||||
U32 ecx;
|
||||
U32 edx;
|
||||
U32 esi;
|
||||
U32 edi;
|
||||
U32 ebp;
|
||||
U32 eax;
|
||||
U32 ds;
|
||||
U32 es;
|
||||
U32 fs;
|
||||
U32 gs;
|
||||
U32 orig_eax;
|
||||
U32 eip;
|
||||
U32 cs;
|
||||
U32 eflags;
|
||||
U32 sp;
|
||||
U32 ss;
|
||||
};
|
||||
|
||||
// NOTE(rjf): (32-Bit Protected Mode Format)
|
||||
typedef struct DMN_LNX_FSave DMN_LNX_FSave;
|
||||
struct DMN_LNX_FSave
|
||||
{
|
||||
// control registers
|
||||
U16 fcw;
|
||||
U16 _pad0;
|
||||
U16 fsw;
|
||||
U16 _pad1;
|
||||
U16 ftw;
|
||||
U16 _pad2;
|
||||
U32 fip;
|
||||
U16 fips;
|
||||
U16 fop;
|
||||
U32 fdp;
|
||||
U16 fds;
|
||||
U16 _pad3;
|
||||
|
||||
// data registers
|
||||
U8 st[80];
|
||||
};
|
||||
|
||||
typedef struct DMN_LNX_UserX86 DMN_LNX_UserX86;
|
||||
struct DMN_LNX_UserX86
|
||||
{
|
||||
DMN_LNX_UserRegsX86 regs;
|
||||
S32 u_fpvalid;
|
||||
DMN_LNX_FSave i387;
|
||||
U32 u_tsize, u_dsize, u_ssize, start_code, start_stack;
|
||||
S32 signal, reserved;
|
||||
U32 u_ar0, u_fpstate;
|
||||
U32 magic;
|
||||
U8 u_comm[32];
|
||||
U32 u_debugreg[8];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Process Info Extraction Types
|
||||
|
||||
typedef struct DMN_LNX_ProcessAux DMN_LNX_ProcessAux;
|
||||
struct DMN_LNX_ProcessAux
|
||||
{
|
||||
@@ -57,6 +232,9 @@ struct DMN_LNX_ModuleInfoList
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entity Types
|
||||
|
||||
typedef enum DMN_LNX_EntityKind
|
||||
{
|
||||
DMN_LNX_EntityKind_Null,
|
||||
@@ -91,6 +269,9 @@ struct DMN_LNX_EntityNode
|
||||
DMN_LNX_Entity *v;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Main State Bundle
|
||||
|
||||
typedef struct DMN_LNX_State DMN_LNX_State;
|
||||
struct DMN_LNX_State
|
||||
{
|
||||
@@ -149,5 +330,6 @@ internal void dmn_lnx_entity_release(DMN_LNX_Entity *entity);
|
||||
internal DMN_Handle dmn_lnx_handle_from_entity(DMN_LNX_Entity *entity);
|
||||
internal DMN_LNX_Entity *dmn_lnx_entity_from_handle(DMN_Handle handle);
|
||||
internal DMN_LNX_Entity *dmn_lnx_thread_from_pid(pid_t pid);
|
||||
internal B32 dmn_lnx_thread_read_reg_block(DMN_LNX_Entity *thread, void *reg_block);
|
||||
|
||||
#endif // DEMON_CORE_LINUX_H
|
||||
|
||||
@@ -1012,8 +1012,8 @@ os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us)
|
||||
endt_timespec.tv_sec = endt_us/Million(1);
|
||||
endt_timespec.tv_nsec = Thousand(1) * (endt_us - (endt_us/Million(1))*Million(1));
|
||||
B32 result = 0;
|
||||
pthread_rwlock_unlock(&rw_mutex_entity->rwmutex_handle);
|
||||
pthread_mutex_lock(&cv_entity->cv.rwlock_mutex_handle);
|
||||
pthread_rwlock_unlock(&rw_mutex_entity->rwmutex_handle);
|
||||
for(;;)
|
||||
{
|
||||
int wait_result = pthread_cond_timedwait(&cv_entity->cv.cond_handle, &cv_entity->cv.rwlock_mutex_handle, &endt_timespec);
|
||||
@@ -1048,8 +1048,8 @@ os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us)
|
||||
endt_timespec.tv_sec = endt_us/Million(1);
|
||||
endt_timespec.tv_nsec = Thousand(1) * (endt_us - (endt_us/Million(1))*Million(1));
|
||||
B32 result = 0;
|
||||
pthread_rwlock_unlock(&rw_mutex_entity->rwmutex_handle);
|
||||
pthread_mutex_lock(&cv_entity->cv.rwlock_mutex_handle);
|
||||
pthread_rwlock_unlock(&rw_mutex_entity->rwmutex_handle);
|
||||
for(;;)
|
||||
{
|
||||
int wait_result = pthread_cond_timedwait(&cv_entity->cv.cond_handle, &cv_entity->cv.rwlock_mutex_handle, &endt_timespec);
|
||||
|
||||
@@ -566,8 +566,8 @@ REGS_Rng regs_g_reg_code_x64_rng_table[101] =
|
||||
{(U16)OffsetOf(REGS_RegBlockX64, fop), 2},
|
||||
{(U16)OffsetOf(REGS_RegBlockX64, fcs), 2},
|
||||
{(U16)OffsetOf(REGS_RegBlockX64, fds), 2},
|
||||
{(U16)OffsetOf(REGS_RegBlockX64, fip), 4},
|
||||
{(U16)OffsetOf(REGS_RegBlockX64, fdp), 4},
|
||||
{(U16)OffsetOf(REGS_RegBlockX64, fip), 8},
|
||||
{(U16)OffsetOf(REGS_RegBlockX64, fdp), 8},
|
||||
{(U16)OffsetOf(REGS_RegBlockX64, mxcsr), 4},
|
||||
{(U16)OffsetOf(REGS_RegBlockX64, mxcsr_mask), 4},
|
||||
{(U16)OffsetOf(REGS_RegBlockX64, ss), 2},
|
||||
|
||||
@@ -373,8 +373,8 @@ REGS_Reg16 ftw;
|
||||
REGS_Reg16 fop;
|
||||
REGS_Reg16 fcs;
|
||||
REGS_Reg16 fds;
|
||||
REGS_Reg32 fip;
|
||||
REGS_Reg32 fdp;
|
||||
REGS_Reg64 fip;
|
||||
REGS_Reg64 fdp;
|
||||
REGS_Reg32 mxcsr;
|
||||
REGS_Reg32 mxcsr_mask;
|
||||
REGS_Reg16 ss;
|
||||
|
||||
+2
-2
@@ -57,8 +57,8 @@ REGS_RegTableX64:
|
||||
{fop 16 Normal}
|
||||
{fcs 16 Normal}
|
||||
{fds 16 Normal}
|
||||
{fip 32 Normal}
|
||||
{fdp 32 Normal}
|
||||
{fip 64 Normal}
|
||||
{fdp 64 Normal}
|
||||
{mxcsr 32 Normal}
|
||||
{mxcsr_mask 32 Normal}
|
||||
{ss 16 Normal}
|
||||
|
||||
Reference in New Issue
Block a user