1use crate::commands::event_kinds;
6use crate::protocol::JdwpResult;
7use crate::reader::{read_i32, read_string, read_u64, read_u8};
8use crate::types::{FieldId, Location, ObjectId, ReferenceTypeId, ThreadId, Value};
9use serde::{Deserialize, Serialize};
10use tracing::warn;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct EventSet {
15 pub suspend_policy: u8,
16 pub events: Vec<Event>,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct Event {
22 pub kind: u8,
23 pub request_id: i32,
24 pub details: EventKind,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
28#[serde(tag = "type")]
29pub enum EventKind {
30 VMStart {
31 thread: ThreadId,
32 },
33 VMDeath,
34 ThreadStart {
35 thread: ThreadId,
36 },
37 ThreadDeath {
38 thread: ThreadId,
39 },
40 ClassPrepare {
41 thread: ThreadId,
42 ref_type: ReferenceTypeId,
43 signature: String,
44 status: i32,
45 },
46 Breakpoint {
47 thread: ThreadId,
48 location: Location,
49 },
50 Step {
51 thread: ThreadId,
52 location: Location,
53 },
54 Exception {
55 thread: ThreadId,
56 location: Location,
57 exception: ObjectId,
58 catch_location: Option<Location>,
59 },
60 MethodExit {
68 thread: ThreadId,
69 location: Location,
70 return_value: Option<Value>,
74 },
75 FieldAccess {
77 field: FieldEvent,
78 },
79 FieldModification {
83 field: FieldEvent,
84 new_value: Value,
86 },
87 MonitorContendedEnter {
91 monitor: MonitorEvent,
92 },
93 MonitorContendedEntered {
100 monitor: MonitorEvent,
101 },
102 MonitorWait {
104 monitor: MonitorEvent,
105 timeout: i64,
109 },
110 MonitorWaited {
112 monitor: MonitorEvent,
113 timed_out: bool,
117 },
118 Unknown {
119 kind: u8,
120 },
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct MonitorEvent {
129 pub thread: ThreadId,
131 pub location: Location,
134 pub monitor: ObjectId,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct FieldEvent {
143 pub thread: ThreadId,
144 pub location: Location,
146 pub ref_type: ReferenceTypeId,
148 pub field_id: FieldId,
149 pub object: ObjectId,
151}
152
153#[derive(Debug, Clone)]
155pub enum EventModifier {
156 Count(i32),
157 ThreadOnly(ThreadId),
158 ClassOnly(ReferenceTypeId),
159 ClassMatch(String),
160 ClassExclude(String),
161 LocationOnly(Location),
162 ExceptionOnly { ref_type: ReferenceTypeId, caught: bool, uncaught: bool },
163 FieldOnly { ref_type: ReferenceTypeId, field_id: FieldId },
164 Step { thread: ThreadId, size: i32, depth: i32 },
165 InstanceOnly(ObjectId),
166}
167
168pub fn parse_event_packet(data: &[u8]) -> JdwpResult<EventSet> {
173 let mut buf = data;
174
175 let suspend_policy = read_u8(&mut buf)?;
177
178 let event_count = read_i32(&mut buf)?;
180
181 let mut events = Vec::with_capacity(usize::try_from(event_count).unwrap_or(0));
182
183 for _ in 0..event_count {
184 let kind = read_u8(&mut buf)?;
185 let request_id = read_i32(&mut buf)?;
186
187 let details = parse_event_details(kind, &mut buf)?;
188
189 events.push(Event { kind, request_id, details });
190 }
191
192 Ok(EventSet { suspend_policy, events })
193}
194
195fn parse_event_details(kind: u8, buf: &mut &[u8]) -> JdwpResult<EventKind> {
203 if let Some(parsed) = parse_vm_lifecycle_event(kind, buf) {
204 return parsed;
205 }
206 if let Some(parsed) = parse_monitor_event(kind, buf) {
207 return parsed;
208 }
209 match kind {
210 event_kinds::BREAKPOINT => parse_breakpoint_event(buf),
211 event_kinds::SINGLE_STEP => parse_step_event(buf),
212 event_kinds::EXCEPTION => parse_exception_event(buf),
213 event_kinds::FIELD_ACCESS => parse_field_access_event(buf),
214 event_kinds::FIELD_MODIFICATION => parse_field_modification_event(buf),
215 event_kinds::METHOD_EXIT => parse_method_exit_event(buf, false),
216 event_kinds::METHOD_EXIT_WITH_RETURN_VALUE => parse_method_exit_event(buf, true),
217 _ => {
218 warn!("Unsupported event kind: {}", kind);
219 Ok(EventKind::Unknown { kind })
220 }
221 }
222}
223
224fn parse_vm_lifecycle_event(kind: u8, buf: &mut &[u8]) -> Option<JdwpResult<EventKind>> {
230 match kind {
231 event_kinds::VM_START => Some(parse_vm_start_event(buf)),
232 event_kinds::VM_DEATH => Some(Ok(EventKind::VMDeath)),
233 event_kinds::THREAD_START => Some(parse_thread_start_event(buf)),
234 event_kinds::THREAD_DEATH => Some(parse_thread_death_event(buf)),
235 event_kinds::CLASS_PREPARE => Some(parse_class_prepare_event(buf)),
236 _ => None,
237 }
238}
239
240fn parse_monitor_event(kind: u8, buf: &mut &[u8]) -> Option<JdwpResult<EventKind>> {
245 match kind {
246 event_kinds::MONITOR_CONTENDED_ENTER => {
247 Some(parse_monitor_event_head(buf).map(|monitor| EventKind::MonitorContendedEnter { monitor }))
248 }
249 event_kinds::MONITOR_CONTENDED_ENTERED => {
250 Some(parse_monitor_event_head(buf).map(|monitor| EventKind::MonitorContendedEntered { monitor }))
251 }
252 event_kinds::MONITOR_WAIT => Some(parse_monitor_wait_event(buf)),
253 event_kinds::MONITOR_WAITED => Some(parse_monitor_waited_event(buf)),
254 _ => None,
255 }
256}
257
258fn parse_breakpoint_event(buf: &mut &[u8]) -> JdwpResult<EventKind> {
259 let thread = read_u64(buf)?;
260 let location = read_location(buf)?;
261 Ok(EventKind::Breakpoint { thread, location })
262}
263
264fn parse_step_event(buf: &mut &[u8]) -> JdwpResult<EventKind> {
265 let thread = read_u64(buf)?;
266 let location = read_location(buf)?;
267 Ok(EventKind::Step { thread, location })
268}
269
270fn parse_vm_start_event(buf: &mut &[u8]) -> JdwpResult<EventKind> {
271 let thread = read_u64(buf)?;
272 Ok(EventKind::VMStart { thread })
273}
274
275fn parse_thread_start_event(buf: &mut &[u8]) -> JdwpResult<EventKind> {
276 let thread = read_u64(buf)?;
277 Ok(EventKind::ThreadStart { thread })
278}
279
280fn parse_thread_death_event(buf: &mut &[u8]) -> JdwpResult<EventKind> {
281 let thread = read_u64(buf)?;
282 Ok(EventKind::ThreadDeath { thread })
283}
284
285fn parse_class_prepare_event(buf: &mut &[u8]) -> JdwpResult<EventKind> {
286 let thread = read_u64(buf)?;
288 let _ref_type_tag = read_u8(buf)?;
289 let ref_type = read_u64(buf)?;
290 let signature = read_string(buf)?;
291 let status = read_i32(buf)?;
292 Ok(EventKind::ClassPrepare { thread, ref_type, signature, status })
293}
294
295fn parse_exception_event(buf: &mut &[u8]) -> JdwpResult<EventKind> {
296 let thread = read_u64(buf)?;
299 let location = read_location(buf)?;
300 let _exc_tag = read_u8(buf)?;
301 let exception = read_u64(buf)?;
302 let catch = read_location(buf)?;
303 let catch_location =
304 if catch.class_id == 0 && catch.method_id == 0 && catch.index == 0 { None } else { Some(catch) };
305 Ok(EventKind::Exception { thread, location, exception, catch_location })
306}
307
308fn parse_field_event_head(buf: &mut &[u8]) -> JdwpResult<FieldEvent> {
311 let thread = read_u64(buf)?;
312 let location = read_location(buf)?;
313 let _ref_type_tag = read_u8(buf)?;
314 let ref_type = read_u64(buf)?;
315 let field_id = read_u64(buf)?;
316 let _obj_tag = read_u8(buf)?;
317 let object = read_u64(buf)?;
318 Ok(FieldEvent { thread, location, ref_type, field_id, object })
319}
320
321fn parse_field_access_event(buf: &mut &[u8]) -> JdwpResult<EventKind> {
322 Ok(EventKind::FieldAccess { field: parse_field_event_head(buf)? })
323}
324
325fn parse_field_modification_event(buf: &mut &[u8]) -> JdwpResult<EventKind> {
326 let field = parse_field_event_head(buf)?;
327 let tag = read_u8(buf)?;
329 let new_value = Value { tag, data: crate::reader::read_value_by_tag(tag, buf)? };
330 Ok(EventKind::FieldModification { field, new_value })
331}
332
333fn parse_monitor_event_head(buf: &mut &[u8]) -> JdwpResult<MonitorEvent> {
347 let thread = read_u64(buf)?;
348 let _monitor_tag = read_u8(buf)?;
351 let monitor = read_u64(buf)?;
352 let location = read_location(buf)?;
353 Ok(MonitorEvent { thread, location, monitor })
354}
355
356fn parse_monitor_wait_event(buf: &mut &[u8]) -> JdwpResult<EventKind> {
357 let monitor = parse_monitor_event_head(buf)?;
358 let timeout = crate::reader::read_i64(buf)?;
361 Ok(EventKind::MonitorWait { monitor, timeout })
362}
363
364fn parse_monitor_waited_event(buf: &mut &[u8]) -> JdwpResult<EventKind> {
365 let monitor = parse_monitor_event_head(buf)?;
366 let timed_out = read_u8(buf)? != 0;
367 Ok(EventKind::MonitorWaited { monitor, timed_out })
368}
369
370fn parse_method_exit_event(buf: &mut &[u8], with_return_value: bool) -> JdwpResult<EventKind> {
375 let thread = read_u64(buf)?;
376 let location = read_location(buf)?;
377 let return_value = if with_return_value {
378 let tag = read_u8(buf)?;
379 Some(Value { tag, data: crate::reader::read_value_by_tag(tag, buf)? })
380 } else {
381 None
382 };
383 Ok(EventKind::MethodExit { thread, location, return_value })
384}
385
386fn read_location(buf: &mut &[u8]) -> JdwpResult<Location> {
388 let type_tag = read_u8(buf)?;
389 let class_id = read_u64(buf)?;
390 let method_id = read_u64(buf)?;
391 let index = read_u64(buf)?;
392
393 Ok(Location { type_tag, class_id, method_id, index })
394}
395
396#[cfg(test)]
397mod tests {
398 use super::*;
399 use crate::commands::event_kinds;
400
401 fn packet(suspend_policy: u8, events: &[Vec<u8>]) -> Vec<u8> {
403 let mut out = vec![suspend_policy];
404 out.extend_from_slice(&i32::try_from(events.len()).unwrap_or(0).to_be_bytes());
405 for e in events {
406 out.extend_from_slice(e);
407 }
408 out
409 }
410
411 fn location(class: u64, method: u64, index: u64) -> Vec<u8> {
413 let mut out = vec![1];
414 out.extend_from_slice(&class.to_be_bytes());
415 out.extend_from_slice(&method.to_be_bytes());
416 out.extend_from_slice(&index.to_be_bytes());
417 out
418 }
419
420 fn breakpoint_event(request_id: i32, thread: u64) -> Vec<u8> {
421 let mut out = vec![event_kinds::BREAKPOINT];
422 out.extend_from_slice(&request_id.to_be_bytes());
423 out.extend_from_slice(&thread.to_be_bytes());
424 out.extend_from_slice(&location(0x11, 0x22, 3));
425 out
426 }
427
428 fn field_modification_event(new_value: i32) -> Vec<u8> {
431 let mut out = vec![event_kinds::FIELD_MODIFICATION];
432 out.extend_from_slice(&7i32.to_be_bytes()); out.extend_from_slice(&0x1u64.to_be_bytes()); out.extend_from_slice(&location(0x11, 0x22, 3));
435 out.push(1); out.extend_from_slice(&0x33u64.to_be_bytes()); out.extend_from_slice(&0x44u64.to_be_bytes()); out.push(crate::reader::value_tags::OBJECT); out.extend_from_slice(&0u64.to_be_bytes()); out.push(crate::reader::value_tags::INT);
441 out.extend_from_slice(&new_value.to_be_bytes());
442 out
443 }
444
445 fn method_exit_event(with_return_value: bool, returned: i32) -> Vec<u8> {
448 let mut out = vec![if with_return_value {
449 event_kinds::METHOD_EXIT_WITH_RETURN_VALUE
450 } else {
451 event_kinds::METHOD_EXIT
452 }];
453 out.extend_from_slice(&9i32.to_be_bytes()); out.extend_from_slice(&0x1u64.to_be_bytes()); out.extend_from_slice(&location(0x55, 0x66, 12));
456 if with_return_value {
457 out.push(crate::reader::value_tags::INT);
458 out.extend_from_slice(&returned.to_be_bytes());
459 }
460 out
461 }
462
463 #[test]
467 fn method_exit_parses_with_and_without_a_return_value() {
468 let with = parse_event_packet(&packet(1, &[method_exit_event(true, 42)])).expect("well-formed");
469 match with.events.first().map(|e| &e.details) {
470 Some(EventKind::MethodExit { location, return_value: Some(v), .. }) => {
471 assert_eq!(location.method_id, 0x66, "the return site is the hit location");
472 assert!(matches!(v.data, crate::types::ValueData::Int(42)), "got {:?}", v.data);
473 }
474 other => panic!("expected a method exit with a value, got {other:?}"),
475 }
476
477 let without = parse_event_packet(&packet(1, &[method_exit_event(false, 0)])).expect("well-formed");
478 assert!(
479 matches!(
480 without.events.first().map(|e| &e.details),
481 Some(EventKind::MethodExit { return_value: None, .. })
482 ),
483 "kind 41 carries no value, got {:?}",
484 without.events.first().map(|e| &e.details)
485 );
486
487 let pair = parse_event_packet(&packet(1, &[method_exit_event(true, 7), method_exit_event(true, 8)]))
490 .expect("well-formed");
491 assert_eq!(pair.events.len(), 2, "the first event must consume exactly its own bytes");
492 }
493
494 #[test]
495 fn an_empty_event_set_parses_as_zero_events() {
496 let set = parse_event_packet(&packet(2, &[])).expect("an empty set is well-formed");
497 assert_eq!(set.suspend_policy, 2);
498 assert!(set.events.is_empty());
499 }
500
501 #[test]
502 fn a_well_formed_set_parses_every_event() {
503 let wire = packet(1, &[breakpoint_event(5, 0xabc), field_modification_event(42)]);
504 let set = parse_event_packet(&wire).expect("well-formed");
505 assert_eq!(set.events.len(), 2);
506 match &set.events[0].details {
507 EventKind::Breakpoint { thread, location } => {
508 assert_eq!(*thread, 0xabc);
509 assert_eq!(location.method_id, 0x22);
510 }
511 other => panic!("expected a breakpoint, got {other:?}"),
512 }
513 match &set.events[1].details {
514 EventKind::FieldModification { field, new_value } => {
515 assert_eq!(field.field_id, 0x44);
516 assert!(matches!(new_value.data, crate::types::ValueData::Int(42)));
517 }
518 other => panic!("expected a field modification, got {other:?}"),
519 }
520 }
521
522 #[test]
526 fn an_unhandled_event_kind_becomes_unknown_rather_than_an_error() {
527 let mut ev = vec![event_kinds::FRAME_POP];
531 ev.extend_from_slice(&1i32.to_be_bytes());
532 let set = parse_event_packet(&packet(0, &[ev])).expect("an unhandled kind is not a parse failure");
533 assert!(
534 matches!(set.events.first().map(|e| &e.details), Some(EventKind::Unknown { kind })
535 if *kind == event_kinds::FRAME_POP),
536 "expected Unknown, got {:?}",
537 set.events.first().map(|e| &e.details)
538 );
539 }
540
541 fn monitor_event(kind: u8, monitor: u64, tail: &[u8]) -> Vec<u8> {
544 let mut out = vec![kind];
545 out.extend_from_slice(&11i32.to_be_bytes()); out.extend_from_slice(&0x7fu64.to_be_bytes()); out.push(crate::reader::value_tags::OBJECT); out.extend_from_slice(&monitor.to_be_bytes());
549 out.extend_from_slice(&location(0x99, 0xaa, 4));
550 out.extend_from_slice(tail);
551 out
552 }
553
554 #[test]
562 fn every_monitor_event_kind_decodes_with_its_own_tail() {
563 let enter = parse_event_packet(&packet(
564 1,
565 &[monitor_event(event_kinds::MONITOR_CONTENDED_ENTER, 0x1234, &[])],
566 ))
567 .expect("well-formed");
568 match enter.events.first().map(|e| &e.details) {
569 Some(EventKind::MonitorContendedEnter { monitor }) => {
570 assert_eq!(monitor.monitor, 0x1234, "the monitor object, not the location's typeTag");
571 assert_eq!(monitor.thread, 0x7f);
572 assert_eq!(monitor.location.method_id, 0xaa);
573 }
574 other => panic!("expected a contended enter, got {other:?}"),
575 }
576
577 let pair = parse_event_packet(&packet(
581 1,
582 &[
583 monitor_event(event_kinds::MONITOR_CONTENDED_ENTER, 0x1234, &[]),
584 monitor_event(event_kinds::MONITOR_CONTENDED_ENTERED, 0x1234, &[]),
585 ],
586 ))
587 .expect("well-formed");
588 assert_eq!(pair.events.len(), 2, "an enter must consume exactly its own bytes");
589 assert!(
590 matches!(&pair.events[1].details, EventKind::MonitorContendedEntered { monitor } if monitor.monitor == 0x1234),
591 "got {:?}",
592 pair.events[1].details
593 );
594
595 let waits = parse_event_packet(&packet(
598 1,
599 &[
600 monitor_event(event_kinds::MONITOR_WAIT, 0x55, &5000i64.to_be_bytes()),
601 monitor_event(event_kinds::MONITOR_WAITED, 0x55, &[1]),
602 monitor_event(event_kinds::MONITOR_WAITED, 0x55, &[0]),
603 ],
604 ))
605 .expect("well-formed");
606 assert_eq!(waits.events.len(), 3, "each tail must be consumed at its own width");
607 assert!(
608 matches!(&waits.events[0].details, EventKind::MonitorWait { timeout: 5000, .. }),
609 "got {:?}",
610 waits.events[0].details
611 );
612 assert!(
613 matches!(&waits.events[1].details, EventKind::MonitorWaited { timed_out: true, .. }),
614 "got {:?}",
615 waits.events[1].details
616 );
617 assert!(
618 matches!(&waits.events[2].details, EventKind::MonitorWaited { timed_out: false, .. }),
619 "a notified wait did not time out, got {:?}",
620 waits.events[2].details
621 );
622 }
623
624 #[test]
628 fn every_truncation_of_a_packet_errors_instead_of_panicking() {
629 for event in [
630 breakpoint_event(5, 0xabc),
631 field_modification_event(42),
632 method_exit_event(true, 42),
633 monitor_event(event_kinds::MONITOR_WAIT, 0x55, &5000i64.to_be_bytes()),
634 ] {
635 let wire = packet(1, &[event]);
636 for keep in 0..wire.len() {
637 let short = &wire[..keep];
638 let parsed = parse_event_packet(short);
640 if let Ok(set) = parsed {
641 assert!(
642 set.events.is_empty(),
643 "{keep} of {} bytes parsed as {} complete event(s)",
644 wire.len(),
645 set.events.len()
646 );
647 }
648 }
649 }
650 }
651
652 #[test]
655 fn a_lying_event_count_errors_rather_than_over_reading() {
656 let mut wire = vec![1u8];
657 wire.extend_from_slice(&1000i32.to_be_bytes());
658 wire.extend_from_slice(&breakpoint_event(5, 0xabc));
659 assert!(parse_event_packet(&wire).is_err(), "1000 claimed, 1 supplied");
660 }
661}