moved xsemaphore to xthread.d
add typed guest pointer template add X_KSPINLOCK, rework spinlock functions. rework irql related code, use irql on pcr instead of on XThread add guest linked list helper functions renamed ProcessInfoBlock to X_KPROCESS assigned names to many kernel structure fields
This commit is contained in:
committed by
Radosław Gliński
parent
32f7241526
commit
b5ddd30572
@@ -32,6 +32,24 @@ class XEvent;
|
||||
constexpr uint32_t X_CREATE_SUSPENDED = 0x00000001;
|
||||
|
||||
constexpr uint32_t X_TLS_OUT_OF_INDEXES = UINT32_MAX;
|
||||
struct XDPC {
|
||||
xe::be<uint16_t> type;
|
||||
uint8_t selected_cpu_number;
|
||||
uint8_t desired_cpu_number;
|
||||
X_LIST_ENTRY list_entry;
|
||||
xe::be<uint32_t> routine;
|
||||
xe::be<uint32_t> context;
|
||||
xe::be<uint32_t> arg1;
|
||||
xe::be<uint32_t> arg2;
|
||||
|
||||
void Initialize(uint32_t guest_func, uint32_t guest_context) {
|
||||
type = 19;
|
||||
selected_cpu_number = 0;
|
||||
desired_cpu_number = 0;
|
||||
routine = guest_func;
|
||||
context = guest_context;
|
||||
}
|
||||
};
|
||||
|
||||
struct XAPC {
|
||||
static const uint32_t kSize = 40;
|
||||
@@ -42,118 +60,198 @@ struct XAPC {
|
||||
// This is 4b shorter than NT - looks like the reserved dword at +4 is gone.
|
||||
// NOTE: stored in guest memory.
|
||||
uint16_t type; // +0
|
||||
uint8_t processor_mode; // +2
|
||||
uint8_t apc_mode; // +2
|
||||
uint8_t enqueued; // +3
|
||||
xe::be<uint32_t> thread_ptr; // +4
|
||||
xe::be<uint32_t> flink; // +8
|
||||
xe::be<uint32_t> blink; // +12
|
||||
X_LIST_ENTRY list_entry; // +8
|
||||
xe::be<uint32_t> kernel_routine; // +16
|
||||
xe::be<uint32_t> rundown_routine; // +20
|
||||
xe::be<uint32_t> normal_routine; // +24
|
||||
xe::be<uint32_t> normal_context; // +28
|
||||
xe::be<uint32_t> arg1; // +32
|
||||
xe::be<uint32_t> arg2; // +36
|
||||
|
||||
void Initialize() {
|
||||
type = 18; // ApcObject
|
||||
processor_mode = 0;
|
||||
enqueued = 0;
|
||||
thread_ptr = 0;
|
||||
flink = blink = 0;
|
||||
kernel_routine = 0;
|
||||
normal_routine = 0;
|
||||
normal_context = 0;
|
||||
arg1 = arg2 = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct X_KSEMAPHORE {
|
||||
X_DISPATCH_HEADER header;
|
||||
xe::be<uint32_t> limit;
|
||||
};
|
||||
static_assert_size(X_KSEMAPHORE, 0x14);
|
||||
|
||||
struct X_KTHREAD;
|
||||
struct X_KPROCESS;
|
||||
struct X_KPRCB {
|
||||
TypedGuestPointer<X_KTHREAD> current_thread; // 0x0
|
||||
TypedGuestPointer<X_KTHREAD> unk_4; // 0x4
|
||||
TypedGuestPointer<X_KTHREAD> idle_thread; // 0x8
|
||||
uint8_t current_cpu; // 0xC
|
||||
uint8_t unk_D[3]; // 0xD
|
||||
// should only have 1 bit set, used for ipis
|
||||
xe::be<uint32_t> processor_mask; // 0x10
|
||||
// incremented in clock interrupt
|
||||
xe::be<uint32_t> dpc_clock; // 0x14
|
||||
xe::be<uint32_t> interrupt_clock; // 0x18
|
||||
xe::be<uint32_t> unk_1C; // 0x1C
|
||||
xe::be<uint32_t> unk_20; // 0x20
|
||||
// various fields used by KeIpiGenericCall
|
||||
xe::be<uint32_t> ipi_args[3]; // 0x24
|
||||
// looks like the target cpus clear their corresponding bit
|
||||
// in this mask to signal completion to the initiator
|
||||
xe::be<uint32_t> targeted_ipi_cpus_mask; // 0x30
|
||||
xe::be<uint32_t> ipi_function; // 0x34
|
||||
// used to synchronize?
|
||||
TypedGuestPointer<X_KPRCB> ipi_initiator_prcb; // 0x38
|
||||
xe::be<uint32_t> unk_3C; // 0x3C
|
||||
xe::be<uint32_t> dpc_related_40; // 0x40
|
||||
// must be held to modify any dpc-related fields in the kprcb
|
||||
xe::be<uint32_t> dpc_lock; // 0x44
|
||||
X_LIST_ENTRY queued_dpcs_list_head; // 0x48
|
||||
xe::be<uint32_t> dpc_active; // 0x50
|
||||
xe::be<uint32_t> unk_54; // 0x54
|
||||
xe::be<uint32_t> unk_58; // 0x58
|
||||
// definitely scheduler related
|
||||
X_SINGLE_LIST_ENTRY unk_5C; // 0x5C
|
||||
xe::be<uint32_t> unk_60; // 0x60
|
||||
// i think the following mask has something to do with the array that comes
|
||||
// after
|
||||
xe::be<uint32_t> unk_mask_64; // 0x64
|
||||
|
||||
X_LIST_ENTRY unk_68[32]; // 0x68
|
||||
// ExTerminateThread tail calls a function that does KeInsertQueueDpc of this
|
||||
// dpc
|
||||
XDPC thread_exit_dpc; // 0x168
|
||||
// thread_exit_dpc's routine drains this list and frees each threads threadid,
|
||||
// kernel stack and dereferences the thread
|
||||
X_LIST_ENTRY terminating_threads_list; // 0x184
|
||||
XDPC unk_18C; // 0x18C
|
||||
};
|
||||
// Processor Control Region
|
||||
struct X_KPCR {
|
||||
xe::be<uint32_t> tls_ptr; // 0x0
|
||||
xe::be<uint32_t> msr_mask; // 0x4
|
||||
xe::be<uint16_t> interrupt_related; // 0x8
|
||||
uint8_t unk_08[0xE]; // 0xA
|
||||
uint8_t current_irql; // 0x18
|
||||
uint8_t unk_19[0x17]; // 0x19
|
||||
xe::be<uint32_t> pcr_ptr; // 0x30
|
||||
uint8_t unk_34[0x38]; // 0x34
|
||||
xe::be<uint32_t> use_alternative_stack; //0x6C
|
||||
xe::be<uint32_t> tls_ptr; // 0x0
|
||||
xe::be<uint32_t> msr_mask; // 0x4
|
||||
union {
|
||||
xe::be<uint16_t> software_interrupt_state; // 0x8
|
||||
struct {
|
||||
uint8_t unknown_8; // 0x8
|
||||
uint8_t apc_software_interrupt_state; // 0x9
|
||||
};
|
||||
};
|
||||
uint8_t unk_0A[2]; // 0xA
|
||||
uint8_t processtype_value_in_dpc; // 0xC
|
||||
uint8_t unk_0D[3]; // 0xD
|
||||
// used in KeSaveFloatingPointState / its vmx counterpart
|
||||
xe::be<uint32_t> thread_fpu_related; // 0x10
|
||||
xe::be<uint32_t> thread_vmx_related; // 0x14
|
||||
uint8_t current_irql; // 0x18
|
||||
uint8_t unk_19[0x17]; // 0x19
|
||||
xe::be<uint64_t> pcr_ptr; // 0x30
|
||||
|
||||
// this seems to be just garbage data? we can stash a pointer to context here
|
||||
// as a hack for now
|
||||
union {
|
||||
uint8_t unk_38[8]; // 0x38
|
||||
uint64_t host_stash; // 0x38
|
||||
};
|
||||
uint8_t unk_40[28]; // 0x40
|
||||
xe::be<uint32_t> unk_stack_5c; // 0x5C
|
||||
uint8_t unk_60[12]; // 0x60
|
||||
xe::be<uint32_t> use_alternative_stack; // 0x6C
|
||||
xe::be<uint32_t> stack_base_ptr; // 0x70 Stack base address (high addr)
|
||||
xe::be<uint32_t> stack_end_ptr; // 0x74 Stack end (low addr)
|
||||
|
||||
//maybe these are the stacks used in apcs?
|
||||
//i know they're stacks, RtlGetStackLimits returns them if another var here is set
|
||||
// maybe these are the stacks used in apcs?
|
||||
// i know they're stacks, RtlGetStackLimits returns them if another var here
|
||||
// is set
|
||||
|
||||
xe::be<uint32_t> alt_stack_base_ptr; // 0x78
|
||||
xe::be<uint32_t> alt_stack_end_ptr; // 0x7C
|
||||
uint8_t unk_80[0x80]; // 0x80
|
||||
xe::be<uint32_t> current_thread; // 0x100
|
||||
uint8_t unk_104[0x8]; // 0x104
|
||||
uint8_t current_cpu; // 0x10C
|
||||
uint8_t unk_10D[0x43]; // 0x10D
|
||||
xe::be<uint32_t> dpc_active; // 0x150
|
||||
// if bit 1 is set in a handler pointer, it actually points to a KINTERRUPT
|
||||
// otherwise, it points to a function to execute
|
||||
xe::be<uint32_t> interrupt_handlers[32]; // 0x80
|
||||
X_KPRCB prcb_data; // 0x100
|
||||
// pointer to KPCRB?
|
||||
TypedGuestPointer<X_KPRCB> prcb; // 0x2A8
|
||||
uint8_t unk_2AC[0x2C]; // 0x2AC
|
||||
};
|
||||
|
||||
struct X_KTHREAD {
|
||||
X_DISPATCH_HEADER header; // 0x0
|
||||
xe::be<uint32_t> unk_10; // 0x10
|
||||
xe::be<uint32_t> unk_14; // 0x14
|
||||
uint8_t unk_18[0x28]; // 0x10
|
||||
xe::be<uint32_t> unk_40; // 0x40
|
||||
xe::be<uint32_t> unk_44; // 0x44
|
||||
xe::be<uint32_t> unk_48; // 0x48
|
||||
xe::be<uint32_t> unk_4C; // 0x4C
|
||||
uint8_t unk_50[0x4]; // 0x50
|
||||
xe::be<uint16_t> unk_54; // 0x54
|
||||
xe::be<uint16_t> unk_56; // 0x56
|
||||
uint8_t unk_58[0x4]; // 0x58
|
||||
xe::be<uint32_t> stack_base; // 0x5C
|
||||
xe::be<uint32_t> stack_limit; // 0x60
|
||||
xe::be<uint32_t> stack_kernel; // 0x64
|
||||
xe::be<uint32_t> tls_address; // 0x68
|
||||
uint8_t unk_6C; // 0x6C
|
||||
//0x70 = priority?
|
||||
uint8_t unk_6D[0x3]; // 0x6D
|
||||
uint8_t priority; // 0x70
|
||||
uint8_t fpu_exceptions_on; // 0x71
|
||||
uint8_t unk_72;
|
||||
uint8_t unk_73;
|
||||
xe::be<uint32_t> unk_74; // 0x74
|
||||
xe::be<uint32_t> unk_78; // 0x78
|
||||
xe::be<uint32_t> unk_7C; // 0x7C
|
||||
xe::be<uint32_t> unk_80; // 0x80
|
||||
xe::be<uint32_t> unk_84; // 0x84
|
||||
uint8_t unk_88[0x3]; // 0x88
|
||||
uint8_t unk_8B; // 0x8B
|
||||
uint8_t unk_8C[0x10]; // 0x8C
|
||||
xe::be<uint32_t> unk_9C; // 0x9C
|
||||
uint8_t unk_A0[0x10]; // 0xA0
|
||||
int32_t apc_disable_count; // 0xB0
|
||||
uint8_t unk_B4[0x8]; // 0xB4
|
||||
uint8_t suspend_count; // 0xBC
|
||||
uint8_t unk_BD; // 0xBD
|
||||
X_DISPATCH_HEADER header; // 0x0
|
||||
xe::be<uint32_t> unk_10; // 0x10
|
||||
xe::be<uint32_t> unk_14; // 0x14
|
||||
uint8_t unk_18[0x28]; // 0x10
|
||||
xe::be<uint32_t> unk_40; // 0x40
|
||||
xe::be<uint32_t> unk_44; // 0x44
|
||||
xe::be<uint32_t> unk_48; // 0x48
|
||||
xe::be<uint32_t> unk_4C; // 0x4C
|
||||
uint8_t unk_50[0x4]; // 0x50
|
||||
xe::be<uint16_t> unk_54; // 0x54
|
||||
xe::be<uint16_t> unk_56; // 0x56
|
||||
uint8_t unk_58[0x4]; // 0x58
|
||||
xe::be<uint32_t> stack_base; // 0x5C
|
||||
xe::be<uint32_t> stack_limit; // 0x60
|
||||
xe::be<uint32_t> stack_kernel; // 0x64
|
||||
xe::be<uint32_t> tls_address; // 0x68
|
||||
// state = is thread running, suspended, etc
|
||||
uint8_t thread_state; // 0x6C
|
||||
// 0x70 = priority?
|
||||
uint8_t unk_6D[0x3]; // 0x6D
|
||||
uint8_t priority; // 0x70
|
||||
uint8_t fpu_exceptions_on; // 0x71
|
||||
// these two process types both get set to the same thing, process_type is
|
||||
// referenced most frequently, however process_type_dup gets referenced a few
|
||||
// times while the process is being created
|
||||
uint8_t process_type_dup;
|
||||
uint8_t process_type;
|
||||
//apc_mode determines which list an apc goes into
|
||||
util::X_TYPED_LIST<XAPC, offsetof(XAPC, list_entry)> apc_lists[2];
|
||||
TypedGuestPointer<X_KPROCESS> process; // 0x84
|
||||
uint8_t unk_88[0x3]; // 0x88
|
||||
uint8_t apc_related; // 0x8B
|
||||
uint8_t unk_8C[0x10]; // 0x8C
|
||||
xe::be<uint32_t> msr_mask; // 0x9C
|
||||
uint8_t unk_A0[4]; // 0xA0
|
||||
uint8_t unk_A4; // 0xA4
|
||||
uint8_t unk_A5[0xB]; // 0xA5
|
||||
int32_t apc_disable_count; // 0xB0
|
||||
uint8_t unk_B4[0x8]; // 0xB4
|
||||
uint8_t suspend_count; // 0xBC
|
||||
uint8_t unk_BD; // 0xBD
|
||||
uint8_t terminated; // 0xBE
|
||||
uint8_t current_cpu; // 0xBF
|
||||
uint8_t unk_C0[0x10]; // 0xC0
|
||||
xe::be<uint32_t> stack_alloc_base; // 0xD0
|
||||
uint8_t unk_D4[0x5C]; // 0xD4
|
||||
xe::be<uint64_t> create_time; // 0x130
|
||||
xe::be<uint64_t> exit_time; // 0x138
|
||||
xe::be<uint32_t> exit_status; // 0x140
|
||||
xe::be<uint32_t> unk_144; // 0x144
|
||||
xe::be<uint32_t> unk_148; // 0x148
|
||||
xe::be<uint32_t> thread_id; // 0x14C
|
||||
xe::be<uint32_t> start_address; // 0x150
|
||||
xe::be<uint32_t> unk_154; // 0x154
|
||||
xe::be<uint32_t> unk_158; // 0x158
|
||||
uint8_t unk_15C[0x4]; // 0x15C
|
||||
xe::be<uint32_t> last_error; // 0x160
|
||||
xe::be<uint32_t> fiber_ptr; // 0x164
|
||||
uint8_t unk_168[0x4]; // 0x168
|
||||
xe::be<uint32_t> creation_flags; // 0x16C
|
||||
uint8_t unk_170[0xC]; // 0x170
|
||||
xe::be<uint32_t> unk_17C; // 0x17C
|
||||
uint8_t unk_180[0x930]; // 0x180
|
||||
uint8_t current_cpu; // 0xBF
|
||||
// these two pointers point to KPRCBs, but seem to be rarely referenced, if at
|
||||
// all
|
||||
TypedGuestPointer<X_KPRCB> a_prcb_ptr; // 0xC0
|
||||
TypedGuestPointer<X_KPRCB> another_prcb_ptr; // 0xC4
|
||||
uint8_t unk_C8[8]; // 0xC8
|
||||
xe::be<uint32_t> stack_alloc_base; // 0xD0
|
||||
// uint8_t unk_D4[0x5C]; // 0xD4
|
||||
XAPC on_suspend; // 0xD4
|
||||
X_KSEMAPHORE unk_FC; // 0xFC
|
||||
// this is an entry in
|
||||
X_LIST_ENTRY process_threads; // 0x110
|
||||
xe::be<uint32_t> unk_118; // 0x118
|
||||
xe::be<uint32_t> unk_11C; // 0x11C
|
||||
xe::be<uint32_t> unk_120; // 0x120
|
||||
xe::be<uint32_t> unk_124; // 0x124
|
||||
xe::be<uint32_t> unk_128; // 0x128
|
||||
xe::be<uint32_t> unk_12C; // 0x12C
|
||||
xe::be<uint64_t> create_time; // 0x130
|
||||
xe::be<uint64_t> exit_time; // 0x138
|
||||
xe::be<uint32_t> exit_status; // 0x140
|
||||
xe::be<uint32_t> unk_144; // 0x144
|
||||
xe::be<uint32_t> unk_148; // 0x148
|
||||
xe::be<uint32_t> thread_id; // 0x14C
|
||||
xe::be<uint32_t> start_address; // 0x150
|
||||
xe::be<uint32_t> unk_154; // 0x154
|
||||
xe::be<uint32_t> unk_158; // 0x158
|
||||
uint8_t unk_15C[0x4]; // 0x15C
|
||||
xe::be<uint32_t> last_error; // 0x160
|
||||
xe::be<uint32_t> fiber_ptr; // 0x164
|
||||
uint8_t unk_168[0x4]; // 0x168
|
||||
xe::be<uint32_t> creation_flags; // 0x16C
|
||||
uint8_t unk_170[0xC]; // 0x170
|
||||
xe::be<uint32_t> unk_17C; // 0x17C
|
||||
uint8_t unk_180[0x930]; // 0x180
|
||||
|
||||
// This struct is actually quite long... so uh, not filling this out!
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user