Skip to content

Commit 1a6d44e

Browse files
committed
aya: plumb PerfEventScope through probe attach
Remove the intermediate Option<u32> pid plumbing from probe attachment paths and pass PerfEventScope through to the perf_event helpers directly. This keeps the UProbeScope to PerfEventScope conversion in UProbe::attach, where both the process scope and /proc/<pid>/maps lookup semantics are visible. These kprobe, uprobe, and tracepoint attach paths are backed by perf_event. For all-processes attachment, perf_event_open requires an explicit CPU, so use CPU 0 only to open the backing perf event. Process-scoped uprobes continue to use cpu=-1 through PerfEventScope.
1 parent 0507050 commit 1a6d44e

5 files changed

Lines changed: 81 additions & 52 deletions

File tree

aya/src/programs/kprobe.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::{
1515
ProgramData, ProgramError, ProgramType, define_link_wrapper, impl_try_from_fdlink,
1616
impl_try_into_fdlink, load_program_without_attach_type,
1717
perf_attach::{PerfLinkIdInner, PerfLinkInner},
18+
perf_event::PerfEventScope,
1819
probe::{Probe, ProbeKind, attach},
1920
},
2021
};
@@ -87,7 +88,9 @@ impl KProbe {
8788
*kind,
8889
fn_name.as_ref(),
8990
offset,
90-
None, // pid
91+
// For all-processes attachment, perf_event_open requires an explicit
92+
// CPU. Use CPU 0 only to open the backing perf event.
93+
PerfEventScope::AllProcessesOneCpu { cpu: 0 },
9194
None, // cookie
9295
)
9396
}

aya/src/programs/probe.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use std::{
1212
use crate::{
1313
programs::{
1414
Link, ProgramData, ProgramError, perf_attach, perf_attach::PerfLinkInner,
15-
perf_attach_debugfs, trace_point::read_sys_fs_trace_point_id, utils::find_tracefs_path,
15+
perf_attach_debugfs, perf_event::PerfEventScope, trace_point::read_sys_fs_trace_point_id,
16+
utils::find_tracefs_path,
1617
},
1718
sys::{SyscallError, perf_event_open_probe, perf_event_open_trace_point},
1819
util::KernelVersion,
@@ -145,21 +146,21 @@ pub(crate) fn attach<P: Probe, T: Link + From<PerfLinkInner>>(
145146
// separate argument.
146147
fn_name: &OsStr,
147148
offset: u64,
148-
pid: Option<u32>,
149+
scope: PerfEventScope,
149150
cookie: Option<u64>,
150151
) -> Result<T::Id, ProgramError> {
151152
// https://github.com/torvalds/linux/commit/e12f03d7031a977356e3d7b75a68c2185ff8d155
152153
// Use debugfs to create probe
153154
let prog_fd = program_data.fd()?;
154155
let prog_fd = prog_fd.as_fd();
155156
let link = if KernelVersion::at_least(4, 17, 0) {
156-
let perf_fd = create_as_probe::<P>(kind, fn_name, offset, pid)?;
157+
let perf_fd = create_as_probe::<P>(kind, fn_name, offset, scope)?;
157158
perf_attach(prog_fd, perf_fd, cookie)
158159
} else {
159160
if cookie.is_some() {
160161
return Err(ProgramError::AttachCookieNotSupported);
161162
}
162-
let (perf_fd, event) = create_as_trace_point::<P>(kind, fn_name, offset, pid)?;
163+
let (perf_fd, event) = create_as_trace_point::<P>(kind, fn_name, offset, scope)?;
163164
perf_attach_debugfs(prog_fd, perf_fd, event)
164165
}?;
165166
program_data.links.insert(T::from(link))
@@ -176,7 +177,7 @@ fn create_as_probe<P: Probe>(
176177
kind: ProbeKind,
177178
fn_name: &OsStr,
178179
offset: u64,
179-
pid: Option<u32>,
180+
scope: PerfEventScope,
180181
) -> Result<crate::MockableFd, ProgramError> {
181182
let perf_ty = read_sys_fs_perf_type(P::PMU)
182183
.map_err(|(filename, io_error)| P::file_error(filename, io_error).into())?;
@@ -189,7 +190,7 @@ fn create_as_probe<P: Probe>(
189190
ProbeKind::Entry => None,
190191
};
191192

192-
perf_event_open_probe(perf_ty, ret_bit, fn_name, offset, pid)
193+
perf_event_open_probe(perf_ty, ret_bit, fn_name, offset, scope)
193194
.map_err(|io_error| SyscallError {
194195
call: "perf_event_open",
195196
io_error,
@@ -201,7 +202,7 @@ fn create_as_trace_point<P: Probe>(
201202
kind: ProbeKind,
202203
name: &OsStr,
203204
offset: u64,
204-
pid: Option<u32>,
205+
scope: PerfEventScope,
205206
) -> Result<(crate::MockableFd, ProbeEvent), ProgramError> {
206207
let tracefs = find_tracefs_path()?;
207208

@@ -214,7 +215,7 @@ fn create_as_trace_point<P: Probe>(
214215
} = &event;
215216
let category = format!("{}s", P::PMU);
216217
let tpid = read_sys_fs_trace_point_id(tracefs, &category, event_alias.as_ref())?;
217-
let perf_fd = perf_event_open_trace_point(tpid, pid).map_err(|io_error| SyscallError {
218+
let perf_fd = perf_event_open_trace_point(tpid, scope).map_err(|io_error| SyscallError {
218219
call: "perf_event_open",
219220
io_error,
220221
})?;

aya/src/programs/trace_point.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::{
1313
ProgramData, ProgramError, ProgramType, define_link_wrapper, impl_try_from_fdlink,
1414
impl_try_into_fdlink, load_program_without_attach_type,
1515
perf_attach::{PerfLinkIdInner, PerfLinkInner, perf_attach},
16+
perf_event::PerfEventScope,
1617
utils::find_tracefs_path,
1718
},
1819
sys::{SyscallError, perf_event_open_trace_point},
@@ -80,7 +81,13 @@ impl TracePoint {
8081
let prog_fd = prog_fd.as_fd();
8182
let tracefs = find_tracefs_path()?;
8283
let id = read_sys_fs_trace_point_id(tracefs, category, name.as_ref())?;
83-
let perf_fd = perf_event_open_trace_point(id, None).map_err(|io_error| SyscallError {
84+
let perf_fd = perf_event_open_trace_point(
85+
id,
86+
// For all-processes attachment, perf_event_open requires an explicit
87+
// CPU. Use CPU 0 only to open the backing perf event.
88+
PerfEventScope::AllProcessesOneCpu { cpu: 0 },
89+
)
90+
.map_err(|io_error| SyscallError {
8491
call: "perf_event_open_trace_point",
8592
io_error,
8693
})?;

aya/src/programs/uprobe.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::{
2121
Pid, ProgramData, ProgramError, ProgramType, define_link_wrapper, impl_try_from_fdlink,
2222
impl_try_into_fdlink, load_program_without_attach_type,
2323
perf_attach::{PerfLinkIdInner, PerfLinkInner},
24+
perf_event::PerfEventScope,
2425
probe::{OsStringExt as _, Probe, ProbeKind, attach},
2526
},
2627
util::MMap,
@@ -143,15 +144,21 @@ impl UProbe {
143144
) -> Result<UProbeLinkId, ProgramError> {
144145
let UProbeAttachPoint { location, cookie } = point.into();
145146
let target = target.as_ref();
146-
let (proc_map_pid, perf_event_pid) = match scope {
147-
UProbeScope::AllProcesses => (None, None),
147+
let (proc_map_pid, perf_event_scope) = match scope {
148+
// For an all-processes uprobe, perf_event_open uses pid=-1 and
149+
// requires an explicit CPU. Use CPU 0 only to open the backing
150+
// perf event.
151+
UProbeScope::AllProcesses => (None, PerfEventScope::AllProcessesOneCpu { cpu: 0 }),
148152
// /proc/0/maps does not exist, so use the real pid for ProcMap
149153
// resolution while keeping the kernel's pid=0 sentinel for attach.
150-
UProbeScope::CallingProcess => (Some(std::process::id()), Some(0)),
151-
UProbeScope::OneProcess(pid) => {
152-
let pid = pid.get();
153-
(Some(pid), Some(pid))
154-
}
154+
UProbeScope::CallingProcess => (
155+
Some(std::process::id()),
156+
PerfEventScope::CallingProcess { cpu: None },
157+
),
158+
UProbeScope::OneProcess(pid) => (
159+
Some(pid.get()),
160+
PerfEventScope::OneProcess { pid, cpu: None },
161+
),
155162
};
156163

157164
// Keep ProcMap in this scope so resolve_attach_target_basename can return
@@ -186,7 +193,7 @@ impl UProbe {
186193

187194
let Self { data, kind } = self;
188195
let path = path.as_os_str();
189-
attach::<Self, _>(data, *kind, path, offset, perf_event_pid, cookie)
196+
attach::<Self, _>(data, *kind, path, offset, perf_event_scope, cookie)
190197
}
191198

192199
/// Creates a program from a pinned entry on a bpffs.

aya/src/sys/perf_event.rs

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,9 @@ use aya_obj::generated::{
1616
use libc::pid_t;
1717

1818
use super::{PerfEventIoctlRequest, Syscall, syscall};
19-
use crate::programs::{
20-
Pid,
21-
perf_event::{
22-
BreakpointConfig, PerfEventConfig, PerfEventScope, SamplePolicy, WakeupPolicy,
23-
perf_type_id_to_u32,
24-
},
19+
use crate::programs::perf_event::{
20+
BreakpointConfig, PerfEventConfig, PerfEventScope, SamplePolicy, WakeupPolicy,
21+
perf_type_id_to_u32,
2522
};
2623

2724
pub(crate) fn perf_event_open(
@@ -126,13 +123,7 @@ pub(crate) fn perf_event_open(
126123
}
127124
}
128125

129-
let (pid, cpu) = match scope {
130-
PerfEventScope::CallingProcess { cpu } => (0, cpu.map_or(-1, |cpu| cpu as i32)),
131-
PerfEventScope::OneProcess { pid, cpu } => {
132-
(pid.get() as i32, cpu.map_or(-1, |cpu| cpu as i32))
133-
}
134-
PerfEventScope::AllProcessesOneCpu { cpu } => (-1, cpu as i32),
135-
};
126+
let (pid, cpu) = perf_event_scope_pid_cpu(scope);
136127

137128
perf_event_sys(attr, pid, cpu, flags)
138129
}
@@ -142,7 +133,7 @@ pub(crate) fn perf_event_open_probe(
142133
ret_bit: Option<u32>,
143134
name: &OsStr,
144135
offset: u64,
145-
pid: Option<u32>,
136+
scope: PerfEventScope,
146137
) -> io::Result<crate::MockableFd> {
147138
use std::os::unix::ffi::OsStrExt as _;
148139

@@ -159,26 +150,15 @@ pub(crate) fn perf_event_open_probe(
159150
attr.__bindgen_anon_3.config1 = c_name.as_ptr() as u64;
160151
attr.__bindgen_anon_4.config2 = offset;
161152

162-
let (pid, cpu) = match pid {
163-
Some(pid) => (pid as i32, -1),
164-
None => (-1, 0),
165-
};
153+
let (pid, cpu) = perf_event_scope_pid_cpu(scope);
166154

167155
perf_event_sys(attr, pid, cpu, PERF_FLAG_FD_CLOEXEC)
168156
}
169157

170158
pub(crate) fn perf_event_open_trace_point(
171159
event_id: u64,
172-
pid: Option<u32>,
160+
scope: PerfEventScope,
173161
) -> io::Result<crate::MockableFd> {
174-
let scope = match pid {
175-
None => PerfEventScope::AllProcessesOneCpu { cpu: 0 },
176-
Some(0) => PerfEventScope::CallingProcess { cpu: None },
177-
Some(pid) => PerfEventScope::OneProcess {
178-
pid: Pid::new(pid).unwrap(),
179-
cpu: None,
180-
},
181-
};
182162
perf_event_open(
183163
PerfEventConfig::TracePoint { event_id },
184164
scope,
@@ -189,6 +169,16 @@ pub(crate) fn perf_event_open_trace_point(
189169
)
190170
}
191171

172+
fn perf_event_scope_pid_cpu(scope: PerfEventScope) -> (pid_t, i32) {
173+
match scope {
174+
PerfEventScope::CallingProcess { cpu } => (0, cpu.map_or(-1, |cpu| cpu as i32)),
175+
PerfEventScope::OneProcess { pid, cpu } => {
176+
(pid.get() as i32, cpu.map_or(-1, |cpu| cpu as i32))
177+
}
178+
PerfEventScope::AllProcessesOneCpu { cpu } => (-1, cpu as i32),
179+
}
180+
}
181+
192182
pub(crate) fn perf_event_ioctl(
193183
fd: BorrowedFd<'_>,
194184
request: PerfEventIoctlRequest<'_>,
@@ -271,15 +261,36 @@ mod tests {
271261
use test_case::test_case;
272262

273263
use super::{PERF_FLAG_FD_CLOEXEC, perf_event_open_trace_point};
274-
use crate::sys::{Syscall, override_syscall};
264+
use crate::{
265+
programs::{Pid, perf_event::PerfEventScope},
266+
sys::{Syscall, override_syscall},
267+
};
275268

276269
const EVENT_ID: u64 = 123;
277270

278-
#[test_case(None, -1, 0; "all_processes")]
279-
#[test_case(Some(0), 0, -1; "calling_process")]
280-
#[test_case(Some(42), 42, -1; "one_process")]
281-
fn perf_event_open_trace_point_maps_pid_scope(
282-
pid: Option<u32>,
271+
#[test_case(
272+
PerfEventScope::AllProcessesOneCpu { cpu: 0 },
273+
-1,
274+
0;
275+
"all_processes"
276+
)]
277+
#[test_case(
278+
PerfEventScope::CallingProcess { cpu: None },
279+
0,
280+
-1;
281+
"calling_process"
282+
)]
283+
#[test_case(
284+
PerfEventScope::OneProcess {
285+
pid: Pid::new(42).unwrap(),
286+
cpu: None,
287+
},
288+
42,
289+
-1;
290+
"one_process"
291+
)]
292+
fn perf_event_open_trace_point_maps_scope(
293+
scope: PerfEventScope,
283294
expected_pid: pid_t,
284295
expected_cpu: i32,
285296
) {
@@ -302,7 +313,7 @@ mod tests {
302313
call => panic!("unexpected syscall: {call:?}"),
303314
});
304315

305-
let fd = perf_event_open_trace_point(EVENT_ID, pid).unwrap();
316+
let fd = perf_event_open_trace_point(EVENT_ID, scope).unwrap();
306317
assert_eq!(fd.as_raw_fd(), crate::MockableFd::mock_signed_fd());
307318
}
308319
}

0 commit comments

Comments
 (0)