Skip to content

Commit aaacb30

Browse files
committed
feat: eBPF Collect Java crash log file hs_err_pid<pid>.log
1 parent 3236aa9 commit aaacb30

File tree

6 files changed

+243
-174
lines changed

6 files changed

+243
-174
lines changed

agent/src/ebpf/kernel/files_rw.bpf.c

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -346,16 +346,30 @@ static __inline int trace_io_event_common(void *ctx,
346346
v->coroutine_id = trace_key.goid;
347347
v->timestamp = data_args->enter_ts;
348348
v->syscall_len = sizeof(*buffer);
349-
v->source = DATA_SOURCE_IO_EVENT;
349+
// hs_err_pid
350+
if (buffer->filename[0] == 'h' && buffer->filename[1] == 's' &&
351+
buffer->filename[2] == '_' && buffer->filename[3] == 'e' &&
352+
buffer->filename[4] == 'r' && buffer->filename[5] == 'r' &&
353+
buffer->filename[6] == '_' && buffer->filename[7] == 'p') {
354+
v->source = DATA_SOURCE_FILE_WRITE;
355+
v->syscall_len = data_args->bytes_count;
356+
} else {
357+
return 0;
358+
v->source = DATA_SOURCE_IO_EVENT;
359+
v->syscall_len = sizeof(*buffer);
360+
}
350361
v->thread_trace_id = trace_id;
351362
v->msg_type = MSG_COMMON;
352363
bpf_get_current_comm(v->comm, sizeof(v->comm));
364+
bool is_vecs = false;
365+
if (data_args->iov != NULL)
366+
is_vecs = true;
353367
#if !defined(LINUX_VER_KFUNC) && !defined(LINUX_VER_5_2_PLUS)
354368
struct tail_calls_context *context =
355369
(struct tail_calls_context *)v->data;
356370
context->max_size_limit = data_max_sz;
357371
context->push_reassembly_bytes = 0;
358-
context->vecs = false;
372+
context->vecs = is_vecs;
359373
context->is_close = false;
360374
context->dir = direction;
361375
#ifdef SUPPORTS_KPROBE_ONLY
@@ -366,7 +380,7 @@ static __inline int trace_io_event_common(void *ctx,
366380
return 0;
367381
#else
368382
return __output_data_common(ctx, tracer_ctx, v_buff, data_args,
369-
direction, false, data_max_sz, false, 0);
383+
direction, is_vecs, data_max_sz, false, 0);
370384
#endif
371385
}
372386

@@ -479,7 +493,9 @@ TP_SYSCALL_PROG(exit_preadv2) (struct syscall_comm_exit_ctx * ctx) {
479493
#endif /* SUPPORTS_KPROBE_ONLY */
480494

481495
// File Write Event Tracing
482-
static __inline int do_sys_enter_pwrite(int fd, enum syscall_src_func fn)
496+
static __inline int do_sys_enter_pwrite(int fd, const char *buf,
497+
struct iovec *iov, int iovlen,
498+
enum syscall_src_func fn)
483499
{
484500
__u32 k0 = 0;
485501
struct member_fields_offset *offset = members_offset__lookup(&k0);
@@ -490,6 +506,9 @@ static __inline int do_sys_enter_pwrite(int fd, enum syscall_src_func fn)
490506
struct data_args_t write_args = {};
491507
write_args.source_fn = fn;
492508
write_args.fd = fd;
509+
write_args.buf = buf;
510+
write_args.iov = iov;
511+
write_args.iovlen = iovlen;
493512
write_args.enter_ts = bpf_ktime_get_ns();
494513
active_write_args_map__update(&id, &write_args);
495514
return 0;
@@ -500,7 +519,8 @@ static __inline int do_sys_enter_pwrite(int fd, enum syscall_src_func fn)
500519
#ifdef SUPPORTS_KPROBE_ONLY
501520
KPROG(ksys_pwrite64) (struct pt_regs * ctx) {
502521
int fd = (int)PT_REGS_PARM1(ctx);
503-
return do_sys_enter_pwrite(fd, SYSCALL_FUNC_PWRITE64);
522+
const char *buf = (char *)PT_REGS_PARM2(ctx);
523+
return do_sys_enter_pwrite(fd, buf, NULL, 0, SYSCALL_FUNC_PWRITE64);
504524
}
505525

506526
/*
@@ -510,25 +530,32 @@ KPROG(ksys_pwrite64) (struct pt_regs * ctx) {
510530
*/
511531
KPROG(do_pwritev) (struct pt_regs * ctx) {
512532
int fd = (int)PT_REGS_PARM1(ctx);
513-
return do_sys_enter_pwrite(fd, SYSCALL_FUNC_PWRITEV);
533+
struct iovec *iov = (struct iovec *)PT_REGS_PARM2(ctx);
534+
int iovlen = (int)PT_REGS_PARM3(ctx);
535+
return do_sys_enter_pwrite(fd, NULL, iov, iovlen, SYSCALL_FUNC_PWRITEV);
514536
}
515537
#else
516538
// /sys/kernel/debug/tracing/events/syscalls/sys_enter_pwrite64/format
517539
TP_SYSCALL_PROG(enter_pwrite64) (struct syscall_comm_enter_ctx * ctx) {
518540
int fd = ctx->fd;
519-
return do_sys_enter_pwrite(fd, SYSCALL_FUNC_PWRITE64);
541+
const char *buf = (const char *)ctx->buf;
542+
return do_sys_enter_pwrite(fd, buf, NULL, 0, SYSCALL_FUNC_PWRITE64);
520543
}
521544

522545
// /sys/kernel/debug/tracing/events/syscalls/sys_enter_pwritev/format
523546
TP_SYSCALL_PROG(enter_pwritev) (struct syscall_comm_enter_ctx * ctx) {
524547
int fd = ctx->fd;
525-
return do_sys_enter_pwrite(fd, SYSCALL_FUNC_PWRITEV);
548+
struct iovec *iov = (struct iovec *)ctx->buf;
549+
int iovlen = (int)ctx->count;
550+
return do_sys_enter_pwrite(fd, NULL, iov, iovlen, SYSCALL_FUNC_PWRITEV);
526551
}
527552

528553
// /sys/kernel/debug/tracing/events/syscalls/sys_enter_pwritev2/format
529554
TP_SYSCALL_PROG(enter_pwritev2) (struct syscall_comm_enter_ctx * ctx) {
530555
int fd = ctx->fd;
531-
return do_sys_enter_pwrite(fd, SYSCALL_FUNC_PWRITEV2);
556+
struct iovec *iov = (struct iovec *)ctx->buf;
557+
int iovlen = (int)ctx->count;
558+
return do_sys_enter_pwrite(fd, NULL, iov, iovlen, SYSCALL_FUNC_PWRITEV2);
532559
}
533560
#endif /* SUPPORTS_KPROBE_ONLY */
534561

agent/src/ebpf/kernel/include/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ enum process_data_extra_source {
112112
DATA_SOURCE_RESERVED,
113113
DATA_SOURCE_DPDK,
114114
DATA_SOURCE_UNIX_SOCKET,
115+
DATA_SOURCE_FILE_WRITE
115116
};
116117

117118
struct protocol_message_t {

agent/src/ebpf/kernel/socket_trace.bpf.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3282,12 +3282,14 @@ static __inline int __output_data_common(void *ctx,
32823282
* 1. The delay of the periodic push event exceeds the threshold (typically 50 milliseconds).
32833283
* 2. The number of events exceeds the maximum batch size (MAX_EVENTS_BURST, typically 32).
32843284
* 3. The data buffer is full (not enough space for another struct __socket_data).
3285+
* 4. Send the file content immediately when collecting it to prevent out-of-order issues caused by buffering.
32853286
*/
32863287
__u64 curr_time = bpf_ktime_get_ns();
32873288
__u64 diff = curr_time - tracer_ctx->last_period_timestamp;
32883289
if (diff > PERIODIC_PUSH_DELAY_THRESHOLD_NS ||
32893290
v_buff->events_num >= MAX_EVENTS_BURST ||
32903291
(args && args->extra_iovlen) ||
3292+
v->source == DATA_SOURCE_FILE_WRITE ||
32913293
((sizeof(v_buff->data) - v_buff->len) < sizeof(*v))) {
32923294
finalize_data_output(ctx, tracer_ctx, curr_time, diff, v_buff);
32933295
}
@@ -3391,6 +3393,7 @@ static __inline int output_data_common(void *ctx)
33913393
if (diff > PERIODIC_PUSH_DELAY_THRESHOLD_NS ||
33923394
v_buff->events_num >= MAX_EVENTS_BURST ||
33933395
(args && args->extra_iovlen) ||
3396+
v->source == DATA_SOURCE_FILE_WRITE ||
33943397
((sizeof(v_buff->data) - v_buff->len) < sizeof(*v))) {
33953398
finalize_data_output(ctx, tracer_ctx, curr_time, diff, v_buff);
33963399
}

agent/src/ebpf/samples/rust/socket-tracer/src/main.rs

Lines changed: 30 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -202,137 +202,6 @@ extern "C" fn debug_callback(_data: *mut c_char, len: c_int) {
202202
}
203203

204204
extern "C" fn socket_trace_callback(_: *mut c_void, queue_id: c_int, sd: *mut SK_BPF_DATA) -> c_int {
205-
unsafe {
206-
let mut proto_tag = String::from("");
207-
if sk_proto_safe(sd) == SOCK_DATA_OTHER {
208-
proto_tag.push_str("ORTHER");
209-
} else if sk_proto_safe(sd) == SOCK_DATA_HTTP1 {
210-
proto_tag.push_str("HTTP1");
211-
} else if sk_proto_safe(sd) == SOCK_DATA_HTTP2 {
212-
proto_tag.push_str("HTTP2");
213-
} else if sk_proto_safe(sd) == SOCK_DATA_DNS {
214-
proto_tag.push_str("DNS");
215-
} else if sk_proto_safe(sd) == SOCK_DATA_MYSQL {
216-
proto_tag.push_str("MYSQL");
217-
} else if sk_proto_safe(sd) == SOCK_DATA_POSTGRESQL {
218-
proto_tag.push_str("POSTGRESQL");
219-
} else if sk_proto_safe(sd) == SOCK_DATA_REDIS {
220-
proto_tag.push_str("REDIS");
221-
} else if sk_proto_safe(sd) == SOCK_DATA_KAFKA {
222-
proto_tag.push_str("KAFKA");
223-
} else if sk_proto_safe(sd) == SOCK_DATA_MQTT {
224-
proto_tag.push_str("MQTT");
225-
} else if sk_proto_safe(sd) == SOCK_DATA_AMQP {
226-
proto_tag.push_str("AMQP");
227-
} else if sk_proto_safe(sd) == SOCK_DATA_NATS {
228-
proto_tag.push_str("NATS");
229-
} else if sk_proto_safe(sd) == SOCK_DATA_PULSAR {
230-
proto_tag.push_str("PULSAR");
231-
} else if sk_proto_safe(sd) == SOCK_DATA_DUBBO {
232-
proto_tag.push_str("DUBBO");
233-
} else if sk_proto_safe(sd) == SOCK_DATA_SOFARPC {
234-
proto_tag.push_str("SOFARPC");
235-
} else if sk_proto_safe(sd) == SOCK_DATA_FASTCGI {
236-
proto_tag.push_str("FASTCGI");
237-
} else if sk_proto_safe(sd) == SOCK_DATA_BRPC {
238-
proto_tag.push_str("BRPC");
239-
} else if sk_proto_safe(sd) == SOCK_DATA_TARS {
240-
proto_tag.push_str("TARS");
241-
} else if sk_proto_safe(sd) == SOCK_DATA_SOME_IP {
242-
proto_tag.push_str("SomeIP");
243-
} else if sk_proto_safe(sd) == SOCK_DATA_ISO8583 {
244-
proto_tag.push_str("ISO8583");
245-
} else if sk_proto_safe(sd) == SOCK_DATA_MONGO {
246-
proto_tag.push_str("MONGO");
247-
} else if sk_proto_safe(sd) == SOCK_DATA_TLS {
248-
proto_tag.push_str("TLS");
249-
} else if sk_proto_safe(sd) == SOCK_DATA_ORACLE {
250-
proto_tag.push_str("ORACLE");
251-
} else if sk_proto_safe(sd) == SOCK_DATA_OPENWIRE {
252-
proto_tag.push_str("OPENWIRE");
253-
} else if sk_proto_safe(sd) == SOCK_DATA_ZMTP {
254-
proto_tag.push_str("ZMTP");
255-
} else if sk_proto_safe(sd) == SOCK_DATA_WEBSPHEREMQ {
256-
proto_tag.push_str("WEBSPHEREMQ");
257-
} else {
258-
proto_tag.push_str("UNSPEC");
259-
}
260-
261-
println!("+ --------------------------------- +");
262-
if sk_proto_safe(sd) == SOCK_DATA_HTTP1 {
263-
let data = sk_data_str_safe(sd);
264-
println!("{} <{}> BATCHLAST {} DIR {} TYPE {} PID {} THREAD_ID {} COROUTINE_ID {} CONTAINER_ID {} SOURCE {} ROLE {} COMM {} {} LEN {} SYSCALL_LEN {} SOCKET_ID 0x{:x} TRACE_ID 0x{:x} TCP_SEQ {} DATA_SEQ {} TLS {} TimeStamp {}\n{}",
265-
date_time((*sd).timestamp),
266-
proto_tag,
267-
(*sd).batch_last_data,
268-
(*sd).direction,
269-
(*sd).msg_type,
270-
(*sd).process_id,
271-
(*sd).thread_id,
272-
(*sd).coroutine_id,
273-
sd_container_id_safe(sd),
274-
(*sd).source,
275-
(*sd).socket_role,
276-
process_name_safe(sd),
277-
flow_info(sd),
278-
(*sd).cap_len,
279-
(*sd).syscall_len,
280-
(*sd).socket_id,
281-
(*sd).syscall_trace_id_call,
282-
(*sd).tcp_seq,
283-
(*sd).cap_seq,
284-
(*sd).is_tls,
285-
(*sd).timestamp,
286-
data);
287-
} else {
288-
let data: Vec<u8> = sk_data_bytes_safe(sd);
289-
println!("{} <{}> BATCHLAST {} DIR {} TYPE {} PID {} THREAD_ID {} COROUTINE_ID {} CONTAINER_ID {} SOURCE {} ROLE {} COMM {} {} LEN {} SYSCALL_LEN {} SOCKET_ID 0x{:x} TRACE_ID 0x{:x} TCP_SEQ {} DATA_SEQ {} TLS {} TimeStamp {}",
290-
date_time((*sd).timestamp),
291-
proto_tag,
292-
(*sd).batch_last_data,
293-
(*sd).direction,
294-
(*sd).msg_type,
295-
(*sd).process_id,
296-
(*sd).thread_id,
297-
(*sd).coroutine_id,
298-
sd_container_id_safe(sd),
299-
(*sd).source,
300-
(*sd).socket_role,
301-
process_name_safe(sd),
302-
flow_info(sd),
303-
(*sd).cap_len,
304-
(*sd).syscall_len,
305-
(*sd).socket_id,
306-
(*sd).syscall_trace_id_call,
307-
(*sd).tcp_seq,
308-
(*sd).cap_seq,
309-
(*sd).is_tls,
310-
(*sd).timestamp);
311-
if (*sd).source == 2 {
312-
print_uprobe_http2_info((*sd).cap_data, (*sd).cap_len);
313-
} else if (*sd).source == 4 {
314-
print_io_event_info((*sd).cap_data, (*sd).cap_len);
315-
} else if (*sd).source == 5 {
316-
print_uprobe_grpc_dataframe((*sd).cap_data, (*sd).cap_len);
317-
} else if sk_proto_safe(sd) == SOCK_DATA_OTHER {
318-
for x in data.into_iter() {
319-
print!("{} ", format!("{:02x}", x));
320-
}
321-
} else {
322-
for x in data.into_iter() {
323-
if x < 32 || x > 126 {
324-
print!(".");
325-
continue;
326-
}
327-
let b = x as char;
328-
print!("{0}", b);
329-
}
330-
}
331-
print!("\x1b[0m\n");
332-
}
333-
334-
println!("+ --------------------------------- +\n");
335-
}
336205

337206
0
338207
}
@@ -416,29 +285,29 @@ fn main() {
416285
}
417286
}
418287
unsafe {
419-
enable_ebpf_protocol(SOCK_DATA_HTTP1 as c_int);
420-
enable_ebpf_protocol(SOCK_DATA_HTTP2 as c_int);
421-
enable_ebpf_protocol(SOCK_DATA_DUBBO as c_int);
422-
enable_ebpf_protocol(SOCK_DATA_SOFARPC as c_int);
423-
enable_ebpf_protocol(SOCK_DATA_FASTCGI as c_int);
424-
enable_ebpf_protocol(SOCK_DATA_BRPC as c_int);
425-
enable_ebpf_protocol(SOCK_DATA_TARS as c_int);
426-
enable_ebpf_protocol(SOCK_DATA_SOME_IP as c_int);
427-
enable_ebpf_protocol(SOCK_DATA_ISO8583 as c_int);
428-
enable_ebpf_protocol(SOCK_DATA_MYSQL as c_int);
429-
enable_ebpf_protocol(SOCK_DATA_POSTGRESQL as c_int);
430-
enable_ebpf_protocol(SOCK_DATA_REDIS as c_int);
431-
enable_ebpf_protocol(SOCK_DATA_KAFKA as c_int);
432-
enable_ebpf_protocol(SOCK_DATA_MQTT as c_int);
433-
enable_ebpf_protocol(SOCK_DATA_AMQP as c_int);
434-
enable_ebpf_protocol(SOCK_DATA_OPENWIRE as c_int);
435-
enable_ebpf_protocol(SOCK_DATA_ZMTP as c_int);
436-
enable_ebpf_protocol(SOCK_DATA_WEBSPHEREMQ as c_int);
437-
enable_ebpf_protocol(SOCK_DATA_NATS as c_int);
438-
enable_ebpf_protocol(SOCK_DATA_PULSAR as c_int);
439-
enable_ebpf_protocol(SOCK_DATA_DNS as c_int);
440-
enable_ebpf_protocol(SOCK_DATA_MONGO as c_int);
441-
enable_ebpf_protocol(SOCK_DATA_TLS as c_int);
288+
// enable_ebpf_protocol(SOCK_DATA_HTTP1 as c_int);
289+
// enable_ebpf_protocol(SOCK_DATA_HTTP2 as c_int);
290+
// enable_ebpf_protocol(SOCK_DATA_DUBBO as c_int);
291+
// enable_ebpf_protocol(SOCK_DATA_SOFARPC as c_int);
292+
// enable_ebpf_protocol(SOCK_DATA_FASTCGI as c_int);
293+
// enable_ebpf_protocol(SOCK_DATA_BRPC as c_int);
294+
// enable_ebpf_protocol(SOCK_DATA_TARS as c_int);
295+
// enable_ebpf_protocol(SOCK_DATA_SOME_IP as c_int);
296+
// enable_ebpf_protocol(SOCK_DATA_ISO8583 as c_int);
297+
// enable_ebpf_protocol(SOCK_DATA_MYSQL as c_int);
298+
// enable_ebpf_protocol(SOCK_DATA_POSTGRESQL as c_int);
299+
// enable_ebpf_protocol(SOCK_DATA_REDIS as c_int);
300+
// enable_ebpf_protocol(SOCK_DATA_KAFKA as c_int);
301+
// enable_ebpf_protocol(SOCK_DATA_MQTT as c_int);
302+
// enable_ebpf_protocol(SOCK_DATA_AMQP as c_int);
303+
// enable_ebpf_protocol(SOCK_DATA_OPENWIRE as c_int);
304+
// enable_ebpf_protocol(SOCK_DATA_ZMTP as c_int);
305+
// enable_ebpf_protocol(SOCK_DATA_WEBSPHEREMQ as c_int);
306+
// enable_ebpf_protocol(SOCK_DATA_NATS as c_int);
307+
// enable_ebpf_protocol(SOCK_DATA_PULSAR as c_int);
308+
// enable_ebpf_protocol(SOCK_DATA_DNS as c_int);
309+
// enable_ebpf_protocol(SOCK_DATA_MONGO as c_int);
310+
// enable_ebpf_protocol(SOCK_DATA_TLS as c_int);
442311

443312
//set_feature_regex(
444313
// FEATURE_UPROBE_OPENSSL,
@@ -449,9 +318,9 @@ fn main() {
449318
// CString::new(".*".as_bytes()).unwrap().as_c_str().as_ptr(),
450319
//);
451320

452-
//set_io_event_collect_mode(1);
321+
set_io_event_collect_mode(2);
453322

454-
//set_io_event_minimal_duration(1000000);
323+
set_io_event_minimal_duration(10);
455324

456325
//// enable go auto traceing,
457326
//set_go_tracing_timeout(120);
@@ -682,11 +551,11 @@ fn main() {
682551
// test data limit max
683552
set_data_limit_max(10000);
684553

685-
//let empty_string = CString::new("").expect("CString::new failed");
686-
//if datadump_set_config(0, empty_string.as_ptr(), 0, 60, debug_callback) != 0 {
687-
// println!("datadump_set_config() error");
688-
// ::std::process::exit(1);
689-
//}
554+
let empty_string = CString::new("").expect("CString::new failed");
555+
if datadump_set_config(0, empty_string.as_ptr(), 0, 600000, debug_callback) != 0 {
556+
println!("datadump_set_config() error");
557+
::std::process::exit(1);
558+
}
690559

691560
print!("socket_tracer_start() finish\n");
692561

0 commit comments

Comments
 (0)