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
69 changes: 13 additions & 56 deletions ghostscope-compiler/src/ebpf/dwarf_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,24 +66,21 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> {
fn planned_value_to_llvm_value(
&mut self,
value: &ghostscope_dwarf::PlannedValue,
dwarf_type: &TypeInfo,
var_name: &str,
_pc_address: u64,
status_ptr: Option<PointerValue<'ctx>>,
) -> Result<BasicValueEnum<'ctx>> {
let pt_regs_ptr = self.get_pt_regs_parameter()?;
let result_size = MemoryAccessSize::from_size(Self::get_dwarf_type_size(dwarf_type));
match value {
ghostscope_dwarf::PlannedValue::Constant(value) => Ok(self
ghostscope_dwarf::PlannedValue::Constant { value, .. } => Ok(self
.context
.i64_type()
.const_int(*value as u64, true)
.into()),
ghostscope_dwarf::PlannedValue::RegisterValue { dwarf_reg } => {
ghostscope_dwarf::PlannedValue::RegisterValue { dwarf_reg, .. } => {
debug!("Generating register value: {dwarf_reg}");
self.load_register_value(*dwarf_reg, pt_regs_ptr)
}
ghostscope_dwarf::PlannedValue::ComputedValue { steps } => {
ghostscope_dwarf::PlannedValue::ComputedValue { steps, result_size } => {
debug!("Generating computed value: {} steps", steps.len());
let runtime_status_ptr = if self.condition_context_active {
Some(self.get_or_create_cond_error_global())
Expand All @@ -93,7 +90,7 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> {
self.generate_compute_steps(
steps,
pt_regs_ptr,
Some(result_size),
Some(*result_size),
runtime_status_ptr,
None,
)
Expand All @@ -106,7 +103,7 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> {
}
Ok(self.context.i64_type().const_int(value, false).into())
}
ghostscope_dwarf::PlannedValue::AddressValue { address } => {
ghostscope_dwarf::PlannedValue::AddressValue { address, .. } => {
debug!("Generating address direct value for variable: {var_name}");
let runtime_status_ptr = if self.condition_context_active {
Some(self.get_or_create_cond_error_global())
Expand Down Expand Up @@ -302,14 +299,7 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> {

/// Convert DWARF type size to MemoryAccessSize
fn dwarf_type_to_memory_access_size(&self, dwarf_type: &TypeInfo) -> MemoryAccessSize {
let size = Self::get_dwarf_type_size(dwarf_type);
match size {
1 => MemoryAccessSize::U8,
2 => MemoryAccessSize::U16,
4 => MemoryAccessSize::U32,
8 => MemoryAccessSize::U64,
_ => MemoryAccessSize::U64, // Default to U64 for unknown sizes
}
MemoryAccessSize::from_size(dwarf_type.size())
}

fn is_signed_integer_type(dwarf_type: &TypeInfo) -> bool {
Expand Down Expand Up @@ -377,7 +367,12 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> {
));
}

if materialization.availability != Availability::OptimizedOut {
if materialization.availability != Availability::OptimizedOut
&& matches!(
materialization.materialization,
ghostscope_dwarf::VariableMaterialization::UserMemoryRead { .. }
)
{
materialization.dwarf_type.as_ref().ok_or_else(|| {
CodeGenError::DwarfError("Expression has no DWARF type information".to_string())
})?;
Expand All @@ -394,18 +389,7 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> {
) -> Result<BasicValueEnum<'ctx>> {
match &materialization.materialization {
ghostscope_dwarf::VariableMaterialization::DirectValue { value } => {
let dwarf_type = materialization.dwarf_type.as_ref().ok_or_else(|| {
CodeGenError::DwarfError(
"Expression has no DWARF type information".to_string(),
)
})?;
self.planned_value_to_llvm_value(
value,
dwarf_type,
&materialization.name,
pc_address,
status_ptr,
)
self.planned_value_to_llvm_value(value, &materialization.name, status_ptr)
}
ghostscope_dwarf::VariableMaterialization::UserMemoryRead { address } => {
let dwarf_type = materialization.dwarf_type.as_ref().ok_or_else(|| {
Expand Down Expand Up @@ -1399,33 +1383,6 @@ impl<'ctx, 'dw> EbpfContext<'ctx, 'dw> {
Ok(Some((base, VariableAccessPath::new(segments))))
}

/// Get DWARF type size in bytes
pub fn get_dwarf_type_size(dwarf_type: &TypeInfo) -> u64 {
match dwarf_type {
TypeInfo::BaseType { size, .. } => *size,
TypeInfo::PointerType { size, .. } => *size,
TypeInfo::ArrayType { total_size, .. } => total_size.unwrap_or(0),
TypeInfo::StructType { size, .. } => *size,
TypeInfo::UnionType { size, .. } => *size,
TypeInfo::EnumType { size, .. } => *size,
TypeInfo::BitfieldType {
underlying_type, ..
} => {
// Read size equals the storage type size
Self::get_dwarf_type_size(underlying_type)
}
TypeInfo::TypedefType {
underlying_type, ..
} => Self::get_dwarf_type_size(underlying_type),
TypeInfo::QualifiedType {
underlying_type, ..
} => Self::get_dwarf_type_size(underlying_type),
TypeInfo::FunctionType { .. } => 8, // Function pointer size
TypeInfo::UnknownType { .. } => 0,
TypeInfo::OptimizedOut { .. } => 0, // Optimized out has no size
}
}

/// Compute a typed pointed-to location for expressions like `ptr +/- K` where K is an element index.
/// Returns a computed location along with the pointed-to DWARF type.
/// The offset is scaled by the element size of the pointer/array target type.
Expand Down
87 changes: 75 additions & 12 deletions ghostscope-dwarf/src/semantics/variable_plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,23 @@ pub enum PlannedAddressKind {

#[derive(Debug, Clone, PartialEq)]
pub enum PlannedValue {
Constant(i64),
RegisterValue { dwarf_reg: u16 },
ComputedValue { steps: Vec<ComputeStep> },
Constant {
value: i64,
size: MemoryAccessSize,
},
RegisterValue {
dwarf_reg: u16,
size: MemoryAccessSize,
},
ComputedValue {
steps: Vec<ComputeStep>,
result_size: MemoryAccessSize,
},
ImplicitBytes(Vec<u8>),
AddressValue { address: PlannedAddress },
AddressValue {
address: PlannedAddress,
size: MemoryAccessSize,
},
}

#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -297,7 +309,8 @@ impl VariableReadPlan {
} else {
match lowering.kind {
VariableLoweringKind::DirectValue => {
match PlannedValue::from_location(self.location.clone()) {
let size = planned_value_size(self.dwarf_type.as_ref());
match PlannedValue::from_location(self.location.clone(), size) {
Some(value) => VariableMaterialization::DirectValue { value },
None => VariableMaterialization::Unavailable {
availability: Availability::Unsupported(
Expand Down Expand Up @@ -470,22 +483,28 @@ impl VariableReadPlan {
}

impl PlannedValue {
pub fn from_location(location: VariableLocation) -> Option<Self> {
pub fn from_location(location: VariableLocation, size: MemoryAccessSize) -> Option<Self> {
match location {
VariableLocation::RegisterValue { dwarf_reg } => {
Some(Self::RegisterValue { dwarf_reg })
Some(Self::RegisterValue { dwarf_reg, size })
}
VariableLocation::ComputedValue(steps) => {
if let [ComputeStep::PushConstant(value)] = steps.as_slice() {
Some(Self::Constant(*value))
Some(Self::Constant {
value: *value,
size,
})
} else {
Some(Self::ComputedValue { steps })
Some(Self::ComputedValue {
steps,
result_size: size,
})
}
}
VariableLocation::ImplicitValue(bytes) => Some(Self::ImplicitBytes(bytes)),
VariableLocation::AbsoluteAddressValue(expr) => {
PlannedAddress::from_location(VariableLocation::AbsoluteAddressValue(expr))
.map(|address| Self::AddressValue { address })
.map(|address| Self::AddressValue { address, size })
}
VariableLocation::Address(_)
| VariableLocation::RegisterAddress { .. }
Expand Down Expand Up @@ -573,6 +592,12 @@ impl RuntimeCapabilities {
}
}

fn planned_value_size(dwarf_type: Option<&TypeInfo>) -> MemoryAccessSize {
dwarf_type
.map(|ty| MemoryAccessSize::from_size(ty.size()))
.unwrap_or(MemoryAccessSize::U64)
}

fn address_origin_for_steps(steps: &[ComputeStep]) -> AddressOrigin {
if fold_constant_steps(steps).is_some() {
return AddressOrigin::LinkTime;
Expand Down Expand Up @@ -1231,6 +1256,7 @@ mod tests {
kind: PlannedAddressKind::Constant { address: 0x2000 },
..
},
size: MemoryAccessSize::U64,
},
} => {}
VariableMaterialization::DirectValue { value } => {
Expand All @@ -1249,7 +1275,40 @@ mod tests {

match materialized.materialization {
VariableMaterialization::DirectValue {
value: PlannedValue::Constant(42),
value:
PlannedValue::Constant {
value: 42,
size: MemoryAccessSize::U64,
},
} => {}
other => panic!("unexpected materialization: {other:?}"),
}
}

#[test]
fn materialization_plan_records_direct_value_size_from_type() {
let byte_type = TypeInfo::BaseType {
name: "uint8_t".to_string(),
size: 1,
encoding: gimli::constants::DW_ATE_unsigned.0 as u16,
};
let plan = typed_read_plan(
VariableLocation::ComputedValue(vec![
ComputeStep::LoadRegister(0),
ComputeStep::PushConstant(1),
ComputeStep::Add,
]),
byte_type,
);
let materialized = plan.materialization_plan(&capabilities(false));

match materialized.materialization {
VariableMaterialization::DirectValue {
value:
PlannedValue::ComputedValue {
result_size: MemoryAccessSize::U8,
..
},
} => {}
other => panic!("unexpected materialization: {other:?}"),
}
Expand All @@ -1262,7 +1321,11 @@ mod tests {

match materialized.materialization {
VariableMaterialization::DirectValue {
value: PlannedValue::RegisterValue { dwarf_reg: 6 },
value:
PlannedValue::RegisterValue {
dwarf_reg: 6,
size: MemoryAccessSize::U64,
},
} => {}
other => panic!("unexpected materialization: {other:?}"),
}
Expand Down
Loading