ReactOS  0.4.13-dev-651-g5dbc677
cpu_x86_64.c
Go to the documentation of this file.
1 /*
2  * File cpu_x86_64.c
3  *
4  * Copyright (C) 1999, 2005 Alexandre Julliard
5  * Copyright (C) 2009, 2011 Eric Pouech.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include <assert.h>
23 
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "dbghelp_private.h"
29 #include "winternl.h"
30 #include "wine/debug.h"
31 
33 
34 /* x86-64 unwind information, for PE modules, as described on MSDN */
35 
36 typedef enum _UNWIND_OP_CODES
37 {
48 
49 typedef union _UNWIND_CODE
50 {
51  struct
52  {
55  BYTE OpInfo : 4;
56  } u;
59 
60 typedef struct _UNWIND_INFO
61 {
63  BYTE Flags : 5;
68  UNWIND_CODE UnwindCode[1]; /* actually CountOfCodes (aligned) */
69 /*
70  * union
71  * {
72  * OPTIONAL ULONG ExceptionHandler;
73  * OPTIONAL ULONG FunctionEntry;
74  * };
75  * OPTIONAL ULONG ExceptionData[];
76  */
78 
80  enum cpu_addr ca, ADDRESS64* addr)
81 {
82  addr->Mode = AddrModeFlat;
83  switch (ca)
84  {
85 #ifdef __x86_64__
86  case cpu_addr_pc: addr->Segment = ctx->SegCs; addr->Offset = ctx->Rip; return TRUE;
87  case cpu_addr_stack: addr->Segment = ctx->SegSs; addr->Offset = ctx->Rsp; return TRUE;
88  case cpu_addr_frame: addr->Segment = ctx->SegSs; addr->Offset = ctx->Rbp; return TRUE;
89 #endif
90  default: addr->Mode = -1;
91  return FALSE;
92  }
93 }
94 
95 #ifdef __x86_64__
96 
97 enum st_mode {stm_start, stm_64bit, stm_done};
98 
99 /* indexes in Reserved array */
100 #define __CurrentMode 0
101 #define __CurrentCount 1
102 /* #define __ 2 (unused) */
103 
104 #define curr_mode (frame->Reserved[__CurrentMode])
105 #define curr_count (frame->Reserved[__CurrentCount])
106 /* #define ??? (frame->Reserved[__]) (unused) */
107 
108 union handler_data
109 {
111  ULONG handler;
112 };
113 
114 static void dump_unwind_info(struct cpu_stack_walk* csw, ULONG64 base, RUNTIME_FUNCTION *function)
115 {
116  static const char * const reg_names[16] =
117  { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
118  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" };
119 
120  union handler_data handler_data;
121  char buffer[sizeof(UNWIND_INFO) + 256 * sizeof(UNWIND_CODE)];
123  unsigned int i, count;
124  RUNTIME_FUNCTION snext;
125  ULONG64 addr;
126 
127  TRACE("**** func %x-%x\n", function->BeginAddress, function->EndAddress);
128  for (;;)
129  {
130  if (function->UnwindData & 1)
131  {
132  if (!sw_read_mem(csw, base + function->UnwindData, &snext, sizeof(snext)))
133  {
134  TRACE("Couldn't unwind RUNTIME_INFO at %lx\n", base + function->UnwindData);
135  return;
136  }
137  TRACE("unwind info for function %p-%p chained to function %p-%p\n",
138  (char*)base + function->BeginAddress, (char*)base + function->EndAddress,
139  (char*)base + snext.BeginAddress, (char*)base + snext.EndAddress);
140  function = &snext;
141  continue;
142  }
143  addr = base + function->UnwindData;
144  if (!sw_read_mem(csw, addr, info, FIELD_OFFSET(UNWIND_INFO, UnwindCode)) ||
145  !sw_read_mem(csw, addr + FIELD_OFFSET(UNWIND_INFO, UnwindCode),
146  info->UnwindCode, info->CountOfCodes * sizeof(UNWIND_CODE)))
147  {
148  FIXME("couldn't read memory for UNWIND_INFO at %lx\n", addr);
149  return;
150  }
151  TRACE("unwind info at %p flags %x prolog 0x%x bytes function %p-%p\n",
152  (char*)addr, info->Flags, info->SizeOfProlog,
153  (char*)base + function->BeginAddress, (char*)base + function->EndAddress);
154 
155  if (info->FrameRegister)
156  TRACE(" frame register %s offset 0x%x(%%rsp)\n",
157  reg_names[info->FrameRegister], info->FrameOffset * 16);
158 
159  for (i = 0; i < info->CountOfCodes; i++)
160  {
161  TRACE(" 0x%x: ", info->UnwindCode[i].u.CodeOffset);
162  switch (info->UnwindCode[i].u.UnwindOp)
163  {
164  case UWOP_PUSH_NONVOL:
165  TRACE("pushq %%%s\n", reg_names[info->UnwindCode[i].u.OpInfo]);
166  break;
167  case UWOP_ALLOC_LARGE:
168  if (info->UnwindCode[i].u.OpInfo)
169  {
170  count = *(DWORD*)&info->UnwindCode[i+1];
171  i += 2;
172  }
173  else
174  {
175  count = *(USHORT*)&info->UnwindCode[i+1] * 8;
176  i++;
177  }
178  TRACE("subq $0x%x,%%rsp\n", count);
179  break;
180  case UWOP_ALLOC_SMALL:
181  count = (info->UnwindCode[i].u.OpInfo + 1) * 8;
182  TRACE("subq $0x%x,%%rsp\n", count);
183  break;
184  case UWOP_SET_FPREG:
185  TRACE("leaq 0x%x(%%rsp),%s\n",
186  info->FrameOffset * 16, reg_names[info->FrameRegister]);
187  break;
188  case UWOP_SAVE_NONVOL:
189  count = *(USHORT*)&info->UnwindCode[i+1] * 8;
190  TRACE("movq %%%s,0x%x(%%rsp)\n", reg_names[info->UnwindCode[i].u.OpInfo], count);
191  i++;
192  break;
194  count = *(DWORD*)&info->UnwindCode[i+1];
195  TRACE("movq %%%s,0x%x(%%rsp)\n", reg_names[info->UnwindCode[i].u.OpInfo], count);
196  i += 2;
197  break;
198  case UWOP_SAVE_XMM128:
199  count = *(USHORT*)&info->UnwindCode[i+1] * 16;
200  TRACE("movaps %%xmm%u,0x%x(%%rsp)\n", info->UnwindCode[i].u.OpInfo, count);
201  i++;
202  break;
204  count = *(DWORD*)&info->UnwindCode[i+1];
205  TRACE("movaps %%xmm%u,0x%x(%%rsp)\n", info->UnwindCode[i].u.OpInfo, count);
206  i += 2;
207  break;
208  case UWOP_PUSH_MACHFRAME:
209  TRACE("PUSH_MACHFRAME %u\n", info->UnwindCode[i].u.OpInfo);
210  break;
211  default:
212  FIXME("unknown code %u\n", info->UnwindCode[i].u.UnwindOp);
213  break;
214  }
215  }
216 
217  addr += FIELD_OFFSET(UNWIND_INFO, UnwindCode) +
218  ((info->CountOfCodes + 1) & ~1) * sizeof(UNWIND_CODE);
219  if (info->Flags & UNW_FLAG_CHAININFO)
220  {
221  if (!sw_read_mem(csw, addr, &handler_data, sizeof(handler_data.chain)))
222  {
223  FIXME("couldn't read memory for handler_data.chain\n");
224  return;
225  }
226  TRACE(" chained to function %p-%p\n",
227  (char*)base + handler_data.chain.BeginAddress,
228  (char*)base + handler_data.chain.EndAddress);
229  function = &handler_data.chain;
230  continue;
231  }
232  if (info->Flags & (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER))
233  {
234  if (!sw_read_mem(csw, addr, &handler_data, sizeof(handler_data.handler)))
235  {
236  FIXME("couldn't read memory for handler_data.handler\n");
237  return;
238  }
239  TRACE(" handler %p data at %p\n",
240  (char*)base + handler_data.handler, (char*)addr + sizeof(handler_data.handler));
241  }
242  break;
243  }
244 }
245 
246 /* highly derived from dlls/ntdll/signal_x86_64.c */
247 static ULONG64 get_int_reg(CONTEXT *context, int reg)
248 {
249  return *(&context->Rax + reg);
250 }
251 
252 static void set_int_reg(CONTEXT *context, int reg, ULONG64 val)
253 {
254  *(&context->Rax + reg) = val;
255 }
256 
257 static void set_float_reg(CONTEXT *context, int reg, M128A val)
258 {
259  *(&context->u.s.Xmm0 + reg) = val;
260 }
261 
262 static int get_opcode_size(UNWIND_CODE op)
263 {
264  switch (op.u.UnwindOp)
265  {
266  case UWOP_ALLOC_LARGE:
267  return 2 + (op.u.OpInfo != 0);
268  case UWOP_SAVE_NONVOL:
269  case UWOP_SAVE_XMM128:
270  return 2;
273  return 3;
274  default:
275  return 1;
276  }
277 }
278 
279 static BOOL is_inside_epilog(struct cpu_stack_walk* csw, DWORD64 pc,
280  DWORD64 base, const RUNTIME_FUNCTION *function )
281 {
282  BYTE op0, op1, op2;
283  LONG val32;
284 
285  if (!sw_read_mem(csw, pc, &op0, 1)) return FALSE;
286 
287  /* add or lea must be the first instruction, and it must have a rex.W prefix */
288  if ((op0 & 0xf8) == 0x48)
289  {
290  if (!sw_read_mem(csw, pc + 1, &op1, 1)) return FALSE;
291  if (!sw_read_mem(csw, pc + 2, &op2, 1)) return FALSE;
292  switch (op1)
293  {
294  case 0x81: /* add $nnnn,%rsp */
295  if (op0 == 0x48 && op2 == 0xc4)
296  {
297  pc += 7;
298  break;
299  }
300  return FALSE;
301  case 0x83: /* add $n,%rsp */
302  if (op0 == 0x48 && op2 == 0xc4)
303  {
304  pc += 4;
305  break;
306  }
307  return FALSE;
308  case 0x8d: /* lea n(reg),%rsp */
309  if (op0 & 0x06) return FALSE; /* rex.RX must be cleared */
310  if (((op2 >> 3) & 7) != 4) return FALSE; /* dest reg mus be %rsp */
311  if ((op2 & 7) == 4) return FALSE; /* no SIB byte allowed */
312  if ((op2 >> 6) == 1) /* 8-bit offset */
313  {
314  pc += 4;
315  break;
316  }
317  if ((op2 >> 6) == 2) /* 32-bit offset */
318  {
319  pc += 7;
320  break;
321  }
322  return FALSE;
323  }
324  }
325 
326  /* now check for various pop instructions */
327  for (;;)
328  {
329  if (!sw_read_mem(csw, pc, &op0, 1)) return FALSE;
330  if ((op0 & 0xf0) == 0x40) /* rex prefix */
331  {
332  if (!sw_read_mem(csw, ++pc, &op0, 1)) return FALSE;
333  }
334 
335  switch (op0)
336  {
337  case 0x58: /* pop %rax/%r8 */
338  case 0x59: /* pop %rcx/%r9 */
339  case 0x5a: /* pop %rdx/%r10 */
340  case 0x5b: /* pop %rbx/%r11 */
341  case 0x5c: /* pop %rsp/%r12 */
342  case 0x5d: /* pop %rbp/%r13 */
343  case 0x5e: /* pop %rsi/%r14 */
344  case 0x5f: /* pop %rdi/%r15 */
345  pc++;
346  continue;
347  case 0xc2: /* ret $nn */
348  case 0xc3: /* ret */
349  return TRUE;
350  case 0xe9: /* jmp nnnn */
351  if (!sw_read_mem(csw, pc + 1, &val32, sizeof(LONG))) return FALSE;
352  pc += 5 + val32;
353  if (pc - base >= function->BeginAddress && pc - base < function->EndAddress)
354  continue;
355  break;
356  case 0xeb: /* jmp n */
357  if (!sw_read_mem(csw, pc + 1, &op1, 1)) return FALSE;
358  pc += 2 + (signed char)op1;
359  if (pc - base >= function->BeginAddress && pc - base < function->EndAddress)
360  continue;
361  break;
362  case 0xf3: /* rep; ret (for amd64 prediction bug) */
363  if (!sw_read_mem(csw, pc + 1, &op1, 1)) return FALSE;
364  return op1 == 0xc3;
365  }
366  return FALSE;
367  }
368 }
369 
370 static BOOL interpret_epilog(struct cpu_stack_walk* csw, ULONG64 pc, CONTEXT *context )
371 {
372  BYTE insn, val8;
373  WORD val16;
374  LONG val32;
375  DWORD64 val64;
376 
377  for (;;)
378  {
379  BYTE rex = 0;
380 
381  if (!sw_read_mem(csw, pc, &insn, 1)) return FALSE;
382  if ((insn & 0xf0) == 0x40)
383  {
384  rex = insn & 0x0f; /* rex prefix */
385  if (!sw_read_mem(csw, ++pc, &insn, 1)) return FALSE;
386  }
387 
388  switch (insn)
389  {
390  case 0x58: /* pop %rax/r8 */
391  case 0x59: /* pop %rcx/r9 */
392  case 0x5a: /* pop %rdx/r10 */
393  case 0x5b: /* pop %rbx/r11 */
394  case 0x5c: /* pop %rsp/r12 */
395  case 0x5d: /* pop %rbp/r13 */
396  case 0x5e: /* pop %rsi/r14 */
397  case 0x5f: /* pop %rdi/r15 */
398  if (!sw_read_mem(csw, context->Rsp, &val64, sizeof(DWORD64))) return FALSE;
399  set_int_reg(context, insn - 0x58 + (rex & 1) * 8, val64);
400  context->Rsp += sizeof(ULONG64);
401  pc++;
402  continue;
403  case 0x81: /* add $nnnn,%rsp */
404  if (!sw_read_mem(csw, pc + 2, &val32, sizeof(LONG))) return FALSE;
405  context->Rsp += val32;
406  pc += 2 + sizeof(LONG);
407  continue;
408  case 0x83: /* add $n,%rsp */
409  if (!sw_read_mem(csw, pc + 2, &val8, sizeof(BYTE))) return FALSE;
410  context->Rsp += (signed char)val8;
411  pc += 3;
412  continue;
413  case 0x8d:
414  if (!sw_read_mem(csw, pc + 1, &insn, sizeof(BYTE))) return FALSE;
415  if ((insn >> 6) == 1) /* lea n(reg),%rsp */
416  {
417  if (!sw_read_mem(csw, pc + 2, &val8, sizeof(BYTE))) return FALSE;
418  context->Rsp = get_int_reg( context, (insn & 7) + (rex & 1) * 8 ) + (signed char)val8;
419  pc += 3;
420  }
421  else /* lea nnnn(reg),%rsp */
422  {
423  if (!sw_read_mem(csw, pc + 2, &val32, sizeof(LONG))) return FALSE;
424  context->Rsp = get_int_reg( context, (insn & 7) + (rex & 1) * 8 ) + val32;
425  pc += 2 + sizeof(LONG);
426  }
427  continue;
428  case 0xc2: /* ret $nn */
429  if (!sw_read_mem(csw, context->Rsp, &val64, sizeof(DWORD64))) return FALSE;
430  if (!sw_read_mem(csw, pc + 1, &val16, sizeof(WORD))) return FALSE;
431  context->Rip = val64;
432  context->Rsp += sizeof(ULONG64) + val16;
433  return TRUE;
434  case 0xc3: /* ret */
435  case 0xf3: /* rep; ret */
436  if (!sw_read_mem(csw, context->Rsp, &val64, sizeof(DWORD64))) return FALSE;
437  context->Rip = val64;
438  context->Rsp += sizeof(ULONG64);
439  return TRUE;
440  case 0xe9: /* jmp nnnn */
441  if (!sw_read_mem(csw, pc + 1, &val32, sizeof(LONG))) return FALSE;
442  pc += 5 + val32;
443  continue;
444  case 0xeb: /* jmp n */
445  if (!sw_read_mem(csw, pc + 1, &val8, sizeof(BYTE))) return FALSE;
446  pc += 2 + (signed char)val8;
447  continue;
448  }
449  FIXME("unsupported insn %x\n", insn);
450  return FALSE;
451  }
452 }
453 
454 static BOOL default_unwind(struct cpu_stack_walk* csw, CONTEXT* context)
455 {
456  if (!sw_read_mem(csw, context->Rsp, &context->Rip, sizeof(DWORD64)))
457  {
458  WARN("Cannot read new frame offset %s\n", wine_dbgstr_longlong(context->Rsp));
459  return FALSE;
460  }
461  context->Rsp += sizeof(DWORD64);
462  return TRUE;
463 }
464 
465 static BOOL interpret_function_table_entry(struct cpu_stack_walk* csw,
467 {
468  char buffer[sizeof(UNWIND_INFO) + 256 * sizeof(UNWIND_CODE)];
470  unsigned i;
471  DWORD64 newframe, prolog_offset, off, value;
472  M128A floatvalue;
473  union handler_data handler_data;
474 
475  /* FIXME: we have some assumptions here */
476  assert(context);
477  dump_unwind_info(csw, sw_module_base(csw, context->Rip), function);
478  newframe = context->Rsp;
479  for (;;)
480  {
481  if (!sw_read_mem(csw, base + function->UnwindData, info, sizeof(*info)) ||
482  !sw_read_mem(csw, base + function->UnwindData + FIELD_OFFSET(UNWIND_INFO, UnwindCode),
483  info->UnwindCode, info->CountOfCodes * sizeof(UNWIND_CODE)))
484  {
485  WARN("Couldn't read unwind_code at %lx\n", base + function->UnwindData);
486  return FALSE;
487  }
488 
489  if (info->Version != 1)
490  {
491  WARN("unknown unwind info version %u at %lx\n", info->Version, base + function->UnwindData);
492  return FALSE;
493  }
494 
495  if (info->FrameRegister)
496  newframe = get_int_reg(context, info->FrameRegister) - info->FrameOffset * 16;
497 
498  /* check if in prolog */
499  if (context->Rip >= base + function->BeginAddress &&
500  context->Rip < base + function->BeginAddress + info->SizeOfProlog)
501  {
502  prolog_offset = context->Rip - base - function->BeginAddress;
503  }
504  else
505  {
506  prolog_offset = ~0;
507  if (is_inside_epilog(csw, context->Rip, base, function))
508  {
509  interpret_epilog(csw, context->Rip, context);
510  return TRUE;
511  }
512  }
513 
514  for (i = 0; i < info->CountOfCodes; i += get_opcode_size(info->UnwindCode[i]))
515  {
516  if (prolog_offset < info->UnwindCode[i].u.CodeOffset) continue; /* skip it */
517 
518  switch (info->UnwindCode[i].u.UnwindOp)
519  {
520  case UWOP_PUSH_NONVOL: /* pushq %reg */
521  if (!sw_read_mem(csw, context->Rsp, &value, sizeof(DWORD64))) return FALSE;
522  set_int_reg(context, info->UnwindCode[i].u.OpInfo, value);
523  context->Rsp += sizeof(ULONG64);
524  break;
525  case UWOP_ALLOC_LARGE: /* subq $nn,%rsp */
526  if (info->UnwindCode[i].u.OpInfo) context->Rsp += *(DWORD*)&info->UnwindCode[i+1];
527  else context->Rsp += *(USHORT*)&info->UnwindCode[i+1] * 8;
528  break;
529  case UWOP_ALLOC_SMALL: /* subq $n,%rsp */
530  context->Rsp += (info->UnwindCode[i].u.OpInfo + 1) * 8;
531  break;
532  case UWOP_SET_FPREG: /* leaq nn(%rsp),%framereg */
533  context->Rsp = newframe;
534  break;
535  case UWOP_SAVE_NONVOL: /* movq %reg,n(%rsp) */
536  off = newframe + *(USHORT*)&info->UnwindCode[i+1] * 8;
537  if (!sw_read_mem(csw, off, &value, sizeof(DWORD64))) return FALSE;
538  set_int_reg(context, info->UnwindCode[i].u.OpInfo, value);
539  break;
540  case UWOP_SAVE_NONVOL_FAR: /* movq %reg,nn(%rsp) */
541  off = newframe + *(DWORD*)&info->UnwindCode[i+1];
542  if (!sw_read_mem(csw, off, &value, sizeof(DWORD64))) return FALSE;
543  set_int_reg(context, info->UnwindCode[i].u.OpInfo, value);
544  break;
545  case UWOP_SAVE_XMM128: /* movaps %xmmreg,n(%rsp) */
546  off = newframe + *(USHORT*)&info->UnwindCode[i+1] * 16;
547  if (!sw_read_mem(csw, off, &floatvalue, sizeof(M128A))) return FALSE;
548  set_float_reg(context, info->UnwindCode[i].u.OpInfo, floatvalue);
549  break;
550  case UWOP_SAVE_XMM128_FAR: /* movaps %xmmreg,nn(%rsp) */
551  off = newframe + *(DWORD*)&info->UnwindCode[i+1];
552  if (!sw_read_mem(csw, off, &floatvalue, sizeof(M128A))) return FALSE;
553  set_float_reg(context, info->UnwindCode[i].u.OpInfo, floatvalue);
554  break;
555  case UWOP_PUSH_MACHFRAME:
556  FIXME("PUSH_MACHFRAME %u\n", info->UnwindCode[i].u.OpInfo);
557  break;
558  default:
559  FIXME("unknown code %u\n", info->UnwindCode[i].u.UnwindOp);
560  break;
561  }
562  }
563  if (!(info->Flags & UNW_FLAG_CHAININFO)) break;
564  if (!sw_read_mem(csw, base + function->UnwindData + FIELD_OFFSET(UNWIND_INFO, UnwindCode) +
565  ((info->CountOfCodes + 1) & ~1) * sizeof(UNWIND_CODE),
566  &handler_data, sizeof(handler_data))) return FALSE;
567  function = &handler_data.chain; /* restart with the chained info */
568  }
569  return default_unwind(csw, context);
570 }
571 
572 /* fetch_next_frame()
573  *
574  * modify (at least) context.{rip, rsp, rbp} using unwind information
575  * either out of PE exception handlers, debug info (dwarf), or simple stack unwind
576  */
577 static BOOL fetch_next_frame(struct cpu_stack_walk* csw, CONTEXT* context,
578  DWORD_PTR curr_pc, void** prtf)
579 {
580  DWORD_PTR cfa;
581  RUNTIME_FUNCTION* rtf;
582  DWORD64 base;
583 
584  if (!curr_pc || !(base = sw_module_base(csw, curr_pc))) return FALSE;
585  rtf = sw_table_access(csw, curr_pc);
586  if (prtf) *prtf = rtf;
587  if (rtf)
588  {
589  return interpret_function_table_entry(csw, context, rtf, base);
590  }
591  else if (dwarf2_virtual_unwind(csw, curr_pc, context, &cfa))
592  {
593  context->Rsp = cfa;
594  TRACE("next function rip=%016lx\n", context->Rip);
595  TRACE(" rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n",
596  context->Rax, context->Rbx, context->Rcx, context->Rdx);
597  TRACE(" rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n",
598  context->Rsi, context->Rdi, context->Rbp, context->Rsp);
599  TRACE(" r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n",
600  context->R8, context->R9, context->R10, context->R11);
601  TRACE(" r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
602  context->R12, context->R13, context->R14, context->R15);
603  return TRUE;
604  }
605  else
606  return default_unwind(csw, context);
607 }
608 
610 {
611  unsigned deltapc = curr_count <= 1 ? 0 : 1;
612 
613  /* sanity check */
614  if (curr_mode >= stm_done) return FALSE;
615  assert(!csw->is32);
616 
617  TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s Count=%s\n",
618  wine_dbgstr_addr(&frame->AddrPC),
619  wine_dbgstr_addr(&frame->AddrFrame),
620  wine_dbgstr_addr(&frame->AddrReturn),
621  wine_dbgstr_addr(&frame->AddrStack),
622  curr_mode == stm_start ? "start" : "64bit",
624 
625  if (curr_mode == stm_start)
626  {
627  if ((frame->AddrPC.Mode == AddrModeFlat) &&
628  (frame->AddrFrame.Mode != AddrModeFlat))
629  {
630  WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
631  goto done_err;
632  }
633 
634  /* Init done */
635  curr_mode = stm_64bit;
636  frame->AddrReturn.Mode = frame->AddrStack.Mode = AddrModeFlat;
637  /* don't set up AddrStack on first call. Either the caller has set it up, or
638  * we will get it in the next frame
639  */
640  memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
641  }
642  else
643  {
644  if (context->Rsp != frame->AddrStack.Offset) FIXME("inconsistent Stack Pointer\n");
645  if (context->Rip != frame->AddrPC.Offset) FIXME("inconsistent Instruction Pointer\n");
646 
647  if (frame->AddrReturn.Offset == 0) goto done_err;
648  if (!fetch_next_frame(csw, context, frame->AddrPC.Offset - deltapc, &frame->FuncTableEntry))
649  goto done_err;
650  deltapc = 1;
651  }
652 
653  memset(&frame->Params, 0, sizeof(frame->Params));
654 
655  /* set frame information */
656  frame->AddrStack.Offset = context->Rsp;
657  frame->AddrFrame.Offset = context->Rbp;
658  frame->AddrPC.Offset = context->Rip;
659  if (1)
660  {
661  CONTEXT newctx = *context;
662 
663  if (!fetch_next_frame(csw, &newctx, frame->AddrPC.Offset - deltapc, NULL))
664  goto done_err;
665  frame->AddrReturn.Mode = AddrModeFlat;
666  frame->AddrReturn.Offset = newctx.Rip;
667  }
668 
669  frame->Far = TRUE;
670  frame->Virtual = TRUE;
671  curr_count++;
672 
673  TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s Count=%s FuncTable=%p\n",
674  wine_dbgstr_addr(&frame->AddrPC),
675  wine_dbgstr_addr(&frame->AddrFrame),
676  wine_dbgstr_addr(&frame->AddrReturn),
677  wine_dbgstr_addr(&frame->AddrStack),
678  curr_mode == stm_start ? "start" : "64bit",
680  frame->FuncTableEntry);
681 
682  return TRUE;
683 done_err:
685  return FALSE;
686 }
687 #else
689 {
690  return FALSE;
691 }
692 #endif
693 
695 {
696 #ifdef __x86_64__
697  RUNTIME_FUNCTION* rtf;
698  ULONG size;
699  int min, max;
700 
702  if (rtf) for (min = 0, max = size / sizeof(*rtf); min <= max; )
703  {
704  int pos = (min + max) / 2;
705  if (addr < module->module.BaseOfImage + rtf[pos].BeginAddress) max = pos - 1;
706  else if (addr >= module->module.BaseOfImage + rtf[pos].EndAddress) min = pos + 1;
707  else
708  {
709  rtf += pos;
710  while (rtf->UnwindData & 1) /* follow chained entry */
711  {
712  FIXME("RunTime_Function outside IMAGE_DIRECTORY_ENTRY_EXCEPTION unimplemented yet!\n");
713  return NULL;
714  /* we need to read into the other process */
715  /* rtf = (RUNTIME_FUNCTION*)(module->module.BaseOfImage + (rtf->UnwindData & ~1)); */
716  }
717  return rtf;
718  }
719  }
720 #endif
721  return NULL;
722 }
723 
724 static unsigned x86_64_map_dwarf_register(unsigned regno, BOOL eh_frame)
725 {
726  unsigned reg;
727 
728  if (regno >= 17 && regno <= 24)
729  reg = CV_AMD64_XMM0 + regno - 17;
730  else if (regno >= 25 && regno <= 32)
731  reg = CV_AMD64_XMM8 + regno - 25;
732  else if (regno >= 33 && regno <= 40)
733  reg = CV_AMD64_ST0 + regno - 33;
734  else switch (regno)
735  {
736  case 0: reg = CV_AMD64_RAX; break;
737  case 1: reg = CV_AMD64_RDX; break;
738  case 2: reg = CV_AMD64_RCX; break;
739  case 3: reg = CV_AMD64_RBX; break;
740  case 4: reg = CV_AMD64_RSI; break;
741  case 5: reg = CV_AMD64_RDI; break;
742  case 6: reg = CV_AMD64_RBP; break;
743  case 7: reg = CV_AMD64_RSP; break;
744  case 8: reg = CV_AMD64_R8; break;
745  case 9: reg = CV_AMD64_R9; break;
746  case 10: reg = CV_AMD64_R10; break;
747  case 11: reg = CV_AMD64_R11; break;
748  case 12: reg = CV_AMD64_R12; break;
749  case 13: reg = CV_AMD64_R13; break;
750  case 14: reg = CV_AMD64_R14; break;
751  case 15: reg = CV_AMD64_R15; break;
752  case 16: reg = CV_AMD64_RIP; break;
753  case 49: reg = CV_AMD64_EFLAGS; break;
754  case 50: reg = CV_AMD64_ES; break;
755  case 51: reg = CV_AMD64_CS; break;
756  case 52: reg = CV_AMD64_SS; break;
757  case 53: reg = CV_AMD64_DS; break;
758  case 54: reg = CV_AMD64_FS; break;
759  case 55: reg = CV_AMD64_GS; break;
760  case 62: reg = CV_AMD64_TR; break;
761  case 63: reg = CV_AMD64_LDTR; break;
762  case 64: reg = CV_AMD64_MXCSR; break;
763  case 65: reg = CV_AMD64_CTRL; break;
764  case 66: reg = CV_AMD64_STAT; break;
765 /*
766  * 56-57 reserved
767  * 58 %fs.base
768  * 59 %gs.base
769  * 60-61 reserved
770  */
771  default:
772  FIXME("Don't know how to map register %d\n", regno);
773  return 0;
774  }
775  return reg;
776 }
777 
778 static void* x86_64_fetch_context_reg(CONTEXT* ctx, unsigned regno, unsigned* size)
779 {
780 #ifdef __x86_64__
781  switch (regno)
782  {
783  case CV_AMD64_RAX: *size = sizeof(ctx->Rax); return &ctx->Rax;
784  case CV_AMD64_RDX: *size = sizeof(ctx->Rdx); return &ctx->Rdx;
785  case CV_AMD64_RCX: *size = sizeof(ctx->Rcx); return &ctx->Rcx;
786  case CV_AMD64_RBX: *size = sizeof(ctx->Rbx); return &ctx->Rbx;
787  case CV_AMD64_RSI: *size = sizeof(ctx->Rsi); return &ctx->Rsi;
788  case CV_AMD64_RDI: *size = sizeof(ctx->Rdi); return &ctx->Rdi;
789  case CV_AMD64_RBP: *size = sizeof(ctx->Rbp); return &ctx->Rbp;
790  case CV_AMD64_RSP: *size = sizeof(ctx->Rsp); return &ctx->Rsp;
791  case CV_AMD64_R8: *size = sizeof(ctx->R8); return &ctx->R8;
792  case CV_AMD64_R9: *size = sizeof(ctx->R9); return &ctx->R9;
793  case CV_AMD64_R10: *size = sizeof(ctx->R10); return &ctx->R10;
794  case CV_AMD64_R11: *size = sizeof(ctx->R11); return &ctx->R11;
795  case CV_AMD64_R12: *size = sizeof(ctx->R12); return &ctx->R12;
796  case CV_AMD64_R13: *size = sizeof(ctx->R13); return &ctx->R13;
797  case CV_AMD64_R14: *size = sizeof(ctx->R14); return &ctx->R14;
798  case CV_AMD64_R15: *size = sizeof(ctx->R15); return &ctx->R15;
799  case CV_AMD64_RIP: *size = sizeof(ctx->Rip); return &ctx->Rip;
800 
801  case CV_AMD64_XMM0 + 0: *size = sizeof(ctx->u.s.Xmm0 ); return &ctx->u.s.Xmm0;
802  case CV_AMD64_XMM0 + 1: *size = sizeof(ctx->u.s.Xmm1 ); return &ctx->u.s.Xmm1;
803  case CV_AMD64_XMM0 + 2: *size = sizeof(ctx->u.s.Xmm2 ); return &ctx->u.s.Xmm2;
804  case CV_AMD64_XMM0 + 3: *size = sizeof(ctx->u.s.Xmm3 ); return &ctx->u.s.Xmm3;
805  case CV_AMD64_XMM0 + 4: *size = sizeof(ctx->u.s.Xmm4 ); return &ctx->u.s.Xmm4;
806  case CV_AMD64_XMM0 + 5: *size = sizeof(ctx->u.s.Xmm5 ); return &ctx->u.s.Xmm5;
807  case CV_AMD64_XMM0 + 6: *size = sizeof(ctx->u.s.Xmm6 ); return &ctx->u.s.Xmm6;
808  case CV_AMD64_XMM0 + 7: *size = sizeof(ctx->u.s.Xmm7 ); return &ctx->u.s.Xmm7;
809  case CV_AMD64_XMM8 + 0: *size = sizeof(ctx->u.s.Xmm8 ); return &ctx->u.s.Xmm8;
810  case CV_AMD64_XMM8 + 1: *size = sizeof(ctx->u.s.Xmm9 ); return &ctx->u.s.Xmm9;
811  case CV_AMD64_XMM8 + 2: *size = sizeof(ctx->u.s.Xmm10); return &ctx->u.s.Xmm10;
812  case CV_AMD64_XMM8 + 3: *size = sizeof(ctx->u.s.Xmm11); return &ctx->u.s.Xmm11;
813  case CV_AMD64_XMM8 + 4: *size = sizeof(ctx->u.s.Xmm12); return &ctx->u.s.Xmm12;
814  case CV_AMD64_XMM8 + 5: *size = sizeof(ctx->u.s.Xmm13); return &ctx->u.s.Xmm13;
815  case CV_AMD64_XMM8 + 6: *size = sizeof(ctx->u.s.Xmm14); return &ctx->u.s.Xmm14;
816  case CV_AMD64_XMM8 + 7: *size = sizeof(ctx->u.s.Xmm15); return &ctx->u.s.Xmm15;
817 
818  case CV_AMD64_ST0 + 0: *size = sizeof(ctx->u.s.Legacy[0]); return &ctx->u.s.Legacy[0];
819  case CV_AMD64_ST0 + 1: *size = sizeof(ctx->u.s.Legacy[1]); return &ctx->u.s.Legacy[1];
820  case CV_AMD64_ST0 + 2: *size = sizeof(ctx->u.s.Legacy[2]); return &ctx->u.s.Legacy[2];
821  case CV_AMD64_ST0 + 3: *size = sizeof(ctx->u.s.Legacy[3]); return &ctx->u.s.Legacy[3];
822  case CV_AMD64_ST0 + 4: *size = sizeof(ctx->u.s.Legacy[4]); return &ctx->u.s.Legacy[4];
823  case CV_AMD64_ST0 + 5: *size = sizeof(ctx->u.s.Legacy[5]); return &ctx->u.s.Legacy[5];
824  case CV_AMD64_ST0 + 6: *size = sizeof(ctx->u.s.Legacy[6]); return &ctx->u.s.Legacy[6];
825  case CV_AMD64_ST0 + 7: *size = sizeof(ctx->u.s.Legacy[7]); return &ctx->u.s.Legacy[7];
826 
827  case CV_AMD64_EFLAGS: *size = sizeof(ctx->EFlags); return &ctx->EFlags;
828  case CV_AMD64_ES: *size = sizeof(ctx->SegEs); return &ctx->SegEs;
829  case CV_AMD64_CS: *size = sizeof(ctx->SegCs); return &ctx->SegCs;
830  case CV_AMD64_SS: *size = sizeof(ctx->SegSs); return &ctx->SegSs;
831  case CV_AMD64_DS: *size = sizeof(ctx->SegDs); return &ctx->SegDs;
832  case CV_AMD64_FS: *size = sizeof(ctx->SegFs); return &ctx->SegFs;
833  case CV_AMD64_GS: *size = sizeof(ctx->SegGs); return &ctx->SegGs;
834 
835  }
836 #endif
837  FIXME("Unknown register %x\n", regno);
838  return NULL;
839 }
840 
841 static const char* x86_64_fetch_regname(unsigned regno)
842 {
843  switch (regno)
844  {
845  case CV_AMD64_RAX: return "rax";
846  case CV_AMD64_RDX: return "rdx";
847  case CV_AMD64_RCX: return "rcx";
848  case CV_AMD64_RBX: return "rbx";
849  case CV_AMD64_RSI: return "rsi";
850  case CV_AMD64_RDI: return "rdi";
851  case CV_AMD64_RBP: return "rbp";
852  case CV_AMD64_RSP: return "rsp";
853  case CV_AMD64_R8: return "r8";
854  case CV_AMD64_R9: return "r9";
855  case CV_AMD64_R10: return "r10";
856  case CV_AMD64_R11: return "r11";
857  case CV_AMD64_R12: return "r12";
858  case CV_AMD64_R13: return "r13";
859  case CV_AMD64_R14: return "r14";
860  case CV_AMD64_R15: return "r15";
861  case CV_AMD64_RIP: return "rip";
862 
863  case CV_AMD64_XMM0 + 0: return "xmm0";
864  case CV_AMD64_XMM0 + 1: return "xmm1";
865  case CV_AMD64_XMM0 + 2: return "xmm2";
866  case CV_AMD64_XMM0 + 3: return "xmm3";
867  case CV_AMD64_XMM0 + 4: return "xmm4";
868  case CV_AMD64_XMM0 + 5: return "xmm5";
869  case CV_AMD64_XMM0 + 6: return "xmm6";
870  case CV_AMD64_XMM0 + 7: return "xmm7";
871  case CV_AMD64_XMM8 + 0: return "xmm8";
872  case CV_AMD64_XMM8 + 1: return "xmm9";
873  case CV_AMD64_XMM8 + 2: return "xmm10";
874  case CV_AMD64_XMM8 + 3: return "xmm11";
875  case CV_AMD64_XMM8 + 4: return "xmm12";
876  case CV_AMD64_XMM8 + 5: return "xmm13";
877  case CV_AMD64_XMM8 + 6: return "xmm14";
878  case CV_AMD64_XMM8 + 7: return "xmm15";
879 
880  case CV_AMD64_ST0 + 0: return "st0";
881  case CV_AMD64_ST0 + 1: return "st1";
882  case CV_AMD64_ST0 + 2: return "st2";
883  case CV_AMD64_ST0 + 3: return "st3";
884  case CV_AMD64_ST0 + 4: return "st4";
885  case CV_AMD64_ST0 + 5: return "st5";
886  case CV_AMD64_ST0 + 6: return "st6";
887  case CV_AMD64_ST0 + 7: return "st7";
888 
889  case CV_AMD64_EFLAGS: return "eflags";
890  case CV_AMD64_ES: return "es";
891  case CV_AMD64_CS: return "cs";
892  case CV_AMD64_SS: return "ss";
893  case CV_AMD64_DS: return "ds";
894  case CV_AMD64_FS: return "fs";
895  case CV_AMD64_GS: return "gs";
896  }
897  FIXME("Unknown register %x\n", regno);
898  return NULL;
899 }
900 
901 static BOOL x86_64_fetch_minidump_thread(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx)
902 {
904  {
905  /* FIXME: crop values across module boundaries, */
906 #ifdef __x86_64__
907  ULONG64 base = ctx->Rip <= 0x80 ? 0 : ctx->Rip - 0x80;
908  minidump_add_memory_block(dc, base, ctx->Rip + 0x80 - base, 0);
909 #endif
910  }
911 
912  return TRUE;
913 }
914 
915 static BOOL x86_64_fetch_minidump_module(struct dump_context* dc, unsigned index, unsigned flags)
916 {
917  /* FIXME: not sure about the flags... */
918  if (1)
919  {
920  /* FIXME: crop values across module boundaries, */
921 #ifdef __x86_64__
922  struct process* pcs;
923  struct module* module;
924  const RUNTIME_FUNCTION* rtf;
925  ULONG size;
926 
927  if (!(pcs = process_find_by_handle(dc->hProcess)) ||
928  !(module = module_find_by_addr(pcs, dc->modules[index].base, DMT_UNKNOWN)))
929  return FALSE;
931  if (rtf)
932  {
933  const RUNTIME_FUNCTION* end = (const RUNTIME_FUNCTION*)((const char*)rtf + size);
934  UNWIND_INFO ui;
935 
936  while (rtf + 1 < end)
937  {
938  while (rtf->UnwindData & 1) /* follow chained entry */
939  {
940  FIXME("RunTime_Function outside IMAGE_DIRECTORY_ENTRY_EXCEPTION unimplemented yet!\n");
941  return FALSE;
942  /* we need to read into the other process */
943  /* rtf = (RUNTIME_FUNCTION*)(module->module.BaseOfImage + (rtf->UnwindData & ~1)); */
944  }
945  if (ReadProcessMemory(dc->hProcess,
946  (void*)(dc->modules[index].base + rtf->UnwindData),
947  &ui, sizeof(ui), NULL))
948  minidump_add_memory_block(dc, dc->modules[index].base + rtf->UnwindData,
949  FIELD_OFFSET(UNWIND_INFO, UnwindCode) + ui.CountOfCodes * sizeof(UNWIND_CODE), 0);
950  rtf++;
951  }
952  }
953 #endif
954  }
955 
956  return TRUE;
957 }
958 
961  8,
962  CV_AMD64_RSP,
971 };
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp)
static BOOL x86_64_stack_walk(struct cpu_stack_walk *csw, LPSTACKFRAME64 frame, CONTEXT *context)
Definition: cpu_x86_64.c:688
#define max(a, b)
Definition: svc.c:63
#define TRUE
Definition: types.h:120
HMODULE module
Definition: main.cpp:47
struct process * process_find_by_handle(HANDLE hProcess)
Definition: dbghelp.c:80
BYTE FrameOffset
Definition: cpu_x86_64.c:67
Definition: http.c:6587
DWORD64 BaseOfImage
Definition: compat.h:719
M128A
Definition: ketypes.h:918
_UNWIND_OP_CODES
Definition: cpu_x86_64.c:36
GLuint GLuint GLsizei count
Definition: gl.h:1545
union _UNWIND_CODE UNWIND_CODE
#define WARN(fmt,...)
Definition: debug.h:111
UINT ui
Definition: oleauto.h:49
BYTE UnwindOp
Definition: cpu_x86_64.c:54
void * sw_table_access(struct cpu_stack_walk *csw, DWORD64 addr) DECLSPEC_HIDDEN
Definition: stack.c:120
#define assert(x)
Definition: debug.h:53
GLuint buffer
Definition: glext.h:5915
HDC dc
Definition: cylfrac.c:34
DWORD64 Params[4]
Definition: compat.h:1048
#define ReadProcessMemory(a, b, c, d, e)
Definition: compat.h:415
ULONG SegGs
Definition: nt_native.h:1453
GLuint GLuint end
Definition: gl.h:1545
ULONG SegFs
Definition: nt_native.h:1454
ULONG SegDs
Definition: nt_native.h:1456
ADDRESS64 AddrBStore
Definition: compat.h:1046
void minidump_add_memory_block(struct dump_context *dc, ULONG64 base, ULONG size, ULONG rva) DECLSPEC_HIDDEN
Definition: minidump.c:338
#define curr_mode
Definition: cpu_i386.c:150
#define IMAGE_FILE_MACHINE_AMD64
Definition: ntimage.h:17
static const char * x86_64_fetch_regname(unsigned regno)
Definition: cpu_x86_64.c:841
union _UNWIND_CODE * PUNWIND_CODE
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ULONG R8
Definition: compat.h:343
BOOL dwarf2_virtual_unwind(struct cpu_stack_walk *csw, DWORD_PTR ip, CONTEXT *context, ULONG_PTR *cfa) DECLSPEC_HIDDEN
Definition: dwarf.c:3265
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint base
Definition: 3dtext.c:35
long LONG
Definition: pedump.c:60
BYTE CodeOffset
Definition: cpu_x86_64.c:53
ULONG SegEs
Definition: nt_native.h:1455
#define FIXME(fmt,...)
Definition: debug.h:110
cpu_addr
DWORD64 sw_module_base(struct cpu_stack_walk *csw, DWORD64 addr) DECLSPEC_HIDDEN
Definition: stack.c:128
ULONG SegCs
Definition: nt_native.h:1477
smooth NULL
Definition: ftsmooth.c:416
unsigned char
Definition: typeof.h:29
ULONG R9
Definition: compat.h:344
struct sock * chain
Definition: tcpcore.h:1164
ULONG EFlags
Definition: nt_native.h:1478
DWORD BeginAddress
Definition: compat.h:278
GLuint index
Definition: glext.h:6031
struct _UNWIND_INFO * PUNWIND_INFO
ULONG ContextFlags
Definition: compat.h:331
GLuint GLfloat * val
Definition: glext.h:7180
const char * wine_dbgstr_addr(const ADDRESS64 *addr)
Definition: dbghelp.c:123
#define TRACE(s)
Definition: solgame.cpp:4
static int rex
Definition: i386-dis.c:269
GLsizeiptr size
Definition: glext.h:5919
if(!(yy_init))
Definition: macro.lex.yy.c:714
BYTE Version
Definition: cpu_x86_64.c:62
ULONG R11
Definition: ke.h:266
BYTE FrameRegister
Definition: cpu_x86_64.c:66
DWORD64 Offset
Definition: compat.h:815
ADDRESS64 AddrReturn
Definition: compat.h:1043
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
GLbitfield flags
Definition: glext.h:7161
PVOID FuncTableEntry
Definition: compat.h:1047
unsigned __int64 ULONG64
Definition: imports.h:198
ADDRESS64 AddrStack
Definition: compat.h:1045
GLenum const GLvoid * addr
Definition: glext.h:9621
static unsigned x86_64_map_dwarf_register(unsigned regno, BOOL eh_frame)
Definition: cpu_x86_64.c:724
struct module * module_find_by_addr(const struct process *pcs, DWORD64 addr, enum module_type type) DECLSPEC_HIDDEN
Definition: module.c:399
unsigned char BYTE
Definition: mem.h:68
uint32_t DWORD_PTR
Definition: typedefs.h:63
GLsizei const GLfloat * value
Definition: glext.h:6069
UNWIND_CODE UnwindCode[1]
Definition: cpu_x86_64.c:68
BOOL sw_read_mem(struct cpu_stack_walk *csw, DWORD64 addr, void *ptr, DWORD sz) DECLSPEC_HIDDEN
Definition: stack.c:96
BYTE SizeOfProlog
Definition: cpu_x86_64.c:64
USHORT FrameOffset
Definition: cpu_x86_64.c:57
st_mode
Definition: cpu_i386.c:143
#define DECLSPEC_HIDDEN
Definition: precomp.h:8
uint64_t DWORD64
Definition: typedefs.h:65
ULONG SegSs
Definition: nt_native.h:1480
static BOOL x86_64_get_addr(HANDLE hThread, const CONTEXT *ctx, enum cpu_addr ca, ADDRESS64 *addr)
Definition: cpu_x86_64.c:79
static void * x86_64_find_runtime_function(struct module *module, DWORD64 addr)
Definition: cpu_x86_64.c:694
unsigned short USHORT
Definition: pedump.c:61
static void * x86_64_fetch_context_reg(CONTEXT *ctx, unsigned regno, unsigned *size)
Definition: cpu_x86_64.c:778
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
static BOOL x86_64_fetch_minidump_module(struct dump_context *dc, unsigned index, unsigned flags)
Definition: cpu_x86_64.c:915
#define min(a, b)
Definition: monoChain.cc:55
ADDRESS64 AddrPC
Definition: compat.h:1042
ULONG R12
Definition: ke.h:267
static int reg
Definition: i386-dis.c:1275
HANDLE hThread
Definition: wizard.c:27
static BOOL x86_64_fetch_minidump_thread(struct dump_context *dc, unsigned index, unsigned flags, const CONTEXT *ctx)
Definition: cpu_x86_64.c:901
DWORD UnwindData
Definition: compat.h:280
unsigned int ULONG
Definition: retypes.h:1
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:41
ULONG R10
Definition: compat.h:345
UINT op
Definition: effect.c:223
#define curr_count
Definition: cpu_i386.c:151
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7786
static const WCHAR ca[]
Definition: main.c:457
DECLSPEC_HIDDEN struct cpu cpu_x86_64
Definition: cpu_x86_64.c:959
struct _UNWIND_INFO UNWIND_INFO
struct _UNWIND_CODE::@353 u
#define memset(x, y, z)
Definition: compat.h:39
enum _UNWIND_OP_CODES UNWIND_CODE_OPS
ADDRESS_MODE Mode
Definition: compat.h:817
IMAGEHLP_MODULEW64 module
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION
Definition: pedump.c:262
BYTE CountOfCodes
Definition: cpu_x86_64.c:65
ADDRESS64 AddrFrame
Definition: compat.h:1044
BOOL Virtual
Definition: compat.h:1050
off
Definition: i386-dis.c:3909
const char * pe_map_directory(struct module *module, int dirno, DWORD *size) DECLSPEC_HIDDEN
Definition: pe_module.c:313