mod.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. use crate::{KprobeBasic, KprobeBuilder, KprobeOps};
  2. use alloc::string::ToString;
  3. use alloc::sync::Arc;
  4. use core::{
  5. fmt::Debug,
  6. ops::{Deref, DerefMut},
  7. };
  8. use yaxpeax_arch::LengthedInstruction;
  9. const EBREAK_INST: u8 = 0xcc; // x86_64: 0xcc
  10. const MAX_INSTRUCTION_SIZE: usize = 15; // x86_64 max instruction length
  11. pub struct Kprobe {
  12. basic: KprobeBasic,
  13. point: Arc<X86KprobePoint>,
  14. }
  15. #[derive(Debug)]
  16. pub struct X86KprobePoint {
  17. addr: usize,
  18. old_instruction: [u8; MAX_INSTRUCTION_SIZE],
  19. old_instruction_len: usize,
  20. }
  21. impl Drop for X86KprobePoint {
  22. fn drop(&mut self) {
  23. let address = self.addr;
  24. unsafe {
  25. core::ptr::copy(
  26. self.old_instruction.as_ptr(),
  27. address as *mut u8,
  28. self.old_instruction_len,
  29. );
  30. core::arch::x86_64::_mm_mfence();
  31. }
  32. let decoder = yaxpeax_x86::amd64::InstDecoder::default();
  33. let inst = decoder.decode_slice(&self.old_instruction).unwrap();
  34. log::trace!(
  35. "Kprobe::uninstall: address: {:#x}, old_instruction: {:?}",
  36. address,
  37. inst.to_string()
  38. );
  39. }
  40. }
  41. impl Debug for Kprobe {
  42. fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  43. f.debug_struct("Kprobe")
  44. .field("basic", &self.basic)
  45. .field("point", &self.point)
  46. .finish()
  47. }
  48. }
  49. impl Deref for Kprobe {
  50. type Target = KprobeBasic;
  51. fn deref(&self) -> &Self::Target {
  52. &self.basic
  53. }
  54. }
  55. impl DerefMut for Kprobe {
  56. fn deref_mut(&mut self) -> &mut Self::Target {
  57. &mut self.basic
  58. }
  59. }
  60. impl KprobeBuilder {
  61. pub fn install(self) -> (Kprobe, Arc<X86KprobePoint>) {
  62. let probe_point = match &self.probe_point {
  63. Some(point) => point.clone(),
  64. None => self.replace_inst(),
  65. };
  66. let kprobe = Kprobe {
  67. basic: KprobeBasic::from(self),
  68. point: probe_point.clone(),
  69. };
  70. (kprobe, probe_point)
  71. }
  72. /// # 安装kprobe
  73. ///
  74. /// 不同的架构下需要保存原指令,然后替换为断点指令
  75. fn replace_inst(&self) -> Arc<X86KprobePoint> {
  76. let address = self.symbol_addr + self.offset;
  77. let mut inst_tmp = [0u8; MAX_INSTRUCTION_SIZE];
  78. unsafe {
  79. core::ptr::copy(
  80. address as *const u8,
  81. inst_tmp.as_mut_ptr(),
  82. MAX_INSTRUCTION_SIZE,
  83. );
  84. }
  85. let decoder = yaxpeax_x86::amd64::InstDecoder::default();
  86. let inst = decoder.decode_slice(&inst_tmp).unwrap();
  87. let len = inst.len().to_const();
  88. log::trace!("inst: {:?}, len: {:?}", inst.to_string(), len);
  89. let point = Arc::new(X86KprobePoint {
  90. addr: address,
  91. old_instruction: inst_tmp,
  92. old_instruction_len: len as usize,
  93. });
  94. unsafe {
  95. core::ptr::write_volatile(address as *mut u8, EBREAK_INST);
  96. core::arch::x86_64::_mm_mfence();
  97. }
  98. log::trace!(
  99. "Kprobe::install: address: {:#x}, func_name: {:?}",
  100. address,
  101. self.symbol
  102. );
  103. point
  104. }
  105. }
  106. impl Kprobe {
  107. pub fn probe_point(&self) -> &Arc<X86KprobePoint> {
  108. &self.point
  109. }
  110. }
  111. impl KprobeOps for X86KprobePoint {
  112. fn return_address(&self) -> usize {
  113. self.addr + self.old_instruction_len
  114. }
  115. fn single_step_address(&self) -> usize {
  116. self.old_instruction.as_ptr() as usize
  117. }
  118. fn debug_address(&self) -> usize {
  119. self.old_instruction.as_ptr() as usize + self.old_instruction_len
  120. }
  121. fn break_address(&self) -> usize {
  122. self.addr
  123. }
  124. }