mod.rs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. mod bpf;
  2. mod netlink;
  3. mod perf_event;
  4. #[cfg(test)]
  5. mod fake;
  6. use std::io;
  7. #[cfg(not(test))]
  8. use std::{ffi::CString, mem};
  9. #[cfg(not(test))]
  10. use libc::utsname;
  11. use libc::{c_int, c_long, pid_t};
  12. pub(crate) use bpf::*;
  13. #[cfg(test)]
  14. pub(crate) use fake::*;
  15. pub(crate) use netlink::*;
  16. pub(crate) use perf_event::*;
  17. use crate::generated::{bpf_attr, bpf_cmd, perf_event_attr};
  18. pub(crate) type SysResult = Result<c_long, (c_long, io::Error)>;
  19. #[cfg_attr(test, allow(dead_code))]
  20. pub(crate) enum Syscall<'a> {
  21. Bpf {
  22. cmd: bpf_cmd,
  23. attr: &'a bpf_attr,
  24. },
  25. PerfEventOpen {
  26. attr: perf_event_attr,
  27. pid: pid_t,
  28. cpu: i32,
  29. group: i32,
  30. flags: u32,
  31. },
  32. PerfEventIoctl {
  33. fd: c_int,
  34. request: c_int,
  35. arg: c_int,
  36. },
  37. }
  38. fn syscall(call: Syscall) -> SysResult {
  39. #[cfg(not(test))]
  40. return unsafe { syscall_impl(call) };
  41. #[cfg(test)]
  42. return TEST_SYSCALL.with(|test_impl| unsafe { test_impl.borrow()(call) });
  43. }
  44. #[cfg(not(test))]
  45. unsafe fn syscall_impl(call: Syscall) -> SysResult {
  46. use libc::{SYS_bpf, SYS_perf_event_open};
  47. use Syscall::*;
  48. let ret = match call {
  49. Bpf { cmd, attr } => libc::syscall(SYS_bpf, cmd, attr, mem::size_of::<bpf_attr>()),
  50. PerfEventOpen {
  51. attr,
  52. pid,
  53. cpu,
  54. group,
  55. flags,
  56. } => libc::syscall(SYS_perf_event_open, &attr, pid, cpu, group, flags),
  57. PerfEventIoctl { fd, request, arg } => {
  58. libc::ioctl(fd, request.try_into().unwrap(), arg) as libc::c_long
  59. }
  60. };
  61. if ret < 0 {
  62. return Err((ret, io::Error::last_os_error()));
  63. }
  64. Ok(ret)
  65. }
  66. #[cfg(test)]
  67. pub(crate) fn kernel_version() -> Result<(u32, u32, u32), ()> {
  68. Ok((0xff, 0xff, 0xff))
  69. }
  70. #[cfg(not(test))]
  71. pub(crate) fn kernel_version() -> Result<(u32, u32, u32), ()> {
  72. unsafe {
  73. let mut v = mem::zeroed::<utsname>();
  74. if libc::uname(&mut v as *mut _) != 0 {
  75. return Err(());
  76. }
  77. let mut major = 0u32;
  78. let mut minor = 0u32;
  79. let mut patch = 0u32;
  80. let format = CString::new("%u.%u.%u").unwrap();
  81. if libc::sscanf(
  82. v.release.as_ptr(),
  83. format.as_ptr(),
  84. &mut major as *mut u32,
  85. &mut minor as *mut _,
  86. &mut patch as *mut _,
  87. ) != 3
  88. {
  89. return Err(());
  90. }
  91. Ok((major, minor, patch))
  92. }
  93. }