summaryrefslogtreecommitdiffstats
path: root/private/ntos/rtl/ppc/jumps.c
blob: 7613543182040b778982ba1cc95460e42f1ca28a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*++

Copyright (c) 1990  Microsoft Corporation

Module Name:

    jumps.c

Abstract:

    This module implements the C runtime library functions for set jump and
    long jump that are compatible with structured exception handling.

Author:

    David N. Cutler (davec) 15-Sep-1990

Environment:

    Any mode.

Revision History:

    Tom Wood  23-Aug-1994
    Add stack limit parameters to RtlVirtualUnwind.

--*/

#include "ntrtlp.h"
#include "setjmp.h"

VOID
longjmp (
    IN jmp_buf JumpBuffer,
    IN int ReturnValue
    )

/*++

Routine Description:

    This function executes a long jump operation by virtually unwinding to
    the caller of the corresponding call to set jump and then calling unwind
    to transfer control to the jump target.

Arguments:


    JumpBuffer - Supplies the address of a jump buffer that contains the
        virtual frame pointer and target address.

        N.B. This is an array of double to force quadword alignment.

    ReturnValue - Supplies the value that is to be returned to the caller
        of set jump.

Return Value:

    None.

--*/

{

    PULONG JumpArray;

    //
    // If the specified return value is zero, then set it to one.
    //

    if (ReturnValue == 0) {
        ReturnValue = 1;
    }

    //
    // Unwind to the caller of set jump and return the specified value.
    // There is no return from unwind.
    //

    JumpArray = (PULONG)&JumpBuffer[0];
    RtlUnwind((PVOID)JumpArray[0],
              (PVOID)JumpArray[1],
              NULL,
              (PVOID)ReturnValue);
}

int
setjmp (
    IN jmp_buf JumpBuffer
    )

/*++

Routine Description:

    This function performs a set jump operation by capturing the current
    context, virtualy unwinding to the caller of set jump, and returns zero
    to the caller.

Arguments:

    JumpBuffer - Supplies the address of a jump buffer to store the virtual
        frame pointer and target address of the caller.

        N.B. This is an array of double to force quadword alignment.

Return Value:

    A value of zero is returned.

--*/

{

    CONTEXT ContextRecord;
    ULONG EstablisherFrame;
    PRUNTIME_FUNCTION FunctionEntry;
    BOOLEAN InFunction;
    PULONG JumpArray;
    ULONG NextPc;

    //
    // Capture the current context, virtually unwind to the caller of set
    // jump, and return zero to the caller.
    //

    JumpArray = (PULONG)&JumpBuffer[0];
    RtlCaptureContext(&ContextRecord);
    NextPc = ContextRecord.Lr - 4;
    FunctionEntry = RtlLookupFunctionEntry(NextPc);
    NextPc = RtlVirtualUnwind(NextPc,
                              FunctionEntry,
                              &ContextRecord,
                              &InFunction,
                              &EstablisherFrame,
                              NULL,
                              0,
                              0xffffffff);

    JumpArray[1] = NextPc + 4;
    FunctionEntry = RtlLookupFunctionEntry(NextPc);
    NextPc = RtlVirtualUnwind(NextPc,
                              FunctionEntry,
                              &ContextRecord,
                              &InFunction,
                              &EstablisherFrame,
                              NULL,
                              0,
                              0xffffffff);

    JumpArray[0] = EstablisherFrame;
    return 0;
}