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 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
#include "ntrtlp.h"
00057 
int __cdecl 
sprintf(
char *, 
const char *, ...);
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 #define RAISE_EXCEPTION(Status, ExceptionRecordt) { \
00066 
    EXCEPTION_RECORD ExceptionRecordn; \
00067 
                                            \
00068 
    ExceptionRecordn.ExceptionCode = Status; \
00069 
    ExceptionRecordn.ExceptionFlags = EXCEPTION_NONCONTINUABLE; \
00070 
    ExceptionRecordn.ExceptionRecord = ExceptionRecordt; \
00071 
    ExceptionRecordn.NumberParameters = 0; \
00072 
    RtlRaiseException(&ExceptionRecordn); \
00073 
    }
00074 
00075 
00076 
00077 
00078 
00079 #define IS_HANDLER_DEFINED(FunctionEntry) \
00080 
    (RF_EXCEPTION_HANDLER(FunctionEntry) != 0)
00081 
00082 
#if DBG
00083 
00084 
00085 
00086 
00087 
00088 
#define PC_HISTORY_DEPTH 4
00089 
00090 
00091 
00092 
00093 
00094 
00095 ULONG RtlDebugFlags = 0;
00096 
00097 
void
00098 ShowRuntimeFunction(
00099     PRUNTIME_FUNCTION FunctionEntry,
00100     PSTR Label
00101     );
00102 
00103 
#endif
00104 
00105 #define Virtual VirtualFramePointer
00106 #define Real RealFramePointer
00107 
00108 
00109 
00110 
00111 
00112 
VOID
00113 
RtlpRaiseException (
00114     IN PEXCEPTION_RECORD ExceptionRecord
00115     );
00116 
00117 
VOID
00118 
RtlpRaiseStatus (
00119     IN NTSTATUS Status
00120     );
00121 
00122 ULONG_PTR
00123 
RtlpVirtualUnwind (
00124     IN ULONG_PTR ControlPc,
00125     IN PRUNTIME_FUNCTION FunctionEntry,
00126     IN PCONTEXT ContextRecord,
00127     OUT PBOOLEAN InFunction,
00128     OUT PFRAME_POINTERS EstablisherFrame
00129     );
00130 
00131 
#if !defined(NTOS_KERNEL_RUNTIME)
00132 
00133 
00134 
00135 
00136 
00137 LIST_ENTRY 
DynamicFunctionTable;
00138 
00139 PRUNTIME_FUNCTION
00140 
RtlLookupDynamicFunctionEntry(
00141     IN ULONG_PTR ControlPc
00142     );
00143 
00144 
#endif
00145 
00146 PRUNTIME_FUNCTION
00147 
RtlLookupStaticFunctionEntry(
00148     IN ULONG_PTR ControlPc,
00149     OUT PBOOLEAN InImage
00150     );
00151 
00152 
VOID
00153 
RtlGetUnwindFunctionEntry(
00154     IN ULONG_PTR ControlPc,
00155     IN PRUNTIME_FUNCTION FunctionEntry,
00156     OUT PRUNTIME_FUNCTION UnwindFunctionEntry,
00157     OUT PULONG StackAdjust,
00158     OUT PULONG_PTR FixedReturn
00159     );
00160 
00161 BOOLEAN
00162 RtlDispatchException (
00163     IN PEXCEPTION_RECORD ExceptionRecord,
00164     IN PCONTEXT ContextRecord
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 
00198 
00199 {
00200 
00201     CONTEXT ContextRecord1;
00202     ULONG_PTR ControlPc;
00203 
#if DBG
00204 
    ULONG_PTR ControlPcHistory[PC_HISTORY_DEPTH];
00205     ULONG ControlPcHistoryIndex = 0;
00206 
#endif
00207 
    DISPATCHER_CONTEXT DispatcherContext;
00208     EXCEPTION_DISPOSITION Disposition;
00209     FRAME_POINTERS EstablisherFrame;
00210     ULONG ExceptionFlags;
00211 
#if DBG
00212 
    LONG FrameDepth = 0;
00213 
#endif
00214 
    PRUNTIME_FUNCTION FunctionEntry;
00215     ULONG_PTR HighLimit;
00216     BOOLEAN InFunction;
00217     ULONG_PTR LowLimit;
00218     ULONG_PTR NestedFrame;
00219     ULONG_PTR NextPc;
00220 
00221     
00222     
00223     
00224     
00225     
00226     
00227     
00228     
00229 
00230     
RtlpGetStackLimits(&LowLimit, &HighLimit);
00231     RtlMoveMemory(&ContextRecord1, ContextRecord, 
sizeof(CONTEXT));
00232     ControlPc = (ULONG_PTR)ExceptionRecord->ExceptionAddress;
00233 
00234 
#if DBG
00235 
    if ((ULONG_PTR)ExceptionRecord->ExceptionAddress != (ULONG_PTR)ContextRecord->Fir) {
00236         
DbgPrint(
"RtlDispatchException: ExceptionAddress = %p, Fir = %p\n",
00237                  ExceptionRecord->ExceptionAddress, (ULONG_PTR)ContextRecord->Fir);
00238     }
00239 
#endif
00240 
00241     ExceptionFlags = ExceptionRecord->ExceptionFlags & 
EXCEPTION_NONCONTINUABLE;
00242     NestedFrame = 0;
00243 
00244 
#if DBG
00245 
    if (RtlDebugFlags & RTL_DBG_DISPATCH_EXCEPTION) {
00246         
DbgPrint(
"\nRtlDispatchException(ExceptionRecord = %p, ContextRecord = %p)\n",
00247                  ExceptionRecord, ContextRecord);
00248         
DbgPrint(
"RtlDispatchException: ControlPc = %p, ExceptionRecord->ExceptionCode = %lx\n",
00249                  ControlPc, ExceptionRecord->ExceptionCode);
00250     }
00251 
#endif
00252 
00253     
00254     
00255     
00256     
00257     
00258 
00259     
do {
00260 
#if DBG
00261 
        if (RtlDebugFlags & RTL_DBG_DISPATCH_EXCEPTION_DETAIL) {
00262             
DbgPrint(
"RtlDispatchException: Loop: FrameDepth = %d, sp = %p, ControlPc = %p\n",
00263                      FrameDepth, (ULONG_PTR)ContextRecord1.IntSp, ControlPc);
00264             FrameDepth -= 1;
00265         }
00266 
#endif
00267 
00268         
00269         
00270         
00271         
00272 
00273         FunctionEntry = 
RtlLookupFunctionEntry(ControlPc);
00274 
00275         
00276         
00277         
00278         
00279         
00280         
00281 
00282         
if (FunctionEntry != 
NULL) {
00283             NextPc = 
RtlVirtualUnwind(ControlPc,
00284                                       FunctionEntry,
00285                                       &ContextRecord1,
00286                                       &InFunction,
00287                                       &EstablisherFrame,
00288                                       
NULL);
00289 
00290             
00291             
00292             
00293             
00294             
00295             
00296             
00297 
00298             
if ((EstablisherFrame.Virtual < LowLimit) ||
00299                 (EstablisherFrame.Virtual > HighLimit) ||
00300                 ((EstablisherFrame.Virtual & 0xF) != 0)) {
00301 
00302 
#if DBG
00303 
                DbgPrint(
"\n****** Warning - stack invalid (exception).\n");
00304                 
DbgPrint(
"  EstablisherFrame.Virtual = %p, EstablisherFrame.Real = %p\n",
00305                          EstablisherFrame.Virtual, EstablisherFrame.Real);
00306                 
DbgPrint(
"  LowLimit = %p, HighLimit = %p\n",
00307                          LowLimit, HighLimit);
00308                 
DbgPrint(
"  NextPc = %p, ControlPc = %p\n",
00309                          NextPc, ControlPc);
00310                 
DbgPrint(
"  Now setting EXCEPTION_STACK_INVALID flag.\n");
00311 
#endif
00312 
00313                 ExceptionFlags |= 
EXCEPTION_STACK_INVALID;
00314                 
break;
00315 
00316             } 
else if (
IS_HANDLER_DEFINED(FunctionEntry) && InFunction) {
00317 
00318                 ULONG 
Index;
00319 
00320 
#if DBG
00321 
                if (RtlDebugFlags & RTL_DBG_DISPATCH_EXCEPTION_DETAIL) {
00322                     
DbgPrint(
"RtlDispatchException: ExceptionHandler = %p, HandlerData = %p\n",
00323                              FunctionEntry->ExceptionHandler, FunctionEntry->HandlerData);
00324                 }
00325 
#endif
00326 
00327                 
00328                 
00329                 
00330                 
00331                 
00332                 
00333                 
00334 
00335                 DispatcherContext.ControlPc = ControlPc;
00336                 DispatcherContext.FunctionEntry = FunctionEntry;
00337                 DispatcherContext.EstablisherFrame = EstablisherFrame.Virtual;
00338                 DispatcherContext.ContextRecord = ContextRecord;
00339                 ExceptionRecord->ExceptionFlags = ExceptionFlags;
00340 
00341                 
if (
NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING) {
00342                     
Index = 
RtlpLogExceptionHandler(
00343                                     ExceptionRecord,
00344                                     ContextRecord,
00345                                     ControlPc,
00346                                     FunctionEntry,
00347                                     
sizeof(RUNTIME_FUNCTION));
00348                 }
00349 
00350 
#if DBG
00351 
                if (RtlDebugFlags & RTL_DBG_DISPATCH_EXCEPTION_DETAIL) {
00352                     
DbgPrint(
"RtlDispatchException: calling RtlpExecuteHandlerForException, ControlPc = %lx Handler = %lx\n",
00353                              ControlPc, RF_EXCEPTION_HANDLER(FunctionEntry) );
00354                 }
00355 
#endif
00356 
                Disposition =
00357                     
RtlpExecuteHandlerForException(ExceptionRecord,
00358                                                    EstablisherFrame.Virtual,
00359                                                    ContextRecord,
00360                                                    &DispatcherContext,
00361                                                    RF_EXCEPTION_HANDLER(FunctionEntry));
00362 
#if DBG
00363 
                if (RtlDebugFlags & RTL_DBG_DISPATCH_EXCEPTION_DETAIL) {
00364                     
DbgPrint(
"RtlDispatchException: RtlpExecuteHandlerForException returned Disposition = %lx\n", Disposition);
00365                 }
00366 
#endif
00367 
00368                 
if (
NtGlobalFlag & FLG_ENABLE_EXCEPTION_LOGGING) {
00369                     
RtlpLogLastExceptionDisposition(
Index, Disposition);
00370                 }
00371 
00372                 ExceptionFlags |=
00373                     (ExceptionRecord->ExceptionFlags & 
EXCEPTION_NONCONTINUABLE);
00374 
00375                 
00376                 
00377                 
00378                 
00379                 
00380                 
00381 
00382                 
if (NestedFrame == EstablisherFrame.Virtual) {
00383                     ExceptionFlags &= (~
EXCEPTION_NESTED_CALL);
00384                     NestedFrame = 0;
00385                 }
00386 
00387                 
00388                 
00389                 
00390 
00391                 
switch (Disposition) {
00392 
00393                     
00394                     
00395                     
00396                     
00397                     
00398                     
00399                     
00400 
00401                 
case ExceptionContinueExecution :
00402                     
if ((ExceptionFlags & 
EXCEPTION_NONCONTINUABLE) != 0) {
00403                         
RAISE_EXCEPTION(STATUS_NONCONTINUABLE_EXCEPTION, ExceptionRecord);
00404 
00405                     } 
else {
00406 
#if DBG
00407 
                        if (RtlDebugFlags & RTL_DBG_DISPATCH_EXCEPTION) {
00408                             
DbgPrint(
"RtlDispatchException: returning TRUE\n");
00409                         }
00410 
#endif
00411 
                        return TRUE;
00412                     }
00413 
00414                     
00415                     
00416                     
00417                     
00418                     
00419 
00420                 
case ExceptionContinueSearch :
00421                     
break;
00422 
00423                     
00424                     
00425                     
00426                     
00427                     
00428                     
00429                     
00430 
00431                 
case ExceptionNestedException :
00432                     ExceptionFlags |= 
EXCEPTION_NESTED_CALL;
00433                     
if (DispatcherContext.EstablisherFrame > NestedFrame) {
00434                         NestedFrame = DispatcherContext.EstablisherFrame;
00435                     }
00436 
00437                     
break;
00438 
00439                     
00440                     
00441                     
00442                     
00443                     
00444 
00445                 
default :
00446                     
RAISE_EXCEPTION(STATUS_INVALID_DISPOSITION, ExceptionRecord);
00447                 }
00448             }
00449 
00450         } 
else {
00451 
00452             
00453             
00454             
00455 
00456             NextPc = (ULONG_PTR)ContextRecord1.IntRa - 4;
00457 
00458             
00459             
00460             
00461             
00462 
00463             
if (NextPc == ControlPc) {
00464 
#if DBG
00465 
                ULONG 
Count;
00466                 
DbgPrint(
"\n****** Warning - malformed function table (exception).\n");
00467                 
DbgPrint(
"ControlPc = %p, NextPc %p", NextPc, ControlPc);
00468                 
for (
Count = 0; 
Count < PC_HISTORY_DEPTH; 
Count += 1) {
00469                     
if (ControlPcHistoryIndex > 0) {
00470                         ControlPcHistoryIndex -= 1;
00471                         ControlPc = ControlPcHistory[ControlPcHistoryIndex % PC_HISTORY_DEPTH];
00472                         
DbgPrint(
", %p", ControlPc);
00473                     }
00474                 }
00475                 
DbgPrint(ControlPcHistoryIndex == 0 ? 
".\n" : 
", ...\n");
00476 
#endif
00477 
                break;
00478             }
00479         }
00480 
00481         
00482         
00483         
00484 
00485 
#if DBG
00486 
        ControlPcHistory[ControlPcHistoryIndex % PC_HISTORY_DEPTH] = ControlPc;
00487         ControlPcHistoryIndex += 1;
00488 
#endif
00489 
        ControlPc = NextPc;
00490 
00491     } 
while ((ULONG_PTR)ContextRecord1.IntSp < HighLimit);
00492 
00493     
00494     
00495     
00496 
00497     ExceptionRecord->ExceptionFlags = ExceptionFlags;
00498 
#if DBG
00499 
    if (RtlDebugFlags & RTL_DBG_DISPATCH_EXCEPTION) {
00500         
DbgPrint(
"RtlDispatchException: returning FALSE\n");
00501     }
00502 
#endif
00503 
    return FALSE;
00504 }
00505 
00506 PRUNTIME_FUNCTION
00507 RtlLookupFunctionEntry (
00508     IN ULONG_PTR ControlPc
00509     )
00510 
00511 
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519 
00520 
00521 
00522 
00523 
00524 
00525 
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 {
00543     PRUNTIME_FUNCTION FunctionEntry;
00544 
00545     
00546 
00547     FunctionEntry = 
RtlLookupDirectFunctionEntry( ControlPc );
00548 
00549     
if (FunctionEntry != 
NULL) {
00550 
00551         
00552         
00553         
00554         
00555         
00556         
00557         
00558         
00559         
00560         
00561         
00562 
00563         
if ((RF_PROLOG_END_ADDRESS(FunctionEntry) <  RF_BEGIN_ADDRESS(FunctionEntry)) ||
00564             (RF_PROLOG_END_ADDRESS(FunctionEntry) >= RF_END_ADDRESS(FunctionEntry))) {
00565 
#if DBG
00566 
            ShowRuntimeFunction(FunctionEntry, 
"RtlLookupFunctionEntry: secondary entry" );
00567 
#endif
00568 
            
00569             
00570             
00571 
00572             FunctionEntry = (PRUNTIME_FUNCTION)RF_PROLOG_END_ADDRESS(FunctionEntry);
00573         } 
else if (RF_IS_FIXED_RETURN(FunctionEntry)) {
00574             ULONG_PTR FixedReturn = RF_FIXED_RETURN(FunctionEntry);
00575     
00576 
#if DBG
00577 
            ShowRuntimeFunction(FunctionEntry, 
"LookupFunctionEntry: fixed return entry");
00578 
#endif
00579 
            
00580             
00581     
00582             
if ((FixedReturn <  RF_BEGIN_ADDRESS(FunctionEntry)) ||
00583                 (FixedReturn >= RF_END_ADDRESS(FunctionEntry))) {
00584                 FunctionEntry = 
RtlLookupFunctionEntry( RF_FIXED_RETURN(FunctionEntry) );
00585             }
00586         }
00587 
#if DBG
00588 
        else {
00589             ShowRuntimeFunction(FunctionEntry, 
"RtlLookupFunctionEntry: primary entry" );
00590         }
00591 
#endif
00592 
    }
00593 
00594 
#if DBG
00595 
    if (RtlDebugFlags & RTL_DBG_FUNCTION_ENTRY) {
00596         
DbgPrint(
"RtlLookupFunctionEntry: returning FunctionEntry = %lx\n", FunctionEntry);
00597     }
00598 
#endif
00599 
    return FunctionEntry;
00600 }
00601 
00602 
VOID
00603 RtlRaiseException (
00604     IN PEXCEPTION_RECORD ExceptionRecord
00605     )
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 
00621 
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 {
00630 
00631 
#if DBG
00632 
    if (RtlDebugFlags & RTL_DBG_RAISE_EXCEPTION) {
00633         
DbgPrint(
"RtlRaiseException(ExceptionRecord = %p) Status = %lx\n",
00634                  ExceptionRecord, ExceptionRecord->ExceptionCode);
00635     }
00636 
#endif
00637 
00638     
RtlpRaiseException(ExceptionRecord);
00639     
return;
00640 }
00641 
00642 
VOID
00643 RtlpRaiseException (
00644     IN PEXCEPTION_RECORD ExceptionRecord
00645     )
00646 
00647 
00648 
00649 
00650 
00651 
00652 
00653 
00654 
00655 
00656 
00657 
00658 
00659 
00660 
00661 
00662 
00663 
00664 {
00665 
00666     ULONG_PTR ControlPc;
00667     CONTEXT ContextRecord;
00668     FRAME_POINTERS EstablisherFrame;
00669     PRUNTIME_FUNCTION FunctionEntry;
00670     BOOLEAN InFunction;
00671     ULONG_PTR NextPc;
00672     
NTSTATUS Status;
00673 
00674     
00675     
00676     
00677     
00678     
00679 
00680     RtlCaptureContext(&ContextRecord);
00681     ControlPc = (ULONG_PTR)ContextRecord.IntRa - 4;
00682     FunctionEntry = 
RtlLookupFunctionEntry(ControlPc);
00683     NextPc = 
RtlVirtualUnwind(ControlPc,
00684                               FunctionEntry,
00685                               &ContextRecord,
00686                               &InFunction,
00687                               &EstablisherFrame,
00688                               
NULL);
00689 
00690     ContextRecord.Fir = (ULONGLONG)(LONG_PTR)NextPc + 4;
00691     ExceptionRecord->ExceptionAddress = (PVOID)ContextRecord.Fir;
00692     
Status = ZwRaiseException(ExceptionRecord, &ContextRecord, 
TRUE);
00693 
00694     
00695     
00696     
00697     
00698     
00699 
00700     
RtlRaiseStatus(
Status);
00701     
return;
00702 }
00703 
00704 
VOID
00705 RtlRaiseStatus (
00706     IN NTSTATUS Status
00707     )
00708 
00709 
00710 
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726 
00727 
00728 
00729 
00730 
00731 
00732 {
00733 
00734 
#if DBG
00735 
    if (RtlDebugFlags & RTL_DBG_RAISE_EXCEPTION) {
00736         
DbgPrint(
"RtlRaiseStatus(Status = %lx)\n", 
Status);
00737     }
00738 
#endif
00739 
00740     
RtlpRaiseStatus(
Status);
00741     
return;
00742 }
00743 
00744 
VOID
00745 RtlpRaiseStatus (
00746     IN NTSTATUS Status
00747     )
00748 
00749 
00750 
00751 
00752 
00753 
00754 
00755 
00756 
00757 
00758 
00759 
00760 
00761 
00762 
00763 
00764 
00765 
00766 
00767 {
00768 
00769     ULONG_PTR ControlPc;
00770     CONTEXT ContextRecord;
00771     FRAME_POINTERS EstablisherFrame;
00772     EXCEPTION_RECORD ExceptionRecord;
00773     PRUNTIME_FUNCTION FunctionEntry;
00774     BOOLEAN InFunction;
00775     ULONG_PTR NextPc;
00776 
00777     
00778     
00779     
00780 
00781     ExceptionRecord.ExceptionCode = 
Status;
00782     ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD)
NULL;
00783     ExceptionRecord.NumberParameters = 0;
00784     ExceptionRecord.ExceptionFlags = 
EXCEPTION_NONCONTINUABLE;
00785 
00786     
00787     
00788     
00789     
00790     
00791 
00792     RtlCaptureContext(&ContextRecord);
00793     ControlPc = (ULONG_PTR)ContextRecord.IntRa - 4;
00794     FunctionEntry = 
RtlLookupFunctionEntry(ControlPc);
00795     NextPc = 
RtlVirtualUnwind(ControlPc,
00796                               FunctionEntry,
00797                               &ContextRecord,
00798                               &InFunction,
00799                               &EstablisherFrame,
00800                               
NULL);
00801 
00802     ContextRecord.Fir = (ULONGLONG)(LONG_PTR)NextPc + 4;
00803     ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.Fir;
00804     
Status = ZwRaiseException(&ExceptionRecord, &ContextRecord, 
TRUE);
00805 
00806     
00807     
00808     
00809     
00810     
00811 
00812     
RtlRaiseStatus(
Status);
00813     
return;
00814 }
00815 
00816 
VOID
00817 RtlUnwind (
00818     IN PVOID TargetFrame OPTIONAL,
00819     IN PVOID TargetIp OPTIONAL,
00820     IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
00821     IN PVOID ReturnValue
00822     )
00823 
00824 
00825 
00826 
00827 
00828 
00829 
00830 
00831 
00832 
00833 
00834 
00835 
00836 
00837 
00838 
00839 
00840 
00841 
00842 
00843 
00844 
00845 
00846 
00847 
00848 
00849 
00850 
00851 
00852 
00853 
00854 
00855 
00856 
00857 
00858 
00859 
00860 
00861 
00862 
00863 
00864 {
00865     CONTEXT ContextRecord;
00866 
00867 
00868     
00869     
00870     
00871     
00872 
00873     
RtlUnwind2(TargetFrame,
00874                TargetIp,
00875                ExceptionRecord,
00876                ReturnValue,
00877                &ContextRecord);
00878 
00879     
return;
00880 }
00881 
00882 
VOID
00883 RtlUnwind2 (
00884     IN PVOID TargetFrame OPTIONAL,
00885     IN PVOID TargetIp OPTIONAL,
00886     IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
00887     IN PVOID ReturnValue,
00888     IN PCONTEXT ContextRecord
00889     )
00890 
00891 
00892 
00893 
00894 
00895 
00896 
00897 
00898 
00899 
00900 
00901 
00902 
00903 
00904 
00905 
00906 
00907 
00908 
00909 
00910 
00911 
00912 
00913 
00914 
00915 
00916 
00917 
00918 
00919 
00920 
00921 
00922 
00923 
00924 
00925 
00926 
00927 
00928 
00929 
00930 
00931 {
00932     ULONG_PTR ControlPc;
00933 
#if DBG
00934 
    ULONG_PTR ControlPcHistory[PC_HISTORY_DEPTH];
00935     ULONG ControlPcHistoryIndex = 0;
00936 
#endif
00937 
    DISPATCHER_CONTEXT DispatcherContext;
00938     EXCEPTION_DISPOSITION Disposition;
00939     FRAME_POINTERS EstablisherFrame;
00940     ULONG ExceptionFlags;
00941     EXCEPTION_RECORD ExceptionRecord1;
00942 
#if DBG
00943 
    LONG FrameDepth = 0;
00944 
#endif
00945 
    PRUNTIME_FUNCTION FunctionEntry;
00946     ULONG_PTR HighLimit;
00947     BOOLEAN InFunction;
00948     ULONG_PTR LowLimit;
00949     ULONG_PTR NextPc;
00950 
00951 
#if DBG
00952 
    if (RtlDebugFlags & RTL_DBG_UNWIND) {
00953         
DbgPrint(
"\nRtlUnwind(TargetFrame = %p, TargetIp = %p,, ReturnValue = %lx)\n",
00954                  TargetFrame, TargetIp, ReturnValue);
00955     }
00956 
#endif
00957 
00958     
00959     
00960     
00961     
00962     
00963 
00964     
RtlpGetStackLimits(&LowLimit, &HighLimit);
00965     RtlCaptureContext(ContextRecord);
00966     ControlPc = (ULONG_PTR)ContextRecord->IntRa - 4;
00967     FunctionEntry = 
RtlLookupFunctionEntry(ControlPc);
00968     NextPc = 
RtlVirtualUnwind(ControlPc,
00969                               FunctionEntry,
00970                               ContextRecord,
00971                               &InFunction,
00972                               &EstablisherFrame,
00973                               
NULL);
00974 
00975     ControlPc = NextPc;
00976     ContextRecord->Fir = (ULONGLONG)(LONG_PTR)TargetIp;
00977 
00978     
00979     
00980     
00981     
00982 
00983     
if (ARGUMENT_PRESENT(ExceptionRecord) == 
FALSE) {
00984         ExceptionRecord = &ExceptionRecord1;
00985         ExceptionRecord1.ExceptionCode = STATUS_UNWIND;
00986         ExceptionRecord1.ExceptionRecord = 
NULL;
00987         ExceptionRecord1.ExceptionAddress = (PVOID)ControlPc;
00988         ExceptionRecord1.NumberParameters = 0;
00989     }
00990 
00991     
00992     
00993     
00994     
00995 
00996     ExceptionFlags = 
EXCEPTION_UNWINDING;
00997     
if (ARGUMENT_PRESENT(TargetFrame) == 
FALSE) {
00998         ExceptionRecord->ExceptionFlags |= 
EXCEPTION_EXIT_UNWIND;
00999     }
01000 
01001     
01002     
01003     
01004     
01005 
01006     
do {
01007 
01008 
#if DBG
01009 
    if (RtlDebugFlags & RTL_DBG_UNWIND_DETAIL) {
01010         
DbgPrint(
"RtlUnwind: Loop: FrameDepth = %d, sp = %p, ControlPc = %p\n",
01011                  FrameDepth, (ULONG_PTR)ContextRecord->IntSp, ControlPc);
01012         FrameDepth -= 1;
01013     }
01014 
#endif
01015 
01016         
01017         
01018         
01019         
01020 
01021         FunctionEntry = 
RtlLookupFunctionEntry(ControlPc);
01022 
01023         
01024         
01025         
01026         
01027         
01028 
01029         
if (FunctionEntry != 
NULL) {
01030             NextPc = 
RtlpVirtualUnwind(ControlPc,
01031                                        FunctionEntry,
01032                                        ContextRecord,
01033                                        &InFunction,
01034                                        &EstablisherFrame);
01035 
01036             
01037             
01038             
01039             
01040             
01041             
01042             
01043             
01044 
01045             
if ((EstablisherFrame.Virtual < LowLimit) ||
01046                 (EstablisherFrame.Virtual > HighLimit) ||
01047                 ((ARGUMENT_PRESENT(TargetFrame) != 
FALSE) &&
01048                  ((ULONG_PTR)TargetFrame < EstablisherFrame.Virtual)) ||
01049                 ((EstablisherFrame.Virtual & 0xF) != 0)) {
01050 
01051 
#if DBG
01052 
                DbgPrint(
"\n****** Warning - bad stack or target frame (unwind).\n");
01053                 
DbgPrint(
"  EstablisherFrame Virtual = %p, Real = %p\n",
01054                          EstablisherFrame.Virtual, EstablisherFrame.Real);
01055                 
DbgPrint(
"  TargetFrame = %p\n", TargetFrame);
01056                 
if ((ARGUMENT_PRESENT(TargetFrame) != 
FALSE) &&
01057                     ((ULONG_PTR)TargetFrame < EstablisherFrame.Virtual)) {
01058                     
DbgPrint(
"  TargetFrame is below EstablisherFrame!\n");
01059                 }
01060                 
DbgPrint(
"  Previous EstablisherFrame (sp) = %p\n",
01061                          (ULONG_PTR)ContextRecord->IntSp);
01062                 
DbgPrint(
"  LowLimit = %p, HighLimit = %p\n",
01063                          LowLimit, HighLimit);
01064                 
DbgPrint(
"  NextPc = %p, ControlPc = %p\n",
01065                          NextPc, ControlPc);
01066                 
DbgPrint(
"  Now raising STATUS_BAD_STACK exception.\n");
01067 
#endif
01068 
01069                 
RAISE_EXCEPTION(STATUS_BAD_STACK, ExceptionRecord);
01070 
01071             } 
else if (
IS_HANDLER_DEFINED(FunctionEntry) && InFunction) {
01072 
01073 
#if DBG
01074 
    if (RtlDebugFlags & RTL_DBG_DISPATCH_EXCEPTION_DETAIL) {
01075     
DbgPrint(
"RtlUnwind: ExceptionHandler = %p, HandlerData = %p\n",
01076              FunctionEntry->ExceptionHandler, FunctionEntry->HandlerData);
01077 }
01078 
#endif
01079 
01080                 
01081                 
01082                 
01083                 
01084                 
01085                 
01086                 
01087                 
01088                 
01089                 
01090                 
01091                 
01092                 
01093                 
01094                 
01095 
01096                 DispatcherContext.ControlPc = ControlPc;
01097                 DispatcherContext.FunctionEntry = FunctionEntry;
01098                 DispatcherContext.EstablisherFrame = EstablisherFrame.Virtual;
01099                 DispatcherContext.ContextRecord = ContextRecord;
01100 
01101                 
01102                 
01103                 
01104 
01105                 
do {
01106 
01107                     
01108                     
01109                     
01110                     
01111 
01112                     
if ((ULONG_PTR)TargetFrame == EstablisherFrame.Virtual) {
01113                         ExceptionFlags |= 
EXCEPTION_TARGET_UNWIND;
01114                     }
01115 
01116                     ExceptionRecord->ExceptionFlags = ExceptionFlags;
01117 
01118                     
01119                     
01120                     
01121                     
01122 
01123                     ContextRecord->IntV0 = (ULONGLONG)(LONG_PTR)ReturnValue;
01124 
#if DBG
01125 
    if (RtlDebugFlags & RTL_DBG_UNWIND_DETAIL) {
01126         
DbgPrint(
"RtlUnwind: calling RtlpExecuteHandlerForUnwind, ControlPc = %p\n", ControlPc);
01127     }
01128 
#endif
01129 
                    Disposition =
01130                         
RtlpExecuteHandlerForUnwind(ExceptionRecord,
01131                                                     EstablisherFrame.Virtual,
01132                                                     ContextRecord,
01133                                                     &DispatcherContext,
01134                                                     RF_EXCEPTION_HANDLER(FunctionEntry));
01135 
#if DBG
01136 
    if (RtlDebugFlags & RTL_DBG_UNWIND_DETAIL) {
01137         
DbgPrint(
"RtlUnwind: RtlpExecuteHandlerForUnwind returned Disposition = %lx\n", Disposition);
01138     }
01139 
#endif
01140 
01141                     
01142                     
01143                     
01144 
01145                     ExceptionFlags &= ~(
EXCEPTION_COLLIDED_UNWIND |
01146                                         
EXCEPTION_TARGET_UNWIND);
01147 
01148                     
01149                     
01150                     
01151 
01152                     
switch (Disposition) {
01153 
01154                         
01155                         
01156                         
01157                         
01158                         
01159                         
01160                         
01161                         
01162 
01163                     
case ExceptionContinueSearch :
01164                         
if (EstablisherFrame.Virtual != (ULONG_PTR)TargetFrame) {
01165                             NextPc = 
RtlVirtualUnwind(ControlPc,
01166                                                       FunctionEntry,
01167                                                       ContextRecord,
01168                                                       &InFunction,
01169                                                       &EstablisherFrame,
01170                                                       
NULL);
01171                         }
01172 
01173                         
break;
01174 
01175                         
01176                         
01177                         
01178                         
01179                         
01180                         
01181                         
01182                         
01183 
01184                     
case ExceptionCollidedUnwind :
01185                         ControlPc = DispatcherContext.ControlPc;
01186                         FunctionEntry = DispatcherContext.FunctionEntry;
01187                         ContextRecord = DispatcherContext.ContextRecord;
01188                         ContextRecord->Fir = (ULONGLONG)(LONG_PTR)TargetIp;
01189                         ExceptionFlags |= 
EXCEPTION_COLLIDED_UNWIND;
01190                         EstablisherFrame.Virtual = DispatcherContext.EstablisherFrame;
01191                         
break;
01192 
01193                         
01194                         
01195                         
01196                         
01197                         
01198 
01199                     
default :
01200                         
RAISE_EXCEPTION(STATUS_INVALID_DISPOSITION, ExceptionRecord);
01201                     }
01202 
01203                 } 
while ((ExceptionFlags & 
EXCEPTION_COLLIDED_UNWIND) != 0);
01204             } 
else {
01205 
01206                 
01207                 
01208                 
01209                 
01210 
01211                 
if (EstablisherFrame.Virtual != (ULONG_PTR)TargetFrame) {
01212                     NextPc = 
RtlVirtualUnwind(ControlPc,
01213                                               FunctionEntry,
01214                                               ContextRecord,
01215                                               &InFunction,
01216                                               &EstablisherFrame,
01217                                               
NULL);
01218                 }
01219             }
01220 
01221         } 
else {
01222 
01223             
01224             
01225             
01226 
01227             NextPc = (ULONG_PTR)ContextRecord->IntRa - 4;
01228 
01229             
01230             
01231             
01232             
01233 
01234             
if (NextPc == ControlPc) {
01235 
#if DBG
01236 
                ULONG 
Count;
01237                 
DbgPrint(
"\n****** Warning - malformed function table (unwind).\n");
01238                 
DbgPrint(
"ControlPc = %p, %p", NextPc, ControlPc);
01239                 
for (
Count = 0; 
Count < PC_HISTORY_DEPTH; 
Count += 1) {
01240                     
if (ControlPcHistoryIndex > 0) {
01241                         ControlPcHistoryIndex -= 1;
01242                         ControlPc = ControlPcHistory[ControlPcHistoryIndex % PC_HISTORY_DEPTH];
01243                         
DbgPrint(
", %p", ControlPc);
01244                     }
01245                 }
01246                 
DbgPrint(ControlPcHistoryIndex == 0 ? 
".\n" : 
", ...\n");
01247                 
DbgPrint(
"  Now raising STATUS_BAD_FUNCTION_TABLE exception.\n");
01248 
#endif
01249 
                RtlRaiseStatus(STATUS_BAD_FUNCTION_TABLE);
01250             }
01251         }
01252 
01253         
01254         
01255         
01256 
01257 
#if DBG
01258 
        ControlPcHistory[ControlPcHistoryIndex % PC_HISTORY_DEPTH] = ControlPc;
01259         ControlPcHistoryIndex += 1;
01260 
#endif
01261 
        ControlPc = NextPc;
01262 
01263     } 
while ((EstablisherFrame.Virtual < HighLimit) &&
01264              (EstablisherFrame.Virtual != (ULONG_PTR)TargetFrame));
01265 
01266     
01267     
01268     
01269     
01270     
01271     
01272     
01273 
01274     
if (EstablisherFrame.Virtual == (ULONG_PTR)TargetFrame) {
01275         ContextRecord->IntV0 = (ULONGLONG)(LONG_PTR)ReturnValue;
01276 
01277 
#if DBG
01278 
    if (RtlDebugFlags & RTL_DBG_UNWIND) {
01279         
DbgPrint(
"RtlUnwind: finished unwinding, and calling RtlpRestoreContext(%lx)\n",ContextRecord);
01280     }
01281 
#endif
01282 
01283         
RtlpRestoreContext(ContextRecord);
01284 
01285     } 
else {
01286 
01287 
#if DBG
01288 
    if (RtlDebugFlags & RTL_DBG_UNWIND) {
01289         
DbgPrint(
"RtlUnwind: finished unwinding, but calling ZwRaiseException\n");
01290     }
01291 
#endif
01292 
01293         ZwRaiseException(ExceptionRecord, ContextRecord, 
FALSE);
01294     }
01295 
01296 }
01297 
01298 
#if DBG
01299 
01300 
01301 
01302 
01303 PCHAR RtlpIntegerRegisterNames[32] = {
01304     
"v0",  
"t0",  
"t1",  
"t2",  
"t3",  
"t4",  
"t5",  
"t6",      
01305     
"t7",  
"s0",  
"s1",  
"s2",  
"s3",  
"s4",  
"s5",  
"fp",      
01306     
"a0",  
"a1",  
"a2",  
"a3",  
"a4",  
"a5",  
"t8",  
"t9",      
01307     
"t10", 
"t11", 
"ra",  
"t12", 
"at",  
"gp",  
"sp",  
"zero",    
01308 };
01309 
01310 
01311 
01312 
01313 
01314 
01315 
01316 
VOID
01317 
_RtlpDebugDisassemble (
01318     IN ULONG_PTR ControlPc,
01319     IN PCONTEXT ContextRecord
01320     )
01321 
01322 {
01323     UCHAR Comments[50];
01324     PULONGLONG FloatingRegister;
01325     ULONG Function;
01326     ULONG Hint;
01327     ULONG Literal8;
01328     ALPHA_INSTRUCTION Instruction;
01329     PULONGLONG IntegerRegister;
01330     LONG  Offset16;
01331     UCHAR Operands[20];
01332     ULONG Opcode;
01333     PCHAR OpName;
01334     ULONG Ra;
01335     ULONG Rb;
01336     ULONG Rc;
01337     PCHAR RaName;
01338     PCHAR RbName;
01339     PCHAR RcName;
01340 
01341     
if (RtlDebugFlags & RTL_DBG_VIRTUAL_UNWIND_DETAIL) {
01342         Instruction.Long = *((PULONG)ControlPc);
01343         Hint = Instruction.Jump.Hint;
01344         Literal8 = Instruction.OpLit.Literal;
01345         Offset16 = Instruction.Memory.MemDisp;
01346         Opcode = Instruction.Memory.Opcode;
01347         Ra = Instruction.OpReg.Ra;
01348         RaName = RtlpIntegerRegisterNames[Ra];
01349         Rb = Instruction.OpReg.Rb;
01350         RbName = RtlpIntegerRegisterNames[Rb];
01351         Rc = Instruction.OpReg.Rc;
01352         RcName = RtlpIntegerRegisterNames[Rc];
01353 
01354         IntegerRegister = &ContextRecord->IntV0;
01355         FloatingRegister = &ContextRecord->FltF0;
01356 
01357         OpName = 
NULL;
01358         
switch (Opcode) {
01359         
case JMP_OP :
01360             
if (Instruction.Jump.Function == RET_FUNC) {
01361                 OpName = 
"ret";
01362                 
sprintf(Operands, 
"%s, (%s), %04lx", RaName, RbName, Hint);
01363                 
sprintf(Comments, 
"%s = %Lx", RbName, IntegerRegister[Rb]);
01364             }
01365             
break;
01366 
01367         
case LDAH_OP :
01368         
case LDA_OP :
01369         
case STQ_OP :
01370             
if (Opcode == 
LDA_OP) {
01371                 OpName = 
"lda";
01372 
01373             } 
else if (Opcode == LDAH_OP) {
01374                 OpName = 
"ldah";
01375 
01376             } 
else if (Opcode == STQ_OP) {
01377                 OpName = 
"stq";
01378             }
01379             
sprintf(Operands, 
"%s, $%d(%s)", RaName, Offset16, RbName);
01380             
sprintf(Comments, 
"%s = %Lx", RaName, IntegerRegister[Ra]);
01381             
break;
01382 
01383         
case ARITH_OP :
01384         
case BIT_OP :
01385             Function = Instruction.OpReg.Function;
01386             
if ((Opcode == ARITH_OP) && (Function == ADDQ_FUNC)) {
01387                     OpName = 
"addq";
01388 
01389             } 
else if ((Opcode == ARITH_OP) && (Function == SUBQ_FUNC)) {
01390                     OpName = 
"subq";
01391 
01392             } 
else if ((Opcode == BIT_OP) && (Function == BIS_FUNC)) {
01393                     OpName = 
"bis";
01394 
01395             } 
else {
01396                 
break;
01397             }
01398             
if (Instruction.OpReg.RbvType == RBV_REGISTER_FORMAT) {
01399                 
sprintf(Operands, 
"%s, %s, %s", RaName, RbName, RcName);
01400 
01401             } 
else {
01402                 
sprintf(Operands, 
"%s, $%d, %s", RaName, Literal8, RcName);
01403             }
01404             
sprintf(Comments, 
"%s = %Lx", RcName, IntegerRegister[Rc]);
01405             
break;
01406 
01407         
case FPOP_OP :
01408             
if (Instruction.FpOp.Function == CPYS_FUNC) {
01409                 OpName = 
"cpys";
01410                 
sprintf(Operands, 
"f%d, f%d, f%d", Ra, Rb, Rc);
01411                 
sprintf(Comments, 
"f%d = %Lx", Rc, FloatingRegister[Rc]);
01412             }
01413             
break;
01414 
01415         
case STT_OP :
01416             OpName = 
"stt";
01417             
sprintf(Operands, 
"f%d, $%d(%s)", Ra, Offset16, RbName);
01418             
sprintf(Comments, 
"f%d = %Lx", Ra, FloatingRegister[Ra]);
01419             
break;
01420         }
01421         
if (OpName == 
NULL) {
01422             OpName = 
"???";
01423             
sprintf(Operands, 
"...");
01424             
sprintf(Comments, 
"Unknown to virtual unwind.");
01425         }
01426         
DbgPrint(
"    %p: %08lx  %-5s %-16s // %s\n",
01427                  ControlPc, Instruction.Long, OpName, Operands, Comments);
01428     }
01429     
return;
01430 }
01431 
01432 
#define _RtlpFoundTrapFrame(NextPc) \
01433 
    if (RtlDebugFlags & RTL_DBG_VIRTUAL_UNWIND) { \
01434 
        DbgPrint("    *** Looks like a trap frame (fake prologue), Fir = %lx\n", \
01435 
                 NextPc); \
01436 
    }
01437 
01438 
#define _RtlpVirtualUnwindExit(NextPc, ContextRecord, EstablisherFrame) \
01439 
    if (RtlDebugFlags & RTL_DBG_VIRTUAL_UNWIND) { \
01440 
        DbgPrint("RtlVirtualUnwind: EstablisherFrame Virtual = %08lx, Real = %08lx\n", \
01441 
        (EstablisherFrame)->Virtual, (EstablisherFrame)->Real); \
01442 
        DbgPrint("RtlVirtualUnwind: returning NextPc = %p, sp = %p\n\n", \
01443 
                 NextPc, (ULONG_PTR)ContextRecord->IntSp); \
01444 
    }
01445 
01446 
#else
01447 
01448 #define _RtlpDebugDisassemble(ControlPc, ContextRecord)
01449 #define _RtlpFoundTrapFrame(NextPc)
01450 #define _RtlpVirtualUnwindExit(NextPc, ContextRecord, EstablisherFrame)
01451 
01452 
#endif
01453 
01454 ULONG_PTR
01455 RtlVirtualUnwind (
01456     IN ULONG_PTR ControlPc,
01457     IN PRUNTIME_FUNCTION FunctionEntry,
01458     IN OUT PCONTEXT ContextRecord,
01459     OUT PBOOLEAN InFunction,
01460     OUT PFRAME_POINTERS EstablisherFrame,
01461     IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL
01462     )
01463 
01464 
01465 
01466 
01467 
01468 
01469 
01470 
01471 
01472 
01473 
01474 
01475 
01476 
01477 
01478 
01479 
01480 
01481 
01482 
01483 
01484 
01485 
01486 
01487 
01488 
01489 
01490 
01491 
01492 
01493 
01494 
01495 
01496 
01497 
01498 
01499 
01500 
01501 
01502 
01503 
01504 
01505 
01506 
01507 
01508 
01509 
01510 
01511 
01512 
01513 
01514 
01515 
01516 
01517 
01518 
01519 
01520 
01521 
01522 
01523 
01524 
01525 
01526 
01527 
01528 
01529 
01530 
01531 
01532 
01533 
01534 
01535 
01536 
01537 
01538 
01539 
01540 
01541 
01542 
01543 
01544 
01545 
01546 
01547 
01548 
01549 {
01550 
01551     ULONG_PTR Address;
01552     ULONG DecrementOffset;
01553     ULONG DecrementRegister;
01554     ALPHA_INSTRUCTION FollowingInstruction;
01555     PULONGLONG FloatingRegister;
01556     ULONG_PTR FrameSize;
01557     ULONG Function;
01558     ALPHA_INSTRUCTION Instruction;
01559     PULONGLONG IntegerRegister;
01560     ULONG Literal8;
01561     ULONG_PTR NextPc;
01562     LONG Offset16;
01563     ULONG Opcode;
01564     ULONG Ra;
01565     ULONG Rb;
01566     ULONG Rc;
01567     BOOLEAN RestoredRa;
01568     BOOLEAN RestoredSp;
01569     RUNTIME_FUNCTION UnwindFunctionEntry;
01570     ULONG StackAdjust;
01571     ULONG_PTR FixedReturn;
01572 
01573 
#if DBG
01574 
    if (RtlDebugFlags & RTL_DBG_VIRTUAL_UNWIND) {
01575         
DbgPrint(
"\nRtlVirtualUnwind(ControlPc = %p, FunctionEntry = %p,) sp = %p\n",
01576                  ControlPc, FunctionEntry, (ULONG_PTR)ContextRecord->IntSp);
01577     }
01578 
#endif
01579 
01580     
01581 
01582     
RtlGetUnwindFunctionEntry( ControlPc, FunctionEntry, &UnwindFunctionEntry, &StackAdjust, &FixedReturn );
01583 
01584 
#if DBG
01585 
    ShowRuntimeFunction(&UnwindFunctionEntry, 
"RtlVirtualUnwind: unwind function entry" );
01586 
#endif
01587 
    
01588     
01589     
01590     
01591 
01592     IntegerRegister = &ContextRecord->IntV0;
01593     FloatingRegister = &ContextRecord->FltF0;
01594 
01595     
01596     
01597     
01598     
01599     
01600     
01601     
01602 
01603     Instruction.Long = *((PULONG)ControlPc);
01604     
if (IS_RETURN_0001_INSTRUCTION(Instruction.Long)) {
01605         Rb = Instruction.Jump.Rb;
01606         NextPc = (ULONG_PTR)IntegerRegister[Rb] - 4;
01607 
01608         
01609         
01610         
01611         
01612         
01613         
01614         
01615         
01616         
01617         
01618         
01619         
01620         
01621         
01622         
01623         
01624         
01625         
01626         
01627         
01628         
01629         
01630         
01631         
01632 
01633         EstablisherFrame->Real = 0;
01634         EstablisherFrame->Virtual = (ULONG_PTR)ContextRecord->IntSp;
01635         *InFunction = 
FALSE;
01636         
_RtlpDebugDisassemble(ControlPc, ContextRecord);
01637         
_RtlpVirtualUnwindExit(NextPc, ContextRecord, EstablisherFrame);
01638         
return NextPc;
01639     }
01640 
01641     
01642     
01643     
01644     
01645 
01646     FollowingInstruction.Long = *((PULONG)(ControlPc + 4));
01647     
if (IS_RETURN_0001_INSTRUCTION(FollowingInstruction.Long)) {
01648         Rb = FollowingInstruction.Jump.Rb;
01649         NextPc = (ULONG_PTR)IntegerRegister[Rb] - 4;
01650 
01651         
01652         
01653         
01654         
01655         
01656         
01657         
01658         
01659         
01660         
01661         
01662         
01663         
01664         
01665         
01666         
01667         
01668         
01669         
01670 
01671         Function = Instruction.OpReg.Function;
01672         Offset16 = Instruction.Memory.MemDisp;
01673         Opcode = Instruction.OpReg.Opcode;
01674         Ra = Instruction.OpReg.Ra;
01675         Rb = Instruction.OpReg.Rb;
01676         Rc = Instruction.OpReg.Rc;
01677 
01678         
if ((Opcode == 
LDA_OP) && (Ra == SP_REG)) {
01679 
01680             
01681             
01682             
01683             
01684             
01685             
01686             
01687             
01688             
01689             
01690             
01691             
01692             
01693             
01694             
01695             
01696             
01697             
01698             
01699             
01700 
01701             ContextRecord->IntSp = Offset16 + IntegerRegister[Rb];
01702             EstablisherFrame->Real = 0;
01703             EstablisherFrame->Virtual = (ULONG_PTR)ContextRecord->IntSp;
01704             *InFunction = 
FALSE;
01705             
_RtlpDebugDisassemble(ControlPc, ContextRecord);
01706             
_RtlpDebugDisassemble(ControlPc + 4, ContextRecord);
01707             
_RtlpVirtualUnwindExit(NextPc, ContextRecord, EstablisherFrame);
01708             
return NextPc;
01709 
01710         } 
else if ((Opcode == ARITH_OP) && (Function == ADDQ_FUNC) &&
01711                    (Rc == SP_REG) &&
01712                    (Instruction.OpReg.RbvType == RBV_REGISTER_FORMAT)) {
01713 
01714             
01715             
01716             
01717             
01718             
01719             
01720             
01721             
01722             
01723             
01724             
01725             
01726             
01727             
01728             
01729             
01730             
01731             
01732             
01733             
01734             
01735 
01736             ContextRecord->IntSp = IntegerRegister[Ra] + IntegerRegister[Rb];
01737             EstablisherFrame->Real = 0;
01738             EstablisherFrame->Virtual = (ULONG_PTR)ContextRecord->IntSp;
01739             *InFunction = 
FALSE;
01740             
_RtlpDebugDisassemble(ControlPc, ContextRecord);
01741             
_RtlpDebugDisassemble(ControlPc + 4, ContextRecord);
01742             
_RtlpVirtualUnwindExit(NextPc, ContextRecord, EstablisherFrame);
01743             
return NextPc;
01744         }
01745     }
01746 
01747     
01748     
01749     
01750     
01751     
01752     
01753     
01754     
01755     
01756     
01757 
01758     EstablisherFrame->Real = (ULONG_PTR)ContextRecord->IntSp;
01759     EstablisherFrame->Virtual = (ULONG_PTR)ContextRecord->IntSp;
01760 
01761     
01762     
01763     
01764     
01765     
01766     
01767     
01768     
01769     
01770     
01771     
01772     
01773 
01774     
if ((ControlPc < UnwindFunctionEntry.BeginAddress) ||
01775         (ControlPc >= UnwindFunctionEntry.PrologEndAddress)) {
01776         *InFunction = 
TRUE;
01777         ControlPc = (UnwindFunctionEntry.PrologEndAddress & (~(UINT_PTR)0x3));
01778 
01779     } 
else {
01780         *InFunction = 
FALSE;
01781     }
01782 
01783     
01784     
01785     
01786     
01787     
01788 
01789     DecrementRegister = ZERO_REG;
01790     NextPc = (ULONG_PTR)ContextRecord->IntRa - 4;
01791     RestoredRa = 
FALSE;
01792     RestoredSp = 
FALSE;
01793     
while (ControlPc > UnwindFunctionEntry.BeginAddress) {
01794 
01795         
01796         
01797         
01798         
01799         
01800         
01801 
01802         ControlPc -= 4;
01803         Instruction.Long = *((PULONG)ControlPc);
01804         Function = Instruction.OpReg.Function;
01805         Literal8 = Instruction.OpLit.Literal;
01806         Offset16 = Instruction.Memory.MemDisp;
01807         Opcode = Instruction.OpReg.Opcode;
01808         Ra = Instruction.OpReg.Ra;
01809         Rb = Instruction.OpReg.Rb;
01810         Rc = Instruction.OpReg.Rc;
01811 
01812         
01813         
01814         
01815         
01816         
01817         
01818 
01819         
switch (Opcode) {
01820 
01821         
case STQ_OP :
01822 
01823             
01824             
01825             
01826             
01827             
01828             
01829             
01830             
01831             
01832             
01833 
01834             
if ((Rb == SP_REG) && (Ra != ZERO_REG)) {
01835 
01836                 
01837                 
01838                 
01839                 
01840 
01841                 Address = Offset16 + (LONG_PTR)ContextRecord->IntSp;
01842                 IntegerRegister[Ra] = *((PULONGLONG)Address);
01843 
01844                 
01845                 
01846                 
01847                 
01848                 
01849                 
01850                 
01851                 
01852 
01853                 
if (Ra == RA_REG) {
01854                     
if (RestoredRa == 
FALSE) {
01855                         NextPc = (ULONG_PTR)ContextRecord->IntRa - 4;
01856                         RestoredRa = 
TRUE;
01857 
01858                     } 
else {
01859                         NextPc += 4;
01860                         
_RtlpFoundTrapFrame(NextPc);
01861                     }
01862 
01863                 
01864                 
01865                 
01866                 
01867                 
01868 
01869                 } 
else if ((Ra == SP_REG) && (RestoredSp == 
FALSE)) {
01870                     EstablisherFrame->Virtual = (ULONG_PTR)ContextRecord->IntSp;
01871                     EstablisherFrame->Real = (ULONG_PTR)ContextRecord->IntSp;
01872                     RestoredSp = 
TRUE;
01873                 }
01874 
01875                 
01876                 
01877                 
01878                 
01879                 
01880 
01881                 
if (ARGUMENT_PRESENT(ContextPointers)) {
01882                     ContextPointers->IntegerContext[Ra] = (PULONGLONG)Address;
01883                 }
01884                 
_RtlpDebugDisassemble(ControlPc, ContextRecord);
01885             }
01886             
break;
01887 
01888         
case LDAH_OP :
01889             Offset16 <<= 16;
01890 
01891         
case LDA_OP :
01892 
01893             
01894             
01895             
01896             
01897             
01898             
01899             
01900             
01901             
01902             
01903             
01904 
01905             
if (Ra == SP_REG) {
01906                 
if (Rb == SP_REG) {
01907 
01908                     
01909                     
01910                     
01911                     
01912                     
01913                     
01914                     
01915                     
01916                     
01917                     
01918                     
01919                     
01920                     
01921                     
01922                     
01923 
01924                     FrameSize = -Offset16;
01925                     
goto StackAllocation;
01926 
01927                 } 
else {
01928 
01929                     
01930                     
01931                     
01932                     
01933                     
01934                     
01935                     
01936                     
01937                     
01938                     
01939                     
01940                     
01941                     
01942                     
01943 
01944                     DecrementRegister = Rb;
01945                     DecrementOffset = Offset16;
01946                     
_RtlpDebugDisassemble(ControlPc, ContextRecord);
01947                 }
01948 
01949             } 
else if (Ra == DecrementRegister) {
01950                 
if (Rb == DecrementRegister) {
01951 
01952                     
01953                     
01954                     
01955                     
01956                     
01957                     
01958                     
01959                     
01960                     
01961                     
01962                     
01963                     
01964                     
01965                     
01966                     
01967 
01968                     DecrementOffset += Offset16;
01969                     
_RtlpDebugDisassemble(ControlPc, ContextRecord);
01970 
01971                 } 
else if (Rb == ZERO_REG) {
01972 
01973                     
01974                     
01975                     
01976                     
01977                     
01978                     
01979                     
01980                     
01981                     
01982                     
01983                     
01984                     
01985                     
01986                     
01987                     
01988                     
01989                     
01990                     
01991                     
01992 
01993                     FrameSize = (Offset16 + DecrementOffset);
01994                     
goto StackAllocation;
01995 
01996                 } 
else if (Rb == SP_REG) {
01997 
01998                     
01999                     
02000                     
02001                     
02002                     
02003                     
02004                     
02005                     
02006                     
02007                     
02008                     
02009                     
02010                     
02011 
02012                     FrameSize = -(Offset16 + (LONG)DecrementOffset);
02013                     
goto StackAllocation;
02014                 }
02015             }
02016             
break;
02017 
02018         
case ARITH_OP :
02019 
02020             
if ((Function == ADDQ_FUNC) &&
02021                 (Instruction.OpReg.RbvType != RBV_REGISTER_FORMAT)) {
02022 
02023                 
02024                 
02025                 
02026                 
02027                 
02028                 
02029                 
02030                 
02031                 
02032                 
02033                 
02034                 
02035                 
02036                 
02037                 
02038                 
02039 
02040                 
if ((Ra == ZERO_REG) && (Rc == DecrementRegister)) {
02041                     FrameSize = Literal8;
02042                     
goto StackAllocation;
02043                 }
02044 
02045             } 
else if ((Function == SUBQ_FUNC) &&
02046                        (Instruction.OpReg.RbvType == RBV_REGISTER_FORMAT)) {
02047 
02048                 
02049                 
02050                 
02051                 
02052                 
02053                 
02054                 
02055                 
02056                 
02057                 
02058                 
02059                 
02060                 
02061                 
02062                 
02063                 
02064                 
02065 
02066                 
if ((Ra == SP_REG) && (Rc == SP_REG)) {
02067                     DecrementRegister = Rb;
02068                     DecrementOffset = 0;
02069                     
_RtlpDebugDisassemble(ControlPc, ContextRecord);
02070                 }
02071             }
02072             
break;
02073 
02074         
case BIT_OP :
02075 
02076             
02077             
02078             
02079             
02080             
02081             
02082 
02083             
if ((Function == BIS_FUNC) && (Rc != ZERO_REG)) {
02084                 
if (Instruction.OpReg.RbvType == RBV_REGISTER_FORMAT) {
02085 
02086                     
02087                     
02088                     
02089                     
02090                     
02091                     
02092                     
02093                     
02094                     
02095                     
02096                     
02097                     
02098                     
02099                     
02100                     
02101                     
02102                     
02103                     
02104                     
02105 
02106                     
if (Ra == ZERO_REG) {
02107 
02108                         
02109                         
02110                         
02111 
02112                         Ra = Rb;
02113 
02114                     } 
else if (Rb == ZERO_REG) {
02115 
02116                         
02117                         
02118                         
02119 
02120                         Rb = Ra;
02121                     }
02122 
02123                     
if ((Ra == Rb) && (Ra != ZERO_REG)) {
02124                         IntegerRegister[Ra] = IntegerRegister[Rc];
02125 
02126                         
02127                         
02128                         
02129                         
02130                         
02131                         
02132                         
02133                         
02134                         
02135 
02136                         
if (Ra == RA_REG) {
02137                             
if (RestoredRa == 
FALSE) {
02138                                 NextPc = (ULONG_PTR)ContextRecord->IntRa - 4;
02139                                 RestoredRa = 
TRUE;
02140 
02141                             } 
else {
02142                                 NextPc += 4;
02143                                 
_RtlpFoundTrapFrame(NextPc);
02144                             }
02145 
02146                         
02147                         
02148                         
02149                         
02150                         
02151                         
02152 
02153                         } 
else if ((Ra == SP_REG) && (RestoredSp == 
FALSE)) {
02154                             EstablisherFrame->Virtual = (ULONG_PTR)ContextRecord->IntSp;
02155                             EstablisherFrame->Real = (ULONG_PTR)ContextRecord->IntSp;
02156                             RestoredSp = 
TRUE;
02157                         }
02158 
02159                         
_RtlpDebugDisassemble(ControlPc, ContextRecord);
02160                     }
02161 
02162                 } 
else {
02163 
02164                     
02165                     
02166                     
02167                     
02168                     
02169                     
02170                     
02171                     
02172                     
02173                     
02174                     
02175                     
02176                     
02177                     
02178                     
02179                     
02180 
02181                     
if ((Ra == ZERO_REG) && (Rc == DecrementRegister)) {
02182                         FrameSize = Literal8;
02183 StackAllocation:
02184                         
02185                         
02186                         
02187                         
02188                         
02189                         
02190 
02191                         ContextRecord->IntSp += FrameSize;
02192                         EstablisherFrame->Virtual = (ULONG_PTR)ContextRecord->IntSp;
02193                         DecrementRegister = ZERO_REG;
02194                         
_RtlpDebugDisassemble(ControlPc, ContextRecord);
02195                     }
02196                 }
02197             }
02198             
break;
02199 
02200         
case STT_OP :
02201 
02202             
02203             
02204             
02205             
02206             
02207             
02208             
02209             
02210             
02211             
02212 
02213             
if ((Rb == SP_REG) && (Ra != FZERO_REG)) {
02214 
02215                 
02216                 
02217                 
02218                 
02219 
02220                 Address = Offset16 + (LONG_PTR)ContextRecord->IntSp;
02221                 FloatingRegister[Ra] = *((PULONGLONG)Address);
02222 
02223                 
02224                 
02225                 
02226                 
02227                 
02228 
02229                 
if (ARGUMENT_PRESENT(ContextPointers)) {
02230                     ContextPointers->FloatingContext[Ra] = (PULONGLONG)Address;
02231                 }
02232                 
_RtlpDebugDisassemble(ControlPc, ContextRecord);
02233             }
02234             
break;
02235 
02236         
case FPOP_OP :
02237 
02238             
02239             
02240             
02241             
02242 
02243             
if (Instruction.FpOp.Function == CPYS_FUNC) {
02244 
02245                 
02246                 
02247                 
02248                 
02249                 
02250                 
02251                 
02252                 
02253                 
02254                 
02255                 
02256                 
02257 
02258                 
if ((Ra == Rb) && (Ra != FZERO_REG)) {
02259                     FloatingRegister[Ra] = FloatingRegister[Rc];
02260                     
_RtlpDebugDisassemble(ControlPc, ContextRecord);
02261                 }
02262             }
02263 
02264         
default :
02265             
break;
02266         }
02267     }
02268     
02269     
02270     
02271     
if (StackAdjust) {
02272         ContextRecord->IntSp += StackAdjust;
02273     }
02274 
02275     
if (FixedReturn != 0) {
02276         NextPc = FixedReturn;
02277     }
02278     
02279     
_RtlpVirtualUnwindExit(NextPc, ContextRecord, EstablisherFrame);
02280     
return NextPc;
02281 }
02282 
02283 ULONG_PTR
02284 RtlpVirtualUnwind (
02285     IN ULONG_PTR ControlPc,
02286     IN PRUNTIME_FUNCTION FunctionEntry,
02287     IN PCONTEXT ContextRecord,
02288     OUT PBOOLEAN InFunction,
02289     OUT PFRAME_POINTERS EstablisherFrame
02290     )
02291 
02292 
02293 
02294 
02295 
02296 
02297 
02298 
02299 
02300 
02301 
02302 
02303 
02304 
02305 
02306 
02307 
02308 
02309 
02310 
02311 
02312 
02313 
02314 
02315 
02316 
02317 
02318 
02319 
02320 
02321 
02322 
02323 
02324 
02325 
02326 
02327 
02328 
02329 
02330 
02331 
02332 
02333 
02334 
02335 
02336 
02337 
02338 
02339 
02340 
02341 
02342 
02343 
02344 {
02345 
02346     CONTEXT LocalContext;
02347 
02348     
02349     
02350     
02351     
02352     
02353 
02354     RtlMoveMemory((PVOID)&LocalContext, ContextRecord, 
sizeof(CONTEXT));
02355     
return RtlVirtualUnwind(ControlPc,
02356                             FunctionEntry,
02357                             &LocalContext,
02358                             InFunction,
02359                             EstablisherFrame,
02360                             
NULL);
02361 }
02362 
02363 PRUNTIME_FUNCTION
02364 RtlLookupDirectFunctionEntry (
02365     IN ULONG_PTR ControlPc
02366     )
02367 
02368 
02369 
02370 
02371 
02372 
02373 
02374 
02375 
02376 
02377 
02378 
02379 
02380 
02381 
02382 
02383 
02384 
02385 
02386 
02387 
02388 {
02389     PRUNTIME_FUNCTION FunctionEntry;
02390     BOOLEAN InImage;
02391 
02392     
02393     
02394     
02395 
02396     FunctionEntry = 
RtlLookupStaticFunctionEntry( ControlPc, &InImage );
02397 
02398 
#if !defined(NTOS_KERNEL_RUNTIME)
02399 
    
02400     
02401     
02402     
02403 
02404     
if (FunctionEntry == 
NULL && !InImage) {
02405 
02406         FunctionEntry = 
RtlLookupDynamicFunctionEntry( ControlPc );
02407 
02408     }
02409 
#endif
02410 
02411 
#if DBG
02412 
    if (RtlDebugFlags & RTL_DBG_FUNCTION_ENTRY) {
02413         
DbgPrint(
"RtlLookupDirectFunctionEntry: returning FunctionEntry = %p\n", FunctionEntry);
02414     }
02415 
#endif
02416 
02417     
return FunctionEntry;
02418 }
02419 
02420 PRUNTIME_FUNCTION
02421 RtlLookupStaticFunctionEntry(
02422     IN ULONG_PTR ControlPc,
02423     OUT PBOOLEAN InImage
02424     )
02425 
02426 
02427 
02428 
02429 
02430 
02431 
02432 
02433 
02434 
02435 
02436 
02437 
02438 
02439 
02440 
02441 
02442 
02443 
02444 
02445 
02446 
02447 
02448 
02449 {
02450     PRUNTIME_FUNCTION FunctionEntry;
02451     PRUNTIME_FUNCTION FunctionTable;
02452     ULONG SizeOfExceptionTable;
02453     LONG High;
02454     PVOID ImageBase;
02455     LONG Low;
02456     LONG Middle;
02457 
02458     
02459     
02460     
02461 
02462     ImageBase = 
RtlPcToFileHeader((PVOID)ControlPc, &ImageBase);
02463 
02464 
#if DBG
02465 
    if (RtlDebugFlags & RTL_DBG_FUNCTION_ENTRY) {
02466         
DbgPrint(
"RtlLookupStaticFunctionEntry(ControlPc = %p) ImageBase = %p\n",
02467                  ControlPc, ImageBase);
02468     }
02469 
#endif
02470 
02471     
02472     
02473     
02474     
02475 
02476     *InImage = (ImageBase != 
NULL);
02477     FunctionEntry = 
NULL;
02478     
if (ImageBase != 
NULL) {
02479         FunctionTable = (PRUNTIME_FUNCTION)
RtlImageDirectoryEntryToData(
02480                          ImageBase, 
TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION,
02481                          &SizeOfExceptionTable);
02482 
#if DBG
02483 
        if (RtlDebugFlags & RTL_DBG_FUNCTION_ENTRY_DETAIL) {
02484             
DbgPrint(
"RtlLookupStaticFunctionEntry: FunctionTable = %p, SizeOfExceptionTable = %lx\n",
02485                      FunctionTable, SizeOfExceptionTable);
02486         }
02487 
#endif
02488 
02489         
02490         
02491         
02492         
02493 
02494         
if (FunctionTable != 
NULL) {
02495 
02496             
02497             
02498             
02499 
02500             Low = 0;
02501             High = (SizeOfExceptionTable / 
sizeof(RUNTIME_FUNCTION)) - 1;
02502 
02503             
02504             
02505             
02506             
02507 
02508             
while (High >= Low) {
02509 
02510                 
02511                 
02512                 
02513                 
02514                 
02515                 
02516                 
02517 
02518                 Middle = (Low + High) >> 1;
02519                 FunctionEntry = &FunctionTable[Middle];
02520                 
if (ControlPc < RF_BEGIN_ADDRESS(FunctionEntry)) {
02521                     High = Middle - 1;
02522 
02523                 } 
else if (ControlPc >= RF_END_ADDRESS(FunctionEntry)) {
02524                     Low = Middle + 1;
02525 
02526                 } 
else {
02527                     
return FunctionEntry;
02528                 }
02529             } 
02530         } 
02531     } 
02532     
return NULL;
02533 }
02534 
02535 
VOID
02536 RtlGetUnwindFunctionEntry(
02537     IN ULONG_PTR ControlPc,
02538     IN PRUNTIME_FUNCTION FunctionEntry,
02539     OUT PRUNTIME_FUNCTION UnwindFunctionEntry,
02540     OUT PULONG StackAdjust,
02541     OUT PULONG_PTR FixedReturn
02542     )
02543 
02544 
02545 
02546 
02547 
02548 
02549 
02550 
02551 
02552 
02553 
02554 
02555 
02556 
02557 
02558 
02559 
02560 
02561 
02562 
02563 
02564 
02565 
02566 
02567 
02568 
02569 
02570 
02571 
02572 
02573 
02574 
02575 
02576 {
02577     ULONG EntryType = 0;
02578     PRUNTIME_FUNCTION SecondaryFunctionEntry = 
NULL;
02579     ULONG_PTR AlternateProlog;
02580 
02581     *FixedReturn = 0;
02582     *StackAdjust = 0;
02583     
02584     
02585     
02586 
02587     
if (FunctionEntry == 
NULL) {
02588 
#if DBG
02589 
        DbgPrint(
"\n****** Warning - Null function table entry for unwinding.\n");
02590 
#endif
02591 
        UnwindFunctionEntry->BeginAddress     = ControlPc;
02592         UnwindFunctionEntry->EndAddress       = ControlPc+4;
02593         UnwindFunctionEntry->ExceptionHandler = 
NULL;
02594         UnwindFunctionEntry->HandlerData      = 0;
02595         UnwindFunctionEntry->PrologEndAddress = ControlPc;
02596         
return;
02597     }
02598 
02599     
02600     
02601     
02602     
02603     
02604     
02605     
02606     
02607     
02608     
02609     
02610     
02611     
02612     
02613     
02614     
02615     
02616 
02617     
if ((ControlPc <  RF_BEGIN_ADDRESS(FunctionEntry)) ||
02618         (ControlPc >= RF_END_ADDRESS(FunctionEntry))) {
02619 
02620         
02621         
02622         
02623 
02624 
#if DBG
02625 
        if (RtlDebugFlags & RTL_DBG_FUNCTION_ENTRY) {
02626             
DbgPrint(
"\nGetUnwindFunctionEntry:RtlLookupDirectFunctionEntry(ControlPc=%lx)\n", ControlPc);
02627         }
02628 
#endif
02629 
        SecondaryFunctionEntry = 
RtlLookupDirectFunctionEntry( ControlPc );
02630 
02631         
if (SecondaryFunctionEntry) {
02632             
02633 
#if DBG
02634 
            ShowRuntimeFunction(SecondaryFunctionEntry, 
"GetUnwindFunctionEntry: LookupDirectFunctionEntry");
02635 
#endif
02636 
            
02637             
02638 
02639             
if ((ControlPc >= RF_END_ADDRESS(SecondaryFunctionEntry)-(RF_NULL_CONTEXT_COUNT(SecondaryFunctionEntry)*4)) &&
02640                 (ControlPc <  RF_END_ADDRESS(SecondaryFunctionEntry))) {
02641 
02642                 
02643                 
02644 
02645                 UnwindFunctionEntry->BeginAddress     = RF_BEGIN_ADDRESS(SecondaryFunctionEntry);
02646                 UnwindFunctionEntry->EndAddress       = RF_END_ADDRESS(SecondaryFunctionEntry);
02647                 UnwindFunctionEntry->ExceptionHandler = 0;
02648                 UnwindFunctionEntry->HandlerData      = 0;
02649                 UnwindFunctionEntry->PrologEndAddress = RF_BEGIN_ADDRESS(SecondaryFunctionEntry);
02650                 
return;
02651             }
02652             
02653             
if ((SecondaryFunctionEntry->PrologEndAddress < RF_BEGIN_ADDRESS(SecondaryFunctionEntry)) ||
02654                 (SecondaryFunctionEntry->PrologEndAddress > RF_END_ADDRESS(SecondaryFunctionEntry))) {
02655                 
02656                 
02657                 
02658 
02659                 
if (RF_PROLOG_END_ADDRESS(SecondaryFunctionEntry) != (ULONG_PTR)FunctionEntry) {
02660 
#if DBG
02661 
                    DbgPrint(
"RtlGetUnwindFunctionEntry: unexpected secondary function entry from RtlLookupDirectFunctionEntry\n");
02662 
#endif
02663 
                    SecondaryFunctionEntry = 
NULL;
02664                 }
02665             } 
else {
02666 
02667                 
02668                 
02669                 
02670                 
02671 
02672                 FunctionEntry = SecondaryFunctionEntry;
02673                 SecondaryFunctionEntry = 
NULL;
02674 
02675 
#if DBG
02676 
                if (!RF_FIXED_RETURN(FunctionEntry)) {
02677                 
DbgPrint(
"RtlGetUnwindFunctionEntry: unexpected primary function entry from RtlLookupDirectFunctionEntry\n");
02678                 }
02679 
#endif
02680 
            }
02681 
#if DBG
02682 
        } 
else {
02683             
DbgPrint(
"GetUnwindFunctionEntry: LookupDirectFunctionEntry returned NULL\n");
02684 
#endif
02685 
        }
02686         
02687     } 
else {
02688 
02689         
02690         
02691         
02692 
02693         
02694 
02695         
if ((ControlPc >= RF_END_ADDRESS(FunctionEntry)-(RF_NULL_CONTEXT_COUNT(FunctionEntry)*4)) &&
02696             (ControlPc <  RF_END_ADDRESS(FunctionEntry))) {
02697             
02698             
02699             
02700 
02701             UnwindFunctionEntry->BeginAddress     = RF_BEGIN_ADDRESS(FunctionEntry);
02702             UnwindFunctionEntry->EndAddress       = RF_END_ADDRESS(FunctionEntry);
02703             UnwindFunctionEntry->ExceptionHandler = 0;
02704             UnwindFunctionEntry->HandlerData      = 0;
02705             UnwindFunctionEntry->PrologEndAddress = RF_BEGIN_ADDRESS(FunctionEntry);
02706             
return;
02707         }
02708         
02709         
if ((FunctionEntry->PrologEndAddress < RF_BEGIN_ADDRESS(FunctionEntry)) ||
02710             (FunctionEntry->PrologEndAddress > RF_END_ADDRESS(FunctionEntry))) {
02711 
02712             SecondaryFunctionEntry = FunctionEntry;
02713             FunctionEntry = (PRUNTIME_FUNCTION)RF_PROLOG_END_ADDRESS(SecondaryFunctionEntry);
02714 
#if DBG
02715 
            DbgPrint(
"RtlGetUnwindFunctionEntry: received secondary function entry\n");
02716 
#endif
02717 
        }
02718     }
02719 
02720 
#if DBG
02721 
    if (ControlPc & 0x3) {
02722         
DbgPrint(
"RtlGetUnwindFunctionEntry: Warning - Invalid ControlPc %lx for unwinding.\n", ControlPc);
02723     } 
else if (RF_BEGIN_ADDRESS(FunctionEntry) >= RF_END_ADDRESS(FunctionEntry)) {
02724         ShowRuntimeFunction(FunctionEntry, 
"RtlGetUnwindFunctionEntry: Warning - BeginAddress < EndAddress.");
02725     } 
else if (FunctionEntry->PrologEndAddress < RF_BEGIN_ADDRESS(FunctionEntry)) {
02726         ShowRuntimeFunction(FunctionEntry, 
"RtlGetUnwindFunctionEntry: Warning - PrologEndAddress < BeginAddress.");
02727     } 
else if (FunctionEntry->PrologEndAddress > RF_END_ADDRESS(FunctionEntry)) {
02728         ShowRuntimeFunction(FunctionEntry, 
"RtlGetUnwindFunctionEntry: Warning - PrologEndAddress > EndAddress.");
02729     }
02730 
#endif
02731 
02732     
02733     
02734     
02735 
02736     
if (SecondaryFunctionEntry) {
02737 
02738         
02739 
02740         EntryType = RF_ENTRY_TYPE(SecondaryFunctionEntry);
02741 
02742         
if (EntryType == RF_NOT_CONTIGUOUS) {
02743             
02744             
02745             
02746             
02747             
02748             
02749     
02750             AlternateProlog = RF_ALT_PROLOG(SecondaryFunctionEntry);
02751     
02752             
if ((AlternateProlog >= RF_BEGIN_ADDRESS(SecondaryFunctionEntry)) &&
02753                 (AlternateProlog <  RF_END_ADDRESS(SecondaryFunctionEntry))) {
02754 
02755                 
02756                 
02757 
02758                 
if ((ControlPc >= RF_BEGIN_ADDRESS(SecondaryFunctionEntry)) &&
02759                     (ControlPc <  AlternateProlog)) {
02760 
02761                     UnwindFunctionEntry->BeginAddress     = RF_BEGIN_ADDRESS(SecondaryFunctionEntry);
02762                     UnwindFunctionEntry->EndAddress       = RF_END_ADDRESS(SecondaryFunctionEntry);
02763                     UnwindFunctionEntry->ExceptionHandler = 0;
02764                     UnwindFunctionEntry->HandlerData      = 0;
02765                     UnwindFunctionEntry->PrologEndAddress = AlternateProlog;
02766                     
return;
02767                 }
02768             }
02769 
02770             
02771             
02772             
02773         
02774         
02775         } 
else if (EntryType == RF_ALT_ENT_PROLOG) {
02776             
02777             
02778             
02779 
02780             UnwindFunctionEntry->BeginAddress     = RF_BEGIN_ADDRESS(SecondaryFunctionEntry);
02781             UnwindFunctionEntry->EndAddress       = RF_END_ADDRESS(SecondaryFunctionEntry);
02782             UnwindFunctionEntry->ExceptionHandler = 0;
02783             UnwindFunctionEntry->HandlerData      = 0;
02784             UnwindFunctionEntry->PrologEndAddress = RF_END_ADDRESS(UnwindFunctionEntry);
02785             
02786             
02787             
02788             AlternateProlog = RF_ALT_PROLOG(SecondaryFunctionEntry);
02789             
if (AlternateProlog >= UnwindFunctionEntry->BeginAddress &&
02790                 AlternateProlog <  UnwindFunctionEntry->EndAddress ) {
02791                 
02792                 UnwindFunctionEntry->PrologEndAddress = AlternateProlog;
02793             }
02794 
02795             
return;
02796         
02797         } 
else if (EntryType == RF_NULL_CONTEXT) {
02798 
02799             
02800             
02801             
02802 
02803             *StackAdjust = RF_STACK_ADJUST(SecondaryFunctionEntry);
02804             UnwindFunctionEntry->BeginAddress     = RF_BEGIN_ADDRESS(SecondaryFunctionEntry);
02805             UnwindFunctionEntry->EndAddress       = RF_END_ADDRESS(SecondaryFunctionEntry);
02806             UnwindFunctionEntry->ExceptionHandler = 0;
02807             UnwindFunctionEntry->HandlerData      = 0;
02808             UnwindFunctionEntry->PrologEndAddress = RF_BEGIN_ADDRESS(SecondaryFunctionEntry);
02809             
return;
02810         }
02811 
02812     }
02813     
02814     
02815     
02816     *UnwindFunctionEntry = *FunctionEntry;
02817     UnwindFunctionEntry->EndAddress = RF_END_ADDRESS(UnwindFunctionEntry);  
02818     
02819     
02820 
02821     
if (RF_IS_FIXED_RETURN(FunctionEntry)) {
02822         *FixedReturn = RF_FIXED_RETURN(FunctionEntry);
02823         UnwindFunctionEntry->ExceptionHandler = 0;
02824         UnwindFunctionEntry->HandlerData      = 0;
02825     }
02826 
02827     
02828     
02829 
02830     
if ((ControlPc >= RF_END_ADDRESS(FunctionEntry)-(RF_NULL_CONTEXT_COUNT(FunctionEntry)*4)) &&
02831         (ControlPc <  RF_END_ADDRESS(FunctionEntry))) {
02832 
02833         
02834         
02835         
02836 
02837         UnwindFunctionEntry->EndAddress       = RF_END_ADDRESS(FunctionEntry);
02838         UnwindFunctionEntry->ExceptionHandler = 0;
02839         UnwindFunctionEntry->HandlerData      = 0;
02840         UnwindFunctionEntry->PrologEndAddress = RF_BEGIN_ADDRESS(FunctionEntry);
02841     }
02842     
else {
02843         UnwindFunctionEntry->EndAddress       = RF_END_ADDRESS(FunctionEntry);
02844     }
02845 }
02846 
#if !defined(NTOS_KERNEL_RUNTIME)
02847 
02848 PLIST_ENTRY
02849 RtlGetFunctionTableListHead (
02850     VOID
02851     )
02852 
02853 
02854 
02855 
02856 
02857 
02858 
02859 
02860 
02861 
02862 
02863 
02864 {
02865     
return &
DynamicFunctionTable;
02866 }
02867 
02868 BOOLEAN
02869 RtlAddFunctionTable(
02870     IN PRUNTIME_FUNCTION FunctionTable,
02871     IN ULONG EntryCount
02872     )
02873 
02874 
02875 
02876 
02877 
02878 
02879 
02880 
02881 
02882 
02883 
02884 
02885 
02886 
02887 
02888 
02889 
02890 
02891 
02892 
02893 
02894 
02895 
02896 
02897 
02898 
02899 
02900 
02901 
02902 
02903 
02904 
02905 {
02906     PDYNAMIC_FUNCTION_TABLE pNew;
02907     PRUNTIME_FUNCTION FunctionEntry;
02908     ULONG i;
02909 
02910     
if (EntryCount == 0)
02911         
return FALSE;
02912 
02913     
02914     
02915     
02916 
02917     
if (
DynamicFunctionTable.Flink == 
NULL) {
02918        InitializeListHead(&
DynamicFunctionTable);
02919     }
02920 
02921     
02922     
02923     
02924 
02925     pNew = 
RtlAllocateHeap( RtlProcessHeap(), 0, 
sizeof(DYNAMIC_FUNCTION_TABLE) );
02926 
02927     
if (pNew != 
NULL) {
02928         pNew->FunctionTable = FunctionTable;
02929         pNew->EntryCount = EntryCount;
02930         NtQuerySystemTime( &pNew->TimeStamp );
02931 
02932         
02933         
02934         
02935         
02936 
02937         FunctionEntry = FunctionTable;
02938         pNew->MinimumAddress = RF_BEGIN_ADDRESS(FunctionEntry);
02939         pNew->MaximumAddress = RF_END_ADDRESS(FunctionEntry);
02940         pNew->Sorted = 
TRUE;
02941         FunctionEntry++;
02942 
02943         
for (i = 1; i < EntryCount; FunctionEntry++, i++) {
02944             
if (pNew->Sorted && FunctionEntry->BeginAddress < FunctionTable[i-1].BeginAddress) {
02945                 pNew->Sorted = 
FALSE;
02946             }
02947             
if (FunctionEntry->BeginAddress < pNew->MinimumAddress) {
02948                 pNew->MinimumAddress = RF_BEGIN_ADDRESS(FunctionEntry);
02949             }
02950             
if (FunctionEntry->EndAddress > pNew->MaximumAddress) {
02951                 pNew->MaximumAddress = RF_END_ADDRESS(FunctionEntry);
02952             }
02953         }
02954 
02955         
02956         
02957         
02958         
02959 
02960         RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
02961         InsertTailList((PLIST_ENTRY)&
DynamicFunctionTable, (PLIST_ENTRY)pNew);
02962         RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
02963 
02964         
return TRUE;
02965     } 
else {
02966         
return FALSE;
02967     }
02968 }
02969 
02970 BOOLEAN
02971 RtlDeleteFunctionTable (
02972     IN PRUNTIME_FUNCTION FunctionTable
02973     )
02974 {
02975 
02976 
02977 
02978 
02979 
02980 
02981 
02982 
02983 
02984 
02985 
02986 
02987 
02988 
02989 
02990 
02991 
02992 
02993 
02994     PDYNAMIC_FUNCTION_TABLE CurrentEntry;
02995     PLIST_ENTRY Head;
02996     PLIST_ENTRY Next;
02997     BOOLEAN 
Status = 
FALSE;
02998 
02999     RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
03000 
03001     
03002     
03003     
03004     
03005 
03006     Head = &
DynamicFunctionTable;
03007     
for (Next = Head->Blink; Next != Head; Next = Next->Blink) {
03008         CurrentEntry = CONTAINING_RECORD(Next,DYNAMIC_FUNCTION_TABLE,Links);
03009         
if (CurrentEntry->FunctionTable == FunctionTable) {
03010             RemoveEntryList((PLIST_ENTRY)CurrentEntry);
03011             
RtlFreeHeap( RtlProcessHeap(), 0, CurrentEntry );
03012             
Status = 
TRUE;
03013             
break;
03014         }
03015     }
03016 
03017     RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
03018     
return Status;
03019 }
03020 
03021 PRUNTIME_FUNCTION
03022 RtlLookupDynamicFunctionEntry(
03023     IN ULONG_PTR ControlPc
03024     )
03025 
03026 
03027 
03028 
03029 
03030 
03031 
03032 
03033 
03034 
03035 
03036 
03037 
03038 
03039 
03040 
03041 
03042 
03043 
03044 
03045 
03046 
03047 
03048 
03049 {
03050     PDYNAMIC_FUNCTION_TABLE CurrentEntry;
03051     PLIST_ENTRY Next,Head;
03052     PRUNTIME_FUNCTION FunctionTable;
03053     PRUNTIME_FUNCTION FunctionEntry;
03054     LONG High;
03055     LONG Low;
03056     LONG Middle;
03057 
03058     
if (
DynamicFunctionTable.Flink == 
NULL)
03059         
return NULL;
03060 
03061     
if (RtlTryEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock) ) {
03062 
03063         
03064         
03065         
03066         
03067 
03068         Head = &
DynamicFunctionTable;
03069         
for (Next = Head->Blink; Next != Head; Next = Next->Blink) {
03070             CurrentEntry = CONTAINING_RECORD(Next,DYNAMIC_FUNCTION_TABLE,Links);
03071             FunctionTable = CurrentEntry->FunctionTable;
03072 
03073             
03074             
03075             
03076 
03077             
if ((ControlPc >= CurrentEntry->MinimumAddress) &&
03078                 (ControlPc <  CurrentEntry->MaximumAddress) ) {
03079 
03080                 
03081 
03082                 
if (CurrentEntry->Sorted) {
03083 
03084                     
03085                     
03086                     
03087                     
03088 
03089                     Low = 0;
03090                     High = CurrentEntry->EntryCount -1 ;
03091                     
while (High >= Low) {
03092 
03093                         
03094                         
03095                         
03096                         
03097                         
03098                         
03099                         
03100 
03101                         Middle = (Low + High) >> 1;
03102                         FunctionEntry = &FunctionTable[Middle];
03103                         
if (ControlPc < RF_BEGIN_ADDRESS(FunctionEntry)) {
03104                             High = Middle - 1;
03105 
03106                         } 
else if (ControlPc >= RF_END_ADDRESS(FunctionEntry)) {
03107                             Low = Middle + 1;
03108 
03109                         } 
else {
03110 
#if DBG
03111 
                            ShowRuntimeFunction(FunctionEntry, 
"RtlLookupDynamicFunctionEntry: binary search" );
03112 
#endif
03113 
                            RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
03114                             
return FunctionEntry;
03115                         }
03116                     }
03117 
03118                 } 
else {    
03119 
03120                     PRUNTIME_FUNCTION LastFunctionEntry = &FunctionTable[CurrentEntry->EntryCount];
03121 
03122                     
for (FunctionEntry = FunctionTable; FunctionEntry < LastFunctionEntry; FunctionEntry++) {
03123                         
if ((ControlPc >= RF_BEGIN_ADDRESS(FunctionEntry)) &&
03124                             (ControlPc <  RF_END_ADDRESS(FunctionEntry))) {
03125 
#if DBG
03126 
                            ShowRuntimeFunction(FunctionEntry, 
"RtlLookupDynamicFunctionEntry: linear search" );
03127 
#endif
03128 
                            RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
03129                             
return FunctionEntry;
03130                         }
03131                     }
03132                 } 
03133             } 
03134         } 
03135 
03136         RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->
LoaderLock);
03137     } 
03138 
03139     
03140     
return NULL;
03141 }
03142 
#endif
03143 
#if DBG
03144 
03145 
void
03146 ShowRuntimeFunction( PRUNTIME_FUNCTION FunctionEntry, PSTR Label )
03147 {
03148     BOOLEAN Secondary;
03149     BOOLEAN FixedReturn;
03150     ULONG EntryType;
03151     ULONG NullCount;
03152     
03153     
if (!(RtlDebugFlags & RTL_DBG_FUNCTION_ENTRY_DETAIL)) {
03154         
return;
03155     }
03156     
03157     
if (FunctionEntry) {
03158         Secondary = 
FALSE;
03159         FixedReturn = 
FALSE;
03160         EntryType = 0;
03161         NullCount = 0;
03162         
03163         
DbgPrint(
"    %lx: %s\n", FunctionEntry, Label );
03164         
03165         
if ((RF_PROLOG_END_ADDRESS(FunctionEntry) < RF_BEGIN_ADDRESS(FunctionEntry)) ||
03166             (RF_PROLOG_END_ADDRESS(FunctionEntry) > RF_END_ADDRESS(FunctionEntry))) {
03167             Secondary = 
TRUE;
03168             EntryType = RF_ENTRY_TYPE(FunctionEntry);
03169         } 
else if (RF_IS_FIXED_RETURN(FunctionEntry)) {
03170             FixedReturn = 
TRUE;
03171         }
03172         NullCount = RF_NULL_CONTEXT_COUNT(FunctionEntry);
03173     
03174         
DbgPrint(
"    BeginAddress     = %lx\n", FunctionEntry->BeginAddress);
03175         
DbgPrint(
"    EndAddress       = %lx", FunctionEntry->EndAddress);
03176         
if (NullCount) {
03177             
DbgPrint(
" %d null-context instructions", NullCount);
03178         }
03179         
DbgPrint(
"\n");
03180         
DbgPrint(
"    ExceptionHandler = %lx", FunctionEntry->ExceptionHandler);
03181         
if (FunctionEntry->ExceptionHandler != 
NULL) {
03182             
if (Secondary) {
03183                 ULONG_PTR AlternateProlog = RF_ALT_PROLOG(FunctionEntry);
03184     
03185                 
switch( EntryType ) {
03186                 
case RF_NOT_CONTIGUOUS:
03187                 
case RF_ALT_ENT_PROLOG:
03188                     
03189                     
if ((AlternateProlog >= RF_BEGIN_ADDRESS(FunctionEntry)) &&
03190                         (AlternateProlog <= RF_END_ADDRESS(FunctionEntry))) {
03191                             
DbgPrint(
" alternate PrologEndAddress");
03192                     }
03193                     
break;
03194                 
case RF_NULL_CONTEXT:
03195                     
DbgPrint(
" stack adjustment");
03196                 
default:
03197                     
DbgPrint(
" invalid entry type");
03198                 }
03199             } 
else if (FixedReturn) {
03200                 
DbgPrint(
" fixed return address");
03201             }
03202         }
03203         
DbgPrint(
"\n");
03204         
DbgPrint(
"    HandlerData      = %lx", FunctionEntry->HandlerData);
03205         
if (Secondary) {
03206             
DbgPrint(
" type %d: ", EntryType);
03207             
if      (EntryType == RF_NOT_CONTIGUOUS) 
DbgPrint(
"RF_NOT_CONTIGUOUS");
03208             
else if (EntryType == RF_ALT_ENT_PROLOG) 
DbgPrint(
"RF_ALT_ENT_PROLOG");
03209             
else if (EntryType == RF_NULL_CONTEXT)   
DbgPrint(
"RF_NULL_CONTEXT");
03210             
else DbgPrint(
"***INVALID***");
03211         }
03212         
DbgPrint(
"\n");
03213         
DbgPrint(
"    PrologEndAddress = %lx\n",   FunctionEntry->PrologEndAddress );
03214     }
03215 }
03216 
#endif
03217