You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For frame chained functions, the fp and lr pair can be saved at any position in the local variable area depending on optimization considerations. The goal is to maximize the number of locals that can be reached by one single instruction based on frame pointer (r29) or stack pointer (sp). However for `alloca` functions, it must be chained and r29 must point to the bottom of stack. To allow for better register-pair-addressing-mode coverage, nonvolatile register aave areas are positioned at the top of the Local area stack. Here are examples that illustrate several of the most efficient prolog sequences. For the sake of clarity and better cache locality, the order of storing callee-saved registers in all canonical prologs is in "growing up" order. `#framesz` below represents the size of entire stack (excluding alloca area). `#localsz` and `#outsz` denote local area size (including the save area for the \<r29, lr> pair) and outgoing parameter size, respectively.
59
59
60
-
1.chained, #localsz <= 512
60
+
1.Chained, #localsz <= 512
61
61
62
62
```asm
63
63
stp r19,r20,[sp,-96]! // pre-indexed, save in 1st FP/INT pair
@@ -71,7 +71,7 @@ For frame chained functions, the fp and lr pair can be saved at any position in
71
71
sub sp, #outsz // (optional for #outsz != 0)
72
72
```
73
73
74
-
2. chained, #localsz > 512
74
+
2. Chained, #localsz > 512
75
75
76
76
```asm
77
77
stp r19,r20,[sp,-96]! // pre-indexed, save in 1st FP/INT pair
@@ -85,7 +85,7 @@ For frame chained functions, the fp and lr pair can be saved at any position in
85
85
add r29,sp, #outsz // setup r29 points to bottom of local area
86
86
```
87
87
88
-
3. unchained, leaf functions (lr unsaved)
88
+
3. Unchained, leaf functions (lr unsaved)
89
89
90
90
```asm
91
91
stp r19,r20,[sp, -72]! // pre-indexed, save in 1st FP/INT reg-pair
@@ -128,7 +128,7 @@ For frame chained functions, the fp and lr pair can be saved at any position in
128
128
sub sp,#framesz-16 // allocate the remaining local area
129
129
```
130
130
131
-
* The reg save area allocation is not folded into the stp because a pre-indexed reg-lr stp cannot be represented with the unwind codes.
131
+
\* The reg save area allocation is not folded into the stp because a pre-indexed reg-lr stp cannot be represented with the unwind codes.
132
132
133
133
All locals are accessed based on SP. \<r29> points to the previous frame.
134
134
@@ -157,7 +157,7 @@ For frame chained functions, the fp and lr pair can be saved at any position in
157
157
158
158
For optimization purpose, r29 can be put at any position in local area to provide a better coverage for "reg-pair" and pre-/post-indexed offset addressing mode. Locals below frame pointers can be accessed based on SP.
When ARM64 RFG is enabled (/d2rwg, /d2rfgfull) lr is encrypted before being stored on the stack and decrypted after being loaded from the stack. The actual encryption/decryption varies depending on the flavor of RFG.
186
-
187
-
### Example
188
-
189
-
```asm
190
-
sub sp,sp,#0x10
191
-
add lr,lr,x28 // add cookie reg to lr (start of encryption)
192
-
ror lr,lr,x28 // ror lr with cookie reg (encryption contd.)
193
-
eor lr,lr,x28 // eor lr with cookie reg (end of encryption)
194
-
stp x19,lr,[sp] // store x19, encrypted lr on the stack
195
-
...
196
-
...
197
-
ldp x19,lr,[sp] // load x19, encrypted lr from the stack
198
-
eor lr,lr,x28 // eor lr with cookie reg (start of decryption)
sub lr,lr,x28 // sub cookie reg from lr (end of decryption)
202
-
add sp,sp,#0x10
203
-
```
204
-
205
-
With the current implementation, functions which have rfg enabled are required to emit .xdata.
206
-
207
-
## ARM64 Exception Handling Information
208
-
209
-
### .pdata Records
185
+
### .pdata records
210
186
211
187
The .pdata records are an ordered array of fixed-length items which describe every stack-manipulating function in a PE binary. Note carefully the phrase "stack-manipulating": leaf functions which do not require any local storage and which do not need to save/restore non-volatile registers do not require a .pdata record; these should be explicitly omitted to save space. A unwind from one of these functions can simply get the return address from LR to move up to the caller.
212
188
@@ -224,7 +200,7 @@ The fields are as follows:
224
200
225
201
- **Packed Unwind Data** is a compressed description of the operations needed to unwind from a function, assuming a canonical form. In this case, no .xdata record is required.
226
202
227
-
### .xdata Records
203
+
### .xdata records
228
204
229
205
When the packed unwind format is insufficient to describe the unwinding of a function, a variable-length .xdata record must be created. The address of this record is stored in the second word of the .pdata record. The format of the .xdata is a packed variable-length set of words:
It should be noted that although the prolog and each epilog has its own index into the unwind codes, the table is shared between them, and it is entirely possible (and not altogether uncommon) that they can all share the same codes (see Example 2 in Appendix A below). Compiler writers should optimize for this case, in particular because the largest index that can be specified is 255, thus limiting the total number of unwind codes for a particular function.
296
272
297
-
### Unwind Codes
273
+
### Unwind codes
298
274
299
275
The array of unwind codes is pool of sequences that describe exactly how to undo the effects of the prolog, in the order in which the operations need to be undone. The unwind codes can be thought of as a mini instruction set, encoded as a string of bytes. When execution is complete, the return address to the calling function is in the lr register, and all non-volatile registers are restored to their values at the time the function was called.
0 commit comments