2 * DWARF unwinding routines
4 * Copyright 2009 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #ifndef __NTDLL_DWARF_H
22 #define __NTDLL_DWARF_H
24 #define WIN32_NO_STATUS
28 /***********************************************************************
29 * Definitions for Dwarf unwind tables
32 #define DW_CFA_advance_loc 0x40
33 #define DW_CFA_offset 0x80
34 #define DW_CFA_restore 0xc0
35 #define DW_CFA_nop 0x00
36 #define DW_CFA_set_loc 0x01
37 #define DW_CFA_advance_loc1 0x02
38 #define DW_CFA_advance_loc2 0x03
39 #define DW_CFA_advance_loc4 0x04
40 #define DW_CFA_offset_extended 0x05
41 #define DW_CFA_restore_extended 0x06
42 #define DW_CFA_undefined 0x07
43 #define DW_CFA_same_value 0x08
44 #define DW_CFA_register 0x09
45 #define DW_CFA_remember_state 0x0a
46 #define DW_CFA_restore_state 0x0b
47 #define DW_CFA_def_cfa 0x0c
48 #define DW_CFA_def_cfa_register 0x0d
49 #define DW_CFA_def_cfa_offset 0x0e
50 #define DW_CFA_def_cfa_expression 0x0f
51 #define DW_CFA_expression 0x10
52 #define DW_CFA_offset_extended_sf 0x11
53 #define DW_CFA_def_cfa_sf 0x12
54 #define DW_CFA_def_cfa_offset_sf 0x13
55 #define DW_CFA_val_offset 0x14
56 #define DW_CFA_val_offset_sf 0x15
57 #define DW_CFA_val_expression 0x16
59 #define DW_OP_addr 0x03
60 #define DW_OP_deref 0x06
61 #define DW_OP_const1u 0x08
62 #define DW_OP_const1s 0x09
63 #define DW_OP_const2u 0x0a
64 #define DW_OP_const2s 0x0b
65 #define DW_OP_const4u 0x0c
66 #define DW_OP_const4s 0x0d
67 #define DW_OP_const8u 0x0e
68 #define DW_OP_const8s 0x0f
69 #define DW_OP_constu 0x10
70 #define DW_OP_consts 0x11
71 #define DW_OP_dup 0x12
72 #define DW_OP_drop 0x13
73 #define DW_OP_over 0x14
74 #define DW_OP_pick 0x15
75 #define DW_OP_swap 0x16
76 #define DW_OP_rot 0x17
77 #define DW_OP_xderef 0x18
78 #define DW_OP_abs 0x19
79 #define DW_OP_and 0x1a
80 #define DW_OP_div 0x1b
81 #define DW_OP_minus 0x1c
82 #define DW_OP_mod 0x1d
83 #define DW_OP_mul 0x1e
84 #define DW_OP_neg 0x1f
85 #define DW_OP_not 0x20
87 #define DW_OP_plus 0x22
88 #define DW_OP_plus_uconst 0x23
89 #define DW_OP_shl 0x24
90 #define DW_OP_shr 0x25
91 #define DW_OP_shra 0x26
92 #define DW_OP_xor 0x27
93 #define DW_OP_bra 0x28
100 #define DW_OP_skip 0x2f
101 #define DW_OP_lit0 0x30
102 #define DW_OP_lit1 0x31
103 #define DW_OP_lit2 0x32
104 #define DW_OP_lit3 0x33
105 #define DW_OP_lit4 0x34
106 #define DW_OP_lit5 0x35
107 #define DW_OP_lit6 0x36
108 #define DW_OP_lit7 0x37
109 #define DW_OP_lit8 0x38
110 #define DW_OP_lit9 0x39
111 #define DW_OP_lit10 0x3a
112 #define DW_OP_lit11 0x3b
113 #define DW_OP_lit12 0x3c
114 #define DW_OP_lit13 0x3d
115 #define DW_OP_lit14 0x3e
116 #define DW_OP_lit15 0x3f
117 #define DW_OP_lit16 0x40
118 #define DW_OP_lit17 0x41
119 #define DW_OP_lit18 0x42
120 #define DW_OP_lit19 0x43
121 #define DW_OP_lit20 0x44
122 #define DW_OP_lit21 0x45
123 #define DW_OP_lit22 0x46
124 #define DW_OP_lit23 0x47
125 #define DW_OP_lit24 0x48
126 #define DW_OP_lit25 0x49
127 #define DW_OP_lit26 0x4a
128 #define DW_OP_lit27 0x4b
129 #define DW_OP_lit28 0x4c
130 #define DW_OP_lit29 0x4d
131 #define DW_OP_lit30 0x4e
132 #define DW_OP_lit31 0x4f
133 #define DW_OP_reg0 0x50
134 #define DW_OP_reg1 0x51
135 #define DW_OP_reg2 0x52
136 #define DW_OP_reg3 0x53
137 #define DW_OP_reg4 0x54
138 #define DW_OP_reg5 0x55
139 #define DW_OP_reg6 0x56
140 #define DW_OP_reg7 0x57
141 #define DW_OP_reg8 0x58
142 #define DW_OP_reg9 0x59
143 #define DW_OP_reg10 0x5a
144 #define DW_OP_reg11 0x5b
145 #define DW_OP_reg12 0x5c
146 #define DW_OP_reg13 0x5d
147 #define DW_OP_reg14 0x5e
148 #define DW_OP_reg15 0x5f
149 #define DW_OP_reg16 0x60
150 #define DW_OP_reg17 0x61
151 #define DW_OP_reg18 0x62
152 #define DW_OP_reg19 0x63
153 #define DW_OP_reg20 0x64
154 #define DW_OP_reg21 0x65
155 #define DW_OP_reg22 0x66
156 #define DW_OP_reg23 0x67
157 #define DW_OP_reg24 0x68
158 #define DW_OP_reg25 0x69
159 #define DW_OP_reg26 0x6a
160 #define DW_OP_reg27 0x6b
161 #define DW_OP_reg28 0x6c
162 #define DW_OP_reg29 0x6d
163 #define DW_OP_reg30 0x6e
164 #define DW_OP_reg31 0x6f
165 #define DW_OP_breg0 0x70
166 #define DW_OP_breg1 0x71
167 #define DW_OP_breg2 0x72
168 #define DW_OP_breg3 0x73
169 #define DW_OP_breg4 0x74
170 #define DW_OP_breg5 0x75
171 #define DW_OP_breg6 0x76
172 #define DW_OP_breg7 0x77
173 #define DW_OP_breg8 0x78
174 #define DW_OP_breg9 0x79
175 #define DW_OP_breg10 0x7a
176 #define DW_OP_breg11 0x7b
177 #define DW_OP_breg12 0x7c
178 #define DW_OP_breg13 0x7d
179 #define DW_OP_breg14 0x7e
180 #define DW_OP_breg15 0x7f
181 #define DW_OP_breg16 0x80
182 #define DW_OP_breg17 0x81
183 #define DW_OP_breg18 0x82
184 #define DW_OP_breg19 0x83
185 #define DW_OP_breg20 0x84
186 #define DW_OP_breg21 0x85
187 #define DW_OP_breg22 0x86
188 #define DW_OP_breg23 0x87
189 #define DW_OP_breg24 0x88
190 #define DW_OP_breg25 0x89
191 #define DW_OP_breg26 0x8a
192 #define DW_OP_breg27 0x8b
193 #define DW_OP_breg28 0x8c
194 #define DW_OP_breg29 0x8d
195 #define DW_OP_breg30 0x8e
196 #define DW_OP_breg31 0x8f
197 #define DW_OP_regx 0x90
198 #define DW_OP_fbreg 0x91
199 #define DW_OP_bregx 0x92
200 #define DW_OP_piece 0x93
201 #define DW_OP_deref_size 0x94
202 #define DW_OP_xderef_size 0x95
203 #define DW_OP_nop 0x96
204 #define DW_OP_push_object_address 0x97
205 #define DW_OP_call2 0x98
206 #define DW_OP_call4 0x99
207 #define DW_OP_call_ref 0x9a
208 #define DW_OP_form_tls_address 0x9b
209 #define DW_OP_call_frame_cfa 0x9c
210 #define DW_OP_bit_piece 0x9d
211 #define DW_OP_lo_user 0xe0
212 #define DW_OP_hi_user 0xff
213 #define DW_OP_GNU_push_tls_address 0xe0
214 #define DW_OP_GNU_uninit 0xf0
215 #define DW_OP_GNU_encoded_addr 0xf1
217 #define DW_EH_PE_native 0x00
218 #define DW_EH_PE_uleb128 0x01
219 #define DW_EH_PE_udata2 0x02
220 #define DW_EH_PE_udata4 0x03
221 #define DW_EH_PE_udata8 0x04
222 #define DW_EH_PE_sleb128 0x09
223 #define DW_EH_PE_sdata2 0x0a
224 #define DW_EH_PE_sdata4 0x0b
225 #define DW_EH_PE_sdata8 0x0c
226 #define DW_EH_PE_signed 0x08
227 #define DW_EH_PE_abs 0x00
228 #define DW_EH_PE_pcrel 0x10
229 #define DW_EH_PE_textrel 0x20
230 #define DW_EH_PE_datarel 0x30
231 #define DW_EH_PE_funcrel 0x40
232 #define DW_EH_PE_aligned 0x50
233 #define DW_EH_PE_indirect 0x80
234 #define DW_EH_PE_omit 0xff
236 #ifndef NTDLL_DWARF_H_NO_UNWINDER
238 struct dwarf_eh_bases
249 unsigned char version
;
250 unsigned char augmentation
[1];
256 unsigned int cie_offset
;
259 extern const struct dwarf_fde
*_Unwind_Find_FDE (void *, struct dwarf_eh_bases
*);
261 static unsigned char dwarf_get_u1( const unsigned char **p
)
266 static unsigned short dwarf_get_u2( const unsigned char **p
)
268 unsigned int ret
= (*p
)[0] | ((*p
)[1] << 8);
273 static unsigned int dwarf_get_u4( const unsigned char **p
)
275 unsigned int ret
= (*p
)[0] | ((*p
)[1] << 8) | ((*p
)[2] << 16) | ((*p
)[3] << 24);
280 static ULONG64
dwarf_get_u8( const unsigned char **p
)
282 ULONG64 low
= dwarf_get_u4( p
);
283 ULONG64 high
= dwarf_get_u4( p
);
284 return low
| (high
<< 32);
287 static ULONG_PTR
dwarf_get_uleb128( const unsigned char **p
)
290 unsigned int shift
= 0;
296 ret
|= (ULONG_PTR
)(byte
& 0x7f) << shift
;
299 } while (byte
& 0x80);
303 static LONG_PTR
dwarf_get_sleb128( const unsigned char **p
)
306 unsigned int shift
= 0;
312 ret
|= (ULONG_PTR
)(byte
& 0x7f) << shift
;
315 } while (byte
& 0x80);
317 if ((shift
< 8 * sizeof(ret
)) && (byte
& 0x40)) ret
|= -((ULONG_PTR
)1 << shift
);
321 static ULONG_PTR
dwarf_get_ptr( const unsigned char **p
, unsigned char encoding
, const struct dwarf_eh_bases
*bases
)
325 if (encoding
== DW_EH_PE_omit
) return 0;
327 switch (encoding
& 0x70)
333 base
= (ULONG_PTR
)*p
;
335 case DW_EH_PE_textrel
:
336 base
= (ULONG_PTR
)bases
->tbase
;
338 case DW_EH_PE_datarel
:
339 base
= (ULONG_PTR
)bases
->dbase
;
341 case DW_EH_PE_funcrel
:
342 base
= (ULONG_PTR
)bases
->func
;
344 case DW_EH_PE_aligned
:
345 base
= ((ULONG_PTR
)*p
+ 7) & ~7ul;
348 FIXME( "unsupported encoding %02x\n", encoding
);
352 switch (encoding
& 0x0f)
354 case DW_EH_PE_native
: base
+= dwarf_get_u8( p
); break;
355 case DW_EH_PE_uleb128
: base
+= dwarf_get_uleb128( p
); break;
356 case DW_EH_PE_udata2
: base
+= dwarf_get_u2( p
); break;
357 case DW_EH_PE_udata4
: base
+= dwarf_get_u4( p
); break;
358 case DW_EH_PE_udata8
: base
+= dwarf_get_u8( p
); break;
359 case DW_EH_PE_sleb128
: base
+= dwarf_get_sleb128( p
); break;
360 case DW_EH_PE_sdata2
: base
+= (signed short)dwarf_get_u2( p
); break;
361 case DW_EH_PE_sdata4
: base
+= (signed int)dwarf_get_u4( p
); break;
362 case DW_EH_PE_sdata8
: base
+= (LONG64
)dwarf_get_u8( p
); break;
364 FIXME( "unsupported encoding %02x\n", encoding
);
367 if (encoding
& DW_EH_PE_indirect
) base
= *(ULONG_PTR
*)base
;
373 RULE_UNSET
, /* not set at all */
374 RULE_UNDEFINED
, /* undefined value */
375 RULE_SAME
, /* same value as previous frame */
376 RULE_CFA_OFFSET
, /* stored at cfa offset */
377 RULE_OTHER_REG
, /* stored in other register */
378 RULE_EXPRESSION
, /* address specified by expression */
379 RULE_VAL_EXPRESSION
/* value specified by expression */
383 #define NB_FRAME_REGS 41
384 #elif defined(__aarch64__)
385 #define NB_FRAME_REGS 96
387 #error Unsupported architecture
389 #define MAX_SAVED_STATES 16
393 ULONG_PTR cfa_offset
;
394 unsigned char cfa_reg
;
395 enum reg_rule cfa_rule
;
396 enum reg_rule rules
[NB_FRAME_REGS
];
397 ULONG64 regs
[NB_FRAME_REGS
];
403 ULONG_PTR code_align
;
405 unsigned char retaddr_reg
;
406 unsigned char fde_encoding
;
407 unsigned char signal_frame
;
408 unsigned char state_sp
;
409 struct frame_state state
;
410 struct frame_state
*state_stack
;
413 static const char *dwarf_reg_names
[NB_FRAME_REGS
] =
416 /* 0-7 */ "%rax", "%rdx", "%rcx", "%rbx", "%rsi", "%rdi", "%rbp", "%rsp",
417 /* 8-16 */ "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "%rip",
418 /* 17-24 */ "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
419 /* 25-32 */ "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15",
420 /* 33-40 */ "%st0", "%st1", "%st2", "%st3", "%st4", "%st5", "%st6", "%st7"
421 #elif defined(__aarch64__)
422 /* 0-7 */ "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
423 /* 8-15 */ "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
424 /* 16-23 */ "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
425 /* 24-31 */ "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp",
426 /* 32-39 */ "pc", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
427 /* 40-47 */ NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
428 /* 48-55 */ NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
429 /* 56-63 */ NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
430 /* 64-71 */ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
431 /* 72-79 */ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
432 /* 80-87 */ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
433 /* 88-95 */ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
437 static BOOL
valid_reg( ULONG_PTR reg
)
439 if (reg
>= NB_FRAME_REGS
) FIXME( "unsupported reg %lx\n", reg
);
440 return (reg
< NB_FRAME_REGS
);
443 static void execute_cfa_instructions( const unsigned char *ptr
, const unsigned char *end
,
444 ULONG_PTR last_ip
, struct frame_info
*info
,
445 const struct dwarf_eh_bases
*bases
)
447 while (ptr
< end
&& info
->ip
< last_ip
+ info
->signal_frame
)
449 const unsigned char op
= *ptr
++;
455 case DW_CFA_advance_loc
:
457 ULONG_PTR offset
= (op
& 0x3f) * info
->code_align
;
458 TRACE( "%lx: DW_CFA_advance_loc %lu\n", info
->ip
, offset
);
464 ULONG_PTR reg
= op
& 0x3f;
465 LONG_PTR offset
= dwarf_get_uleb128( &ptr
) * info
->data_align
;
466 if (!valid_reg( reg
)) break;
467 TRACE( "%lx: DW_CFA_offset %s, %ld\n", info
->ip
, dwarf_reg_names
[reg
], offset
);
468 info
->state
.regs
[reg
] = offset
;
469 info
->state
.rules
[reg
] = RULE_CFA_OFFSET
;
474 ULONG_PTR reg
= op
& 0x3f;
475 if (!valid_reg( reg
)) break;
476 TRACE( "%lx: DW_CFA_restore %s\n", info
->ip
, dwarf_reg_names
[reg
] );
477 info
->state
.rules
[reg
] = RULE_UNSET
;
488 ULONG_PTR loc
= dwarf_get_ptr( &ptr
, info
->fde_encoding
, bases
);
489 TRACE( "%lx: DW_CFA_set_loc %lx\n", info
->ip
, loc
);
493 case DW_CFA_advance_loc1
:
495 ULONG_PTR offset
= *ptr
++ * info
->code_align
;
496 TRACE( "%lx: DW_CFA_advance_loc1 %lu\n", info
->ip
, offset
);
500 case DW_CFA_advance_loc2
:
502 ULONG_PTR offset
= dwarf_get_u2( &ptr
) * info
->code_align
;
503 TRACE( "%lx: DW_CFA_advance_loc2 %lu\n", info
->ip
, offset
);
507 case DW_CFA_advance_loc4
:
509 ULONG_PTR offset
= dwarf_get_u4( &ptr
) * info
->code_align
;
510 TRACE( "%lx: DW_CFA_advance_loc4 %lu\n", info
->ip
, offset
);
514 case DW_CFA_offset_extended
:
515 case DW_CFA_offset_extended_sf
:
517 ULONG_PTR reg
= dwarf_get_uleb128( &ptr
);
518 LONG_PTR offset
= (op
== DW_CFA_offset_extended
) ? dwarf_get_uleb128( &ptr
) * info
->data_align
519 : dwarf_get_sleb128( &ptr
) * info
->data_align
;
520 if (!valid_reg( reg
)) break;
521 TRACE( "%lx: DW_CFA_offset_extended %s, %ld\n", info
->ip
, dwarf_reg_names
[reg
], offset
);
522 info
->state
.regs
[reg
] = offset
;
523 info
->state
.rules
[reg
] = RULE_CFA_OFFSET
;
526 case DW_CFA_restore_extended
:
528 ULONG_PTR reg
= dwarf_get_uleb128( &ptr
);
529 if (!valid_reg( reg
)) break;
530 TRACE( "%lx: DW_CFA_restore_extended %s\n", info
->ip
, dwarf_reg_names
[reg
] );
531 info
->state
.rules
[reg
] = RULE_UNSET
;
534 case DW_CFA_undefined
:
536 ULONG_PTR reg
= dwarf_get_uleb128( &ptr
);
537 if (!valid_reg( reg
)) break;
538 TRACE( "%lx: DW_CFA_undefined %s\n", info
->ip
, dwarf_reg_names
[reg
] );
539 info
->state
.rules
[reg
] = RULE_UNDEFINED
;
542 case DW_CFA_same_value
:
544 ULONG_PTR reg
= dwarf_get_uleb128( &ptr
);
545 if (!valid_reg( reg
)) break;
546 TRACE( "%lx: DW_CFA_same_value %s\n", info
->ip
, dwarf_reg_names
[reg
] );
547 info
->state
.regs
[reg
] = reg
;
548 info
->state
.rules
[reg
] = RULE_SAME
;
551 case DW_CFA_register
:
553 ULONG_PTR reg
= dwarf_get_uleb128( &ptr
);
554 ULONG_PTR reg2
= dwarf_get_uleb128( &ptr
);
555 if (!valid_reg( reg
) || !valid_reg( reg2
)) break;
556 TRACE( "%lx: DW_CFA_register %s == %s\n", info
->ip
, dwarf_reg_names
[reg
], dwarf_reg_names
[reg2
] );
557 info
->state
.regs
[reg
] = reg2
;
558 info
->state
.rules
[reg
] = RULE_OTHER_REG
;
561 case DW_CFA_remember_state
:
562 TRACE( "%lx: DW_CFA_remember_state\n", info
->ip
);
563 if (info
->state_sp
>= MAX_SAVED_STATES
)
564 FIXME( "%lx: DW_CFA_remember_state too many nested saves\n", info
->ip
);
566 info
->state_stack
[info
->state_sp
++] = info
->state
;
568 case DW_CFA_restore_state
:
569 TRACE( "%lx: DW_CFA_restore_state\n", info
->ip
);
571 FIXME( "%lx: DW_CFA_restore_state without corresponding save\n", info
->ip
);
573 info
->state
= info
->state_stack
[--info
->state_sp
];
576 case DW_CFA_def_cfa_sf
:
578 ULONG_PTR reg
= dwarf_get_uleb128( &ptr
);
579 ULONG_PTR offset
= (op
== DW_CFA_def_cfa
) ? dwarf_get_uleb128( &ptr
)
580 : dwarf_get_sleb128( &ptr
) * info
->data_align
;
581 if (!valid_reg( reg
)) break;
582 TRACE( "%lx: DW_CFA_def_cfa %s, %lu\n", info
->ip
, dwarf_reg_names
[reg
], offset
);
583 info
->state
.cfa_reg
= reg
;
584 info
->state
.cfa_offset
= offset
;
585 info
->state
.cfa_rule
= RULE_CFA_OFFSET
;
588 case DW_CFA_def_cfa_register
:
590 ULONG_PTR reg
= dwarf_get_uleb128( &ptr
);
591 if (!valid_reg( reg
)) break;
592 TRACE( "%lx: DW_CFA_def_cfa_register %s\n", info
->ip
, dwarf_reg_names
[reg
] );
593 info
->state
.cfa_reg
= reg
;
594 info
->state
.cfa_rule
= RULE_CFA_OFFSET
;
597 case DW_CFA_def_cfa_offset
:
598 case DW_CFA_def_cfa_offset_sf
:
600 ULONG_PTR offset
= (op
== DW_CFA_def_cfa_offset
) ? dwarf_get_uleb128( &ptr
)
601 : dwarf_get_sleb128( &ptr
) * info
->data_align
;
602 TRACE( "%lx: DW_CFA_def_cfa_offset %lu\n", info
->ip
, offset
);
603 info
->state
.cfa_offset
= offset
;
604 info
->state
.cfa_rule
= RULE_CFA_OFFSET
;
607 case DW_CFA_def_cfa_expression
:
609 ULONG_PTR expr
= (ULONG_PTR
)ptr
;
610 ULONG_PTR len
= dwarf_get_uleb128( &ptr
);
611 TRACE( "%lx: DW_CFA_def_cfa_expression %lx-%lx\n", info
->ip
, expr
, expr
+len
);
612 info
->state
.cfa_offset
= expr
;
613 info
->state
.cfa_rule
= RULE_VAL_EXPRESSION
;
617 case DW_CFA_expression
:
618 case DW_CFA_val_expression
:
620 ULONG_PTR reg
= dwarf_get_uleb128( &ptr
);
621 ULONG_PTR expr
= (ULONG_PTR
)ptr
;
622 ULONG_PTR len
= dwarf_get_uleb128( &ptr
);
623 if (!valid_reg( reg
)) break;
624 TRACE( "%lx: DW_CFA_%sexpression %s %lx-%lx\n",
625 info
->ip
, (op
== DW_CFA_expression
) ? "" : "val_", dwarf_reg_names
[reg
], expr
, expr
+len
);
626 info
->state
.regs
[reg
] = expr
;
627 info
->state
.rules
[reg
] = (op
== DW_CFA_expression
) ? RULE_EXPRESSION
: RULE_VAL_EXPRESSION
;
632 FIXME( "%lx: unknown CFA opcode %02x\n", info
->ip
, op
);
638 /* retrieve a context register from its dwarf number */
639 static void *get_context_reg( CONTEXT
*context
, ULONG_PTR dw_reg
)
644 case 0: return &context
->Rax
;
645 case 1: return &context
->Rdx
;
646 case 2: return &context
->Rcx
;
647 case 3: return &context
->Rbx
;
648 case 4: return &context
->Rsi
;
649 case 5: return &context
->Rdi
;
650 case 6: return &context
->Rbp
;
651 case 7: return &context
->Rsp
;
652 case 8: return &context
->R8
;
653 case 9: return &context
->R9
;
654 case 10: return &context
->R10
;
655 case 11: return &context
->R11
;
656 case 12: return &context
->R12
;
657 case 13: return &context
->R13
;
658 case 14: return &context
->R14
;
659 case 15: return &context
->R15
;
660 case 16: return &context
->Rip
;
661 case 17: return &context
->Xmm0
;
662 case 18: return &context
->Xmm1
;
663 case 19: return &context
->Xmm2
;
664 case 20: return &context
->Xmm3
;
665 case 21: return &context
->Xmm4
;
666 case 22: return &context
->Xmm5
;
667 case 23: return &context
->Xmm6
;
668 case 24: return &context
->Xmm7
;
669 case 25: return &context
->Xmm8
;
670 case 26: return &context
->Xmm9
;
671 case 27: return &context
->Xmm10
;
672 case 28: return &context
->Xmm11
;
673 case 29: return &context
->Xmm12
;
674 case 30: return &context
->Xmm13
;
675 case 31: return &context
->Xmm14
;
676 case 32: return &context
->Xmm15
;
677 case 33: return &context
->Legacy
[0];
678 case 34: return &context
->Legacy
[1];
679 case 35: return &context
->Legacy
[2];
680 case 36: return &context
->Legacy
[3];
681 case 37: return &context
->Legacy
[4];
682 case 38: return &context
->Legacy
[5];
683 case 39: return &context
->Legacy
[6];
684 case 40: return &context
->Legacy
[7];
685 #elif defined(__aarch64__)
686 case 0: return &context
->X0
;
687 case 1: return &context
->X1
;
688 case 2: return &context
->X2
;
689 case 3: return &context
->X3
;
690 case 4: return &context
->X4
;
691 case 5: return &context
->X5
;
692 case 6: return &context
->X6
;
693 case 7: return &context
->X7
;
694 case 8: return &context
->X8
;
695 case 9: return &context
->X9
;
696 case 10: return &context
->X10
;
697 case 11: return &context
->X11
;
698 case 12: return &context
->X12
;
699 case 13: return &context
->X13
;
700 case 14: return &context
->X14
;
701 case 15: return &context
->X15
;
702 case 16: return &context
->X16
;
703 case 17: return &context
->X17
;
704 case 18: return &context
->X18
;
705 case 19: return &context
->X19
;
706 case 20: return &context
->X20
;
707 case 21: return &context
->X21
;
708 case 22: return &context
->X22
;
709 case 23: return &context
->X23
;
710 case 24: return &context
->X24
;
711 case 25: return &context
->X25
;
712 case 26: return &context
->X26
;
713 case 27: return &context
->X27
;
714 case 28: return &context
->X28
;
715 case 29: return &context
->Fp
;
716 case 30: return &context
->Lr
;
717 case 31: return &context
->Sp
;
718 case 32: return &context
->Pc
;
751 return &context
->V
[dw_reg
- 64];
753 default: return NULL
;
757 /* set a context register from its dwarf number */
758 static void set_context_reg( CONTEXT
*context
, ULONG_PTR dw_reg
, void *val
)
763 case 0: context
->Rax
= *(ULONG64
*)val
; break;
764 case 1: context
->Rdx
= *(ULONG64
*)val
; break;
765 case 2: context
->Rcx
= *(ULONG64
*)val
; break;
766 case 3: context
->Rbx
= *(ULONG64
*)val
; break;
767 case 4: context
->Rsi
= *(ULONG64
*)val
; break;
768 case 5: context
->Rdi
= *(ULONG64
*)val
; break;
769 case 6: context
->Rbp
= *(ULONG64
*)val
; break;
770 case 7: context
->Rsp
= *(ULONG64
*)val
; break;
771 case 8: context
->R8
= *(ULONG64
*)val
; break;
772 case 9: context
->R9
= *(ULONG64
*)val
; break;
773 case 10: context
->R10
= *(ULONG64
*)val
; break;
774 case 11: context
->R11
= *(ULONG64
*)val
; break;
775 case 12: context
->R12
= *(ULONG64
*)val
; break;
776 case 13: context
->R13
= *(ULONG64
*)val
; break;
777 case 14: context
->R14
= *(ULONG64
*)val
; break;
778 case 15: context
->R15
= *(ULONG64
*)val
; break;
779 case 16: context
->Rip
= *(ULONG64
*)val
; break;
780 case 17: memcpy( &context
->Xmm0
, val
, sizeof(M128A
) ); break;
781 case 18: memcpy( &context
->Xmm1
, val
, sizeof(M128A
) ); break;
782 case 19: memcpy( &context
->Xmm2
, val
, sizeof(M128A
) ); break;
783 case 20: memcpy( &context
->Xmm3
, val
, sizeof(M128A
) ); break;
784 case 21: memcpy( &context
->Xmm4
, val
, sizeof(M128A
) ); break;
785 case 22: memcpy( &context
->Xmm5
, val
, sizeof(M128A
) ); break;
786 case 23: memcpy( &context
->Xmm6
, val
, sizeof(M128A
) ); break;
787 case 24: memcpy( &context
->Xmm7
, val
, sizeof(M128A
) ); break;
788 case 25: memcpy( &context
->Xmm8
, val
, sizeof(M128A
) ); break;
789 case 26: memcpy( &context
->Xmm9
, val
, sizeof(M128A
) ); break;
790 case 27: memcpy( &context
->Xmm10
, val
, sizeof(M128A
) ); break;
791 case 28: memcpy( &context
->Xmm11
, val
, sizeof(M128A
) ); break;
792 case 29: memcpy( &context
->Xmm12
, val
, sizeof(M128A
) ); break;
793 case 30: memcpy( &context
->Xmm13
, val
, sizeof(M128A
) ); break;
794 case 31: memcpy( &context
->Xmm14
, val
, sizeof(M128A
) ); break;
795 case 32: memcpy( &context
->Xmm15
, val
, sizeof(M128A
) ); break;
796 case 33: memcpy( &context
->Legacy
[0], val
, sizeof(M128A
) ); break;
797 case 34: memcpy( &context
->Legacy
[1], val
, sizeof(M128A
) ); break;
798 case 35: memcpy( &context
->Legacy
[2], val
, sizeof(M128A
) ); break;
799 case 36: memcpy( &context
->Legacy
[3], val
, sizeof(M128A
) ); break;
800 case 37: memcpy( &context
->Legacy
[4], val
, sizeof(M128A
) ); break;
801 case 38: memcpy( &context
->Legacy
[5], val
, sizeof(M128A
) ); break;
802 case 39: memcpy( &context
->Legacy
[6], val
, sizeof(M128A
) ); break;
803 case 40: memcpy( &context
->Legacy
[7], val
, sizeof(M128A
) ); break;
804 #elif defined(__aarch64__)
805 case 0: context
->X0
= *(DWORD64
*)val
; break;
806 case 1: context
->X1
= *(DWORD64
*)val
; break;
807 case 2: context
->X2
= *(DWORD64
*)val
; break;
808 case 3: context
->X3
= *(DWORD64
*)val
; break;
809 case 4: context
->X4
= *(DWORD64
*)val
; break;
810 case 5: context
->X5
= *(DWORD64
*)val
; break;
811 case 6: context
->X6
= *(DWORD64
*)val
; break;
812 case 7: context
->X7
= *(DWORD64
*)val
; break;
813 case 8: context
->X8
= *(DWORD64
*)val
; break;
814 case 9: context
->X9
= *(DWORD64
*)val
; break;
815 case 10: context
->X10
= *(DWORD64
*)val
; break;
816 case 11: context
->X11
= *(DWORD64
*)val
; break;
817 case 12: context
->X12
= *(DWORD64
*)val
; break;
818 case 13: context
->X13
= *(DWORD64
*)val
; break;
819 case 14: context
->X14
= *(DWORD64
*)val
; break;
820 case 15: context
->X15
= *(DWORD64
*)val
; break;
821 case 16: context
->X16
= *(DWORD64
*)val
; break;
822 case 17: context
->X17
= *(DWORD64
*)val
; break;
823 case 18: context
->X18
= *(DWORD64
*)val
; break;
824 case 19: context
->X19
= *(DWORD64
*)val
; break;
825 case 20: context
->X20
= *(DWORD64
*)val
; break;
826 case 21: context
->X21
= *(DWORD64
*)val
; break;
827 case 22: context
->X22
= *(DWORD64
*)val
; break;
828 case 23: context
->X23
= *(DWORD64
*)val
; break;
829 case 24: context
->X24
= *(DWORD64
*)val
; break;
830 case 25: context
->X25
= *(DWORD64
*)val
; break;
831 case 26: context
->X26
= *(DWORD64
*)val
; break;
832 case 27: context
->X27
= *(DWORD64
*)val
; break;
833 case 28: context
->X28
= *(DWORD64
*)val
; break;
834 case 29: context
->Fp
= *(DWORD64
*)val
; break;
835 case 30: context
->Lr
= *(DWORD64
*)val
; break;
836 case 31: context
->Sp
= *(DWORD64
*)val
; break;
837 case 32: context
->Pc
= *(DWORD64
*)val
; break;
870 memcpy( &context
->V
[dw_reg
- 64], val
, sizeof(ARM64_NT_NEON128
) );
876 static ULONG_PTR
eval_expression( const unsigned char *p
, CONTEXT
*context
,
877 const struct dwarf_eh_bases
*bases
)
879 ULONG_PTR reg
, tmp
, stack
[64];
881 ULONG_PTR len
= dwarf_get_uleb128(&p
);
882 const unsigned char *end
= p
+ len
;
886 unsigned char opcode
= dwarf_get_u1(&p
);
888 if (opcode
>= DW_OP_lit0
&& opcode
<= DW_OP_lit31
)
889 stack
[++sp
] = opcode
- DW_OP_lit0
;
890 else if (opcode
>= DW_OP_reg0
&& opcode
<= DW_OP_reg31
)
891 stack
[++sp
] = *(ULONG_PTR
*)get_context_reg( context
, opcode
- DW_OP_reg0
);
892 else if (opcode
>= DW_OP_breg0
&& opcode
<= DW_OP_breg31
)
893 stack
[++sp
] = *(ULONG_PTR
*)get_context_reg( context
, opcode
- DW_OP_breg0
) + dwarf_get_sleb128(&p
);
896 case DW_OP_nop
: break;
897 case DW_OP_addr
: stack
[++sp
] = dwarf_get_u8(&p
); break;
898 case DW_OP_const1u
: stack
[++sp
] = dwarf_get_u1(&p
); break;
899 case DW_OP_const1s
: stack
[++sp
] = (signed char)dwarf_get_u1(&p
); break;
900 case DW_OP_const2u
: stack
[++sp
] = dwarf_get_u2(&p
); break;
901 case DW_OP_const2s
: stack
[++sp
] = (short)dwarf_get_u2(&p
); break;
902 case DW_OP_const4u
: stack
[++sp
] = dwarf_get_u4(&p
); break;
903 case DW_OP_const4s
: stack
[++sp
] = (signed int)dwarf_get_u4(&p
); break;
904 case DW_OP_const8u
: stack
[++sp
] = dwarf_get_u8(&p
); break;
905 case DW_OP_const8s
: stack
[++sp
] = (LONG_PTR
)dwarf_get_u8(&p
); break;
906 case DW_OP_constu
: stack
[++sp
] = dwarf_get_uleb128(&p
); break;
907 case DW_OP_consts
: stack
[++sp
] = dwarf_get_sleb128(&p
); break;
908 case DW_OP_deref
: stack
[sp
] = *(ULONG_PTR
*)stack
[sp
]; break;
909 case DW_OP_dup
: stack
[sp
+ 1] = stack
[sp
]; sp
++; break;
910 case DW_OP_drop
: sp
--; break;
911 case DW_OP_over
: stack
[sp
+ 1] = stack
[sp
- 1]; sp
++; break;
912 case DW_OP_pick
: stack
[sp
+ 1] = stack
[sp
- dwarf_get_u1(&p
)]; sp
++; break;
913 case DW_OP_swap
: tmp
= stack
[sp
]; stack
[sp
] = stack
[sp
-1]; stack
[sp
-1] = tmp
; break;
914 case DW_OP_rot
: tmp
= stack
[sp
]; stack
[sp
] = stack
[sp
-1]; stack
[sp
-1] = stack
[sp
-2]; stack
[sp
-2] = tmp
; break;
915 case DW_OP_abs
: stack
[sp
] = labs(stack
[sp
]); break;
916 case DW_OP_neg
: stack
[sp
] = -stack
[sp
]; break;
917 case DW_OP_not
: stack
[sp
] = ~stack
[sp
]; break;
918 case DW_OP_and
: stack
[sp
-1] &= stack
[sp
]; sp
--; break;
919 case DW_OP_or
: stack
[sp
-1] |= stack
[sp
]; sp
--; break;
920 case DW_OP_minus
: stack
[sp
-1] -= stack
[sp
]; sp
--; break;
921 case DW_OP_mul
: stack
[sp
-1] *= stack
[sp
]; sp
--; break;
922 case DW_OP_plus
: stack
[sp
-1] += stack
[sp
]; sp
--; break;
923 case DW_OP_xor
: stack
[sp
-1] ^= stack
[sp
]; sp
--; break;
924 case DW_OP_shl
: stack
[sp
-1] <<= stack
[sp
]; sp
--; break;
925 case DW_OP_shr
: stack
[sp
-1] >>= stack
[sp
]; sp
--; break;
926 case DW_OP_plus_uconst
: stack
[sp
] += dwarf_get_uleb128(&p
); break;
927 case DW_OP_shra
: stack
[sp
-1] = (LONG_PTR
)stack
[sp
-1] / (1 << stack
[sp
]); sp
--; break;
928 case DW_OP_div
: stack
[sp
-1] = (LONG_PTR
)stack
[sp
-1] / (LONG_PTR
)stack
[sp
]; sp
--; break;
929 case DW_OP_mod
: stack
[sp
-1] = (LONG_PTR
)stack
[sp
-1] % (LONG_PTR
)stack
[sp
]; sp
--; break;
930 case DW_OP_ge
: stack
[sp
-1] = ((LONG_PTR
)stack
[sp
-1] >= (LONG_PTR
)stack
[sp
]); sp
--; break;
931 case DW_OP_gt
: stack
[sp
-1] = ((LONG_PTR
)stack
[sp
-1] > (LONG_PTR
)stack
[sp
]); sp
--; break;
932 case DW_OP_le
: stack
[sp
-1] = ((LONG_PTR
)stack
[sp
-1] <= (LONG_PTR
)stack
[sp
]); sp
--; break;
933 case DW_OP_lt
: stack
[sp
-1] = ((LONG_PTR
)stack
[sp
-1] < (LONG_PTR
)stack
[sp
]); sp
--; break;
934 case DW_OP_eq
: stack
[sp
-1] = (stack
[sp
-1] == stack
[sp
]); sp
--; break;
935 case DW_OP_ne
: stack
[sp
-1] = (stack
[sp
-1] != stack
[sp
]); sp
--; break;
936 case DW_OP_skip
: tmp
= (short)dwarf_get_u2(&p
); p
+= tmp
; break;
937 case DW_OP_bra
: tmp
= (short)dwarf_get_u2(&p
); if (!stack
[sp
--]) { p
+= tmp
; } break;
938 case DW_OP_GNU_encoded_addr
: tmp
= *p
++; stack
[++sp
] = dwarf_get_ptr( &p
, tmp
, bases
); break;
939 case DW_OP_regx
: stack
[++sp
] = *(ULONG_PTR
*)get_context_reg( context
, dwarf_get_uleb128(&p
) ); break;
941 reg
= dwarf_get_uleb128(&p
);
942 tmp
= dwarf_get_sleb128(&p
);
943 stack
[++sp
] = *(ULONG_PTR
*)get_context_reg( context
, reg
) + tmp
;
945 case DW_OP_deref_size
:
948 case 1: stack
[sp
] = *(unsigned char *)stack
[sp
]; break;
949 case 2: stack
[sp
] = *(unsigned short *)stack
[sp
]; break;
950 case 4: stack
[sp
] = *(unsigned int *)stack
[sp
]; break;
951 case 8: stack
[sp
] = *(ULONG_PTR
*)stack
[sp
]; break;
955 FIXME( "unhandled opcode %02x\n", opcode
);
961 /* apply the computed frame info to the actual context */
962 static void apply_frame_state( CONTEXT
*context
, struct frame_state
*state
,
963 const struct dwarf_eh_bases
*bases
)
966 ULONG_PTR cfa
, value
;
967 CONTEXT new_context
= *context
;
969 switch (state
->cfa_rule
)
971 case RULE_EXPRESSION
:
972 cfa
= *(ULONG_PTR
*)eval_expression( (const unsigned char *)state
->cfa_offset
, context
, bases
);
974 case RULE_VAL_EXPRESSION
:
975 cfa
= eval_expression( (const unsigned char *)state
->cfa_offset
, context
, bases
);
978 cfa
= *(ULONG_PTR
*)get_context_reg( context
, state
->cfa_reg
) + state
->cfa_offset
;
983 for (i
= 0; i
< NB_FRAME_REGS
; i
++)
985 switch (state
->rules
[i
])
991 case RULE_CFA_OFFSET
:
992 set_context_reg( &new_context
, i
, (char *)cfa
+ state
->regs
[i
] );
995 set_context_reg( &new_context
, i
, get_context_reg( context
, state
->regs
[i
] ));
997 case RULE_EXPRESSION
:
998 value
= eval_expression( (const unsigned char *)state
->regs
[i
], context
, bases
);
999 set_context_reg( &new_context
, i
, (void *)value
);
1001 case RULE_VAL_EXPRESSION
:
1002 value
= eval_expression( (const unsigned char *)state
->regs
[i
], context
, bases
);
1003 set_context_reg( &new_context
, i
, &value
);
1008 new_context
.Rsp
= cfa
;
1009 #elif defined(__aarch64__)
1010 new_context
.Sp
= cfa
;
1012 *context
= new_context
;
1015 #endif /* NTDLL_DWARF_H_NO_UNWINDER */
1017 #if defined(__i386__)
1019 #define DW_OP_ecx DW_OP_breg1
1020 #define DW_OP_ebx DW_OP_breg3
1021 #define DW_OP_esp DW_OP_breg4
1022 #define DW_OP_ebp DW_OP_breg5
1024 #define DW_REG_eax 0x00
1025 #define DW_REG_ecx 0x01
1026 #define DW_REG_edx 0x02
1027 #define DW_REG_ebx 0x03
1028 #define DW_REG_esp 0x04
1029 #define DW_REG_ebp 0x05
1030 #define DW_REG_esi 0x06
1031 #define DW_REG_edi 0x07
1032 #define DW_REG_eip 0x08
1034 #elif defined(__x86_64__)
1036 #define DW_OP_rcx DW_OP_breg2
1037 #define DW_OP_rbp DW_OP_breg6
1038 #define DW_OP_rsp DW_OP_breg7
1040 #define DW_REG_rbx 0x03
1041 #define DW_REG_rsi 0x04
1042 #define DW_REG_rdi 0x05
1043 #define DW_REG_rbp 0x06
1044 #define DW_REG_rsp 0x07
1045 #define DW_REG_r12 0x0c
1046 #define DW_REG_r13 0x0d
1047 #define DW_REG_r14 0x0e
1048 #define DW_REG_r15 0x0f
1049 #define DW_REG_rip 0x10
1051 #endif /* defined(__x86_64__) */
1053 #define __ASM_CFI_STR(...) #__VA_ARGS__
1054 #define __ASM_CFI_ESC(...) \
1055 __ASM_CFI(".cfi_escape " __ASM_CFI_STR(__VA_ARGS__) "\n\t")
1056 #define __ASM_CFI_CFA_IS_AT1(base, offset) \
1057 __ASM_CFI_ESC(DW_CFA_def_cfa_expression, 0x03, DW_OP_ ## base, offset, DW_OP_deref)
1058 #define __ASM_CFI_REG_IS_AT1(reg, base, offset) \
1059 __ASM_CFI_ESC(DW_CFA_expression, DW_REG_ ## reg, 0x02, DW_OP_ ## base, offset)
1060 #define __ASM_CFI_CFA_IS_AT2(base, lo, hi) \
1061 __ASM_CFI_ESC(DW_CFA_def_cfa_expression, 0x04, DW_OP_ ## base, lo, hi, DW_OP_deref)
1062 #define __ASM_CFI_REG_IS_AT2(reg, base, lo, hi) \
1063 __ASM_CFI_ESC(DW_CFA_expression, DW_REG_ ## reg, 0x03, DW_OP_ ## base, lo, hi)
1065 #endif /* __NTDLL_DWARF_H */