00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
#include "ntrtlp.h"
00026
#include "kxia64.h"
00027
00028
#if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
00029
#pragma alloc_text(PAGE,RtlInitializeContext)
00030
#pragma alloc_text(PAGE,RtlRemoteCall)
00031
#pragma alloc_text(PAGE,RtlSetIaToEmDebugReg)
00032
#pragma alloc_text(PAGE,RtlIaToEmDebugContext)
00033
#pragma alloc_text(PAGE,RtlEmToIaDebugContext)
00034
#endif
00035
00036
00037
VOID
00038 RtlInitializeContext(
00039 IN HANDLE Process,
00040 OUT PCONTEXT Context,
00041 IN PVOID Parameter OPTIONAL,
00042 IN PVOID InitialPc OPTIONAL,
00043 IN PVOID InitialSp OPTIONAL
00044 )
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 {
00072 ULONGLONG Argument;
00073
00074
RTL_PAGED_CODE();
00075
00076
00077
00078
00079
00080
if (((ULONG_PTR)InitialSp & 0xf) != 0) {
00081
RtlRaiseStatus(STATUS_BAD_INITIAL_STACK);
00082 }
00083
00084
00085
00086
00087
00088
00089
if (((ULONG_PTR)InitialPc & 0x7) != 0) {
00090
RtlRaiseStatus(STATUS_BAD_INITIAL_PC);
00091 }
00092
00093
00094
00095
00096
00097 RtlZeroMemory(Context,
sizeof(CONTEXT));
00098
00099
00100
00101
00102
00103 Context->ContextFlags =
CONTEXT_INTEGER |
CONTEXT_CONTROL;
00104
00105 Context->RsBSPSTORE = Context->IntSp = (ULONG_PTR)InitialSp;
00106 Context->IntSp -= STACK_SCRATCH_AREA;
00107
00108
00109
00110
00111
00112
00113
00114 Context->IntS0 = Context->StIIP = (ULONG_PTR)InitialPc;
00115 Context->IntGp = 0;
00116
00117
00118
00119
00120
00121
00122 Context->StFPSR = USER_FPSR_INITIAL;
00123 Context->StIPSR = USER_PSR_INITIAL;
00124 Context->ApDCR = USER_DCR_INITIAL;
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 Argument = (ULONGLONG)Parameter;
00136 ZwWriteVirtualMemory(Process,
00137 (PVOID)((ULONG_PTR)Context->RsBSPSTORE),
00138 (PVOID)&Argument,
00139
sizeof(Argument),
00140
NULL);
00141
00142
00143
00144
00145 Context->StIFS = 0x8000000000000081ULL;
00146 Context->RsBSP = Context->RsBSPSTORE;
00147 Context->RsRSC = USER_RSC_INITIAL;
00148 Context->ApUNAT = 0xFFFFFFFFFFFFFFFF;
00149 }
00150
00151
00152
NTSTATUS
00153 RtlRemoteCall(
00154 HANDLE Process,
00155 HANDLE Thread,
00156 PVOID CallSite,
00157 ULONG ArgumentCount,
00158 PULONG_PTR Arguments,
00159 BOOLEAN PassContext,
00160 BOOLEAN AlreadySuspended
00161 )
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 {
00197
NTSTATUS Status;
00198 CONTEXT Context;
00199 ULONG_PTR ContextAddress;
00200 ULONG_PTR NewSp;
00201 ULONG_PTR NewBspStore;
00202 ULONGLONG ArgumentsCopy[10];
00203 PVOID ptr;
00204 ULONG
Count = 0;
00205 ULONG ShiftCount;
00206 BOOLEAN RnatSaved =
FALSE;
00207
00208
00209
RTL_PAGED_CODE();
00210
00211
if (ArgumentCount > 8)
00212
return STATUS_INVALID_PARAMETER;
00213
00214
00215
00216
00217
00218
if (AlreadySuspended ==
FALSE) {
00219
Status =
NtSuspendThread(Thread,
NULL);
00220
if (
NT_SUCCESS(
Status) ==
FALSE) {
00221
return(
Status);
00222 }
00223 }
00224
00225
00226
00227
00228
00229 Context.ContextFlags =
CONTEXT_FULL;
00230
Status =
NtGetContextThread(Thread, &Context);
00231
if (
NT_SUCCESS(
Status) ==
FALSE) {
00232
if (AlreadySuspended ==
FALSE) {
00233
NtResumeThread(Thread,
NULL);
00234 }
00235
return(
Status);
00236 }
00237
00238
if (AlreadySuspended) {
00239 Context.IntV0 = STATUS_ALERTED;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249 ContextAddress = (((ULONG_PTR)Context.IntSp + 0xf) & 0xf) -
sizeof(CONTEXT);
00250 NewSp = ContextAddress - STACK_SCRATCH_AREA;
00251
Status =
NtWriteVirtualMemory(Process, (PVOID)ContextAddress, &Context,
00252
sizeof(CONTEXT),
NULL);
00253
00254
if (
NT_SUCCESS(
Status) ==
FALSE) {
00255
if (AlreadySuspended ==
FALSE) {
00256
NtResumeThread(Thread,
NULL);
00257 }
00258
return(
Status);
00259 }
00260
00261 RtlZeroMemory((PVOID)ArgumentsCopy,
sizeof(ArgumentsCopy));
00262 NewBspStore = (ULONG_PTR) Context.RsBSPSTORE;
00263
00264
if (PassContext) {
00265
if ( (NewBspStore & 0x1F8) == 0x1F8 ) {
00266 ArgumentsCopy[
Count++] = Context.RsRNAT;
00267 NewBspStore +=
sizeof(ULONGLONG);
00268 RnatSaved =
TRUE;
00269 }
00270 ShiftCount = (ULONG) (NewBspStore & 0x1F8) >> 3;
00271 Context.RsRNAT &= ~(0x1 << ShiftCount);
00272 ArgumentsCopy[
Count++] = ContextAddress;
00273 NewBspStore +=
sizeof(ULONGLONG);
00274 }
00275
00276
for (; ArgumentCount != 0 ; ArgumentCount--) {
00277
if ( (RnatSaved ==
FALSE) && ((NewBspStore & 0x1F8) == 0x1F8) ) {
00278 ArgumentsCopy[
Count++] = Context.RsRNAT;
00279 NewBspStore +=
sizeof(ULONGLONG);
00280 RnatSaved =
TRUE;
00281 }
00282 ShiftCount = (ULONG)(NewBspStore & 0x1F8) >> 3;
00283 Context.RsRNAT &= ~(0x1 << ShiftCount);
00284 ArgumentsCopy[
Count++] = (ULONGLONG)(*Arguments++);
00285 NewBspStore +=
sizeof(ULONGLONG);
00286 }
00287
00288
if ( (RnatSaved ==
FALSE) && ((NewBspStore & 0x1F8) == 0x1F8) ) {
00289 ArgumentsCopy[
Count++] = Context.RsRNAT;
00290 NewBspStore +=
sizeof(ULONGLONG);
00291 }
00292
00293
00294
00295
00296
00297
if (
Count) {
00298
Status =
NtWriteVirtualMemory(Process,
00299 (PVOID)Context.RsBSPSTORE,
00300 ArgumentsCopy,
00301
Count *
sizeof(ULONGLONG),
00302
NULL
00303 );
00304
00305
if (
NT_SUCCESS(
Status) ==
FALSE) {
00306
if (AlreadySuspended ==
FALSE) {
00307
NtResumeThread(Thread,
NULL);
00308 }
00309
return(
Status);
00310 }
00311 }
00312
00313
00314
00315
00316
00317 Context.RsRSC = (RSC_MODE_LY<<RSC_MODE)
00318 | (RSC_BE_LITTLE<<RSC_BE)
00319 | (0x3<<RSC_PL);
00320
00321
00322
00323
00324
00325 Context.StIFS = (ULONGLONG)
Count;
00326 Context.RsBSP = Context.RsBSPSTORE;
00327
00328
00329
00330
00331
00332
00333 Context.IntSp = (ULONG_PTR)NewSp;
00334
00335
00336
00337
00338
00339 Context.StIIP = (ULONG_PTR)CallSite;
00340
00341
00342
00343
00344
00345 SANITIZE_FSR(Context.StFPSR,
UserMode);
00346
00347
Status =
NtSetContextThread(Thread, &Context);
00348
if (!AlreadySuspended) {
00349
NtResumeThread(Thread,
NULL);
00350 }
00351
00352
return(
Status );
00353 }
00354
00355
00356
static VOID
00357 RtlSetIaToEmDebugReg(
00358 IN ULONG Dr7_RW,
00359 IN ULONG Dr7_Len,
00360 IN ULONG Addr,
00361 IN OUT ULONGLONG *DbrAddr1,
00362 IN OUT ULONGLONG *DbrAddr2,
00363 IN OUT ULONGLONG *IbrAddr1,
00364 IN OUT ULONGLONG *IbrAddr2
00365 )
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 {
00397 ULONGLONG mask;
00398
00399
00400
if (Dr7_Len == 2)
00401 Dr7_Len = 0;
00402
00403 mask = (ULONGLONG) DBG_REG_MASK(Dr7_Len);
00404
00405
switch(Dr7_RW) {
00406
case DR7_RW_IX:
00407 *DbrAddr1 = 0;
00408 *IbrAddr1 = (ULONGLONG)Addr;
00409 *DbrAddr2 = 0;
00410 *IbrAddr2 = (IBR_EX | DBG_REG_PLM_USER | DBG_REG_MASK(0));
00411
break;
00412
case DR7_RW_DW:
00413 *DbrAddr1 = (ULONGLONG)Addr;
00414 *IbrAddr1 = 0;
00415 *DbrAddr2 = (DBR_WR | DBG_REG_PLM_USER | mask);
00416 *IbrAddr2 = 0;
00417
break;
00418
case DR7_RW_IORW:
00419 *DbrAddr1 = (ULONGLONG)Addr;
00420 *IbrAddr1 = 0;
00421 *DbrAddr2 = (DBR_RDWR | DBG_REG_PLM_USER | mask);
00422 *IbrAddr2 = 0;
00423
break;
00424
case DR7_RW_DWR:
00425 *DbrAddr1 = (ULONGLONG)Addr;
00426 *IbrAddr1 = 0;
00427 *DbrAddr2 = (DBR_RDWR | DBG_REG_PLM_USER | mask);
00428 *IbrAddr2 = 0;
00429
break;
00430
case DR7_RW_DISABLE:
00431
default:
00432 *DbrAddr1 = 0;
00433 *IbrAddr1 = 0;
00434 *DbrAddr2 = 0;
00435 *IbrAddr2 = 0;
00436 }
00437
00438
return;
00439 }
00440
00441
00442 BOOLEAN
00443 RtlIaToEmDebugContext(
00444 IN PCONTEXT86 ContextX86,
00445 IN OUT PCONTEXT ContextEM
00446 )
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 {
00474 ULONG Dr7 = ContextX86->Dr7;
00475
00476
RtlSetIaToEmDebugReg(DR7_DB0_RW(Dr7),
00477 DR7_DB0_LEN(Dr7),
00478 DR_ADDR_L0(ContextX86->Dr0),
00479 &ContextEM->DbD0,
00480 &ContextEM->DbD1,
00481 &ContextEM->DbI0,
00482 &ContextEM->DbI1);
00483
00484
RtlSetIaToEmDebugReg(DR7_DB1_RW(Dr7),
00485 DR7_DB1_LEN(Dr7),
00486 DR_ADDR_L1(ContextX86->Dr1),
00487 &ContextEM->DbD2,
00488 &ContextEM->DbD3,
00489 &ContextEM->DbI2,
00490 &ContextEM->DbI3);
00491
00492
RtlSetIaToEmDebugReg(DR7_DB2_RW(Dr7),
00493 DR7_DB2_LEN(Dr7),
00494 DR_ADDR_L2(ContextX86->Dr2),
00495 &ContextEM->DbD4,
00496 &ContextEM->DbD5,
00497 &ContextEM->DbI4,
00498 &ContextEM->DbI5);
00499
00500
RtlSetIaToEmDebugReg(DR7_DB3_RW(Dr7),
00501 DR7_DB3_LEN(Dr7),
00502 DR_ADDR_L3(ContextX86->Dr3),
00503 &ContextEM->DbD6,
00504 &ContextEM->DbD7,
00505 &ContextEM->DbI6,
00506 &ContextEM->DbI7);
00507
00508
00509
00510
00511
if (DR7_L0(Dr7) || DR7_L1(Dr7) || DR7_L2(Dr7) || DR7_L3(Dr7))
00512 {
00513 ContextEM->StIPSR &= ~(PSR_DEBUG_SET);
00514 ContextEM->StIPSR |= (1 << PSR_DB);
00515 }
else {
00516 ContextEM->StIPSR &= ~(PSR_DEBUG_SET);
00517
return(
FALSE);
00518 }
00519
00520
return(
TRUE);
00521 }
00522
00523
00524 BOOLEAN
00525 RtlEmToIaDebugContext(
00526 IN PCONTEXT ContextEM,
00527 IN OUT PCONTEXT86 ContextX86
00528 )
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 {
00559
00560
00561
00562
00563
00564 SET_DR7_L0(ContextX86->Dr7);
00565
00566 SET_DR7_DB0_RW(ContextX86->Dr7, DBG_EM_ENABLE_TO_IA_RW(ContextEM->DbD1, ContextEM->DbI1));
00567 SET_DR7_DB0_LEN(ContextX86->Dr7, DBG_EM_MASK_TO_IA_LEN(ContextEM->DbD1, ContextEM->DbI1));
00568 ContextX86->Dr0 = DBG_EM_ADDR_TO_IA_ADDR(ContextEM->DbD0, ContextEM->DbI0);
00569
00570
00571 SET_DR7_L1(ContextX86->Dr7);
00572 SET_DR7_DB1_RW(ContextX86->Dr7, DBG_EM_ENABLE_TO_IA_RW(ContextEM->DbD3, ContextEM->DbI3));
00573 SET_DR7_DB1_LEN(ContextX86->Dr7, DBG_EM_MASK_TO_IA_LEN(ContextEM->DbD3, ContextEM->DbI3));
00574 ContextX86->Dr1 = DBG_EM_ADDR_TO_IA_ADDR(ContextEM->DbD2, ContextEM->DbI2);
00575
00576
00577 SET_DR7_L2(ContextX86->Dr7);
00578 SET_DR7_DB2_RW(ContextX86->Dr7, DBG_EM_ENABLE_TO_IA_RW(ContextEM->DbD5, ContextEM->DbI5));
00579 SET_DR7_DB2_LEN(ContextX86->Dr7, DBG_EM_MASK_TO_IA_LEN(ContextEM->DbD5, ContextEM->DbI5));
00580 ContextX86->Dr2 = DBG_EM_ADDR_TO_IA_ADDR(ContextEM->DbD4, ContextEM->DbI4);
00581
00582
00583 SET_DR7_L3(ContextX86->Dr7);
00584 SET_DR7_DB3_RW(ContextX86->Dr7, DBG_EM_ENABLE_TO_IA_RW(ContextEM->DbD7, ContextEM->DbI7));
00585 SET_DR7_DB3_LEN(ContextX86->Dr7, DBG_EM_MASK_TO_IA_LEN(ContextEM->DbD7, ContextEM->DbI7));
00586 ContextX86->Dr3 = DBG_EM_ADDR_TO_IA_ADDR(ContextEM->DbD6, ContextEM->DbI6);
00587
00588
if (!(DR7_L0(ContextX86->Dr7) || DR7_L1(ContextX86->Dr7)
00589 || DR7_L2(ContextX86->Dr7) || DR7_L3(ContextX86->Dr7)))
00590
return(
FALSE);
00591
else
00592
return(
TRUE);
00593 }
00594
00595
00596
VOID
00597 RtlEmToX86Context(
00598 IN PCONTEXT ContextEm,
00599 IN OUT PCONTEXT86 ContextX86
00600 )
00601 {
00602 ContextX86->ContextFlags =
CONTEXT_FULL | CONTEXT_X86;
00603
00604
00605
00606
00607
00608
00609 RtlEmFpToIaFpContext(&ContextEm->FltT2, &ContextX86->FloatSave);
00610
RtlEmToIaDebugContext(ContextEm, ContextX86);
00611
00612 ContextX86->SegGs = (ULONG)ContextEm->IntT20;
00613 ContextX86->SegFs = (ULONG)ContextEm->IntT19;
00614 ContextX86->SegEs = (ULONG)ContextEm->IntT15;
00615 ContextX86->SegDs = (ULONG)ContextEm->IntT18;
00616 ContextX86->Edi = (ULONG)ContextEm->IntT6;
00617 ContextX86->Esi = (ULONG)ContextEm->IntT5;
00618 ContextX86->Ebx = (ULONG)ContextEm->IntT4;
00619 ContextX86->Edx = (ULONG)ContextEm->IntT3;
00620 ContextX86->Ecx = (ULONG)ContextEm->IntT2;
00621 ContextX86->Eax = (ULONG)ContextEm->IntV0;
00622 ContextX86->Ebp = (ULONG)ContextEm->IntTeb;
00623 ContextX86->Eip = (ULONG)ContextEm->StIIP;
00624 ContextX86->SegCs = (ULONG)ContextEm->SegCSD;
00625 ContextX86->EFlags = (ULONG)ContextEm->Eflag;
00626 ContextX86->Esp = (ULONG)ContextEm->IntSp;
00627 ContextX86->SegSs = (ULONG)ContextEm->SegSSD;
00628 }
00629
00630
00631
VOID
00632 RtlX86ToEmContext(
00633 IN PCONTEXT86 ContextX86,
00634 IN OUT PCONTEXT ContextEm
00635 )
00636 {
00637 FLOAT128 FpWorkArea;
00638
00639 ContextEm->ContextFlags =
CONTEXT_FULL | CONTEXT_IA64;
00640
00641 RtlIaFpToEmFpContext((PVOID)&ContextX86->FloatSave,
00642 &ContextEm->FltT2,
00643 &FpWorkArea);
00644
RtlIaToEmDebugContext(ContextX86, ContextEm);
00645
00646 ContextEm->IntT20 = ContextX86->SegGs;
00647 ContextEm->IntT19 = ContextX86->SegFs;
00648 ContextEm->IntT15 = ContextX86->SegEs;
00649 ContextEm->IntT18 = ContextX86->SegDs;
00650 ContextEm->IntT6 = ContextX86->Edi;
00651 ContextEm->IntT5 = ContextX86->Esi;
00652 ContextEm->IntT4 = ContextX86->Ebx;
00653 ContextEm->IntT3 = ContextX86->Edx;
00654 ContextEm->IntT2 = ContextX86->Ecx;
00655 ContextEm->IntV0 = ContextX86->Eax;
00656 ContextEm->IntTeb = ContextX86->Ebp;
00657 ContextEm->StIIP = ContextX86->Eip;
00658 ContextEm->SegCSD = ContextX86->SegCs;
00659 ContextEm->Eflag = ContextX86->EFlags;
00660 ContextEm->IntSp = ContextX86->Esp;
00661 ContextEm->SegSSD = ContextX86->SegSs;
00662 }