File: stack_sigtramp.go

package info (click to toggle)
delve 1.24.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 14,092 kB
  • sloc: ansic: 111,943; sh: 169; asm: 141; makefile: 43; python: 23
file content (772 lines) | stat: -rw-r--r-- 23,382 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
package proc

import (
	"encoding/binary"
	"errors"
	"fmt"
	"unsafe"

	"github.com/go-delve/delve/pkg/dwarf/op"
	"github.com/go-delve/delve/pkg/dwarf/regnum"
	"github.com/go-delve/delve/pkg/logflags"
)

// readSigtrampgoContext reads runtime.sigtrampgo context at the specified address
func (it *stackIterator) readSigtrampgoContext() (*op.DwarfRegisters, error) {
	logger := logflags.DebuggerLogger()
	scope := FrameToScope(it.target, it.mem, it.g, 0, it.frame)
	bi := it.bi

	findvar := func(name string) *Variable {
		vars, _ := scope.Locals(0, name)
		for i := range vars {
			if vars[i].Name == name {
				return vars[i]
			}
		}
		return nil
	}

	deref := func(v *Variable) (uint64, error) {
		v.loadValue(loadSingleValue)
		if v.Unreadable != nil {
			return 0, fmt.Errorf("could not dereference %s: %v", v.Name, v.Unreadable)
		}
		if len(v.Children) < 1 {
			return 0, fmt.Errorf("could not dereference %s (no children?)", v.Name)
		}
		logger.Debugf("%s address is %#x", v.Name, v.Children[0].Addr)
		return v.Children[0].Addr, nil
	}

	getctxaddr := func() (uint64, error) {
		ctxvar := findvar("ctx")
		if ctxvar == nil {
			return 0, errors.New("ctx variable not found")
		}
		addr, err := deref(ctxvar)
		if err != nil {
			return 0, err
		}
		return addr, nil
	}

	switch bi.GOOS {
	case "windows":
		epvar := findvar("ep")
		if epvar == nil {
			return nil, errors.New("ep variable not found")
		}
		epaddr, err := deref(epvar)
		if err != nil {
			return nil, err
		}
		switch bi.Arch.Name {
		case "amd64":
			return sigtrampContextWindowsAMD64(it.mem, epaddr)
		case "arm64":
			return sigtrampContextWindowsARM64(it.mem, epaddr)
		default:
			return nil, errors.New("not implemented")
		}
	case "linux":
		addr, err := getctxaddr()
		if err != nil {
			return nil, err
		}

		switch bi.Arch.Name {
		case "386":
			return sigtrampContextLinux386(it.mem, addr)
		case "amd64":
			return sigtrampContextLinuxAMD64(it.mem, addr)
		case "arm64":
			return sigtrampContextLinuxARM64(it.mem, addr)
		default:
			return nil, errors.New("not implemented")
		}
	case "freebsd":
		addr, err := getctxaddr()
		if err != nil {
			return nil, err
		}
		return sigtrampContextFreebsdAMD64(it.mem, addr)
	case "darwin":
		addr, err := getctxaddr()
		if err != nil {
			return nil, err
		}
		switch bi.Arch.Name {
		case "amd64":
			return sigtrampContextDarwinAMD64(it.mem, addr)
		case "arm64":
			return sigtrampContextDarwinARM64(it.mem, addr)
		default:
			return nil, errors.New("not implemented")
		}
	default:
		return nil, errors.New("not implemented")
	}
}

func sigtrampContextLinuxAMD64(mem MemoryReader, addr uint64) (*op.DwarfRegisters, error) {
	type stackt struct {
		ss_sp     uint64
		ss_flags  int32
		pad_cgo_0 [4]byte
		ss_size   uintptr
	}

	type mcontext struct {
		r8          uint64
		r9          uint64
		r10         uint64
		r11         uint64
		r12         uint64
		r13         uint64
		r14         uint64
		r15         uint64
		rdi         uint64
		rsi         uint64
		rbp         uint64
		rbx         uint64
		rdx         uint64
		rax         uint64
		rcx         uint64
		rsp         uint64
		rip         uint64
		eflags      uint64
		cs          uint16
		gs          uint16
		fs          uint16
		__pad0      uint16
		err         uint64
		trapno      uint64
		oldmask     uint64
		cr2         uint64
		fpstate     uint64 // pointer
		__reserved1 [8]uint64
	}

	type fpxreg struct {
		significand [4]uint16
		exponent    uint16
		padding     [3]uint16
	}

	type fpstate struct {
		cwd       uint16
		swd       uint16
		ftw       uint16
		fop       uint16
		rip       uint64
		rdp       uint64
		mxcsr     uint32
		mxcr_mask uint32
		_st       [8]fpxreg
		_xmm      [16][4]uint32
		padding   [24]uint32
	}

	type ucontext struct {
		uc_flags     uint64
		uc_link      uint64
		uc_stack     stackt
		uc_mcontext  mcontext
		uc_sigmask   [16]uint64
		__fpregs_mem fpstate
	}

	buf := make([]byte, unsafe.Sizeof(ucontext{}))
	_, err := mem.ReadMemory(buf, addr)
	if err != nil {
		return nil, err
	}
	regs := &(((*ucontext)(unsafe.Pointer(&buf[0]))).uc_mcontext)
	dregs := make([]*op.DwarfRegister, regnum.AMD64MaxRegNum()+1)
	dregs[regnum.AMD64_R8] = op.DwarfRegisterFromUint64(regs.r8)
	dregs[regnum.AMD64_R9] = op.DwarfRegisterFromUint64(regs.r9)
	dregs[regnum.AMD64_R10] = op.DwarfRegisterFromUint64(regs.r10)
	dregs[regnum.AMD64_R11] = op.DwarfRegisterFromUint64(regs.r11)
	dregs[regnum.AMD64_R12] = op.DwarfRegisterFromUint64(regs.r12)
	dregs[regnum.AMD64_R13] = op.DwarfRegisterFromUint64(regs.r13)
	dregs[regnum.AMD64_R14] = op.DwarfRegisterFromUint64(regs.r14)
	dregs[regnum.AMD64_R15] = op.DwarfRegisterFromUint64(regs.r15)
	dregs[regnum.AMD64_Rdi] = op.DwarfRegisterFromUint64(regs.rdi)
	dregs[regnum.AMD64_Rsi] = op.DwarfRegisterFromUint64(regs.rsi)
	dregs[regnum.AMD64_Rbp] = op.DwarfRegisterFromUint64(regs.rbp)
	dregs[regnum.AMD64_Rbx] = op.DwarfRegisterFromUint64(regs.rbx)
	dregs[regnum.AMD64_Rdx] = op.DwarfRegisterFromUint64(regs.rdx)
	dregs[regnum.AMD64_Rax] = op.DwarfRegisterFromUint64(regs.rax)
	dregs[regnum.AMD64_Rcx] = op.DwarfRegisterFromUint64(regs.rcx)
	dregs[regnum.AMD64_Rsp] = op.DwarfRegisterFromUint64(regs.rsp)
	dregs[regnum.AMD64_Rip] = op.DwarfRegisterFromUint64(regs.rip)
	dregs[regnum.AMD64_Rflags] = op.DwarfRegisterFromUint64(regs.eflags)
	dregs[regnum.AMD64_Cs] = op.DwarfRegisterFromUint64(uint64(regs.cs))
	dregs[regnum.AMD64_Gs] = op.DwarfRegisterFromUint64(uint64(regs.gs))
	dregs[regnum.AMD64_Fs] = op.DwarfRegisterFromUint64(uint64(regs.fs))
	return op.NewDwarfRegisters(0, dregs, binary.LittleEndian, regnum.AMD64_Rip, regnum.AMD64_Rsp, regnum.AMD64_Rbp, 0), nil
}

func sigtrampContextLinux386(mem MemoryReader, addr uint64) (*op.DwarfRegisters, error) {
	type sigcontext struct {
		gs            uint16
		__gsh         uint16
		fs            uint16
		__fsh         uint16
		es            uint16
		__esh         uint16
		ds            uint16
		__dsh         uint16
		edi           uint32
		esi           uint32
		ebp           uint32
		esp           uint32
		ebx           uint32
		edx           uint32
		ecx           uint32
		eax           uint32
		trapno        uint32
		err           uint32
		eip           uint32
		cs            uint16
		__csh         uint16
		eflags        uint32
		esp_at_signal uint32
		ss            uint16
		__ssh         uint16
		fpstate       uint32 // pointer
		oldmask       uint32
		cr2           uint32
	}

	type stackt struct {
		ss_sp    uint32 // pointer
		ss_flags int32
		ss_size  uint32
	}

	type ucontext struct {
		uc_flags    uint32
		uc_link     uint32 // pointer
		uc_stack    stackt
		uc_mcontext sigcontext
		uc_sigmask  uint32
	}

	buf := make([]byte, unsafe.Sizeof(ucontext{}))
	_, err := mem.ReadMemory(buf, addr)
	if err != nil {
		return nil, err
	}
	regs := &(((*ucontext)(unsafe.Pointer(&buf[0]))).uc_mcontext)
	dregs := make([]*op.DwarfRegister, regnum.I386MaxRegNum()+1)
	dregs[regnum.I386_Gs] = op.DwarfRegisterFromUint64(uint64(regs.gs))
	dregs[regnum.I386_Fs] = op.DwarfRegisterFromUint64(uint64(regs.fs))
	dregs[regnum.I386_Es] = op.DwarfRegisterFromUint64(uint64(regs.es))
	dregs[regnum.I386_Ds] = op.DwarfRegisterFromUint64(uint64(regs.ds))
	dregs[regnum.I386_Edi] = op.DwarfRegisterFromUint64(uint64(regs.edi))
	dregs[regnum.I386_Esi] = op.DwarfRegisterFromUint64(uint64(regs.esi))
	dregs[regnum.I386_Ebp] = op.DwarfRegisterFromUint64(uint64(regs.ebp))
	dregs[regnum.I386_Esp] = op.DwarfRegisterFromUint64(uint64(regs.esp))
	dregs[regnum.I386_Ebx] = op.DwarfRegisterFromUint64(uint64(regs.ebx))
	dregs[regnum.I386_Edx] = op.DwarfRegisterFromUint64(uint64(regs.edx))
	dregs[regnum.I386_Ecx] = op.DwarfRegisterFromUint64(uint64(regs.ecx))
	dregs[regnum.I386_Eax] = op.DwarfRegisterFromUint64(uint64(regs.eax))
	dregs[regnum.I386_Eip] = op.DwarfRegisterFromUint64(uint64(regs.eip))
	dregs[regnum.I386_Cs] = op.DwarfRegisterFromUint64(uint64(regs.cs))
	dregs[regnum.I386_Ss] = op.DwarfRegisterFromUint64(uint64(regs.ss))
	return op.NewDwarfRegisters(0, dregs, binary.LittleEndian, regnum.I386_Eip, regnum.I386_Esp, regnum.I386_Ebp, 0), nil
}

func sigtrampContextLinuxARM64(mem MemoryReader, addr uint64) (*op.DwarfRegisters, error) {
	type sigcontext struct {
		fault_address uint64
		regs          [31]uint64
		sp            uint64
		pc            uint64
		pstate        uint64
		_pad          [8]byte
		__reserved    [4096]byte
	}

	type stackt struct {
		ss_sp     uint64 // pointer
		ss_flags  int32
		pad_cgo_0 [4]byte
		ss_size   uint64
	}

	type ucontext struct {
		uc_flags    uint64
		uc_link     uint64 // pointer
		uc_stack    stackt
		uc_sigmask  uint64
		_pad        [(1024 - 64) / 8]byte
		_pad2       [8]byte
		uc_mcontext sigcontext
	}

	buf := make([]byte, unsafe.Sizeof(ucontext{}))
	_, err := mem.ReadMemory(buf, addr)
	if err != nil {
		return nil, err
	}
	regs := &(((*ucontext)(unsafe.Pointer(&buf[0]))).uc_mcontext)
	dregs := make([]*op.DwarfRegister, regnum.ARM64MaxRegNum()+1)
	for i := range regs.regs {
		dregs[regnum.ARM64_X0+i] = op.DwarfRegisterFromUint64(regs.regs[i])
	}
	dregs[regnum.ARM64_SP] = op.DwarfRegisterFromUint64(regs.sp)
	dregs[regnum.ARM64_PC] = op.DwarfRegisterFromUint64(regs.pc)
	return op.NewDwarfRegisters(0, dregs, binary.LittleEndian, regnum.ARM64_PC, regnum.ARM64_SP, regnum.ARM64_BP, regnum.ARM64_LR), nil
}

func sigtrampContextFreebsdAMD64(mem MemoryReader, addr uint64) (*op.DwarfRegisters, error) {
	type mcontext struct {
		mc_onstack       uint64
		mc_rdi           uint64
		mc_rsi           uint64
		mc_rdx           uint64
		mc_rcx           uint64
		mc_r8            uint64
		mc_r9            uint64
		mc_rax           uint64
		mc_rbx           uint64
		mc_rbp           uint64
		mc_r10           uint64
		mc_r11           uint64
		mc_r12           uint64
		mc_r13           uint64
		mc_r14           uint64
		mc_r15           uint64
		mc_trapno        uint32
		mc_fs            uint16
		mc_gs            uint16
		mc_addr          uint64
		mc_flags         uint32
		mc_es            uint16
		mc_ds            uint16
		mc_err           uint64
		mc_rip           uint64
		mc_cs            uint64
		mc_rflags        uint64
		mc_rsp           uint64
		mc_ss            uint64
		mc_len           uint64
		mc_fpformat      uint64
		mc_ownedfp       uint64
		mc_fpstate       [64]uint64
		mc_fsbase        uint64
		mc_gsbase        uint64
		mc_xfpustate     uint64
		mc_xfpustate_len uint64
		mc_spare         [4]uint64
	}

	type ucontext struct {
		uc_sigmask struct {
			__bits [4]uint32
		}
		uc_mcontext mcontext
		uc_link     uint64 // pointer
		uc_stack    struct {
			ss_sp     uintptr
			ss_size   uintptr
			ss_flags  int32
			pad_cgo_0 [4]byte
		}
		uc_flags  int32
		__spare__ [4]int32
		pad_cgo_0 [12]byte
	}

	buf := make([]byte, unsafe.Sizeof(ucontext{}))
	_, err := mem.ReadMemory(buf, addr)
	if err != nil {
		return nil, err
	}
	mctxt := ((*ucontext)(unsafe.Pointer(&buf[0]))).uc_mcontext

	dregs := make([]*op.DwarfRegister, regnum.AMD64MaxRegNum()+1)

	dregs[regnum.AMD64_Rdi] = op.DwarfRegisterFromUint64(mctxt.mc_rdi)
	dregs[regnum.AMD64_Rsi] = op.DwarfRegisterFromUint64(mctxt.mc_rsi)
	dregs[regnum.AMD64_Rdx] = op.DwarfRegisterFromUint64(mctxt.mc_rdx)
	dregs[regnum.AMD64_Rcx] = op.DwarfRegisterFromUint64(mctxt.mc_rcx)
	dregs[regnum.AMD64_R8] = op.DwarfRegisterFromUint64(mctxt.mc_r8)
	dregs[regnum.AMD64_R9] = op.DwarfRegisterFromUint64(mctxt.mc_r9)
	dregs[regnum.AMD64_Rax] = op.DwarfRegisterFromUint64(mctxt.mc_rax)
	dregs[regnum.AMD64_Rbx] = op.DwarfRegisterFromUint64(mctxt.mc_rbx)
	dregs[regnum.AMD64_Rbp] = op.DwarfRegisterFromUint64(mctxt.mc_rbp)
	dregs[regnum.AMD64_R10] = op.DwarfRegisterFromUint64(mctxt.mc_r10)
	dregs[regnum.AMD64_R11] = op.DwarfRegisterFromUint64(mctxt.mc_r11)
	dregs[regnum.AMD64_R12] = op.DwarfRegisterFromUint64(mctxt.mc_r12)
	dregs[regnum.AMD64_R13] = op.DwarfRegisterFromUint64(mctxt.mc_r13)
	dregs[regnum.AMD64_R14] = op.DwarfRegisterFromUint64(mctxt.mc_r14)
	dregs[regnum.AMD64_R15] = op.DwarfRegisterFromUint64(mctxt.mc_r15)
	dregs[regnum.AMD64_Fs] = op.DwarfRegisterFromUint64(uint64(mctxt.mc_fs))
	dregs[regnum.AMD64_Gs] = op.DwarfRegisterFromUint64(uint64(mctxt.mc_gs))
	dregs[regnum.AMD64_Es] = op.DwarfRegisterFromUint64(uint64(mctxt.mc_es))
	dregs[regnum.AMD64_Ds] = op.DwarfRegisterFromUint64(uint64(mctxt.mc_ds))
	dregs[regnum.AMD64_Rip] = op.DwarfRegisterFromUint64(mctxt.mc_rip)
	dregs[regnum.AMD64_Cs] = op.DwarfRegisterFromUint64(mctxt.mc_cs)
	dregs[regnum.AMD64_Rflags] = op.DwarfRegisterFromUint64(mctxt.mc_rflags)
	dregs[regnum.AMD64_Rsp] = op.DwarfRegisterFromUint64(mctxt.mc_rsp)
	dregs[regnum.AMD64_Ss] = op.DwarfRegisterFromUint64(mctxt.mc_ss)

	return op.NewDwarfRegisters(0, dregs, binary.LittleEndian, regnum.AMD64_Rip, regnum.AMD64_Rsp, regnum.AMD64_Rbp, 0), nil
}

func sigtrampContextFromExceptionPointers(mem MemoryReader, addr uint64) (uint64, error) {
	type exceptionpointers struct {
		record  uint64 // pointer
		context uint64 // pointer
	}
	buf := make([]byte, unsafe.Sizeof(exceptionpointers{}))
	_, err := mem.ReadMemory(buf, addr)
	if err != nil {
		return 0, err
	}
	return ((*exceptionpointers)(unsafe.Pointer(&buf[0]))).context, nil
}

func sigtrampContextWindowsAMD64(mem MemoryReader, addr uint64) (*op.DwarfRegisters, error) {
	type context struct {
		p1home         uint64
		p2home         uint64
		p3home         uint64
		p4home         uint64
		p5home         uint64
		p6home         uint64
		contextflags   uint32
		mxcsr          uint32
		segcs          uint16
		segds          uint16
		seges          uint16
		segfs          uint16
		seggs          uint16
		segss          uint16
		eflags         uint32
		dr0            uint64
		dr1            uint64
		dr2            uint64
		dr3            uint64
		dr6            uint64
		dr7            uint64
		rax            uint64
		rcx            uint64
		rdx            uint64
		rbx            uint64
		rsp            uint64
		rbp            uint64
		rsi            uint64
		rdi            uint64
		r8             uint64
		r9             uint64
		r10            uint64
		r11            uint64
		r12            uint64
		r13            uint64
		r14            uint64
		r15            uint64
		rip            uint64
		anon0          [512]byte
		vectorregister [26]struct {
			low  uint64
			high int64
		}
		vectorcontrol        uint64
		debugcontrol         uint64
		lastbranchtorip      uint64
		lastbranchfromrip    uint64
		lastexceptiontorip   uint64
		lastexceptionfromrip uint64
	}

	ctxtaddr, err := sigtrampContextFromExceptionPointers(mem, addr)
	if err != nil {
		return nil, err
	}
	buf := make([]byte, unsafe.Sizeof(context{}))
	_, err = mem.ReadMemory(buf, ctxtaddr)
	if err != nil {
		return nil, fmt.Errorf("could not read context: %v", err)
	}
	ctxt := (*context)(unsafe.Pointer(&buf[0]))

	dregs := make([]*op.DwarfRegister, regnum.AMD64MaxRegNum()+1)

	dregs[regnum.AMD64_Cs] = op.DwarfRegisterFromUint64(uint64(ctxt.segcs))
	dregs[regnum.AMD64_Ds] = op.DwarfRegisterFromUint64(uint64(ctxt.segds))
	dregs[regnum.AMD64_Es] = op.DwarfRegisterFromUint64(uint64(ctxt.seges))
	dregs[regnum.AMD64_Fs] = op.DwarfRegisterFromUint64(uint64(ctxt.segfs))
	dregs[regnum.AMD64_Fs] = op.DwarfRegisterFromUint64(uint64(ctxt.seggs))
	dregs[regnum.AMD64_Ss] = op.DwarfRegisterFromUint64(uint64(ctxt.segss))
	dregs[regnum.AMD64_Rflags] = op.DwarfRegisterFromUint64(uint64(ctxt.eflags))
	dregs[regnum.AMD64_Rax] = op.DwarfRegisterFromUint64(ctxt.rax)
	dregs[regnum.AMD64_Rcx] = op.DwarfRegisterFromUint64(ctxt.rcx)
	dregs[regnum.AMD64_Rdx] = op.DwarfRegisterFromUint64(ctxt.rdx)
	dregs[regnum.AMD64_Rbx] = op.DwarfRegisterFromUint64(ctxt.rbx)
	dregs[regnum.AMD64_Rsp] = op.DwarfRegisterFromUint64(ctxt.rsp)
	dregs[regnum.AMD64_Rbp] = op.DwarfRegisterFromUint64(ctxt.rbp)
	dregs[regnum.AMD64_Rsi] = op.DwarfRegisterFromUint64(ctxt.rsi)
	dregs[regnum.AMD64_Rdi] = op.DwarfRegisterFromUint64(ctxt.rdi)
	dregs[regnum.AMD64_R8] = op.DwarfRegisterFromUint64(ctxt.r8)
	dregs[regnum.AMD64_R9] = op.DwarfRegisterFromUint64(ctxt.r9)
	dregs[regnum.AMD64_R10] = op.DwarfRegisterFromUint64(ctxt.r10)
	dregs[regnum.AMD64_R11] = op.DwarfRegisterFromUint64(ctxt.r11)
	dregs[regnum.AMD64_R12] = op.DwarfRegisterFromUint64(ctxt.r12)
	dregs[regnum.AMD64_R13] = op.DwarfRegisterFromUint64(ctxt.r13)
	dregs[regnum.AMD64_R14] = op.DwarfRegisterFromUint64(ctxt.r14)
	dregs[regnum.AMD64_R15] = op.DwarfRegisterFromUint64(ctxt.r15)
	dregs[regnum.AMD64_Rip] = op.DwarfRegisterFromUint64(ctxt.rip)

	return op.NewDwarfRegisters(0, dregs, binary.LittleEndian, regnum.AMD64_Rip, regnum.AMD64_Rsp, regnum.AMD64_Rbp, 0), nil
}

func sigtrampContextWindowsARM64(mem MemoryReader, addr uint64) (*op.DwarfRegisters, error) {
	type context struct {
		contextflags uint32
		cpsr         uint32
		x            [31]uint64 // fp is x[29], lr is x[30]
		xsp          uint64
		pc           uint64
		v            [32]struct {
			low  uint64
			high int64
		}
		fpcr uint32
		fpsr uint32
		bcr  [8]uint32
		bvr  [8]uint64
		wcr  [2]uint32
		wvr  [2]uint64
	}

	ctxtaddr, err := sigtrampContextFromExceptionPointers(mem, addr)
	if err != nil {
		return nil, err
	}
	buf := make([]byte, unsafe.Sizeof(context{}))
	_, err = mem.ReadMemory(buf, ctxtaddr)
	if err != nil {
		return nil, fmt.Errorf("could not read context: %v", err)
	}
	ctxt := (*context)(unsafe.Pointer(&buf[0]))

	dregs := make([]*op.DwarfRegister, regnum.ARM64MaxRegNum()+1)
	for i := range ctxt.x {
		dregs[regnum.ARM64_X0+i] = op.DwarfRegisterFromUint64(ctxt.x[i])
	}
	dregs[regnum.ARM64_SP] = op.DwarfRegisterFromUint64(ctxt.xsp)
	dregs[regnum.ARM64_PC] = op.DwarfRegisterFromUint64(ctxt.pc)
	return op.NewDwarfRegisters(0, dregs, binary.LittleEndian, regnum.ARM64_PC, regnum.ARM64_SP, regnum.ARM64_BP, regnum.ARM64_LR), nil
}

func sigtrampContextDarwinAMD64(mem MemoryReader, addr uint64) (*op.DwarfRegisters, error) {
	type ucontext struct {
		uc_onstack int32
		uc_sigmask uint32
		uc_stack   struct {
			ss_sp     uint64 // pointer
			ss_size   uintptr
			ss_flags  int32
			pad_cgo_0 [4]byte
		}
		uc_link     uint64 // pointer
		uc_mcsize   uint64
		uc_mcontext uint64 // pointer
	}

	type regmmst struct {
		mmst_reg  [10]int8
		mmst_rsrv [6]int8
	}

	type regxmm struct {
		xmm_reg [16]int8
	}

	type floatstate64 struct {
		fpu_reserved  [2]int32
		fpu_fcw       [2]byte
		fpu_fsw       [2]byte
		fpu_ftw       uint8
		fpu_rsrv1     uint8
		fpu_fop       uint16
		fpu_ip        uint32
		fpu_cs        uint16
		fpu_rsrv2     uint16
		fpu_dp        uint32
		fpu_ds        uint16
		fpu_rsrv3     uint16
		fpu_mxcsr     uint32
		fpu_mxcsrmask uint32
		fpu_stmm0     regmmst
		fpu_stmm1     regmmst
		fpu_stmm2     regmmst
		fpu_stmm3     regmmst
		fpu_stmm4     regmmst
		fpu_stmm5     regmmst
		fpu_stmm6     regmmst
		fpu_stmm7     regmmst
		fpu_xmm0      regxmm
		fpu_xmm1      regxmm
		fpu_xmm2      regxmm
		fpu_xmm3      regxmm
		fpu_xmm4      regxmm
		fpu_xmm5      regxmm
		fpu_xmm6      regxmm
		fpu_xmm7      regxmm
		fpu_xmm8      regxmm
		fpu_xmm9      regxmm
		fpu_xmm10     regxmm
		fpu_xmm11     regxmm
		fpu_xmm12     regxmm
		fpu_xmm13     regxmm
		fpu_xmm14     regxmm
		fpu_xmm15     regxmm
		fpu_rsrv4     [96]int8
		fpu_reserved1 int32
	}

	type regs64 struct {
		rax    uint64
		rbx    uint64
		rcx    uint64
		rdx    uint64
		rdi    uint64
		rsi    uint64
		rbp    uint64
		rsp    uint64
		r8     uint64
		r9     uint64
		r10    uint64
		r11    uint64
		r12    uint64
		r13    uint64
		r14    uint64
		r15    uint64
		rip    uint64
		rflags uint64
		cs     uint64
		fs     uint64
		gs     uint64
	}

	type mcontext64 struct {
		es struct {
			trapno     uint16
			cpu        uint16
			err        uint32
			faultvaddr uint64
		}
		ss        regs64
		fs        floatstate64
		pad_cgo_0 [4]byte
	}

	buf := make([]byte, unsafe.Sizeof(ucontext{}))
	_, err := mem.ReadMemory(buf, addr)
	if err != nil {
		return nil, err
	}
	mctxtaddr := ((*ucontext)(unsafe.Pointer(&buf[0]))).uc_mcontext

	buf = make([]byte, unsafe.Sizeof(mcontext64{}))
	_, err = mem.ReadMemory(buf, mctxtaddr)
	if err != nil {
		return nil, err
	}

	ss := ((*mcontext64)(unsafe.Pointer(&buf[0]))).ss
	dregs := make([]*op.DwarfRegister, regnum.AMD64MaxRegNum()+1)
	dregs[regnum.AMD64_Rax] = op.DwarfRegisterFromUint64(ss.rax)
	dregs[regnum.AMD64_Rbx] = op.DwarfRegisterFromUint64(ss.rbx)
	dregs[regnum.AMD64_Rcx] = op.DwarfRegisterFromUint64(ss.rcx)
	dregs[regnum.AMD64_Rdx] = op.DwarfRegisterFromUint64(ss.rdx)
	dregs[regnum.AMD64_Rdi] = op.DwarfRegisterFromUint64(ss.rdi)
	dregs[regnum.AMD64_Rsi] = op.DwarfRegisterFromUint64(ss.rsi)
	dregs[regnum.AMD64_Rbp] = op.DwarfRegisterFromUint64(ss.rbp)
	dregs[regnum.AMD64_Rsp] = op.DwarfRegisterFromUint64(ss.rsp)
	dregs[regnum.AMD64_R8] = op.DwarfRegisterFromUint64(ss.r8)
	dregs[regnum.AMD64_R9] = op.DwarfRegisterFromUint64(ss.r9)
	dregs[regnum.AMD64_R10] = op.DwarfRegisterFromUint64(ss.r10)
	dregs[regnum.AMD64_R11] = op.DwarfRegisterFromUint64(ss.r11)
	dregs[regnum.AMD64_R12] = op.DwarfRegisterFromUint64(ss.r12)
	dregs[regnum.AMD64_R13] = op.DwarfRegisterFromUint64(ss.r13)
	dregs[regnum.AMD64_R14] = op.DwarfRegisterFromUint64(ss.r14)
	dregs[regnum.AMD64_R15] = op.DwarfRegisterFromUint64(ss.r15)
	dregs[regnum.AMD64_Rip] = op.DwarfRegisterFromUint64(ss.rip)
	dregs[regnum.AMD64_Rflags] = op.DwarfRegisterFromUint64(ss.rflags)
	dregs[regnum.AMD64_Cs] = op.DwarfRegisterFromUint64(ss.cs)
	dregs[regnum.AMD64_Fs] = op.DwarfRegisterFromUint64(ss.fs)
	dregs[regnum.AMD64_Gs] = op.DwarfRegisterFromUint64(ss.gs)

	return op.NewDwarfRegisters(0, dregs, binary.LittleEndian, regnum.AMD64_Rip, regnum.AMD64_Rsp, regnum.AMD64_Rbp, 0), nil
}

func sigtrampContextDarwinARM64(mem MemoryReader, addr uint64) (*op.DwarfRegisters, error) {
	type ucontext struct {
		uc_onstack int32
		uc_sigmask uint32
		uc_stack   struct {
			ss_sp     uint64 // pointer
			ss_size   uintptr
			ss_flags  int32
			pad_cgo_0 [4]byte
		}
		uc_link     uint64 // pointer
		uc_mcsize   uint64
		uc_mcontext uint64 // pointer
	}

	type regs64 struct {
		x     [29]uint64 // registers x0 to x28
		fp    uint64     // frame register, x29
		lr    uint64     // link register, x30
		sp    uint64     // stack pointer, x31
		pc    uint64     // program counter
		cpsr  uint32     // current program status register
		__pad uint32
	}

	type mcontext64 struct {
		es struct {
			far uint64 // virtual fault addr
			esr uint32 // exception syndrome
			exc uint32 // number of arm exception taken
		}
		ss regs64
		ns struct {
			v    [64]uint64 // actually [32]uint128
			fpsr uint32
			fpcr uint32
		}
	}

	buf := make([]byte, unsafe.Sizeof(ucontext{}))
	_, err := mem.ReadMemory(buf, addr)
	if err != nil {
		return nil, err
	}
	mctxtaddr := ((*ucontext)(unsafe.Pointer(&buf[0]))).uc_mcontext

	buf = make([]byte, unsafe.Sizeof(mcontext64{}))
	_, err = mem.ReadMemory(buf, mctxtaddr)
	if err != nil {
		return nil, err
	}

	ss := ((*mcontext64)(unsafe.Pointer(&buf[0]))).ss
	dregs := make([]*op.DwarfRegister, regnum.ARM64MaxRegNum()+1)
	for i := range ss.x {
		dregs[regnum.ARM64_X0+i] = op.DwarfRegisterFromUint64(ss.x[i])
	}
	dregs[regnum.ARM64_BP] = op.DwarfRegisterFromUint64(ss.fp)
	dregs[regnum.ARM64_LR] = op.DwarfRegisterFromUint64(ss.lr)
	dregs[regnum.ARM64_SP] = op.DwarfRegisterFromUint64(ss.sp)
	dregs[regnum.ARM64_PC] = op.DwarfRegisterFromUint64(ss.pc)
	return op.NewDwarfRegisters(0, dregs, binary.LittleEndian, regnum.ARM64_PC, regnum.ARM64_SP, regnum.ARM64_BP, regnum.ARM64_LR), nil
}