ntdll: Use nameless unions/structs for register contexts.
[wine.git] / dlls / ntdll / unix / dwarf.h
blobd53bf321916b6e0c7b027a5b6b463eda58d519ac
1 /*
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
25 #include "windef.h"
26 #include "winnt.h"
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
86 #define DW_OP_or 0x21
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
94 #define DW_OP_eq 0x29
95 #define DW_OP_ge 0x2a
96 #define DW_OP_gt 0x2b
97 #define DW_OP_le 0x2c
98 #define DW_OP_lt 0x2d
99 #define DW_OP_ne 0x2e
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
240 void *tbase;
241 void *dbase;
242 void *func;
245 struct dwarf_cie
247 unsigned int length;
248 int id;
249 unsigned char version;
250 unsigned char augmentation[1];
253 struct dwarf_fde
255 unsigned int length;
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 )
263 return *(*p)++;
266 static unsigned short dwarf_get_u2( const unsigned char **p )
268 unsigned int ret = (*p)[0] | ((*p)[1] << 8);
269 (*p) += 2;
270 return ret;
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);
276 (*p) += 4;
277 return ret;
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 )
289 ULONG_PTR ret = 0;
290 unsigned int shift = 0;
291 unsigned char byte;
295 byte = **p;
296 ret |= (ULONG_PTR)(byte & 0x7f) << shift;
297 shift += 7;
298 (*p)++;
299 } while (byte & 0x80);
300 return ret;
303 static LONG_PTR dwarf_get_sleb128( const unsigned char **p )
305 ULONG_PTR ret = 0;
306 unsigned int shift = 0;
307 unsigned char byte;
311 byte = **p;
312 ret |= (ULONG_PTR)(byte & 0x7f) << shift;
313 shift += 7;
314 (*p)++;
315 } while (byte & 0x80);
317 if ((shift < 8 * sizeof(ret)) && (byte & 0x40)) ret |= -((ULONG_PTR)1 << shift);
318 return ret;
321 static ULONG_PTR dwarf_get_ptr( const unsigned char **p, unsigned char encoding, const struct dwarf_eh_bases *bases )
323 ULONG_PTR base;
325 if (encoding == DW_EH_PE_omit) return 0;
327 switch (encoding & 0x70)
329 case DW_EH_PE_abs:
330 base = 0;
331 break;
332 case DW_EH_PE_pcrel:
333 base = (ULONG_PTR)*p;
334 break;
335 case DW_EH_PE_textrel:
336 base = (ULONG_PTR)bases->tbase;
337 break;
338 case DW_EH_PE_datarel:
339 base = (ULONG_PTR)bases->dbase;
340 break;
341 case DW_EH_PE_funcrel:
342 base = (ULONG_PTR)bases->func;
343 break;
344 case DW_EH_PE_aligned:
345 base = ((ULONG_PTR)*p + 7) & ~7ul;
346 break;
347 default:
348 FIXME( "unsupported encoding %02x\n", encoding );
349 return 0;
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;
363 default:
364 FIXME( "unsupported encoding %02x\n", encoding );
365 return 0;
367 if (encoding & DW_EH_PE_indirect) base = *(ULONG_PTR *)base;
368 return base;
371 enum reg_rule
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 */
382 #ifdef __x86_64__
383 #define NB_FRAME_REGS 41
384 #elif defined(__aarch64__)
385 #define NB_FRAME_REGS 96
386 #else
387 #error Unsupported architecture
388 #endif
389 #define MAX_SAVED_STATES 16
391 struct frame_state
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];
400 struct frame_info
402 ULONG_PTR ip;
403 ULONG_PTR code_align;
404 LONG_PTR data_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] =
415 #ifdef __x86_64__
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",
434 #endif
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++;
451 if (op & 0xc0)
453 switch (op & 0xc0)
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 );
459 info->ip += offset;
460 break;
462 case DW_CFA_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;
470 break;
472 case DW_CFA_restore:
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;
478 break;
482 else switch (op)
484 case DW_CFA_nop:
485 break;
486 case DW_CFA_set_loc:
488 ULONG_PTR loc = dwarf_get_ptr( &ptr, info->fde_encoding, bases );
489 TRACE( "%lx: DW_CFA_set_loc %lx\n", info->ip, loc );
490 info->ip = loc;
491 break;
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 );
497 info->ip += offset;
498 break;
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 );
504 info->ip += offset;
505 break;
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 );
511 info->ip += offset;
512 break;
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;
524 break;
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;
532 break;
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;
540 break;
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;
549 break;
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;
559 break;
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 );
565 else
566 info->state_stack[info->state_sp++] = info->state;
567 break;
568 case DW_CFA_restore_state:
569 TRACE( "%lx: DW_CFA_restore_state\n", info->ip );
570 if (!info->state_sp)
571 FIXME( "%lx: DW_CFA_restore_state without corresponding save\n", info->ip );
572 else
573 info->state = info->state_stack[--info->state_sp];
574 break;
575 case DW_CFA_def_cfa:
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;
586 break;
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;
595 break;
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;
605 break;
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;
614 ptr += len;
615 break;
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;
628 ptr += len;
629 break;
631 default:
632 FIXME( "%lx: unknown CFA opcode %02x\n", info->ip, op );
633 break;
638 /* retrieve a context register from its dwarf number */
639 static void *get_context_reg( CONTEXT *context, ULONG_PTR dw_reg )
641 switch (dw_reg)
643 #ifdef __x86_64__
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;
719 case 64:
720 case 65:
721 case 66:
722 case 67:
723 case 68:
724 case 69:
725 case 70:
726 case 71:
727 case 72:
728 case 73:
729 case 74:
730 case 75:
731 case 76:
732 case 77:
733 case 78:
734 case 79:
735 case 80:
736 case 81:
737 case 82:
738 case 83:
739 case 84:
740 case 85:
741 case 86:
742 case 87:
743 case 88:
744 case 89:
745 case 90:
746 case 91:
747 case 92:
748 case 93:
749 case 94:
750 case 95:
751 return &context->V[dw_reg - 64];
752 #endif
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 )
760 switch (dw_reg)
762 #ifdef __x86_64__
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;
838 case 64:
839 case 65:
840 case 66:
841 case 67:
842 case 68:
843 case 69:
844 case 70:
845 case 71:
846 case 72:
847 case 73:
848 case 74:
849 case 75:
850 case 76:
851 case 77:
852 case 78:
853 case 79:
854 case 80:
855 case 81:
856 case 82:
857 case 83:
858 case 84:
859 case 85:
860 case 86:
861 case 87:
862 case 88:
863 case 89:
864 case 90:
865 case 91:
866 case 92:
867 case 93:
868 case 94:
869 case 95:
870 memcpy( &context->V[dw_reg - 64], val, sizeof(ARM64_NT_NEON128) );
871 break;
872 #endif
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];
880 int sp = -1;
881 ULONG_PTR len = dwarf_get_uleb128(&p);
882 const unsigned char *end = p + len;
884 while (p < end)
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);
894 else switch (opcode)
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;
940 case DW_OP_bregx:
941 reg = dwarf_get_uleb128(&p);
942 tmp = dwarf_get_sleb128(&p);
943 stack[++sp] = *(ULONG_PTR *)get_context_reg( context, reg ) + tmp;
944 break;
945 case DW_OP_deref_size:
946 switch (*p++)
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;
953 break;
954 default:
955 FIXME( "unhandled opcode %02x\n", opcode );
958 return stack[sp];
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 )
965 unsigned int i;
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 );
973 break;
974 case RULE_VAL_EXPRESSION:
975 cfa = eval_expression( (const unsigned char *)state->cfa_offset, context, bases );
976 break;
977 default:
978 cfa = *(ULONG_PTR *)get_context_reg( context, state->cfa_reg ) + state->cfa_offset;
979 break;
981 if (!cfa) return;
983 for (i = 0; i < NB_FRAME_REGS; i++)
985 switch (state->rules[i])
987 case RULE_UNSET:
988 case RULE_UNDEFINED:
989 case RULE_SAME:
990 break;
991 case RULE_CFA_OFFSET:
992 set_context_reg( &new_context, i, (char *)cfa + state->regs[i] );
993 break;
994 case RULE_OTHER_REG:
995 set_context_reg( &new_context, i, get_context_reg( context, state->regs[i] ));
996 break;
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 );
1000 break;
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 );
1004 break;
1007 #ifdef __x86_64__
1008 new_context.Rsp = cfa;
1009 #elif defined(__aarch64__)
1010 new_context.Sp = cfa;
1011 #endif
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 */