From 4efad6de36e5bb77100f698eb0fcf4f2b698a9c1 Mon Sep 17 00:00:00 2001 From: swananan Date: Mon, 25 May 2026 18:18:14 +0800 Subject: [PATCH] refactor: derive remaining protocol offsets --- .../src/ebpf/codegen/expr_error.rs | 55 +++++++++---------- ghostscope-compiler/src/ebpf/codegen/mod.rs | 2 + ghostscope-protocol/src/lib.rs | 14 +++-- ghostscope-protocol/src/trace_event.rs | 32 +++++++++++ ghostscope-protocol/src/type_kind.rs | 18 +++--- 5 files changed, 78 insertions(+), 43 deletions(-) diff --git a/ghostscope-compiler/src/ebpf/codegen/expr_error.rs b/ghostscope-compiler/src/ebpf/codegen/expr_error.rs index 257528b..9794349 100644 --- a/ghostscope-compiler/src/ebpf/codegen/expr_error.rs +++ b/ghostscope-compiler/src/ebpf/codegen/expr_error.rs @@ -12,9 +12,7 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> { // Reserve space in accumulation buffer for this instruction let inst_buffer = self .reserve_instruction_region_or_return_zero( - (std::mem::size_of::() - + std::mem::size_of::()) - as u64, + (INSTRUCTION_HEADER_SIZE + EXPR_ERROR_DATA_SIZE) as u64, )? .into_value_after_runtime_returns(); @@ -35,10 +33,10 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> { .build_gep( self.context.i8_type(), inst_buffer, - &[self.context.i32_type().const_int( - std::mem::offset_of!(InstructionHeader, data_length) as u64, - false, - )], + &[self + .context + .i32_type() + .const_int(INSTRUCTION_HEADER_DATA_LENGTH_OFFSET as u64, false)], "exprerr_data_length_ptr", ) .map_err(|e| { @@ -53,16 +51,15 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> { "exprerr_data_length_i16_ptr", ) .map_err(|e| CodeGenError::LLVMError(format!("Failed to cast data_length ptr: {e}")))?; - let data_length_val = self.context.i16_type().const_int( - std::mem::size_of::() as u64, - false, - ); + let data_length_val = self + .context + .i16_type() + .const_int(EXPR_ERROR_DATA_SIZE as u64, false); self.builder .build_store(data_length_i16_ptr, data_length_val) .map_err(|e| CodeGenError::LLVMError(format!("Failed to store data_length: {e}")))?; // Payload fields after header - // string_index at offset sizeof(InstructionHeader) + 0 (u16) // SAFETY: the payload immediately follows InstructionHeader in the // reserved ExprError instruction region. let si_ptr = unsafe { @@ -70,10 +67,10 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> { .build_gep( self.context.i8_type(), inst_buffer, - &[self - .context - .i32_type() - .const_int(std::mem::size_of::() as u64, false)], + &[self.context.i32_type().const_int( + (INSTRUCTION_HEADER_SIZE + EXPR_ERROR_DATA_STRING_INDEX_OFFSET) as u64, + false, + )], "exprerr_si_ptr", ) .map_err(|e| { @@ -98,17 +95,16 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> { .build_store(si_i16_ptr, si_val) .map_err(|e| CodeGenError::LLVMError(format!("Failed to store string_index: {e}")))?; - // error_code at +2, flags at +3 // SAFETY: error_code offset is within ExprErrorData in the reserved payload. let ec_ptr = unsafe { self.builder .build_gep( self.context.i8_type(), inst_buffer, - &[self - .context - .i32_type() - .const_int((std::mem::size_of::() + 2) as u64, false)], + &[self.context.i32_type().const_int( + (INSTRUCTION_HEADER_SIZE + EXPR_ERROR_DATA_ERROR_CODE_OFFSET) as u64, + false, + )], "exprerr_ec_ptr", ) .map_err(|e| { @@ -136,10 +132,10 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> { .build_gep( self.context.i8_type(), inst_buffer, - &[self - .context - .i32_type() - .const_int((std::mem::size_of::() + 3) as u64, false)], + &[self.context.i32_type().const_int( + (INSTRUCTION_HEADER_SIZE + EXPR_ERROR_DATA_FLAGS_OFFSET) as u64, + false, + )], "exprerr_flags_ptr", ) .map_err(|e| CodeGenError::LLVMError(format!("Failed to get flags GEP: {e}")))? @@ -160,17 +156,16 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> { .build_store(fl_ptr, fl_i8) .map_err(|e| CodeGenError::LLVMError(format!("Failed to store flags: {e}")))?; - // failing_addr at +4 (u64) // SAFETY: failing_addr offset is within ExprErrorData in the reserved payload. let addr_ptr = unsafe { self.builder .build_gep( self.context.i8_type(), inst_buffer, - &[self - .context - .i32_type() - .const_int((std::mem::size_of::() + 4) as u64, false)], + &[self.context.i32_type().const_int( + (INSTRUCTION_HEADER_SIZE + EXPR_ERROR_DATA_FAILING_ADDR_OFFSET) as u64, + false, + )], "exprerr_addr_ptr", ) .map_err(|e| CodeGenError::LLVMError(format!("Failed to get addr GEP: {e}")))? diff --git a/ghostscope-compiler/src/ebpf/codegen/mod.rs b/ghostscope-compiler/src/ebpf/codegen/mod.rs index 45555f9..246bc46 100644 --- a/ghostscope-compiler/src/ebpf/codegen/mod.rs +++ b/ghostscope-compiler/src/ebpf/codegen/mod.rs @@ -9,6 +9,8 @@ use aya_ebpf_bindings::bindings::bpf_func_id::BPF_FUNC_probe_read_user; use ghostscope_protocol::trace_event::{ BacktraceData, EndInstructionData, InstructionHeader, PrintComplexFormatData, PrintComplexVariableData, PrintStringIndexData, PrintVariableIndexData, VariableStatus, + EXPR_ERROR_DATA_ERROR_CODE_OFFSET, EXPR_ERROR_DATA_FAILING_ADDR_OFFSET, + EXPR_ERROR_DATA_FLAGS_OFFSET, EXPR_ERROR_DATA_SIZE, EXPR_ERROR_DATA_STRING_INDEX_OFFSET, INSTRUCTION_HEADER_DATA_LENGTH_OFFSET, INSTRUCTION_HEADER_SIZE, PRINT_COMPLEX_FORMAT_ARG_ACCESS_PATH_LEN_OFFSET, PRINT_COMPLEX_FORMAT_ARG_ACCESS_PATH_OFFSET, PRINT_COMPLEX_FORMAT_ARG_FIXED_HEADER_LEN, PRINT_COMPLEX_FORMAT_ARG_STATUS_OFFSET, diff --git a/ghostscope-protocol/src/lib.rs b/ghostscope-protocol/src/lib.rs index e11291a..a075c18 100644 --- a/ghostscope-protocol/src/lib.rs +++ b/ghostscope-protocol/src/lib.rs @@ -14,18 +14,22 @@ pub mod type_info; pub use type_kind::{consts, TypeKind}; pub use trace_event::{ - EndInstructionData, InstructionHeader, InstructionType, PrintComplexFormatArgPrefix, - PrintStringIndexData, PrintVariableIndexData, TraceEventHeader, TraceEventMessage, - VariableReadErrorPayload, VariableStatus, END_INSTRUCTION_DATA_OFFSET, + EndInstructionData, ExprErrorData, InstructionHeader, InstructionType, + PrintComplexFormatArgPrefix, PrintStringIndexData, PrintVariableIndexData, TraceEventHeader, + TraceEventMessage, VariableReadErrorPayload, VariableStatus, END_INSTRUCTION_DATA_OFFSET, END_INSTRUCTION_EXECUTION_STATUS_OFFSET, END_INSTRUCTION_TOTAL_INSTRUCTIONS_OFFSET, + EXPR_ERROR_DATA_ERROR_CODE_OFFSET, EXPR_ERROR_DATA_FAILING_ADDR_OFFSET, + EXPR_ERROR_DATA_FLAGS_OFFSET, EXPR_ERROR_DATA_SIZE, EXPR_ERROR_DATA_STRING_INDEX_OFFSET, INSTRUCTION_HEADER_DATA_LENGTH_OFFSET, INSTRUCTION_HEADER_INST_TYPE_OFFSET, INSTRUCTION_HEADER_RESERVED_OFFSET, INSTRUCTION_HEADER_SIZE, PRINT_COMPLEX_FORMAT_ARG_ACCESS_PATH_LEN_OFFSET, PRINT_COMPLEX_FORMAT_ARG_ACCESS_PATH_OFFSET, PRINT_COMPLEX_FORMAT_ARG_DATA_LEN_SIZE, PRINT_COMPLEX_FORMAT_ARG_FIXED_HEADER_LEN, PRINT_COMPLEX_FORMAT_ARG_STATUS_OFFSET, PRINT_COMPLEX_FORMAT_ARG_TYPE_INDEX_OFFSET, PRINT_COMPLEX_FORMAT_ARG_VAR_NAME_INDEX_OFFSET, PRINT_COMPLEX_FORMAT_DATA_ARG_COUNT_OFFSET, - VARIABLE_READ_ERROR_PAYLOAD_ADDR_OFFSET, VARIABLE_READ_ERROR_PAYLOAD_ERRNO_OFFSET, - VARIABLE_READ_ERROR_PAYLOAD_LEN, + TRACE_EVENT_HEADER_MAGIC_OFFSET, TRACE_EVENT_HEADER_SIZE, TRACE_EVENT_MESSAGE_PID_OFFSET, + TRACE_EVENT_MESSAGE_SIZE, TRACE_EVENT_MESSAGE_TID_OFFSET, TRACE_EVENT_MESSAGE_TIMESTAMP_OFFSET, + TRACE_EVENT_MESSAGE_TRACE_ID_OFFSET, VARIABLE_READ_ERROR_PAYLOAD_ADDR_OFFSET, + VARIABLE_READ_ERROR_PAYLOAD_ERRNO_OFFSET, VARIABLE_READ_ERROR_PAYLOAD_LEN, }; pub use trace_context::TraceContext; diff --git a/ghostscope-protocol/src/trace_event.rs b/ghostscope-protocol/src/trace_event.rs index ece499b..090b939 100644 --- a/ghostscope-protocol/src/trace_event.rs +++ b/ghostscope-protocol/src/trace_event.rs @@ -9,6 +9,9 @@ pub struct TraceEventHeader { pub magic: u32, } +pub const TRACE_EVENT_HEADER_SIZE: usize = std::mem::size_of::(); +pub const TRACE_EVENT_HEADER_MAGIC_OFFSET: usize = std::mem::offset_of!(TraceEventHeader, magic); + #[repr(C, packed)] #[derive(Debug, Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)] pub struct TraceEventMessage { @@ -19,6 +22,14 @@ pub struct TraceEventMessage { // Followed by variable-length instruction sequence ending with EndInstruction } +pub const TRACE_EVENT_MESSAGE_SIZE: usize = std::mem::size_of::(); +pub const TRACE_EVENT_MESSAGE_TRACE_ID_OFFSET: usize = + std::mem::offset_of!(TraceEventMessage, trace_id); +pub const TRACE_EVENT_MESSAGE_TIMESTAMP_OFFSET: usize = + std::mem::offset_of!(TraceEventMessage, timestamp); +pub const TRACE_EVENT_MESSAGE_PID_OFFSET: usize = std::mem::offset_of!(TraceEventMessage, pid); +pub const TRACE_EVENT_MESSAGE_TID_OFFSET: usize = std::mem::offset_of!(TraceEventMessage, tid); + /// Instruction types for trace events #[repr(u8)] #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] @@ -178,6 +189,15 @@ pub struct ExprErrorData { pub failing_addr: u64, // Optional: address involved in failure (0 if unknown) } +pub const EXPR_ERROR_DATA_SIZE: usize = std::mem::size_of::(); +pub const EXPR_ERROR_DATA_STRING_INDEX_OFFSET: usize = + std::mem::offset_of!(ExprErrorData, string_index); +pub const EXPR_ERROR_DATA_ERROR_CODE_OFFSET: usize = + std::mem::offset_of!(ExprErrorData, error_code); +pub const EXPR_ERROR_DATA_FLAGS_OFFSET: usize = std::mem::offset_of!(ExprErrorData, flags); +pub const EXPR_ERROR_DATA_FAILING_ADDR_OFFSET: usize = + std::mem::offset_of!(ExprErrorData, failing_addr); + /// End instruction data - marks the end of instruction sequence #[repr(C, packed)] #[derive(Debug, Clone, Copy, FromBytes, KnownLayout, Immutable, Unaligned)] @@ -257,6 +277,13 @@ mod tests { #[test] fn protocol_layout_constants_match_wire_format() { + assert_eq!(TRACE_EVENT_HEADER_SIZE, 4); + assert_eq!(TRACE_EVENT_HEADER_MAGIC_OFFSET, 0); + assert_eq!(TRACE_EVENT_MESSAGE_SIZE, 24); + assert_eq!(TRACE_EVENT_MESSAGE_TRACE_ID_OFFSET, 0); + assert_eq!(TRACE_EVENT_MESSAGE_TIMESTAMP_OFFSET, 8); + assert_eq!(TRACE_EVENT_MESSAGE_PID_OFFSET, 16); + assert_eq!(TRACE_EVENT_MESSAGE_TID_OFFSET, 20); assert_eq!(INSTRUCTION_HEADER_SIZE, 4); assert_eq!(INSTRUCTION_HEADER_INST_TYPE_OFFSET, 0); assert_eq!(INSTRUCTION_HEADER_DATA_LENGTH_OFFSET, 1); @@ -267,6 +294,11 @@ mod tests { assert_eq!(VARIABLE_READ_ERROR_PAYLOAD_LEN, 12); assert_eq!(VARIABLE_READ_ERROR_PAYLOAD_ERRNO_OFFSET, 0); assert_eq!(VARIABLE_READ_ERROR_PAYLOAD_ADDR_OFFSET, 4); + assert_eq!(EXPR_ERROR_DATA_SIZE, 12); + assert_eq!(EXPR_ERROR_DATA_STRING_INDEX_OFFSET, 0); + assert_eq!(EXPR_ERROR_DATA_ERROR_CODE_OFFSET, 2); + assert_eq!(EXPR_ERROR_DATA_FLAGS_OFFSET, 3); + assert_eq!(EXPR_ERROR_DATA_FAILING_ADDR_OFFSET, 4); assert_eq!(PRINT_COMPLEX_FORMAT_DATA_ARG_COUNT_OFFSET, 2); assert_eq!(PRINT_COMPLEX_FORMAT_ARG_VAR_NAME_INDEX_OFFSET, 0); assert_eq!(PRINT_COMPLEX_FORMAT_ARG_TYPE_INDEX_OFFSET, 2); diff --git a/ghostscope-protocol/src/type_kind.rs b/ghostscope-protocol/src/type_kind.rs index bfc4a2d..e32c746 100644 --- a/ghostscope-protocol/src/type_kind.rs +++ b/ghostscope-protocol/src/type_kind.rs @@ -151,12 +151,10 @@ pub mod consts { pub const MAX_TRACE_EVENT_SIZE: u16 = 8192; /// Trace event message size - pub const TRACE_EVENT_MESSAGE_SIZE: usize = - std::mem::size_of::(); + pub const TRACE_EVENT_MESSAGE_SIZE: usize = crate::trace_event::TRACE_EVENT_MESSAGE_SIZE; /// Trace event header size - pub const TRACE_EVENT_HEADER_SIZE: usize = - std::mem::size_of::(); + pub const TRACE_EVENT_HEADER_SIZE: usize = crate::trace_event::TRACE_EVENT_HEADER_SIZE; /// Instruction header size pub const INSTRUCTION_HEADER_SIZE: usize = crate::trace_event::INSTRUCTION_HEADER_SIZE; @@ -166,10 +164,14 @@ pub mod consts { std::mem::size_of::(); // TraceEventMessage field offsets - pub const TRACE_EVENT_MESSAGE_TRACE_ID_OFFSET: usize = 0; - pub const TRACE_EVENT_MESSAGE_TIMESTAMP_OFFSET: usize = 8; - pub const TRACE_EVENT_MESSAGE_PID_OFFSET: usize = 16; - pub const TRACE_EVENT_MESSAGE_TID_OFFSET: usize = 20; + pub const TRACE_EVENT_MESSAGE_TRACE_ID_OFFSET: usize = + crate::trace_event::TRACE_EVENT_MESSAGE_TRACE_ID_OFFSET; + pub const TRACE_EVENT_MESSAGE_TIMESTAMP_OFFSET: usize = + crate::trace_event::TRACE_EVENT_MESSAGE_TIMESTAMP_OFFSET; + pub const TRACE_EVENT_MESSAGE_PID_OFFSET: usize = + crate::trace_event::TRACE_EVENT_MESSAGE_PID_OFFSET; + pub const TRACE_EVENT_MESSAGE_TID_OFFSET: usize = + crate::trace_event::TRACE_EVENT_MESSAGE_TID_OFFSET; // InstructionHeader field offsets pub const INSTRUCTION_HEADER_INST_TYPE_OFFSET: usize =