proc/native: use cgo instead of C for freebsd (#3529)
There is no benefit to having a small part of the freebsd backend implemented in C, rather than using cgo. While here, add a missing call to procstat_close and check the return value of procstat_getpathname.
This commit is contained in:
parent
9986a9845f
commit
04bb7fda33
@ -1,94 +0,0 @@
|
|||||||
#include <sys/param.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <sys/queue.h>
|
|
||||||
#include <sys/sysctl.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "proc_freebsd.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the absolute pathname of the process's executable, if one was found.
|
|
||||||
* Must be freed by the caller. Sets errno on failure.
|
|
||||||
*/
|
|
||||||
char * find_executable(int pid) {
|
|
||||||
struct procstat *ps;
|
|
||||||
struct kinfo_proc *kp;
|
|
||||||
char *pathname;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* procstat_open_sysctl is for running processes. For core files, use
|
|
||||||
* procstat_open_core
|
|
||||||
*/
|
|
||||||
ps = procstat_open_sysctl();
|
|
||||||
kp = kinfo_getproc(pid);
|
|
||||||
pathname = malloc(MNAMELEN);
|
|
||||||
if (ps && kp && pathname)
|
|
||||||
procstat_getpathname(ps, kp, pathname, MNAMELEN);
|
|
||||||
free(kp);
|
|
||||||
procstat_close(ps);
|
|
||||||
return (pathname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the comm value of the process, which is usually the basename of its
|
|
||||||
* executable. Must be freed by the caller. Sets errno on failure.
|
|
||||||
*/
|
|
||||||
char * find_command_name(int pid) {
|
|
||||||
char *command_name = NULL;
|
|
||||||
struct kinfo_proc *kinfo;
|
|
||||||
|
|
||||||
kinfo = kinfo_getproc(pid);
|
|
||||||
if (kinfo != NULL) {
|
|
||||||
command_name = malloc(COMMLEN + 1);
|
|
||||||
if (command_name != NULL)
|
|
||||||
strlcpy(command_name, kinfo->ki_comm, COMMLEN + 1);
|
|
||||||
free(kinfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (command_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
int find_status(int pid){
|
|
||||||
char status;
|
|
||||||
struct kinfo_proc *kinfo;
|
|
||||||
kinfo = kinfo_getproc(pid);
|
|
||||||
if (kinfo != NULL)
|
|
||||||
status = kinfo->ki_stat;
|
|
||||||
else
|
|
||||||
status = '?';
|
|
||||||
free(kinfo);
|
|
||||||
|
|
||||||
return (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t get_entry_point(int pid) {
|
|
||||||
void *ep = NULL;
|
|
||||||
|
|
||||||
errno = EINVAL;
|
|
||||||
|
|
||||||
struct procstat *ps = procstat_open_sysctl();
|
|
||||||
if (ps == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
uint cnt = 0;
|
|
||||||
struct kinfo_proc *kipp = procstat_getprocs(ps, KERN_PROC_PID, pid, &cnt);
|
|
||||||
if (cnt == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
Elf_Auxinfo *auxv = procstat_getauxv(ps, kipp, &cnt);
|
|
||||||
if (auxv == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < cnt; i++) {
|
|
||||||
if (auxv[i].a_type == AT_ENTRY) {
|
|
||||||
ep = auxv[i].a_un.a_ptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
procstat_freeauxv(ps, auxv);
|
|
||||||
errno = 0;
|
|
||||||
return (uintptr_t)ep;
|
|
||||||
}
|
|
@ -1,11 +1,25 @@
|
|||||||
package native
|
package native
|
||||||
|
|
||||||
// #cgo LDFLAGS: -lprocstat
|
/*
|
||||||
// #include <stdlib.h>
|
#cgo LDFLAGS: -lprocstat
|
||||||
// #include "proc_freebsd.h"
|
|
||||||
// #include <sys/sysctl.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/user.h>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <libprocstat.h>
|
||||||
|
#include <libutil.h>
|
||||||
|
|
||||||
|
uintptr_t elf_aux_info_ptr(Elf_Auxinfo *aux_info) {
|
||||||
|
return (uintptr_t)aux_info->a_un.a_ptr;
|
||||||
|
}
|
||||||
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@ -178,10 +192,15 @@ func waitForSearchProcess(pfx string, seen map[int]struct{}) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initialize(dbp *nativeProcess) (string, error) {
|
func initialize(dbp *nativeProcess) (string, error) {
|
||||||
comm, _ := C.find_command_name(C.int(dbp.pid))
|
kp, err := C.kinfo_getproc(C.int(dbp.pid))
|
||||||
defer C.free(unsafe.Pointer(comm))
|
if err != nil {
|
||||||
comm_str := C.GoString(comm)
|
return "", fmt.Errorf("kinfo_getproc failed: %v", err)
|
||||||
dbp.os.comm = strings.ReplaceAll(string(comm_str), "%", "%%")
|
}
|
||||||
|
defer C.free(unsafe.Pointer(kp))
|
||||||
|
|
||||||
|
comm := C.GoString(&kp.ki_comm[0])
|
||||||
|
dbp.os.comm = strings.ReplaceAll(string(comm), "%", "%%")
|
||||||
|
|
||||||
return getCmdLine(dbp.pid), nil
|
return getCmdLine(dbp.pid), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,14 +271,29 @@ func (dbp *nativeProcess) updateThreadList() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used by Attach
|
|
||||||
func findExecutable(path string, pid int) string {
|
func findExecutable(path string, pid int) string {
|
||||||
if path == "" {
|
if path != "" {
|
||||||
cstr := C.find_executable(C.int(pid))
|
return path
|
||||||
defer C.free(unsafe.Pointer(cstr))
|
|
||||||
path = C.GoString(cstr)
|
|
||||||
}
|
}
|
||||||
return path
|
|
||||||
|
ps := C.procstat_open_sysctl()
|
||||||
|
if ps == nil {
|
||||||
|
panic("procstat_open_sysctl failed")
|
||||||
|
}
|
||||||
|
defer C.procstat_close(ps)
|
||||||
|
|
||||||
|
kp := C.kinfo_getproc(C.int(pid))
|
||||||
|
if kp == nil {
|
||||||
|
panic("kinfo_getproc failed")
|
||||||
|
}
|
||||||
|
defer C.free(unsafe.Pointer(kp))
|
||||||
|
|
||||||
|
var pathname [C.PATH_MAX]C.char
|
||||||
|
if C.procstat_getpathname(ps, kp, (*C.char)(unsafe.Pointer(&pathname[0])), C.PATH_MAX) != 0 {
|
||||||
|
panic("procstat_getpathname failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
return C.GoString(&pathname[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCmdLine(pid int) string {
|
func getCmdLine(pid int) string {
|
||||||
@ -397,11 +431,14 @@ func (dbp *nativeProcess) trapWaitInternal(pid int, mode trapWaitMode) (*nativeT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function used here and in threads_freebsd.go
|
// status returns the status code for the given process.
|
||||||
// Return the status code
|
func status(pid int) int {
|
||||||
func status(pid int) rune {
|
kp, err := C.kinfo_getproc(C.int(pid))
|
||||||
status := rune(C.find_status(C.int(pid)))
|
if err != nil {
|
||||||
return status
|
return -1
|
||||||
|
}
|
||||||
|
defer C.free(unsafe.Pointer(kp))
|
||||||
|
return int(kp.ki_stat)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only used in this file
|
// Only used in this file
|
||||||
@ -543,11 +580,37 @@ func (dbp *nativeProcess) detach(kill bool) error {
|
|||||||
return ptraceDetach(dbp.pid)
|
return ptraceDetach(dbp.pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used by PostInitializationSetup
|
// EntryPoint returns the entry point address of the process.
|
||||||
// EntryPoint will return the process entry point address, useful for debugging PIEs.
|
|
||||||
func (dbp *nativeProcess) EntryPoint() (uint64, error) {
|
func (dbp *nativeProcess) EntryPoint() (uint64, error) {
|
||||||
ep, err := C.get_entry_point(C.int(dbp.pid))
|
ps, err := C.procstat_open_sysctl()
|
||||||
return uint64(ep), err
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("procstat_open_sysctl failed: %v", err)
|
||||||
|
}
|
||||||
|
defer C.procstat_close(ps)
|
||||||
|
|
||||||
|
var count C.uint
|
||||||
|
kipp, err := C.procstat_getprocs(ps, C.KERN_PROC_PID, C.int(dbp.pid), &count)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("procstat_getprocs failed: %v", err)
|
||||||
|
}
|
||||||
|
defer C.procstat_freeprocs(ps, kipp)
|
||||||
|
if count == 0 {
|
||||||
|
return 0, errors.New("procstat_getprocs returned no processes")
|
||||||
|
}
|
||||||
|
|
||||||
|
auxv, err := C.procstat_getauxv(ps, kipp, &count)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("procstat_getauxv failed: %v", err)
|
||||||
|
}
|
||||||
|
defer C.procstat_freeauxv(ps, auxv)
|
||||||
|
|
||||||
|
for i := 0; i < int(count); i++ {
|
||||||
|
if auxv.a_type == C.AT_ENTRY {
|
||||||
|
return uint64(C.elf_aux_info_ptr(auxv)), nil
|
||||||
|
}
|
||||||
|
auxv = (*C.Elf_Auxinfo)(unsafe.Pointer(uintptr(unsafe.Pointer(auxv)) + unsafe.Sizeof(*auxv)))
|
||||||
|
}
|
||||||
|
return 0, errors.New("entry point not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dbp *nativeProcess) SupportsBPF() bool {
|
func (dbp *nativeProcess) SupportsBPF() bool {
|
||||||
@ -568,7 +631,6 @@ func (dbp *nativeProcess) ptraceCont(sig int) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usedy by Detach
|
|
||||||
func killProcess(pid int) error {
|
func killProcess(pid int) error {
|
||||||
return sys.Kill(pid, sys.SIGINT)
|
return sys.Kill(pid, sys.SIGINT)
|
||||||
}
|
}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
#include <sys/types.h>
|
|
||||||
#include <sys/user.h>
|
|
||||||
#include <libutil.h>
|
|
||||||
#include <libprocstat.h>
|
|
||||||
|
|
||||||
char * find_command_name(int pid);
|
|
||||||
char * find_executable(int pid);
|
|
||||||
int find_status(int pid);
|
|
||||||
uintptr_t get_entry_point(int pid);
|
|
Loading…
Reference in New Issue
Block a user