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