Просмотр исходного кода

fixed #TASK_QT-15441 jvm jvm 虚拟机 ebpf stack 堆栈采集

roger.wang 1 год назад
Родитель
Сommit
31efa94374

+ 7 - 2
build.sh

@@ -21,6 +21,11 @@ make -f Makefile2 all debug=1 pid=1121
 # TRACES_ENDPOINT=http://10.0.6.103:8099/docp/api/v2/data/receive BIN_TYPE=go DBG_PATH="" SEND=1 FILTER_PID=$pid WHITE_LIST="handle*|addw.*" ./euspace  --listen="0.0.0.0:8123"
 
 
-pid=`ps aux | grep CoreAoT | grep -v grep | awk '{print $2}'`
+# pid=`ps aux | grep CoreAoT | grep -v grep | awk '{print $2}'`
+# echo $pid
+# TRACES_ENDPOINT=http://10.0.6.103:8099/docp/api/v2/data/receive BIN_TYPE=dotnet DBG_PATH="/data/NET8/CoreAoT/bin/Debug/net8.0/linux-x64/publish/CoreAoT.dbg" SEND=1 FILTER_PID=$pid WHITE_LIST="main.*|Addwj.*|CoreAoT_Program___Main__.*" ./euspace  --listen="0.0.0.0:8123"
+
+
+pid=`pidof java`
 echo $pid
-TRACES_ENDPOINT=http://10.0.6.103:8099/docp/api/v2/data/receive BIN_TYPE=dotnet DBG_PATH="/data/NET8/CoreAoT/bin/Debug/net8.0/linux-x64/publish/CoreAoT.dbg" SEND=1 FILTER_PID=$pid WHITE_LIST="main.*|Addwj.*|CoreAoT_Program___Main__.*" ./euspace  --listen="0.0.0.0:8123"
+TRACES_ENDPOINT=http://10.0.6.103:8099/docp/api/v2/data/receive BIN_TYPE=java DBG_PATH="" SEND=1 FILTER_PID=$pid WHITE_LIST="handle*|addw.*" ./euspace  --listen="0.0.0.0:8124"

+ 30 - 11
containers/container_apm.go

@@ -2,8 +2,16 @@ package containers
 
 import (
 	"bufio"
+	"bytes"
 	"debug/elf"
 	"fmt"
+	"os"
+	"sort"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/coroot/coroot-node-agent/common"
 	"github.com/coroot/coroot-node-agent/ebpftracer"
 	"github.com/coroot/coroot-node-agent/ebpftracer/l7"
 	"github.com/coroot/coroot-node-agent/ebpftracer/tracer"
@@ -11,11 +19,6 @@ import (
 	"github.com/coroot/coroot-node-agent/utils"
 	"github.com/pkg/errors"
 	"inet.af/netaddr"
-	"os"
-	"sort"
-	"strconv"
-	"strings"
-	"time"
 )
 
 func (c *Container) getTrace(traceId uint64) (*tracing.Trace, bool) {
@@ -291,17 +294,33 @@ func (c *Container) StackProcess(event ebpftracer.StackEvent, tracer *ebpftracer
 	}
 }
 
+func byteExtractString(nameString [100]byte) string {
+	n := bytes.IndexByte(nameString[:], 0)
+	if n == -1 {
+		n = len(nameString) // 没找到零值,使用数组长度
+	}
+	return string(nameString[:n])
+}
+
 func (c *Container) StackProcess2(event ebpftracer.StackEvent, tracer *ebpftracer.Tracer) {
 	c.lock.Lock()
 	defer c.lock.Unlock()
 	// get the associated uprobe
 	switch event.Location {
 	case 0: // ret
-		uprobe, err := c.GetUprobe(event, tracer)
-		if err != nil {
-			fmt.Println("GetUprobeGetUprobe errer: %v", err)
-			// log.Errorf("failed to get uprobe for event %+v: %+v", event, err)
-			return
+		Funcname := ""
+		if event.Type != uint64(common.CodeTypeJava) {
+			uprobe, err := c.GetUprobe(event, tracer)
+			if err != nil {
+				fmt.Println("GetUprobeGetUprobe errer: %v", err)
+				// log.Errorf("failed to get uprobe for event %+v: %+v", event, err)
+				return
+			}
+			Funcname = uprobe.Funcname
+		} else {
+			ClassName := byteExtractString(event.ClassName)
+			MethedName := byteExtractString(event.MethedName)
+			Funcname = ClassName + "." + MethedName
 		}
 
 		if event.TraceId <= 0 {
@@ -315,7 +334,7 @@ func (c *Container) StackProcess2(event ebpftracer.StackEvent, tracer *ebpftrace
 		if err == nil {
 			//fmt.Println("append FuncTraceQuery fun:", event.TraceId, uprobe.Funcname, event.Pid)
 			duration := event.TimeNsEnd - event.TimeNsStart
-			apmTrace.FuncTraceQuery(uprobe.Funcname, time.Duration(duration), event.TimeNsStart, event.TimeNsEnd)
+			apmTrace.FuncTraceQuery(Funcname, time.Duration(duration), event.TimeNsStart, event.TimeNsEnd)
 			c.SendEvent(apmTrace, event.TraceId)
 		}
 	}

+ 14 - 2
containers/registry.go

@@ -243,7 +243,14 @@ func (r *Registry) handleEvents(ch <-chan ebpftracer.Event) {
 					//c.attachTlsUprobes(r.tracer, e.Pid)
 					// c.attachJVMUprobes(r.tracer, e.Pid)
 					c.attachUprobes(r.tracer, e.Pid)
-					err := c.stackTrace(r.tracer, e.Pid)
+					codeType := c.GetCodeTypeFromCache(e.Pid)
+					err := error(nil)
+					if codeType.IsJvmCode() {
+						err = c.jvmStackTrace(r.tracer, e.Pid)
+					} else {
+						err = c.stackTrace(r.tracer, e.Pid)
+					}
+
 					if err != nil {
 						klog.Errorf("Stack trace error", err)
 					}
@@ -307,7 +314,12 @@ func (r *Registry) handleEvents(ch <-chan ebpftracer.Event) {
 				}
 
 				if c := r.containersByPid[uint32(e.StackEvent.Pid)]; c != nil {
-					fmt.Printf("e.EventTypeFunEnt: TraceId:%d, Pid:%d, Location:%d, Goid:%d, TimeNs:%d, Ip:%X, CallerIp:%x, Bp:%x, CallerBp:%x\n", e.StackEvent.TraceId, e.StackEvent.Pid, e.StackEvent.Location, e.StackEvent.Goid, e.StackEvent.TimeNsStart, e.StackEvent.Ip, e.StackEvent.CallerIp, e.StackEvent.Bp, e.StackEvent.CallerBp)
+					if e.StackEvent.Type == uint64(common.CodeTypeJava) {
+						fmt.Printf("e.EventTypeFunEnt: TraceId:%d, Pid:%d, Location:%d, Goid:%d, TimeNs:%d, Ip:%X, CallerIp:%d, Bp:%d, CallerBp:%d\n", e.StackEvent.TraceId, e.StackEvent.Pid, e.StackEvent.Location, e.StackEvent.Goid, e.StackEvent.TimeNsStart, e.StackEvent.Ip, e.StackEvent.CallerIp, e.StackEvent.Bp, e.StackEvent.CallerBp)
+						fmt.Printf("e.EventTypeFunEnt: TraceId: MethedName: %d -- %s -- %s", e.StackEvent.Type, e.StackEvent.MethedName, e.StackEvent.ClassName)
+					} else {
+						fmt.Printf("e.EventTypeFunEnt: TraceId:%d, Pid:%d, Location:%d, Goid:%d, TimeNs:%d, Ip:%X, CallerIp:%x, Bp:%x, CallerBp:%x\n", e.StackEvent.TraceId, e.StackEvent.Pid, e.StackEvent.Location, e.StackEvent.Goid, e.StackEvent.TimeNsStart, e.StackEvent.Ip, e.StackEvent.CallerIp, e.StackEvent.Bp, e.StackEvent.CallerBp)
+					}
 					c.StackProcess2(*e.StackEvent, r.tracer)
 				} else {
 					// fmt.Printf("e.EventTypeFunEnt ErrorError: TraceId:%d, Pid:%d, Location:%d, Goid:%d, TimeNs:%d, Ip:%X, CallerIp:%x, Bp:%x, CallerBp:%x", e.StackEvent.TraceId, e.StackEvent.Pid, e.StackEvent.Location, e.StackEvent.Goid, e.StackEvent.TimeNsStart, e.StackEvent.Ip, e.StackEvent.CallerIp, e.StackEvent.Bp, e.StackEvent.CallerBp)

+ 14 - 0
containers/stack.go

@@ -95,6 +95,20 @@ func (c *Container) stackTrace(tracer *ebpftracer.Tracer, pid uint32) error {
 	return nil
 }
 
+func (c *Container) jvmStackTrace(tracer *ebpftracer.Tracer, pid uint32) error {
+	// 禁用stack
+	if tracer.DisableStackTracing() {
+		return nil
+	}
+
+	p := c.processes[pid]
+
+	p.uprobes = append(p.uprobes, tracer.AttachJVMStackUprobes("", c.Uprobes)...)
+	p.stackUprobesChecked = true
+
+	return nil
+}
+
 func (c *Container) getJavaAOTUprobes(binType, path string, dbgpath string, MatchString string) ([]tracer.Uprobe, error) {
 	uprobes := []tracer.Uprobe{}
 

+ 2 - 1
containers/util.go

@@ -3,13 +3,14 @@ package containers
 import (
 	"debug/elf"
 	"fmt"
-	"github.com/coroot/coroot-node-agent/common"
 	"io/ioutil"
 	"os"
 	"os/exec"
 	"regexp"
 	"runtime"
 	"strings"
+
+	"github.com/coroot/coroot-node-agent/common"
 )
 
 var libjvmRegex = regexp.MustCompile(`.*/libjvm\.so`)

+ 11 - 11
ebpftracer/ebpf/common/common.h

@@ -7,7 +7,7 @@
 //    char ____fmt[] = fmt;                                      \
 //    bpf_trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__); \
 //})
-#ifdef _DEBUG_MODE
+// #ifdef _DEBUG_MODE
 #define cw_bpf_debug(fmt, ...)                                 \
 ({                                                             \
     char ____fmt[] = fmt;                                      \
@@ -18,16 +18,16 @@
     char ____fmt[] = fmt;                                      \
     bpf_trace_printk(____fmt, sizeof(____fmt), ##__VA_ARGS__); \
 })
-#else
-#define cw_bpf_debug(fmt, ...)                                  \
-({                                                              \
-                                                                \
-})
-#define debug(fmt, ...)                                         \
-({                                                              \
-                                                                \
-})
-#endif
+// #else
+// #define cw_bpf_debug(fmt, ...)                                  \
+// ({                                                              \
+//                                                                 \
+// })
+// #define debug(fmt, ...)                                         \
+// ({                                                              \
+//                                                                 \
+// })
+// #endif
 
 
 /* Helper macro to print out debug messages */

+ 1 - 0
ebpftracer/ebpf/ebpf.c

@@ -54,6 +54,7 @@
 #include "utrace/go/net/server.probe.bpf.c"
 #include "utrace/go/net/client.probe.bpf.c"
 #include "utrace/go/net/stack.probe.bpf.c"
+#include "utrace/go/net/jvmstack.probe.bpf.c"
 
 #include "utrace/java/net/server.probe.bpf.c"
 #include "utrace/java/net/client.probe.bpf.c"

+ 248 - 0
ebpftracer/ebpf/utrace/go/net/jvmstack.probe.bpf.c

@@ -0,0 +1,248 @@
+#include "arguments.h"
+#include "span_context.h"
+#include "go_context.h"
+#include "go_types.h"
+#include "uprobe.h"
+
+struct jvm_trace_stack_entry_key_t {
+	__u64 trace_id;
+	__u64 pid;
+	__u64 caller_bp;
+	__u64 bp;
+};
+
+struct {
+	__uint(type, BPF_MAP_TYPE_LRU_HASH);
+	__uint(key_size, sizeof(struct jvm_trace_stack_entry_key_t));
+	__uint(value_size, sizeof(struct event));
+	__uint(max_entries, 32768);
+} jvmwww_trace_stack_entry SEC(".maps");
+
+struct bpf_map_def SEC("maps") jvmevent_stack = {
+	.type = BPF_MAP_TYPE_PERCPU_ARRAY,
+	.key_size = sizeof(__u32),
+	.value_size = sizeof(struct event),
+	.max_entries = 1,
+};
+
+SEC("uprobe/setNodeEnter")
+int setNodeEnter(struct pt_regs *ctx)
+{
+    cw_bpf_debug("[Go] [uprobe/setNodeEnter] enter");
+	__u64 pid_tgid = bpf_get_current_pid_tgid();
+    __u64 pid = pid_tgid >> 32;
+
+	struct ebpf_proc_info *info = bpf_map_lookup_elem(&proc_info_map, &pid);
+	if (!info) {
+		return 0;
+	}
+
+	cw_bpf_debug("[Go] [uprobe/setNodeEnter]: proc_info_map::%ld, %d, %d\n", info->code_type);
+
+	__u64 trace_id = get_apm_trace_id(pid, pid_tgid);
+
+	cw_bpf_debug("[Go] [uprobe/setNodeEnter]: get_apm_trace_id::%ld, %d, %d\n", trace_id, pid, pid_tgid);
+	cw_bpf_debug("[Go] [uprobeThread/pidpidpidpid][setNodeEnter][HTTP]pid:[%d]--[%lld]--[%x]", pid_tgid, bpf_ktime_get_ns(), PT_REGS_IP(ctx));
+
+	__u32 key = 0;
+	struct event *e = bpf_map_lookup_elem(&jvmevent_stack, &key);
+	if (!e)
+	{
+		cw_bpf_debug("[Go] [uprobe/setNodeEnter]: conot get event");
+		return 0;
+	}
+	__builtin_memset(e, 0, sizeof(*e));
+
+	// e->goid = get_goid();
+	e->goid = get_current_goroutine();
+
+	// e->ip = ctx->ip;
+	e->ip = PT_REGS_IP(ctx); // 当前函数的地址
+	e->caller_bp = (__u64)PT_REGS_PARM5(ctx);
+	e->bp = (__u64)PT_REGS_PARM6(ctx);
+
+	e->pid = pid;
+	e->trace_id = trace_id;
+	e->location = ENTPOINT; // 标识入口还是出口
+	e->time_ns_start = bpf_ktime_get_ns();
+
+    // bpf_probe_read_user(&e->caller_bp, sizeof(e->caller_bp), (void *)(PT_REGS_SP(ctx) + 8));  
+    // bpf_probe_read_user(&e->bp, sizeof(e->bp), (void *)(PT_REGS_SP(ctx) + 16)); 
+	// cw_bpf_debug("[Go] [uprobe/setNodeEnter]: e->arg7: arg8: %d, %d", e->caller_bp, e->bp);
+
+	__u64 arg7, arg8;  
+    bpf_probe_read_user(&arg7, sizeof(arg7), (void *)(PT_REGS_SP(ctx) + 8));  
+    bpf_probe_read_user(&arg8, sizeof(arg8), (void *)(PT_REGS_SP(ctx) + 16)); 
+
+	cw_bpf_debug("[Go] [uprobe/setNodeEnter]: e->arg7: arg8: %d, %d", arg7, arg8);
+
+	cw_bpf_debug("[Go] [uprobe/setNodeEnter]: e->caller_bp: %d", e->caller_bp);
+	cw_bpf_debug("[Go] [uprobe/setNodeEnter]: e->bp: %d", e->bp);
+	cw_bpf_debug("[Go] [uprobe/setNodeEnter]: e->ip: %d", e->ip);
+	cw_bpf_debug("[Go] [uprobe/setNodeEnter]: yes");
+
+	struct jvm_trace_stack_entry_key_t trace_key = {};
+	trace_key.caller_bp = e->caller_bp;
+	trace_key.bp = e->bp;
+	trace_key.pid = pid;
+	trace_key.trace_id = trace_id;
+
+	cw_bpf_debug("[Go] [uprobe/ent]: trace_keytrace_keytrace_key: trace_id: %llu", trace_key.trace_id);
+	cw_bpf_debug("[Go] [uprobe/setNodeEnter]: trace_keytrace_keytrace_key: caller_bp: %d, bp: %d, pid: %lld", trace_key.caller_bp, trace_key.bp, trace_key.pid);
+
+	struct event *event_p = bpf_map_lookup_elem(&jvmwww_trace_stack_entry, &trace_key);
+
+	if (event_p) {
+		cw_bpf_debug("[Go] [uprobe/ent]:Error get alike funEntry %x, %d, %d", event_p->ip, event_p->caller_bp, event_p->bp);
+	}
+
+	struct event event_current = {};
+	event_current.type = CodeTypeJava,
+	event_current.caller_bp = e->caller_bp,
+	event_current.bp = e->bp,
+	event_current.pid = e->pid,
+	event_current.trace_id = e->trace_id,
+	event_current.goid = e->goid,
+	event_current.ip = e->ip,
+	event_current.time_ns_start = e->time_ns_start,
+	event_current.location = e->location,
+
+	bpf_map_update_elem(&jvmwww_trace_stack_entry, &trace_key, &event_current, BPF_ANY);
+
+	struct event *event_p2 = bpf_map_lookup_elem(&jvmwww_trace_stack_entry, &trace_key);
+
+	if (event_p2) {
+		cw_bpf_debug("[Go] [uprobe/setNodeEnter---]:Error get alike funEntry %x, %d, %d", event_p2->ip, event_p2->caller_bp, event_p2->bp);
+		// return 0;
+	} else {
+		cw_bpf_debug("[Go] [uprobe/setNodeEnter+++]:Error get alike funEntry");
+	}
+
+	cw_bpf_debug("[Go] [uprobe/setNodeEnter] end");
+	return 1;
+}
+
+SEC("uprobe/setNodeReturn")
+int setNodeReturn(struct pt_regs *ctx)
+{
+    cw_bpf_debug("[Go] [uprobe/setNodeReturn] enter");
+	__u64 pid_tgid = bpf_get_current_pid_tgid();
+    __u64 pid = pid_tgid >> 32;
+
+	__u64 trace_id = get_apm_trace_id(pid, pid_tgid);
+	__u32 key = 0;
+	struct event *e = bpf_map_lookup_elem(&jvmevent_stack, &key);
+	if (!e)
+	{
+		cw_bpf_debug("[Go] [uprobe/setNodeReturn]: conot get event");
+		return 0;
+	}
+	__builtin_memset(e, 0, sizeof(*e));
+
+	// ------- 获取 class_name 和 methed_name  Start
+	__u64 class_name_len;
+    bpf_probe_read_user(&class_name_len, sizeof(class_name_len), (void *)(PT_REGS_SP(ctx) + 8));  
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: e->class_name_len: %lld", class_name_len);
+
+	void *rdx_ptr = (void *)PT_REGS_PARM3(ctx);
+
+	void* class_name_ptr;
+    if (bpf_probe_read(&class_name_ptr, sizeof(class_name_ptr), rdx_ptr)) {
+        // return 1;
+    }
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: e->class_name_ptr: %llx", class_name_ptr);
+
+	if (class_name_len >= 100) {
+		class_name_len = 99;
+	}
+	if (class_name_len <= 0) {
+		class_name_len = 0;
+	}
+
+    bpf_probe_read(e->class_name, sizeof(e->class_name), class_name_ptr + 16); 
+	// e->class_name[class_name_len] = '\0';
+
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: e->class_name: %s", e->class_name);
+
+	__u64 methed_name_len;
+	bpf_probe_read_user(&methed_name_len, sizeof(methed_name_len), (void *)(PT_REGS_SP(ctx) + 16)); 
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: e->methed_name_len: %lld", methed_name_len);
+
+	void *rcx_ptr = (void *)PT_REGS_PARM4(ctx);
+
+	void* methed_name_ptr;
+    if (bpf_probe_read(&methed_name_ptr, sizeof(methed_name_ptr), rcx_ptr)) {
+        // return 1;
+    }
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: e->methed_name_ptr: %llx", methed_name_ptr);
+
+	if (methed_name_len >= 100) {
+		methed_name_len = 99;
+	}
+	if (methed_name_len <= 0) {
+		methed_name_len = 0;
+	}
+    bpf_probe_read(e->methed_name, sizeof(e->methed_name), methed_name_ptr + 16); 
+	// e->methed_name[methed_name_len] = '\0';
+
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: e->methed_name: %s", e->methed_name);
+
+	// ------- 获取 class_name 和 methed_name End
+
+	e->goid = get_current_goroutine();
+	e->pid = pid;
+	e->type = CodeTypeJava;
+	e->trace_id = trace_id;
+	e->location = ENTPOINT; // 标识入口还是出口
+	e->caller_bp = (__u64)PT_REGS_PARM5(ctx);
+	e->bp = (__u64)PT_REGS_PARM6(ctx);
+	e->time_ns_end = bpf_ktime_get_ns();
+
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: e->caller_bp: %llu", e->caller_bp);
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: e->bp: %llu", e->bp);
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: e->ip: %d", e->ip);
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: yes");
+
+	struct jvm_trace_stack_entry_key_t trace_key = {};
+	trace_key.caller_bp = e->caller_bp;
+	trace_key.bp = e->bp;
+	trace_key.pid = pid;
+	trace_key.trace_id = trace_id;
+
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: trace_keytrace_keytrace_key: trace_id: %llu", trace_key.trace_id);
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: trace_keytrace_keytrace_key: caller_bp: %llu, bp: %llu, pid: %lld", trace_key.caller_bp, trace_key.bp, trace_key.pid);
+	
+	struct event *event_p = bpf_map_lookup_elem(&jvmwww_trace_stack_entry, &trace_key);
+
+	if (event_p) {
+		cw_bpf_debug("[Go] [uprobe/setNodeReturn---]:Error get alike funEntry %x, %d, %d", event_p->ip, event_p->caller_bp, event_p->bp);
+		// return 0;
+	} else {
+		cw_bpf_debug("[Go] [uprobe/setNodeReturn+++]:Error get alike funEntry");
+	}
+
+	if (!event_p) {
+		cw_bpf_debug("[Go] [uprobe/setNodeReturn]:ErrorErrorErrorError Not get funEntry");
+		return 0;
+	}
+
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: ent:event: location:%d,ip:%x,time_ns_start:%llu\n", event_p->location, event_p->ip, event_p->time_ns_start);
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: ent:event: bp:%d,caller_bp:%d,caller_ip:%llu\n", event_p->caller_bp, event_p->bp, event_p->trace_id);
+
+	e->time_ns_start = event_p->time_ns_start;
+	
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn]: ent:event_ret push: event_p->ip:%llx,ip:%llx\n", event_p->ip, e->ip);
+	long err =  bpf_perf_event_output(ctx, &event_queue, BPF_F_CURRENT_CPU, e, sizeof(*e));
+	if (err == 0) {
+		__u32 count = cw_add_event_count(trace_id);
+		if (event_p->trace_id != trace_id) {
+			cw_bpf_debug("[pref] fuck err<%d> ip->%x->%x", err, PT_REGS_IP(ctx), e->ip);
+		}
+		cw_bpf_debug("[pref] err<%d> count->%d trace_id->%llu", err, count, trace_id);
+	} else {
+		cw_bpf_debug("[pref] err<%d> trace_id->%d", err, trace_id);
+	}
+	bpf_map_delete_elem(&jvmwww_trace_stack_entry, &trace_key);
+	cw_bpf_debug("[Go] [uprobe/setNodeReturn] end");
+	return 1;
+}

+ 3 - 0
ebpftracer/ebpf/utrace/go/net/stack.probe.bpf.c

@@ -12,6 +12,7 @@
 // bpf write event data when enter/exit a function
 struct event
 {
+	__u64 type;
 	__u64 pid;
 	__u64 trace_id;
 	__u64 goid;
@@ -22,6 +23,8 @@ struct event
 	__u64 time_ns_start;
 	__u64 time_ns_end;
 	__u8 location;
+	unsigned char class_name[100];
+	unsigned char methed_name[100];
 }__attribute__((packed));
 
 struct trace_stack_entry_key_t {

+ 3 - 2
ebpftracer/jvm.go

@@ -2,12 +2,13 @@ package ebpftracer
 
 import (
 	"errors"
-	"github.com/coroot/coroot-node-agent/common"
-	"github.com/coroot/coroot-node-agent/ebpftracer/tracer/inject"
 	"io/ioutil"
 	"runtime"
 	"strings"
 
+	"github.com/coroot/coroot-node-agent/common"
+	"github.com/coroot/coroot-node-agent/ebpftracer/tracer/inject"
+
 	"debug/elf"
 	"fmt"
 	"path/filepath"

+ 33 - 1
ebpftracer/stack.go

@@ -30,7 +30,7 @@ func (t *Tracer) AttachStackUprobes(path string, uprobes []tracer.Uprobe) []link
 		}
 		uplink, err := ex.Uprobe(up.Funcname, prog, &link.UprobeOptions{Address: up.Address, Offset: up.AbsOffset})
 		if err != nil {
-			fmt.Printf("attachingERROR:%v, %v, %v\n", err, up, uplink)
+			fmt.Printf("attaching ERROR:%v, %v, %v\n", err, up, uplink)
 			// return nil
 		} else {
 			links = append(links, uplink)
@@ -38,3 +38,35 @@ func (t *Tracer) AttachStackUprobes(path string, uprobes []tracer.Uprobe) []link
 	}
 	return links
 }
+
+func (t *Tracer) AttachJVMStackUprobes(path string, uprobes []tracer.Uprobe) []link.Link {
+	path = "/opt/cloudwise/smartagent/agent/NativeAgent/libnativeAgent.so"
+
+	setNodeEnter := "Java_com_cloudwise_agent_common_natives_TraceNative_setNodeEnter"
+	setNodeReturn := "Java_com_cloudwise_agent_common_natives_TraceNative_setNodeReturn"
+
+	fmt.Println("Attach Start AttachJVMStackUprobes", path)
+
+	var links []link.Link
+	ex, err := link.OpenExecutable(path)
+	if err != nil {
+		return nil
+	}
+
+	fmt.Println("Attach Start " + setNodeEnter)
+	uplink, err := ex.Uprobe(setNodeEnter, t.uprobes["setNodeEnter"], &link.UprobeOptions{Offset: 0x0})
+	if err != nil {
+		fmt.Printf("attaching ERROR: %v, %v, %v\n", err, setNodeEnter, uplink)
+	} else {
+		links = append(links, uplink)
+	}
+
+	fmt.Println("Attach Start " + setNodeReturn)
+	uplink, err = ex.Uprobe(setNodeReturn, t.uprobes["setNodeReturn"], &link.UprobeOptions{Offset: 0x0})
+	if err != nil {
+		fmt.Printf("attaching ERROR: %v, %v, %v\n", err, setNodeReturn, uplink)
+	} else {
+		links = append(links, uplink)
+	}
+	return links
+}

+ 4 - 1
ebpftracer/tracer.go

@@ -470,6 +470,7 @@ type SocketDatadddd struct {
 }
 
 type StackEvent struct {
+	Type        uint64
 	Pid         uint64
 	TraceId     uint64
 	Goid        uint64
@@ -482,7 +483,9 @@ type StackEvent struct {
 	// Nid         uint64
 	// Fpid        uint64
 	// Level       uint64
-	Location byte
+	Location   byte
+	ClassName  [100]byte
+	MethedName [100]byte
 }
 
 type StackFunEvent struct {

+ 7 - 2
run.sh

@@ -13,6 +13,11 @@
 # echo $pid
 # TRACES_ENDPOINT=http://10.0.6.103:8099/docp/api/v2/data/receive BIN_TYPE=go DBG_PATH="" SEND=1 FILTER_PID=$pid WHITE_LIST="handle*|addw.*" ./euspace  --listen="0.0.0.0:8124"
 
-pid=`ps aux | grep CoreAoT | grep -v grep | awk '{print $2}'`
+# pid=`ps aux | grep CoreAoT | grep -v grep | awk '{print $2}'`
+# echo $pid
+# TRACES_ENDPOINT=http://10.0.6.103:8099/docp/api/v2/data/receive BIN_TYPE=dotnet DBG_PATH="/data/NET8/CoreAoT/bin/Debug/net8.0/linux-x64/publish/CoreAoT.dbg" SEND=1 FILTER_PID=$(pidof CoreAoT) WHITE_LIST="main.*|Addwj.*|CoreAoT_Program___Main__.*|*SocketConnection__Start*" ./euspace  --listen="0.0.0.0:8123"
+
+
+pid=`pidof java`
 echo $pid
-TRACES_ENDPOINT=http://10.0.6.103:8099/docp/api/v2/data/receive BIN_TYPE=dotnet DBG_PATH="/data/NET8/CoreAoT/bin/Debug/net8.0/linux-x64/publish/CoreAoT.dbg" SEND=1 FILTER_PID=$(pidof CoreAoT) WHITE_LIST="main.*|Addwj.*|CoreAoT_Program___Main__.*|*SocketConnection__Start*" ./euspace  --listen="0.0.0.0:8123"
+TRACES_ENDPOINT=http://10.0.12.192:18080/docp/api/v2/data/receive BIN_TYPE=java DBG_PATH="" SEND=1 FILTER_PID=$pid WHITE_LIST="handle*|addw.*" ./euspace  --listen="0.0.0.0:8124"