ReactOS 0.4.16-dev-2613-g9533ad7
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
36typedef enum _UNWIND_OP_CODES
37{
48
49typedef union _UNWIND_CODE
50{
51 struct
52 {
56 } u;
59
60typedef struct _UNWIND_INFO
61{
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
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
97enum 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
108union handler_data
109{
110 RUNTIME_FUNCTION chain;
112};
113
114static 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;
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;
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 */
247static ULONG64 get_int_reg(CONTEXT *context, int reg)
248{
249 return *(&context->Rax + reg);
250}
251
252static void set_int_reg(CONTEXT *context, int reg, ULONG64 val)
253{
254 *(&context->Rax + reg) = val;
255}
256
257static void set_float_reg(CONTEXT *context, int reg, M128A val)
258{
259 *(&context->u.s.Xmm0 + reg) = val;
260}
261
262static 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
279static 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
370static 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
454static 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
465static BOOL interpret_function_table_entry(struct cpu_stack_walk* csw,
466 CONTEXT* context, RUNTIME_FUNCTION* function, DWORD64 base)
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 */
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;
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 */
577static BOOL fetch_next_frame(struct cpu_stack_walk *csw, union ctx *pcontext,
578 DWORD_PTR curr_pc, void** prtf)
579{
580 DWORD64 cfa;
581 RUNTIME_FUNCTION* rtf;
583 CONTEXT *context = &pcontext->ctx;
584
585 if (!curr_pc || !(base = sw_module_base(csw, curr_pc))) return FALSE;
586 rtf = sw_table_access(csw, curr_pc);
587 if (prtf) *prtf = rtf;
588 if (rtf)
589 {
590 return interpret_function_table_entry(csw, context, rtf, base);
591 }
592 else if (dwarf2_virtual_unwind(csw, curr_pc, pcontext, &cfa))
593 {
594 context->Rsp = cfa;
595 TRACE("next function rip=%016lx\n", context->Rip);
596 TRACE(" rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n",
597 context->Rax, context->Rbx, context->Rcx, context->Rdx);
598 TRACE(" rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n",
599 context->Rsi, context->Rdi, context->Rbp, context->Rsp);
600 TRACE(" r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n",
601 context->R8, context->R9, context->R10, context->R11);
602 TRACE(" r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
603 context->R12, context->R13, context->R14, context->R15);
604 return TRUE;
605 }
606 else
607 return default_unwind(csw, context);
608}
609
610static BOOL x86_64_stack_walk(struct cpu_stack_walk *csw, STACKFRAME64 *frame,
611 union ctx *context)
612{
613 unsigned deltapc = curr_count <= 1 ? 0 : 1;
614
615 /* sanity check */
616 if (curr_mode >= stm_done) return FALSE;
617 assert(!csw->is32);
618
619 TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s Count=%s\n",
620 wine_dbgstr_addr(&frame->AddrPC),
624 curr_mode == stm_start ? "start" : "64bit",
626
627 if (curr_mode == stm_start)
628 {
629 if ((frame->AddrPC.Mode == AddrModeFlat) &&
630 (frame->AddrFrame.Mode != AddrModeFlat))
631 {
632 WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
633 goto done_err;
634 }
635
636 /* Init done */
637 curr_mode = stm_64bit;
638 frame->AddrReturn.Mode = frame->AddrStack.Mode = AddrModeFlat;
639 /* don't set up AddrStack on first call. Either the caller has set it up, or
640 * we will get it in the next frame
641 */
642 memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
643 }
644 else
645 {
646 if (context->ctx.Rsp != frame->AddrStack.Offset) FIXME("inconsistent Stack Pointer\n");
647 if (context->ctx.Rip != frame->AddrPC.Offset) FIXME("inconsistent Instruction Pointer\n");
648
649 if (frame->AddrReturn.Offset == 0) goto done_err;
650 if (!fetch_next_frame(csw, context, frame->AddrPC.Offset - deltapc, &frame->FuncTableEntry))
651 goto done_err;
652 deltapc = 1;
653 }
654
655 memset(&frame->Params, 0, sizeof(frame->Params));
656
657 /* set frame information */
658 frame->AddrStack.Offset = context->ctx.Rsp;
659 frame->AddrFrame.Offset = context->ctx.Rbp;
660 frame->AddrPC.Offset = context->ctx.Rip;
661 if (1)
662 {
663 union ctx newctx = *context;
664
665 if (!fetch_next_frame(csw, &newctx, frame->AddrPC.Offset - deltapc, NULL))
666 {
667 /*
668 * The current frame is valid, but there is no parent frame to
669 * report (end-of-stack). Return this frame and terminate the walk
670 * on the next call, which matches Windows-observed behavior.
671 */
673 frame->AddrReturn.Offset = 0;
674 }
675 else
676 {
678 frame->AddrReturn.Offset = newctx.ctx.Rip;
679 }
680 }
681
682 frame->Far = TRUE;
683 frame->Virtual = TRUE;
684 curr_count++;
685
686 TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s Count=%s FuncTable=%p\n",
687 wine_dbgstr_addr(&frame->AddrPC),
691 curr_mode == stm_start ? "start" : "64bit",
693 frame->FuncTableEntry);
694
695 return TRUE;
696done_err:
698 return FALSE;
699}
700#else
702 union ctx *ctx)
703{
704 return FALSE;
705}
706#endif
707
709{
710#ifdef __x86_64__
711 RUNTIME_FUNCTION* rtf;
712 ULONG size;
713 int min, max;
714
715 rtf = (RUNTIME_FUNCTION*)pe_map_directory(module, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size);
716 if (rtf) for (min = 0, max = size / sizeof(*rtf); min <= max; )
717 {
718 int pos = (min + max) / 2;
719 if (addr < module->module.BaseOfImage + rtf[pos].BeginAddress) max = pos - 1;
720 else if (addr >= module->module.BaseOfImage + rtf[pos].EndAddress) min = pos + 1;
721 else
722 {
723 rtf += pos;
724 while (rtf->UnwindData & 1) /* follow chained entry */
725 {
726 FIXME("RunTime_Function outside IMAGE_DIRECTORY_ENTRY_EXCEPTION unimplemented yet!\n");
727 return NULL;
728 /* we need to read into the other process */
729 /* rtf = (RUNTIME_FUNCTION*)(module->module.BaseOfImage + (rtf->UnwindData & ~1)); */
730 }
731 return rtf;
732 }
733 }
734#endif
735 return NULL;
736}
737
738static unsigned x86_64_map_dwarf_register(unsigned regno, const struct module* module, BOOL eh_frame)
739{
740 unsigned reg;
741
742 if (regno >= 17 && regno <= 24)
743 reg = CV_AMD64_XMM0 + regno - 17;
744 else if (regno >= 25 && regno <= 32)
745 reg = CV_AMD64_XMM8 + regno - 25;
746 else if (regno >= 33 && regno <= 40)
747 reg = CV_AMD64_ST0 + regno - 33;
748 else switch (regno)
749 {
750 case 0: reg = CV_AMD64_RAX; break;
751 case 1: reg = CV_AMD64_RDX; break;
752 case 2: reg = CV_AMD64_RCX; break;
753 case 3: reg = CV_AMD64_RBX; break;
754 case 4: reg = CV_AMD64_RSI; break;
755 case 5: reg = CV_AMD64_RDI; break;
756 case 6: reg = CV_AMD64_RBP; break;
757 case 7: reg = CV_AMD64_RSP; break;
758 case 8: reg = CV_AMD64_R8; break;
759 case 9: reg = CV_AMD64_R9; break;
760 case 10: reg = CV_AMD64_R10; break;
761 case 11: reg = CV_AMD64_R11; break;
762 case 12: reg = CV_AMD64_R12; break;
763 case 13: reg = CV_AMD64_R13; break;
764 case 14: reg = CV_AMD64_R14; break;
765 case 15: reg = CV_AMD64_R15; break;
766 case 16: reg = CV_AMD64_RIP; break;
767 case 49: reg = CV_AMD64_EFLAGS; break;
768 case 50: reg = CV_AMD64_ES; break;
769 case 51: reg = CV_AMD64_CS; break;
770 case 52: reg = CV_AMD64_SS; break;
771 case 53: reg = CV_AMD64_DS; break;
772 case 54: reg = CV_AMD64_FS; break;
773 case 55: reg = CV_AMD64_GS; break;
774 case 62: reg = CV_AMD64_TR; break;
775 case 63: reg = CV_AMD64_LDTR; break;
776 case 64: reg = CV_AMD64_MXCSR; break;
777 case 65: reg = CV_AMD64_CTRL; break;
778 case 66: reg = CV_AMD64_STAT; break;
779/*
780 * 56-57 reserved
781 * 58 %fs.base
782 * 59 %gs.base
783 * 60-61 reserved
784 */
785 default:
786 FIXME("Don't know how to map register %d\n", regno);
787 return 0;
788 }
789 return reg;
790}
791
792static void *x86_64_fetch_context_reg(union ctx *pctx, unsigned regno, unsigned *size)
793{
794#ifdef __x86_64__
795 CONTEXT *ctx = &pctx->ctx;
796
797 switch (regno)
798 {
799 case CV_AMD64_RAX: *size = sizeof(ctx->Rax); return &ctx->Rax;
800 case CV_AMD64_RDX: *size = sizeof(ctx->Rdx); return &ctx->Rdx;
801 case CV_AMD64_RCX: *size = sizeof(ctx->Rcx); return &ctx->Rcx;
802 case CV_AMD64_RBX: *size = sizeof(ctx->Rbx); return &ctx->Rbx;
803 case CV_AMD64_RSI: *size = sizeof(ctx->Rsi); return &ctx->Rsi;
804 case CV_AMD64_RDI: *size = sizeof(ctx->Rdi); return &ctx->Rdi;
805 case CV_AMD64_RBP: *size = sizeof(ctx->Rbp); return &ctx->Rbp;
806 case CV_AMD64_RSP: *size = sizeof(ctx->Rsp); return &ctx->Rsp;
807 case CV_AMD64_R8: *size = sizeof(ctx->R8); return &ctx->R8;
808 case CV_AMD64_R9: *size = sizeof(ctx->R9); return &ctx->R9;
809 case CV_AMD64_R10: *size = sizeof(ctx->R10); return &ctx->R10;
810 case CV_AMD64_R11: *size = sizeof(ctx->R11); return &ctx->R11;
811 case CV_AMD64_R12: *size = sizeof(ctx->R12); return &ctx->R12;
812 case CV_AMD64_R13: *size = sizeof(ctx->R13); return &ctx->R13;
813 case CV_AMD64_R14: *size = sizeof(ctx->R14); return &ctx->R14;
814 case CV_AMD64_R15: *size = sizeof(ctx->R15); return &ctx->R15;
815 case CV_AMD64_RIP: *size = sizeof(ctx->Rip); return &ctx->Rip;
816
817 case CV_AMD64_XMM0 + 0: *size = sizeof(ctx->u.s.Xmm0 ); return &ctx->u.s.Xmm0;
818 case CV_AMD64_XMM0 + 1: *size = sizeof(ctx->u.s.Xmm1 ); return &ctx->u.s.Xmm1;
819 case CV_AMD64_XMM0 + 2: *size = sizeof(ctx->u.s.Xmm2 ); return &ctx->u.s.Xmm2;
820 case CV_AMD64_XMM0 + 3: *size = sizeof(ctx->u.s.Xmm3 ); return &ctx->u.s.Xmm3;
821 case CV_AMD64_XMM0 + 4: *size = sizeof(ctx->u.s.Xmm4 ); return &ctx->u.s.Xmm4;
822 case CV_AMD64_XMM0 + 5: *size = sizeof(ctx->u.s.Xmm5 ); return &ctx->u.s.Xmm5;
823 case CV_AMD64_XMM0 + 6: *size = sizeof(ctx->u.s.Xmm6 ); return &ctx->u.s.Xmm6;
824 case CV_AMD64_XMM0 + 7: *size = sizeof(ctx->u.s.Xmm7 ); return &ctx->u.s.Xmm7;
825 case CV_AMD64_XMM8 + 0: *size = sizeof(ctx->u.s.Xmm8 ); return &ctx->u.s.Xmm8;
826 case CV_AMD64_XMM8 + 1: *size = sizeof(ctx->u.s.Xmm9 ); return &ctx->u.s.Xmm9;
827 case CV_AMD64_XMM8 + 2: *size = sizeof(ctx->u.s.Xmm10); return &ctx->u.s.Xmm10;
828 case CV_AMD64_XMM8 + 3: *size = sizeof(ctx->u.s.Xmm11); return &ctx->u.s.Xmm11;
829 case CV_AMD64_XMM8 + 4: *size = sizeof(ctx->u.s.Xmm12); return &ctx->u.s.Xmm12;
830 case CV_AMD64_XMM8 + 5: *size = sizeof(ctx->u.s.Xmm13); return &ctx->u.s.Xmm13;
831 case CV_AMD64_XMM8 + 6: *size = sizeof(ctx->u.s.Xmm14); return &ctx->u.s.Xmm14;
832 case CV_AMD64_XMM8 + 7: *size = sizeof(ctx->u.s.Xmm15); return &ctx->u.s.Xmm15;
833
834 case CV_AMD64_ST0 + 0: *size = sizeof(ctx->u.s.Legacy[0]); return &ctx->u.s.Legacy[0];
835 case CV_AMD64_ST0 + 1: *size = sizeof(ctx->u.s.Legacy[1]); return &ctx->u.s.Legacy[1];
836 case CV_AMD64_ST0 + 2: *size = sizeof(ctx->u.s.Legacy[2]); return &ctx->u.s.Legacy[2];
837 case CV_AMD64_ST0 + 3: *size = sizeof(ctx->u.s.Legacy[3]); return &ctx->u.s.Legacy[3];
838 case CV_AMD64_ST0 + 4: *size = sizeof(ctx->u.s.Legacy[4]); return &ctx->u.s.Legacy[4];
839 case CV_AMD64_ST0 + 5: *size = sizeof(ctx->u.s.Legacy[5]); return &ctx->u.s.Legacy[5];
840 case CV_AMD64_ST0 + 6: *size = sizeof(ctx->u.s.Legacy[6]); return &ctx->u.s.Legacy[6];
841 case CV_AMD64_ST0 + 7: *size = sizeof(ctx->u.s.Legacy[7]); return &ctx->u.s.Legacy[7];
842
843 case CV_AMD64_EFLAGS: *size = sizeof(ctx->EFlags); return &ctx->EFlags;
844 case CV_AMD64_ES: *size = sizeof(ctx->SegEs); return &ctx->SegEs;
845 case CV_AMD64_CS: *size = sizeof(ctx->SegCs); return &ctx->SegCs;
846 case CV_AMD64_SS: *size = sizeof(ctx->SegSs); return &ctx->SegSs;
847 case CV_AMD64_DS: *size = sizeof(ctx->SegDs); return &ctx->SegDs;
848 case CV_AMD64_FS: *size = sizeof(ctx->SegFs); return &ctx->SegFs;
849 case CV_AMD64_GS: *size = sizeof(ctx->SegGs); return &ctx->SegGs;
850
851 }
852#endif
853 FIXME("Unknown register %x\n", regno);
854 return NULL;
855}
856
857static const char* x86_64_fetch_regname(unsigned regno)
858{
859 switch (regno)
860 {
861 case CV_AMD64_RAX: return "rax";
862 case CV_AMD64_RDX: return "rdx";
863 case CV_AMD64_RCX: return "rcx";
864 case CV_AMD64_RBX: return "rbx";
865 case CV_AMD64_RSI: return "rsi";
866 case CV_AMD64_RDI: return "rdi";
867 case CV_AMD64_RBP: return "rbp";
868 case CV_AMD64_RSP: return "rsp";
869 case CV_AMD64_R8: return "r8";
870 case CV_AMD64_R9: return "r9";
871 case CV_AMD64_R10: return "r10";
872 case CV_AMD64_R11: return "r11";
873 case CV_AMD64_R12: return "r12";
874 case CV_AMD64_R13: return "r13";
875 case CV_AMD64_R14: return "r14";
876 case CV_AMD64_R15: return "r15";
877 case CV_AMD64_RIP: return "rip";
878
879 case CV_AMD64_XMM0 + 0: return "xmm0";
880 case CV_AMD64_XMM0 + 1: return "xmm1";
881 case CV_AMD64_XMM0 + 2: return "xmm2";
882 case CV_AMD64_XMM0 + 3: return "xmm3";
883 case CV_AMD64_XMM0 + 4: return "xmm4";
884 case CV_AMD64_XMM0 + 5: return "xmm5";
885 case CV_AMD64_XMM0 + 6: return "xmm6";
886 case CV_AMD64_XMM0 + 7: return "xmm7";
887 case CV_AMD64_XMM8 + 0: return "xmm8";
888 case CV_AMD64_XMM8 + 1: return "xmm9";
889 case CV_AMD64_XMM8 + 2: return "xmm10";
890 case CV_AMD64_XMM8 + 3: return "xmm11";
891 case CV_AMD64_XMM8 + 4: return "xmm12";
892 case CV_AMD64_XMM8 + 5: return "xmm13";
893 case CV_AMD64_XMM8 + 6: return "xmm14";
894 case CV_AMD64_XMM8 + 7: return "xmm15";
895
896 case CV_AMD64_ST0 + 0: return "st0";
897 case CV_AMD64_ST0 + 1: return "st1";
898 case CV_AMD64_ST0 + 2: return "st2";
899 case CV_AMD64_ST0 + 3: return "st3";
900 case CV_AMD64_ST0 + 4: return "st4";
901 case CV_AMD64_ST0 + 5: return "st5";
902 case CV_AMD64_ST0 + 6: return "st6";
903 case CV_AMD64_ST0 + 7: return "st7";
904
905 case CV_AMD64_EFLAGS: return "eflags";
906 case CV_AMD64_ES: return "es";
907 case CV_AMD64_CS: return "cs";
908 case CV_AMD64_SS: return "ss";
909 case CV_AMD64_DS: return "ds";
910 case CV_AMD64_FS: return "fs";
911 case CV_AMD64_GS: return "gs";
912 }
913 FIXME("Unknown register %x\n", regno);
914 return NULL;
915}
916
917static BOOL x86_64_fetch_minidump_thread(struct dump_context* dc, unsigned index, unsigned flags, const CONTEXT* ctx)
918{
919 if (ctx->ContextFlags && (flags & ThreadWriteInstructionWindow))
920 {
921 /* FIXME: crop values across module boundaries, */
922#ifdef __x86_64__
923 ULONG64 base = ctx->Rip <= 0x80 ? 0 : ctx->Rip - 0x80;
924 minidump_add_memory_block(dc, base, ctx->Rip + 0x80 - base, 0);
925#endif
926 }
927
928 return TRUE;
929}
930
931static BOOL x86_64_fetch_minidump_module(struct dump_context* dc, unsigned index, unsigned flags)
932{
933 /* FIXME: not sure about the flags... */
934 if (1)
935 {
936 /* FIXME: crop values across module boundaries, */
937#ifdef __x86_64__
938 struct process* pcs;
939 struct module* module;
940 const RUNTIME_FUNCTION* rtf;
941 ULONG size;
942
943 if (!(pcs = process_find_by_handle(dc->process->handle)) ||
944 !(module = module_find_by_addr(pcs, dc->modules[index].base, DMT_UNKNOWN)))
945 return FALSE;
946 rtf = (const RUNTIME_FUNCTION*)pe_map_directory(module, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size);
947 if (rtf)
948 {
949 const RUNTIME_FUNCTION* end = (const RUNTIME_FUNCTION*)((const char*)rtf + size);
951
952 while (rtf + 1 < end)
953 {
954 while (rtf->UnwindData & 1) /* follow chained entry */
955 {
956 FIXME("RunTime_Function outside IMAGE_DIRECTORY_ENTRY_EXCEPTION unimplemented yet!\n");
957 return FALSE;
958 /* we need to read into the other process */
959 /* rtf = (RUNTIME_FUNCTION*)(module->module.BaseOfImage + (rtf->UnwindData & ~1)); */
960 }
961 if (read_process_memory(dc->process, dc->modules[index].base + rtf->UnwindData, &ui, sizeof(ui)))
962 minidump_add_memory_block(dc, dc->modules[index].base + rtf->UnwindData,
963 FIELD_OFFSET(UNWIND_INFO, UnwindCode) + ui.CountOfCodes * sizeof(UNWIND_CODE), 0);
964 rtf++;
965 }
966 }
967#endif
968 }
969
970 return TRUE;
971}
972
975 8,
985};
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
st_mode
Definition: cpu_i386.c:139
@ stm_start
Definition: cpu_i386.c:139
@ stm_done
Definition: cpu_i386.c:139
#define curr_count
Definition: cpu_i386.c:147
#define curr_mode
Definition: cpu_i386.c:146
static BOOL x86_64_stack_walk(struct cpu_stack_walk *csw, STACKFRAME64 *frame, union ctx *ctx)
Definition: cpu_x86_64.c:701
enum _UNWIND_OP_CODES UNWIND_CODE_OPS
static BOOL x86_64_fetch_minidump_module(struct dump_context *dc, unsigned index, unsigned flags)
Definition: cpu_x86_64.c:931
union _UNWIND_CODE UNWIND_CODE
struct _UNWIND_INFO * PUNWIND_INFO
static BOOL x86_64_get_addr(HANDLE hThread, const CONTEXT *ctx, enum cpu_addr ca, ADDRESS64 *addr)
Definition: cpu_x86_64.c:79
_UNWIND_OP_CODES
Definition: cpu_x86_64.c:37
@ UWOP_SET_FPREG
Definition: cpu_x86_64.c:41
@ UWOP_SAVE_XMM128_FAR
Definition: cpu_x86_64.c:45
@ UWOP_ALLOC_LARGE
Definition: cpu_x86_64.c:39
@ UWOP_PUSH_MACHFRAME
Definition: cpu_x86_64.c:46
@ UWOP_SAVE_XMM128
Definition: cpu_x86_64.c:44
@ UWOP_SAVE_NONVOL_FAR
Definition: cpu_x86_64.c:43
@ UWOP_PUSH_NONVOL
Definition: cpu_x86_64.c:38
@ UWOP_ALLOC_SMALL
Definition: cpu_x86_64.c:40
@ UWOP_SAVE_NONVOL
Definition: cpu_x86_64.c:42
struct _UNWIND_INFO UNWIND_INFO
static void * x86_64_find_runtime_function(struct module *module, DWORD64 addr)
Definition: cpu_x86_64.c:708
union _UNWIND_CODE * PUNWIND_CODE
static const char * x86_64_fetch_regname(unsigned regno)
Definition: cpu_x86_64.c:857
DECLSPEC_HIDDEN struct cpu cpu_x86_64
Definition: cpu_x86_64.c:973
static BOOL x86_64_fetch_minidump_thread(struct dump_context *dc, unsigned index, unsigned flags, const CONTEXT *ctx)
Definition: cpu_x86_64.c:917
static void * x86_64_fetch_context_reg(union ctx *pctx, unsigned regno, unsigned *size)
Definition: cpu_x86_64.c:792
static unsigned x86_64_map_dwarf_register(unsigned regno, const struct module *module, BOOL eh_frame)
Definition: cpu_x86_64.c:738
HDC dc
Definition: cylfrac.c:34
cpu_addr
@ cpu_addr_frame
@ cpu_addr_pc
@ cpu_addr_stack
void * sw_table_access(struct cpu_stack_walk *csw, DWORD64 addr) DECLSPEC_HIDDEN
Definition: stack.c:119
const char * pe_map_directory(struct module *module, int dirno, DWORD *size) DECLSPEC_HIDDEN
Definition: pe_module.c:331
static BOOL read_process_memory(const struct process *process, UINT64 addr, void *buf, size_t size)
BOOL dwarf2_virtual_unwind(struct cpu_stack_walk *csw, DWORD_PTR ip, union ctx *ctx, DWORD64 *cfa) DECLSPEC_HIDDEN
Definition: dwarf.c:3258
DWORD64 sw_module_base(struct cpu_stack_walk *csw, DWORD64 addr) DECLSPEC_HIDDEN
Definition: stack.c:127
void minidump_add_memory_block(struct dump_context *dc, ULONG64 base, ULONG size, ULONG rva) DECLSPEC_HIDDEN
Definition: minidump.c:355
BOOL sw_read_mem(struct cpu_stack_walk *csw, DWORD64 addr, void *ptr, DWORD sz) DECLSPEC_HIDDEN
Definition: stack.c:95
struct module * module_find_by_addr(const struct process *pcs, DWORD64 addr, enum module_type type) DECLSPEC_HIDDEN
Definition: module.c:420
@ DMT_UNKNOWN
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:236
#define DECLSPEC_HIDDEN
Definition: precomp.h:8
static const WCHAR ca[]
Definition: main.c:457
@ AddrModeFlat
Definition: compat.h:1159
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
@ CV_AMD64_XMM8
Definition: compat.h:2186
@ CV_AMD64_RSI
Definition: compat.h:2192
@ CV_AMD64_XMM0
Definition: compat.h:2161
@ CV_AMD64_RIP
Definition: compat.h:2129
@ CV_AMD64_R9
Definition: compat.h:2198
@ CV_AMD64_LDTR
Definition: compat.h:2145
@ CV_AMD64_ST0
Definition: compat.h:2149
@ CV_AMD64_CS
Definition: compat.h:2123
@ CV_AMD64_R13
Definition: compat.h:2202
@ CV_AMD64_MXCSR
Definition: compat.h:2165
@ CV_AMD64_RBX
Definition: compat.h:2189
@ CV_AMD64_RDI
Definition: compat.h:2193
@ CV_AMD64_FS
Definition: compat.h:2126
@ CV_AMD64_CTRL
Definition: compat.h:2150
@ CV_AMD64_STAT
Definition: compat.h:2151
@ CV_AMD64_ES
Definition: compat.h:2122
@ CV_AMD64_EFLAGS
Definition: compat.h:2130
@ CV_AMD64_SS
Definition: compat.h:2124
@ CV_AMD64_R15
Definition: compat.h:2204
@ CV_AMD64_R14
Definition: compat.h:2203
@ CV_AMD64_R12
Definition: compat.h:2201
@ CV_AMD64_RDX
Definition: compat.h:2191
@ CV_AMD64_R11
Definition: compat.h:2200
@ CV_AMD64_R8
Definition: compat.h:2197
@ CV_AMD64_TR
Definition: compat.h:2146
@ CV_AMD64_RBP
Definition: compat.h:2194
@ CV_AMD64_RAX
Definition: compat.h:2188
@ CV_AMD64_GS
Definition: compat.h:2127
@ CV_AMD64_RCX
Definition: compat.h:2190
@ CV_AMD64_RSP
Definition: compat.h:2195
@ CV_AMD64_R10
Definition: compat.h:2199
@ CV_AMD64_DS
Definition: compat.h:2125
@ ThreadWriteInstructionWindow
Definition: compat.h:1150
const char * wine_dbgstr_addr(const ADDRESS64 *addr)
Definition: dbghelp.c:142
struct process * process_find_by_handle(HANDLE hProcess)
Definition: dbghelp.c:99
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7512
#define assert(_expr)
Definition: assert.h:32
unsigned char
Definition: typeof.h:29
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLuint index
Definition: glext.h:6031
GLbitfield flags
Definition: glext.h:7161
GLenum const GLvoid * addr
Definition: glext.h:9621
GLuint GLfloat * val
Definition: glext.h:7180
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
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
static int rex
Definition: i386-dis.c:279
static int reg
Definition: i386-dis.c:1290
if(dx< 0)
Definition: linetemp.h:194
unsigned __int64 ULONG64
Definition: imports.h:198
#define min(a, b)
Definition: monoChain.cc:55
HANDLE hThread
Definition: wizard.c:28
#define IMAGE_FILE_MACHINE_AMD64
Definition: ntimage.h:17
UINT ui
Definition: oleauto.h:49
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION
Definition: pedump.c:262
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
DWORD64 BaseOfImage
Definition: compat.h:1070
PVOID FuncTableEntry
Definition: compat.h:1406
ADDRESS64 AddrBStore
Definition: compat.h:1405
ADDRESS64 AddrStack
Definition: compat.h:1404
ADDRESS64 AddrFrame
Definition: compat.h:1403
ADDRESS64 AddrPC
Definition: compat.h:1401
DWORD64 Params[4]
Definition: compat.h:1407
BOOL Virtual
Definition: compat.h:1409
ADDRESS64 AddrReturn
Definition: compat.h:1402
BYTE CountOfCodes
Definition: cpu_x86_64.c:65
BYTE FrameOffset
Definition: cpu_x86_64.c:67
BYTE Version
Definition: cpu_x86_64.c:62
UNWIND_CODE UnwindCode[1]
Definition: cpu_x86_64.c:68
BYTE SizeOfProlog
Definition: cpu_x86_64.c:64
BYTE FrameRegister
Definition: cpu_x86_64.c:66
ADDRESS_MODE Mode
Definition: compat.h:1176
DWORD64 Offset
Definition: compat.h:1174
Definition: http.c:7252
IMAGEHLP_MODULEW64 module
#define max(a, b)
Definition: svc.c:63
struct sock * chain
Definition: tcpcore.h:1
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
uint64_t DWORD64
Definition: typedefs.h:67
uint32_t ULONG
Definition: typedefs.h:59
BYTE UnwindOp
Definition: cpu_x86_64.c:54
BYTE CodeOffset
Definition: cpu_x86_64.c:53
USHORT FrameOffset
Definition: cpu_x86_64.c:57
struct _UNWIND_CODE::@362 u
CONTEXT ctx
Definition: pdh_main.c:96
M128A
Definition: ketypes.h:992
unsigned char BYTE
Definition: xxhash.c:193