mirror of https://github.com/yshui/picom.git
74 lines
2.8 KiB
Rust
74 lines
2.8 KiB
Rust
use libbpf_rs::skel::{OpenSkel, Skel, SkelBuilder};
|
|
use libbpf_rs::{PerfBufferBuilder, UprobeOpts};
|
|
use std::os::unix::ffi::OsStrExt;
|
|
use object::read::elf::{Dyn, FileHeader};
|
|
|
|
mod uprobe {
|
|
include!(concat!(env!("OUT_DIR"), "/uprobe.skel.rs"));
|
|
}
|
|
use object::Object;
|
|
use uprobe::*;
|
|
fn handle_lost_events(cpu: i32, count: u64) {
|
|
eprintln!("Lost {count} events on CPU {cpu}");
|
|
}
|
|
fn handle_event(cpu: i32, data: &[u8]) {
|
|
eprintln!("Got {} bytes of data on {cpu}", data.len());
|
|
}
|
|
fn main() {
|
|
let mut builder = UprobeSkelBuilder::default();
|
|
let picom_path = std::env::args().nth(1).unwrap();
|
|
let data = std::fs::read(&picom_path).unwrap();
|
|
let file = object::read::elf::ElfFile64::<'_, object::NativeEndian, _>::parse(&*data).unwrap();
|
|
let header = file.raw_header();
|
|
let sections = header.sections(object::NativeEndian, &*data).unwrap();
|
|
let (dyanmic, dynamic_index) = sections.dynamic(object::NativeEndian, &*data).unwrap().unwrap();
|
|
let strings = sections.strings(object::NativeEndian, &*data, dynamic_index).unwrap();
|
|
let mut runpath = None;
|
|
let mut libc_name = None;
|
|
for d in dyanmic {
|
|
if d.is_string(object::NativeEndian) {
|
|
let s = d.string(object::NativeEndian, strings).unwrap();
|
|
let tag = d.d_tag(object::NativeEndian);
|
|
if tag == object::elf::DT_RUNPATH as u64 {
|
|
runpath = Some(s.to_vec());
|
|
}
|
|
if tag == object::elf::DT_NEEDED as u64 && s.starts_with(b"libc.so") {
|
|
libc_name = Some(s.to_vec())
|
|
}
|
|
eprintln!("{} {}", tag, String::from_utf8_lossy(s));
|
|
}
|
|
}
|
|
let runpath = runpath.unwrap();
|
|
let libc_name = libc_name.unwrap();
|
|
let libc_name = std::ffi::OsStr::from_bytes(&libc_name);
|
|
let mut libc_path = None;
|
|
for p in runpath.split(|ch| *ch == b':') {
|
|
let p = std::ffi::OsStr::from_bytes(p);
|
|
let p = std::path::Path::new(p);
|
|
let p = p.join(libc_name);
|
|
if p.exists() {
|
|
libc_path = Some(p);
|
|
}
|
|
}
|
|
let libc_path = libc_path.unwrap();
|
|
eprintln!("{}", libc_path.to_string_lossy());
|
|
builder.obj_builder.debug(true);
|
|
|
|
let open_skel = builder.open().unwrap();
|
|
let mut skel = open_skel.load().unwrap();
|
|
let obj = skel.object_mut();
|
|
let xcb_probe = obj.prog_mut("uprobe_xcb_conn").unwrap();
|
|
let _link = xcb_probe.attach_uprobe_with_opts(-1, &picom_path, 0, UprobeOpts {
|
|
retprobe: false,
|
|
func_name: "xcb_connection_probe".to_string(),
|
|
..Default::default()
|
|
}).unwrap();
|
|
let epoll_probe = obj.prog_mut("uprobe_epoll_wait").unwrap();
|
|
let _link2 = epoll_probe.attach_uprobe_with_opts(-1, libc_path, 0, UprobeOpts {
|
|
retprobe: false,
|
|
func_name: "epoll_wait".to_string(),
|
|
..Default::default()
|
|
}).unwrap();
|
|
std::thread::park();
|
|
}
|