Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
27 changes: 8 additions & 19 deletions profile-bee-ebpf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use aya_ebpf::{
bindings::{bpf_raw_tracepoint_args, pt_regs, BPF_F_USER_STACK},
helpers::{
bpf_get_current_pid_tgid, bpf_get_current_task_btf, bpf_get_smp_processor_id,
bpf_ktime_get_ns, bpf_map_lookup_elem, bpf_probe_read, bpf_probe_read_kernel,
bpf_probe_read_user, bpf_task_pt_regs,
bpf_ktime_get_ns, bpf_probe_read, bpf_probe_read_kernel, bpf_probe_read_user,
bpf_task_pt_regs,
},
macros::map,
maps::{Array, ArrayOfMaps, HashMap, PerCpuArray, ProgramArray, RingBuf, StackTrace},
Expand Down Expand Up @@ -1086,25 +1086,14 @@ unsafe fn try_fp_step(bp: u64) -> Option<(u64, u64)> {

/// Look up an UnwindEntry from the array-of-maps by shard_id and index.
///
/// 1. Look up shard_id in the outer UNWIND_SHARDS → get pointer to inner map
/// 2. Look up idx in the inner map via raw bpf_map_lookup_elem
///
/// Uses the typed ArrayOfMaps for the outer lookup but raw helper for the inner
/// lookup to avoid verifier complexity from the typed Array::get() code path.
/// Uses the fused `get_value()` API which performs both outer and inner
/// `bpf_map_lookup_elem` calls without intermediate struct indirection.
/// This avoids verifier state explosion that occurs when the two lookups
/// are separated by typed wrapper code (MapDef::as_ptr() on the inner map).
#[inline(always)]
unsafe fn shard_lookup(shard_id: u8, idx: u32) -> Option<UnwindEntry> {
// Step 1: look up the inner map in the outer array-of-maps
let inner_map_ptr = UNWIND_SHARDS.get(shard_id as u32)?;

// Step 2: look up the entry in the inner map using raw helper
let entry_ptr = bpf_map_lookup_elem(
inner_map_ptr as *const _ as *mut core::ffi::c_void,
&idx as *const u32 as *const core::ffi::c_void,
);
if entry_ptr.is_null() {
return None;
}
Some(core::ptr::read_unaligned(entry_ptr as *const UnwindEntry))
let entry: &UnwindEntry = UNWIND_SHARDS.get_value(shard_id as u32, &idx)?;
Some(*entry)
}

#[inline(always)]
Expand Down
9 changes: 6 additions & 3 deletions profile-bee/bin/profile-bee.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use aya::maps::{InnerMap, MapData, RingBuf, StackTraceMap};
use aya::maps::{MapData, RingBuf, StackTraceMap};
use aya::Ebpf;
use clap::Parser;
use inferno::flamegraph::{self, Options};
Expand Down Expand Up @@ -1191,11 +1191,14 @@ fn apply_dwarf_refresh(bpf: &mut Ebpf, update: DwarfRefreshUpdate) {
let map = bpf.map_mut("unwind_shards").ok_or_else(|| {
tracing::warn!("DWARF refresh: unwind_shards map not found");
})?;
let mut outer = aya::maps::ArrayOfMaps::try_from(map).map_err(|e| {
let mut outer: aya::maps::ArrayOfMaps<
&mut aya::maps::MapData,
aya::maps::Array<aya::maps::MapData, profile_bee::ebpf::UnwindEntryPod>,
> = aya::maps::ArrayOfMaps::try_from(map).map_err(|e| {
tracing::warn!("DWARF refresh: unwind_shards is not ArrayOfMaps: {}", e);
})?;
for (shard_id, inner_array) in &created_maps {
if let Err(e) = outer.set(*shard_id as u32, inner_array.fd(), 0) {
if let Err(e) = outer.set(*shard_id as u32, inner_array, 0) {
tracing::warn!(
"DWARF refresh: failed to insert shard_{} into outer map: {}",
shard_id,
Expand Down
Binary file modified profile-bee/ebpf-bin/profile-bee.bpf.o
Binary file not shown.
21 changes: 11 additions & 10 deletions profile-bee/src/ebpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,21 +513,22 @@ impl EbpfProfiler {
let inner_array = create_and_populate_inner_map(shard_id, entries)?;

// Get the outer ArrayOfMaps and insert the inner map's FD
let mut outer: aya::maps::ArrayOfMaps<&mut MapData> = aya::maps::ArrayOfMaps::try_from(
let mut outer: aya::maps::ArrayOfMaps<
&mut MapData,
aya::maps::Array<MapData, UnwindEntryPod>,
> = aya::maps::ArrayOfMaps::try_from(
self.bpf
.map_mut("unwind_shards")
.ok_or(anyhow!("unwind_shards map not found"))?,
)?;

outer
.set(shard_id as u32, inner_array.fd(), 0)
.map_err(|e| {
anyhow!(
"failed to insert shard_{} into outer ArrayOfMaps: {}",
shard_id,
e
)
})?;
outer.set(shard_id as u32, &inner_array, 0).map_err(|e| {
anyhow!(
"failed to insert shard_{} into outer ArrayOfMaps: {}",
shard_id,
e
)
})?;

// inner_array is dropped here — the kernel holds a reference to the inner map
// via the outer ArrayOfMaps, so the inner map stays alive.
Expand Down