4
0

args.rs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. use crate::cty::c_void;
  2. // aarch64 uses user_pt_regs instead of pt_regs
  3. #[cfg(not(bpf_target_arch = "aarch64"))]
  4. use crate::bindings::pt_regs;
  5. #[cfg(bpf_target_arch = "aarch64")]
  6. use crate::bindings::user_pt_regs as pt_regs;
  7. /// A trait that indicates a valid type for an argument which can be coerced from a BTF
  8. /// context.
  9. ///
  10. /// Users should not implement this trait.
  11. ///
  12. /// SAFETY: This trait is _only_ safe to implement on primitive types that can fit into
  13. /// a `u64`. For example, integers and raw pointers may be coerced from a BTF context.
  14. pub unsafe trait FromBtfArgument: Sized {
  15. /// Coerces a `T` from the `n`th argument from a BTF context where `n` starts
  16. /// at 0 and increases by 1 for each successive argument.
  17. ///
  18. /// SAFETY: This function is deeply unsafe, as we are reading raw pointers into kernel
  19. /// memory. In particular, the value of `n` must not exceed the number of function
  20. /// arguments. Moreover, `ctx` must be a valid pointer to a BTF context, and `T` must
  21. /// be the right type for the given argument.
  22. unsafe fn from_argument(ctx: *const c_void, n: usize) -> Self;
  23. }
  24. unsafe impl<T> FromBtfArgument for *const T {
  25. unsafe fn from_argument(ctx: *const c_void, n: usize) -> *const T {
  26. // BTF arguments are exposed as an array of `usize` where `usize` can
  27. // either be treated as a pointer or a primitive type
  28. *(ctx as *const usize).add(n) as _
  29. }
  30. }
  31. /// Helper macro to implement [`FromBtfArgument`] for a primitive type.
  32. macro_rules! unsafe_impl_from_btf_argument {
  33. ($type:ident) => {
  34. unsafe impl FromBtfArgument for $type {
  35. unsafe fn from_argument(ctx: *const c_void, n: usize) -> Self {
  36. // BTF arguments are exposed as an array of `usize` where `usize` can
  37. // either be treated as a pointer or a primitive type
  38. *(ctx as *const usize).add(n) as _
  39. }
  40. }
  41. };
  42. }
  43. unsafe_impl_from_btf_argument!(u8);
  44. unsafe_impl_from_btf_argument!(u16);
  45. unsafe_impl_from_btf_argument!(u32);
  46. unsafe_impl_from_btf_argument!(u64);
  47. unsafe_impl_from_btf_argument!(i8);
  48. unsafe_impl_from_btf_argument!(i16);
  49. unsafe_impl_from_btf_argument!(i32);
  50. unsafe_impl_from_btf_argument!(i64);
  51. unsafe_impl_from_btf_argument!(usize);
  52. unsafe_impl_from_btf_argument!(isize);
  53. /// A trait that indicates a valid type for an argument which can be coerced from
  54. /// a pt_regs context.
  55. ///
  56. /// Any implementation of this trait is strictly architecture-specific and depends on the
  57. /// layout of the underlying pt_regs struct and the target processor's calling
  58. /// conventions. Users should not implement this trait.
  59. pub trait FromPtRegs: Sized {
  60. /// Coerces a `T` from the `n`th argument of a pt_regs context where `n` starts
  61. /// at 0 and increases by 1 for each successive argument.
  62. fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self>;
  63. /// Coerces a `T` from the return value of a pt_regs context.
  64. fn from_retval(ctx: &pt_regs) -> Option<Self>;
  65. }
  66. #[cfg(bpf_target_arch = "x86_64")]
  67. impl<T> FromPtRegs for *const T {
  68. fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
  69. match n {
  70. 0 => ctx.rdi().map(|v| v as _),
  71. 1 => ctx.rsi().map(|v| v as _),
  72. 2 => ctx.rdx().map(|v| v as _),
  73. 3 => ctx.rcx().map(|v| v as _),
  74. 4 => ctx.r8().map(|v| v as _),
  75. 5 => ctx.r9().map(|v| v as _),
  76. _ => None,
  77. }
  78. }
  79. fn from_retval(ctx: &pt_regs) -> Option<Self> {
  80. ctx.rax().map(|v| v as _)
  81. }
  82. }
  83. #[cfg(bpf_target_arch = "armv7")]
  84. impl<T> FromPtRegs for *const T {
  85. fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
  86. if n <= 6 {
  87. ctx.uregs().map(|regs| regs[n] as _)
  88. } else {
  89. None
  90. }
  91. }
  92. fn from_retval(ctx: &pt_regs) -> Option<Self> {
  93. ctx.uregs().map(|regs| regs[0] as _)
  94. }
  95. }
  96. #[cfg(bpf_target_arch = "aarch64")]
  97. impl<T> FromPtRegs for *const T {
  98. fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
  99. if n <= 7 {
  100. ctx.regs().map(|regs| regs[n] as _)
  101. } else {
  102. None
  103. }
  104. }
  105. fn from_retval(ctx: &pt_regs) -> Option<Self> {
  106. ctx.regs().map(|regs| regs[0] as _)
  107. }
  108. }
  109. #[cfg(bpf_target_arch = "x86_64")]
  110. impl<T> FromPtRegs for *mut T {
  111. fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
  112. match n {
  113. 0 => ctx.rdi().map(|v| v as _),
  114. 1 => ctx.rsi().map(|v| v as _),
  115. 2 => ctx.rdx().map(|v| v as _),
  116. 3 => ctx.rcx().map(|v| v as _),
  117. 4 => ctx.r8().map(|v| v as _),
  118. 5 => ctx.r9().map(|v| v as _),
  119. _ => None,
  120. }
  121. }
  122. fn from_retval(ctx: &pt_regs) -> Option<Self> {
  123. ctx.rax().map(|v| v as _)
  124. }
  125. }
  126. #[cfg(bpf_target_arch = "armv7")]
  127. impl<T> FromPtRegs for *mut T {
  128. fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
  129. if n <= 6 {
  130. ctx.uregs().map(|regs| regs[n] as _)
  131. } else {
  132. None
  133. }
  134. }
  135. fn from_retval(ctx: &pt_regs) -> Option<Self> {
  136. ctx.uregs().map(|regs| regs[0] as _)
  137. }
  138. }
  139. #[cfg(bpf_target_arch = "aarch64")]
  140. impl<T> FromPtRegs for *mut T {
  141. fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
  142. if n <= 7 {
  143. ctx.regs().map(|regs| regs[n] as _)
  144. } else {
  145. None
  146. }
  147. }
  148. fn from_retval(ctx: &pt_regs) -> Option<Self> {
  149. ctx.regs().map(|regs| regs[0] as _)
  150. }
  151. }
  152. /// Helper macro to implement [`FromPtRegs`] for a primitive type.
  153. macro_rules! impl_from_pt_regs {
  154. ($type:ident) => {
  155. #[cfg(bpf_target_arch = "x86_64")]
  156. impl FromPtRegs for $type {
  157. fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
  158. match n {
  159. 0 => ctx.rdi().map(|v| v as _),
  160. 1 => ctx.rsi().map(|v| v as _),
  161. 2 => ctx.rdx().map(|v| v as _),
  162. 3 => ctx.rcx().map(|v| v as _),
  163. 4 => ctx.r8().map(|v| v as _),
  164. 5 => ctx.r9().map(|v| v as _),
  165. _ => None,
  166. }
  167. }
  168. fn from_retval(ctx: &pt_regs) -> Option<Self> {
  169. ctx.rax().map(|v| v as _)
  170. }
  171. }
  172. #[cfg(bpf_target_arch = "armv7")]
  173. impl FromPtRegs for $type {
  174. fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
  175. if n <= 6 {
  176. ctx.uregs().map(|regs| regs[n] as _)
  177. } else {
  178. None
  179. }
  180. }
  181. fn from_retval(ctx: &pt_regs) -> Option<Self> {
  182. ctx.uregs().map(|regs| regs[0] as _)
  183. }
  184. }
  185. #[cfg(bpf_target_arch = "aarch64")]
  186. impl FromPtRegs for $type {
  187. fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
  188. if n <= 7 {
  189. ctx.regs().map(|regs| regs[n] as _)
  190. } else {
  191. None
  192. }
  193. }
  194. fn from_retval(ctx: &pt_regs) -> Option<Self> {
  195. ctx.regs().map(|regs| regs[0] as _)
  196. }
  197. }
  198. };
  199. }
  200. impl_from_pt_regs!(u8);
  201. impl_from_pt_regs!(u16);
  202. impl_from_pt_regs!(u32);
  203. impl_from_pt_regs!(u64);
  204. impl_from_pt_regs!(i8);
  205. impl_from_pt_regs!(i16);
  206. impl_from_pt_regs!(i32);
  207. impl_from_pt_regs!(i64);
  208. impl_from_pt_regs!(usize);
  209. impl_from_pt_regs!(isize);