Skip to content
This repository was archived by the owner on Jul 11, 2023. It is now read-only.

Commit 880eb9b

Browse files
committed
Add Module::global and Loaded::global methods
1 parent 0716b51 commit 880eb9b

File tree

6 files changed

+81
-27
lines changed

6 files changed

+81
-27
lines changed

examples/example-probes/src/global_var/main.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
#![no_std]
22
#![no_main]
3-
use core::sync::atomic::{AtomicU64, Ordering};
3+
use core::sync::atomic::Ordering;
4+
45
use redbpf_probes::kprobe::prelude::*;
56

7+
use example_probes::global_var::{GLOBAL_VAR, GLOBAL_VAR_INCORRECT};
8+
69
program!(0xFFFFFFFE, "GPL");
710

811
#[map]
912
static mut PERCPU_MAP: PerCpuArray<u64> = PerCpuArray::with_max_entries(1);
1013

11-
// global variable is shared between multiple cores so proper synchronization
12-
// should be involved carefully.
13-
static GLOBAL_VAR: AtomicU64 = AtomicU64::new(0);
14-
15-
// global variable without any synchronization mechanism. This results in wrong
16-
// statistics.
17-
static mut GLOBAL_VAR_INCORRECT: u64 = 0;
18-
1914
#[kprobe]
2015
fn incr_write_count(_regs: Registers) {
2116
unsafe {
Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
use cty::*;
1+
use core::sync::atomic::AtomicU64;
22

3-
// This is where you should define the types shared by the kernel and user
4-
// space, eg:
5-
//
6-
// #[repr(C)]
7-
// #[derive(Debug)]
8-
// pub struct SomeEvent {
9-
// pub pid: u64,
10-
// ...
11-
// }
3+
use redbpf_macros::global;
4+
5+
/// global variable is shared between multiple cores so proper synchronization
6+
/// should be involved carefully.
7+
#[global]
8+
pub static GLOBAL_VAR: AtomicU64 = AtomicU64::new(0);
9+
10+
/// global variable without any synchronization mechanism. This results in wrong
11+
/// statistics.
12+
#[global]
13+
pub static mut GLOBAL_VAR_INCORRECT: u64 = 0;

examples/example-userspace/examples/global-var.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use tracing_subscriber::FmtSubscriber;
1515

1616
use redbpf::{load::Loader, Array, PerCpuArray};
1717

18+
use probes::global_var::{GLOBAL_VAR, GLOBAL_VAR_INCORRECT};
1819
#[repr(C)]
1920
#[derive(Debug, Clone)]
2021
struct Data {
@@ -39,19 +40,22 @@ async fn main() {
3940
.expect("kprobe_mut error")
4041
.attach_kprobe("ksys_write", 0)
4142
.expect("error attach_kprobe");
42-
let global = Array::<Data>::new(loaded.map(".bss").expect("map not found"))
43-
.expect("can not initialize Array");
43+
44+
let gvar = loaded
45+
.global::<u64>("GLOBAL_VAR")
46+
.expect("error on accessing gvar");
47+
let gvar_wo_sync = loaded
48+
.global::<u64>("GLOBAL_VAR_INCORRECT")
49+
.expect("error on accessing gvar-wo-sync ");
4450
let percpu_map =
4551
PerCpuArray::<u64>::new(loaded.map("PERCPU_MAP").expect("PERCPU_MAP not found"))
4652
.expect("can not initialize PerCpuArray");
47-
4853
loop {
49-
let gval = global.get(0).expect("global var value");
5054
let pcpu_val = percpu_map.get(0).expect("percpu value");
5155
println!(
5256
"w/ sync, w/o sync, pcpu = {}, {}, {}",
53-
gval.var,
54-
gval.var_wo_sync,
57+
gvar.load().unwrap(),
58+
gvar_wo_sync.load().unwrap(),
5559
pcpu_val.iter().sum::<u64>()
5660
);
5761
select! {

redbpf-macros/src/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,3 +770,20 @@ pub fn task_iter(attrs: TokenStream, item: TokenStream) -> TokenStream {
770770

771771
probe_impl("task_iter", attrs, wrapper, name)
772772
}
773+
774+
/// Attribute macro for defining global variables in probes
775+
///
776+
/// **NOTE** It is not required to use it when global variables are accessed
777+
/// only inside probes. But it has to used if global variables are also
778+
/// accessed by userspace program.
779+
#[proc_macro_attribute]
780+
pub fn global(_attrs: TokenStream, item: TokenStream) -> TokenStream {
781+
let item = parse_macro_input!(item as ItemStatic);
782+
let section_name = format!("globals/{}", item.ident.to_string());
783+
quote! {
784+
#[no_mangle]
785+
#[link_section = #section_name]
786+
#item
787+
}
788+
.into()
789+
}

redbpf/src/lib.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,15 @@ impl Module {
13831383
pub fn task_iter_mut(&mut self, name: &str) -> Option<&mut TaskIter> {
13841384
self.task_iters_mut().find(|p| p.common.name == name)
13851385
}
1386+
1387+
pub fn global<T: Clone>(&self, name: &str) -> Result<GlobalVariable<'_, T>> {
1388+
let map = self.map(name).ok_or_else(|| {
1389+
error!("map not found: {}", name);
1390+
Error::Map
1391+
})?;
1392+
1393+
GlobalVariable::new(map)
1394+
}
13861395
}
13871396

13881397
impl<'a> ModuleBuilder<'a> {
@@ -1486,6 +1495,10 @@ impl<'a> ModuleBuilder<'a> {
14861495
symval_to_map_builders.insert(sym.st_value, map_builder);
14871496
}
14881497
}
1498+
(hdr::SHT_PROGBITS, Some("globals"), Some(name)) => {
1499+
let map_builder = MapBuilder::with_section_data(name, &content)?;
1500+
map_builders.insert(shndx, map_builder);
1501+
}
14891502
(hdr::SHT_PROGBITS, Some(kind @ "kprobe"), Some(name))
14901503
| (hdr::SHT_PROGBITS, Some(kind @ "kretprobe"), Some(name))
14911504
| (hdr::SHT_PROGBITS, Some(kind @ "uprobe"), Some(name))
@@ -2744,6 +2757,25 @@ impl Drop for TaskIter {
27442757
}
27452758
}
27462759

2760+
pub struct GlobalVariable<'a, T: Clone> {
2761+
array: Array<'a, T>,
2762+
}
2763+
2764+
impl<'a, T: Clone> GlobalVariable<'a, T> {
2765+
fn new(map: &Map) -> Result<GlobalVariable<T>> {
2766+
let array = Array::<T>::new(map)?;
2767+
Ok(GlobalVariable { array })
2768+
}
2769+
2770+
pub fn load(&self) -> Option<T> {
2771+
self.array.get(0)
2772+
}
2773+
2774+
pub fn store(&self, val: T) -> Result<()> {
2775+
self.array.set(0, val)
2776+
}
2777+
}
2778+
27472779
#[inline]
27482780
fn add_relocation(
27492781
rels: &mut Vec<RelocationInfo>,

redbpf/src/load/loader.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use std::path::Path;
1515
use crate::load::map_io::PerfMessageStream;
1616
use crate::{cpus, Program};
1717
use crate::{
18-
Error, KProbe, Map, Module, PerfMap, SkLookup, SocketFilter, StreamParser, StreamVerdict,
19-
TaskIter, UProbe, XDP,
18+
Error, GlobalVariable, KProbe, Map, Module, PerfMap, SkLookup, SocketFilter, StreamParser,
19+
StreamVerdict, TaskIter, UProbe, XDP,
2020
};
2121

2222
#[derive(Debug)]
@@ -188,4 +188,8 @@ impl Loaded {
188188
pub fn task_iter_mut(&mut self, name: &str) -> Option<&mut TaskIter> {
189189
self.module.task_iter_mut(name)
190190
}
191+
192+
pub fn global<T: Clone>(&self, name: &str) -> Result<GlobalVariable<'_, T>, Error> {
193+
self.module.global(name)
194+
}
191195
}

0 commit comments

Comments
 (0)