delve/proc/registers_darwin_amd64.go

159 lines
3.7 KiB
Go
Raw Normal View History

2015-06-12 19:49:23 +00:00
package proc
2015-01-14 02:37:10 +00:00
// #include "threads_darwin.h"
import "C"
import (
"bytes"
"fmt"
)
2015-01-14 02:37:10 +00:00
type Regs 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
gs_base uint64
}
func (r *Regs) String() string {
var buf bytes.Buffer
var regs = []struct {
k string
v uint64
}{
{"Rip", r.rip},
{"Rsp", r.rsp},
{"Rax", r.rax},
{"Rbx", r.rbx},
{"Rcx", r.rcx},
{"Rdx", r.rdx},
{"Rdi", r.rdi},
{"Rsi", r.rsi},
{"Rbp", r.rbp},
{"R8", r.r8},
{"R9", r.r9},
{"R10", r.r10},
{"R11", r.r11},
{"R12", r.r12},
{"R13", r.r13},
{"R14", r.r14},
{"R15", r.r15},
{"Rflags", r.rflags},
{"Cs", r.cs},
{"Fs", r.fs},
{"Gs", r.gs},
{"Gs_base", r.gs_base},
}
for _, reg := range regs {
fmt.Fprintf(&buf, "%8s = %0#16x\n", reg.k, reg.v)
}
return buf.String()
2015-01-14 02:37:10 +00:00
}
func (r *Regs) PC() uint64 {
return r.rip
2015-01-14 02:37:10 +00:00
}
func (r *Regs) SP() uint64 {
return r.rsp
2015-01-14 02:37:10 +00:00
}
func (r *Regs) CX() uint64 {
return r.rcx
}
func (r *Regs) TLS() uint64 {
return r.gs_base
}
2015-06-12 19:51:23 +00:00
func (r *Regs) SetPC(thread *Thread, pc uint64) error {
2015-02-28 16:41:05 +00:00
kret := C.set_pc(thread.os.thread_act, C.uint64_t(pc))
if kret != C.KERN_SUCCESS {
2015-05-04 22:31:13 +00:00
return fmt.Errorf("could not set pc")
2015-02-28 16:41:05 +00:00
}
2015-01-14 02:37:10 +00:00
return nil
}
2015-06-12 19:51:23 +00:00
func registers(thread *Thread) (Registers, error) {
2015-02-28 16:39:21 +00:00
var state C.x86_thread_state64_t
var identity C.thread_identifier_info_data_t
2015-02-28 16:39:21 +00:00
kret := C.get_registers(C.mach_port_name_t(thread.os.thread_act), &state)
if kret != C.KERN_SUCCESS {
2015-05-04 22:31:13 +00:00
return nil, fmt.Errorf("could not get registers")
2015-02-28 16:39:21 +00:00
}
kret = C.get_identity(C.mach_port_name_t(thread.os.thread_act), &identity)
if kret != C.KERN_SUCCESS {
return nil, fmt.Errorf("could not get thread identity informations")
}
/*
thread_identifier_info::thread_handle contains the base of the
thread-specific data area, which on x86 and x86_64 is the threads base
address of the %gs segment. 10.9.2 xnu-2422.90.20/osfmk/kern/thread.c
thread_info_internal() gets the value from
machine_thread::cthread_self, which is the same value used to set the
%gs base in xnu-2422.90.20/osfmk/i386/pcb_native.c
act_machine_switch_pcb().
--
comment copied from chromium's crashpad
https://chromium.googlesource.com/crashpad/crashpad/+/master/snapshot/mac/process_reader.cc
*/
regs := &Regs{
rax: uint64(state.__rax),
rbx: uint64(state.__rbx),
rcx: uint64(state.__rcx),
rdx: uint64(state.__rdx),
rdi: uint64(state.__rdi),
rsi: uint64(state.__rsi),
rbp: uint64(state.__rbp),
rsp: uint64(state.__rsp),
r8: uint64(state.__r8),
r9: uint64(state.__r9),
r10: uint64(state.__r10),
r11: uint64(state.__r11),
r12: uint64(state.__r12),
r13: uint64(state.__r13),
r14: uint64(state.__r14),
r15: uint64(state.__r15),
rip: uint64(state.__rip),
rflags: uint64(state.__rflags),
cs: uint64(state.__cs),
fs: uint64(state.__fs),
gs: uint64(state.__gs),
gs_base: uint64(identity.thread_handle),
}
2015-01-14 02:37:10 +00:00
return regs, nil
}
func (thread *Thread) saveRegisters() (Registers, error) {
kret := C.get_registers(C.mach_port_name_t(thread.os.thread_act), &thread.os.registers)
if kret != C.KERN_SUCCESS {
return nil, fmt.Errorf("could not save register contents")
}
return &Regs{rip: uint64(thread.os.registers.__rip), rsp: uint64(thread.os.registers.__rsp)}, nil
}
func (thread *Thread) restoreRegisters() error {
kret := C.set_registers(C.mach_port_name_t(thread.os.thread_act), &thread.os.registers)
if kret != C.KERN_SUCCESS {
return fmt.Errorf("could not save register contents")
}
return nil
}