Esempio n. 1
0
func registers(thread *Thread) (Registers, error) {
	var state C.x86_thread_state64_t
	var identity C.thread_identifier_info_data_t
	kret := C.get_registers(C.mach_port_name_t(thread.os.thread_act), &state)
	if kret != C.KERN_SUCCESS {
		return nil, fmt.Errorf("could not get registers")
	}
	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 thread’s 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),
	}
	return regs, nil
}
Esempio n. 2
0
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
}
Esempio n. 3
0
func registers(thread *Thread) (Registers, error) {
	var state C.x86_thread_state64_t
	kret := C.get_registers(C.mach_port_name_t(thread.os.thread_act), &state)
	if kret != C.KERN_SUCCESS {
		return nil, fmt.Errorf("could not get registers")
	}
	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),
	}
	return regs, nil
}
Esempio n. 4
0
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
}
Esempio n. 5
0
func (c *ProcessStat) Collect(collectAttributes bool) {

	h := c.Processes
	for _, v := range h {
		v.dead = true
	}

	var pDefaultSet C.processor_set_name_t
	var pDefaultSetControl C.processor_set_t
	var tasks C.task_array_t
	var taskCount C.mach_msg_type_number_t

	if C.processor_set_default(c.hport, &pDefaultSet) != C.KERN_SUCCESS {
		return
	}

	// get privileged port to get information about all tasks

	if C.host_processor_set_priv(C.host_priv_t(c.hport),
		pDefaultSet, &pDefaultSetControl) != C.KERN_SUCCESS {
		return
	}

	if C.processor_set_tasks(pDefaultSetControl, &tasks, &taskCount) != C.KERN_SUCCESS {
		return
	}

	// convert tasks to a Go slice
	hdr := reflect.SliceHeader{
		Data: uintptr(unsafe.Pointer(tasks)),
		Len:  int(taskCount),
		Cap:  int(taskCount),
	}

	goTaskList := *(*[]C.task_name_t)(unsafe.Pointer(&hdr))

	// mach_msg_type_number_t - type natural_t = uint32_t
	var i uint32
	for i = 0; i < uint32(taskCount); i++ {

		taskId := goTaskList[i]
		var pid C.int
		// var tinfo C.task_info_data_t
		var count C.mach_msg_type_number_t
		var taskBasicInfo C.mach_task_basic_info_data_t
		var taskAbsoluteInfo C.task_absolutetime_info_data_t

		if (C.pid_for_task(C.mach_port_name_t(taskId), &pid) != C.KERN_SUCCESS) ||
			(pid < 0) {
			continue
		}

		count = C.MACH_TASK_BASIC_INFO_COUNT
		kr := C.task_info(taskId, C.MACH_TASK_BASIC_INFO,
			(C.task_info_t)(unsafe.Pointer(&taskBasicInfo)),
			&count)
		if kr != C.KERN_SUCCESS {
			continue
		}

		spid := fmt.Sprintf("%v", pid)
		pidstat, ok := h[spid]
		if !ok {
			pidstat = NewPerProcessStat(c.m, spid)
			h[spid] = pidstat
		}

		if collectAttributes || !ok {
			pidstat.CollectAttributes(pid)
		}

		pidstat.Metrics.VirtualSize.Set(float64(taskBasicInfo.virtual_size))
		pidstat.Metrics.ResidentSize.Set(float64(taskBasicInfo.resident_size))
		pidstat.Metrics.ResidentSizeMax.Set(float64(taskBasicInfo.resident_size_max))

		count = C.TASK_ABSOLUTETIME_INFO_COUNT
		kr = C.task_info(taskId, C.TASK_ABSOLUTETIME_INFO,
			(C.task_info_t)(unsafe.Pointer(&taskAbsoluteInfo)),
			&count)
		if kr != C.KERN_SUCCESS {
			continue
		}
		pidstat.Metrics.UserTime.Set(
			uint64(C.absolute_to_nano(taskAbsoluteInfo.total_user)))
		pidstat.Metrics.SystemTime.Set(
			uint64(C.absolute_to_nano(taskAbsoluteInfo.total_system)))
		pidstat.dead = false
	}

	// remove dead processes
	for k, v := range h {
		if v.dead {
			delete(h, k)
		}
	}

}