Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,6 @@ GhostScope uses an **instruction-based protocol** for flexible trace event repre
| **PrintStringIndex** | 0x01 | Print static string (indexed) |
| **PrintVariableIndex** | 0x02 | Print simple variable with type info |
| **PrintComplexVariable** | 0x03 | Print struct/array with access path |
| **PrintFormat** | 0x04 | Formatted print with multiple arguments |
| **PrintComplexFormat** | 0x05 | Formatted print with complex variables |
| **Backtrace** | 0x10 | Stack backtrace with frame addresses |
| **EndInstruction** | 0xFF | Marks end of instruction sequence |
Expand Down
1 change: 0 additions & 1 deletion docs/zh/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,6 @@ GhostScope 使用**基于指令的协议**实现灵活的追踪事件表示:
| **PrintStringIndex** | 0x01 | 打印静态字符串(索引化) |
| **PrintVariableIndex** | 0x02 | 打印带类型信息的简单变量 |
| **PrintComplexVariable** | 0x03 | 打印带访问路径的结构体/数组 |
| **PrintFormat** | 0x04 | 带多个参数的格式化打印 |
| **PrintComplexFormat** | 0x05 | 带复杂变量的格式化打印 |
| **Backtrace** | 0x10 | 带栈帧地址的栈回溯 |
| **EndInstruction** | 0xFF | 标记指令序列结束 |
Expand Down
1,280 changes: 3 additions & 1,277 deletions ghostscope-compiler/src/ebpf/codegen.rs

Large diffs are not rendered by default.

543 changes: 14 additions & 529 deletions ghostscope-protocol/src/format_printer.rs

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions ghostscope-protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ pub mod type_info;
pub use type_kind::{consts, TypeKind};

pub use trace_event::{
EndInstructionData, InstructionHeader, InstructionType, PrintFormatData, PrintStringIndexData,
PrintVariableIndexData, TraceEventHeader, TraceEventMessage, VariableData, VariableStatus,
EndInstructionData, InstructionHeader, InstructionType, PrintStringIndexData,
PrintVariableIndexData, TraceEventHeader, TraceEventMessage, VariableStatus,
};

pub use trace_context::TraceContext;

pub use format_printer::{FormatPrinter, ParsedVariable};
pub use format_printer::FormatPrinter;

pub use streaming_parser::{
EventSource, ParseState, ParsedInstruction, ParsedTraceEvent, StreamingTraceParser,
Expand Down
70 changes: 3 additions & 67 deletions ghostscope-protocol/src/streaming_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ pub enum ParsedInstruction {
formatted_value: String,
raw_data: Vec<u8>,
},
PrintFormat {
formatted_output: String,
},
PrintComplexFormat {
formatted_output: String,
},
Expand Down Expand Up @@ -84,11 +81,7 @@ impl ParsedTraceEvent {
i += 1;
}
}
ParsedInstruction::PrintFormat { formatted_output } => {
// Already formatted, just add it
output.push(formatted_output.clone());
i += 1;
}

ParsedInstruction::EndInstruction { .. } => {
// Skip EndInstruction - it's for protocol control, not user output
i += 1;
Expand Down Expand Up @@ -460,63 +453,6 @@ impl StreamingTraceParser {
}
}

t if t == InstructionType::PrintFormat as u8 => {
let (format_data, _) = PrintFormatData::read_from_prefix(inst_data)
.map_err(|_| "Invalid PrintFormat data".to_string())?;

// Parse variable data
let mut variables = Vec::new();
let mut offset = std::mem::size_of::<PrintFormatData>();

for _ in 0..format_data.arg_count {
// Header: var_name_index:u16 (2), type_encoding:u8 (1), data_len:u16 (2), type_index:u16 (2), status:u8 (1)
if offset + 8 > inst_data.len() {
return Err("Invalid PrintFormat variable header".to_string());
}

// Read variable header fields in struct order
let var_name_index =
u16::from_le_bytes([inst_data[offset], inst_data[offset + 1]]);
let type_encoding_byte = inst_data[offset + 2];
let data_len =
u16::from_le_bytes([inst_data[offset + 3], inst_data[offset + 4]]);
let type_index =
u16::from_le_bytes([inst_data[offset + 5], inst_data[offset + 6]]);
let status = inst_data[offset + 7];

offset += 8;

if offset + data_len as usize > inst_data.len() {
return Err("Invalid PrintFormat variable data".to_string());
}

let var_data = inst_data[offset..offset + data_len as usize].to_vec();
offset += data_len as usize;

// Convert type encoding byte to enum
let type_encoding =
TypeKind::from_u8(type_encoding_byte).unwrap_or(TypeKind::Unknown);

variables.push(crate::format_printer::ParsedVariable {
var_name_index,
type_encoding,
// Preserve zero-based indices; 0 is a valid type_index
type_index: Some(type_index),
status,
data: var_data,
});
}

// Use FormatPrinter to generate formatted output
let formatted_output = crate::format_printer::FormatPrinter::format_print_data(
format_data.format_string_index,
&variables,
trace_context,
);

ParsedInstruction::PrintFormat { formatted_output }
}

t if t == InstructionType::PrintComplexFormat as u8 => {
let (format_data, _) = PrintComplexFormatData::read_from_prefix(inst_data)
.map_err(|_| "Invalid PrintComplexFormat data".to_string())?;
Expand Down Expand Up @@ -690,7 +626,7 @@ impl ParsedInstruction {
} => {
format!("{name} ({type_encoding:?}): {formatted_value}")
}
ParsedInstruction::PrintFormat { formatted_output } => formatted_output.clone(),

ParsedInstruction::PrintComplexFormat { formatted_output } => formatted_output.clone(),
ParsedInstruction::PrintComplexVariable {
name: _,
Expand Down Expand Up @@ -725,7 +661,7 @@ impl ParsedInstruction {
match self {
ParsedInstruction::PrintString { .. } => "PrintString".to_string(),
ParsedInstruction::PrintVariable { .. } => "PrintVariable".to_string(),
ParsedInstruction::PrintFormat { .. } => "PrintFormat".to_string(),

ParsedInstruction::PrintComplexFormat { .. } => "PrintComplexFormat".to_string(),
ParsedInstruction::PrintComplexVariable { .. } => "PrintComplexVariable".to_string(),
ParsedInstruction::Backtrace { .. } => "Backtrace".to_string(),
Expand Down
35 changes: 1 addition & 34 deletions ghostscope-protocol/src/trace_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ pub enum InstructionType {
PrintStringIndex = 0x01, // print "string" (using string table index)
PrintVariableIndex = 0x02, // print variable (using variable name index)
PrintComplexVariable = 0x03, // print complex variable (with full type info)
PrintFormat = 0x04, // print "format {} {}", var1, var2 (formatted print)
PrintComplexFormat = 0x05, // print with complex variables in format args
Backtrace = 0x10, // backtrace instruction

Expand Down Expand Up @@ -88,18 +87,6 @@ pub struct PrintComplexVariableData {
// Followed by access_path (UTF-8 string) then variable data
}

/// Format print instruction data
#[repr(C, packed)]
#[derive(Debug, Clone, Copy, FromBytes, KnownLayout, Immutable, Unaligned)]
pub struct PrintFormatData {
pub format_string_index: u16, // Index into string table for format string
pub arg_count: u8, // Number of arguments
pub reserved: u8, // Padding for alignment
// Followed by argument data in struct order (8 bytes header):
// [var_name_index:u16, type_encoding:u8, data_len:u16, type_index:u16, status:u8, data:bytes] * arg_count
// Note: In fast path (script variables/literals), status is always 0 (VariableStatus::Ok)
}

/// Complex format print instruction data (with full type info)
#[repr(C, packed)]
#[derive(Debug, Clone, Copy, FromBytes, KnownLayout, Immutable, Unaligned)]
Expand All @@ -113,7 +100,7 @@ pub struct PrintComplexFormatData {
}

// Note: historical PrintVariableError has been removed; per-variable errors
// are carried via status in PrintVariableIndex/Format/ComplexFormat.
// are carried via status in PrintVariableIndex/ComplexFormat.

/// Backtrace instruction data
#[repr(C, packed)]
Expand Down Expand Up @@ -146,10 +133,6 @@ pub enum Instruction {
type_index: u16, // Index into type table (new field)
data: Vec<u8>,
},
PrintFormat {
format_string_index: u16,
variables: Vec<VariableData>,
},
Backtrace {
depth: u8,
flags: u8,
Expand All @@ -161,22 +144,12 @@ pub enum Instruction {
},
}

/// Variable data for PrintFormat instruction
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VariableData {
pub var_name_index: u16,
pub type_encoding: TypeKind,
pub type_index: u16, // Index into type table (new field)
pub data: Vec<u8>,
}

impl Instruction {
/// Get the instruction type
pub fn instruction_type(&self) -> InstructionType {
match self {
Instruction::PrintStringIndex { .. } => InstructionType::PrintStringIndex,
Instruction::PrintVariableIndex { .. } => InstructionType::PrintVariableIndex,
Instruction::PrintFormat { .. } => InstructionType::PrintFormat,
Instruction::Backtrace { .. } => InstructionType::Backtrace,
Instruction::EndInstruction { .. } => InstructionType::EndInstruction,
}
Expand All @@ -191,12 +164,6 @@ mod tests {
fn test_instruction_types() {
let inst1 = Instruction::PrintStringIndex { string_index: 0 };
assert_eq!(inst1.instruction_type(), InstructionType::PrintStringIndex);

let inst2 = Instruction::PrintFormat {
format_string_index: 0,
variables: vec![],
};
assert_eq!(inst2.instruction_type(), InstructionType::PrintFormat);
}

#[test]
Expand Down
4 changes: 0 additions & 4 deletions ghostscope-protocol/src/type_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,6 @@ pub mod consts {
pub const PRINT_VARIABLE_INDEX_DATA_SIZE: usize =
std::mem::size_of::<crate::trace_event::PrintVariableIndexData>();

/// Print format data size
pub const PRINT_FORMAT_DATA_SIZE: usize =
std::mem::size_of::<crate::trace_event::PrintFormatData>();

// TraceEventMessage field offsets
pub const TRACE_EVENT_MESSAGE_TRACE_ID_OFFSET: usize = 0;
pub const TRACE_EVENT_MESSAGE_TIMESTAMP_OFFSET: usize = 8;
Expand Down