types.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. use std::{
  2. convert::{TryFrom, TryInto},
  3. mem, ptr,
  4. };
  5. use object::Endianness;
  6. use crate::{
  7. generated::{
  8. btf_array, btf_enum, btf_member, btf_param, btf_type, btf_type__bindgen_ty_1, btf_var,
  9. btf_var_secinfo, BTF_KIND_ARRAY, BTF_KIND_CONST, BTF_KIND_DATASEC, BTF_KIND_ENUM,
  10. BTF_KIND_FUNC, BTF_KIND_FUNC_PROTO, BTF_KIND_FWD, BTF_KIND_INT, BTF_KIND_PTR,
  11. BTF_KIND_RESTRICT, BTF_KIND_STRUCT, BTF_KIND_TYPEDEF, BTF_KIND_UNION, BTF_KIND_UNKN,
  12. BTF_KIND_VAR, BTF_KIND_VOLATILE,
  13. },
  14. obj::btf::{Btf, BtfError, MAX_RESOLVE_DEPTH},
  15. };
  16. #[derive(Clone, Debug)]
  17. pub(crate) enum BtfType {
  18. Unknown,
  19. Fwd(btf_type),
  20. Const(btf_type),
  21. Volatile(btf_type),
  22. Restrict(btf_type),
  23. Ptr(btf_type),
  24. Typedef(btf_type),
  25. Func(btf_type),
  26. Int(btf_type, u32),
  27. Enum(btf_type, Vec<btf_enum>),
  28. Array(btf_type, btf_array),
  29. Struct(btf_type, Vec<btf_member>),
  30. Union(btf_type, Vec<btf_member>),
  31. FuncProto(btf_type, Vec<btf_param>),
  32. Var(btf_type, btf_var),
  33. DataSec(btf_type, Vec<btf_var_secinfo>),
  34. }
  35. #[derive(Copy, Clone, Debug, Eq, PartialEq)]
  36. #[repr(u32)]
  37. pub(crate) enum BtfKind {
  38. Unknown = BTF_KIND_UNKN,
  39. Int = BTF_KIND_INT,
  40. Ptr = BTF_KIND_PTR,
  41. Array = BTF_KIND_ARRAY,
  42. Struct = BTF_KIND_STRUCT,
  43. Union = BTF_KIND_UNION,
  44. Enum = BTF_KIND_ENUM,
  45. Fwd = BTF_KIND_FWD,
  46. Typedef = BTF_KIND_TYPEDEF,
  47. Volatile = BTF_KIND_VOLATILE,
  48. Const = BTF_KIND_CONST,
  49. Restrict = BTF_KIND_RESTRICT,
  50. Func = BTF_KIND_FUNC,
  51. FuncProto = BTF_KIND_FUNC_PROTO,
  52. Var = BTF_KIND_VAR,
  53. DataSec = BTF_KIND_DATASEC,
  54. }
  55. impl TryFrom<u32> for BtfKind {
  56. type Error = BtfError;
  57. fn try_from(v: u32) -> Result<Self, Self::Error> {
  58. use BtfKind::*;
  59. Ok(match v {
  60. BTF_KIND_UNKN => Unknown,
  61. BTF_KIND_INT => Int,
  62. BTF_KIND_PTR => Ptr,
  63. BTF_KIND_ARRAY => Array,
  64. BTF_KIND_STRUCT => Struct,
  65. BTF_KIND_UNION => Union,
  66. BTF_KIND_ENUM => Enum,
  67. BTF_KIND_FWD => Fwd,
  68. BTF_KIND_TYPEDEF => Typedef,
  69. BTF_KIND_VOLATILE => Volatile,
  70. BTF_KIND_CONST => Const,
  71. BTF_KIND_RESTRICT => Restrict,
  72. BTF_KIND_FUNC => Func,
  73. BTF_KIND_FUNC_PROTO => FuncProto,
  74. BTF_KIND_VAR => Var,
  75. BTF_KIND_DATASEC => DataSec,
  76. kind => return Err(BtfError::InvalidTypeKind { kind }),
  77. })
  78. }
  79. }
  80. unsafe fn read<T>(data: &[u8]) -> Result<T, BtfError> {
  81. if mem::size_of::<T>() > data.len() {
  82. return Err(BtfError::InvalidTypeInfo);
  83. }
  84. Ok(ptr::read_unaligned::<T>(data.as_ptr() as *const T))
  85. }
  86. unsafe fn read_array<T>(data: &[u8], len: usize) -> Result<Vec<T>, BtfError> {
  87. if mem::size_of::<T>() * len > data.len() {
  88. return Err(BtfError::InvalidTypeInfo);
  89. }
  90. Ok((0..len)
  91. .map(|i| {
  92. ptr::read_unaligned::<T>((data.as_ptr() as usize + i * mem::size_of::<T>()) as *const T)
  93. })
  94. .collect::<Vec<T>>())
  95. }
  96. impl BtfType {
  97. #[allow(unused_unsafe)]
  98. pub(crate) unsafe fn read(data: &[u8], endianness: Endianness) -> Result<BtfType, BtfError> {
  99. let ty = unsafe { read::<btf_type>(data)? };
  100. let data = &data[mem::size_of::<btf_type>()..];
  101. let vlen = type_vlen(&ty) as usize;
  102. use BtfType::*;
  103. Ok(match type_kind(&ty)? {
  104. BtfKind::Unknown => Unknown,
  105. BtfKind::Fwd => Fwd(ty),
  106. BtfKind::Const => Const(ty),
  107. BtfKind::Volatile => Volatile(ty),
  108. BtfKind::Restrict => Restrict(ty),
  109. BtfKind::Ptr => Ptr(ty),
  110. BtfKind::Typedef => Typedef(ty),
  111. BtfKind::Func => Func(ty),
  112. BtfKind::Int => {
  113. if mem::size_of::<u32>() > data.len() {
  114. return Err(BtfError::InvalidTypeInfo);
  115. }
  116. let read_u32 = if endianness == Endianness::Little {
  117. u32::from_le_bytes
  118. } else {
  119. u32::from_be_bytes
  120. };
  121. Int(
  122. ty,
  123. read_u32(data[..mem::size_of::<u32>()].try_into().unwrap()),
  124. )
  125. }
  126. BtfKind::Enum => Enum(ty, unsafe { read_array(data, vlen)? }),
  127. BtfKind::Array => Array(ty, unsafe { read(data)? }),
  128. BtfKind::Struct => Struct(ty, unsafe { read_array(data, vlen)? }),
  129. BtfKind::Union => Union(ty, unsafe { read_array(data, vlen)? }),
  130. BtfKind::FuncProto => FuncProto(ty, unsafe { read_array(data, vlen)? }),
  131. BtfKind::Var => Var(ty, unsafe { read(data)? }),
  132. BtfKind::DataSec => DataSec(ty, unsafe { read_array(data, vlen)? }),
  133. })
  134. }
  135. pub(crate) fn type_info_size(&self) -> usize {
  136. let ty_size = mem::size_of::<btf_type>();
  137. use BtfType::*;
  138. match self {
  139. Unknown => 0,
  140. Fwd(_) | Const(_) | Volatile(_) | Restrict(_) | Ptr(_) | Typedef(_) | Func(_) => {
  141. ty_size
  142. }
  143. Int(_, _) => ty_size + mem::size_of::<u32>(),
  144. Enum(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_enum>(),
  145. Array(_, _) => ty_size + mem::size_of::<btf_array>(),
  146. Struct(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_member>(),
  147. Union(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_member>(),
  148. FuncProto(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_param>(),
  149. Var(_, _) => ty_size + mem::size_of::<btf_var>(),
  150. DataSec(ty, _) => ty_size + type_vlen(ty) * mem::size_of::<btf_var_secinfo>(),
  151. }
  152. }
  153. pub(crate) fn btf_type(&self) -> Option<&btf_type> {
  154. use BtfType::*;
  155. Some(match self {
  156. Unknown => return None,
  157. Fwd(ty) => ty,
  158. Const(ty) => ty,
  159. Volatile(ty) => ty,
  160. Restrict(ty) => ty,
  161. Ptr(ty) => ty,
  162. Typedef(ty) => ty,
  163. Func(ty) => ty,
  164. Int(ty, _) => ty,
  165. Enum(ty, _) => ty,
  166. Array(ty, _) => ty,
  167. Struct(ty, _) => ty,
  168. Union(ty, _) => ty,
  169. FuncProto(ty, _) => ty,
  170. Var(ty, _) => ty,
  171. DataSec(ty, _) => ty,
  172. })
  173. }
  174. pub(crate) fn info(&self) -> Option<u32> {
  175. self.btf_type().map(|ty| ty.info)
  176. }
  177. pub(crate) fn name_offset(&self) -> Option<u32> {
  178. self.btf_type().map(|ty| ty.name_off)
  179. }
  180. pub(crate) fn kind(&self) -> Result<Option<BtfKind>, BtfError> {
  181. self.btf_type().map(type_kind).transpose()
  182. }
  183. pub(crate) fn is_composite(&self) -> bool {
  184. match self {
  185. BtfType::Struct(_, _) | BtfType::Union(_, _) => true,
  186. _ => false,
  187. }
  188. }
  189. }
  190. fn type_kind(ty: &btf_type) -> Result<BtfKind, BtfError> {
  191. ((ty.info >> 24) & 0x0F).try_into()
  192. }
  193. fn type_vlen(ty: &btf_type) -> usize {
  194. (ty.info & 0xFFFF) as usize
  195. }
  196. pub(crate) fn member_bit_offset(info: u32, member: &btf_member) -> usize {
  197. let k_flag = info >> 31 == 1;
  198. let bit_offset = if k_flag {
  199. member.offset & 0xFFFFFF
  200. } else {
  201. member.offset
  202. };
  203. bit_offset as usize
  204. }
  205. pub(crate) fn member_bit_field_size(ty: &btf_type, member: &btf_member) -> usize {
  206. let k_flag = (ty.info >> 31) == 1;
  207. let size = if k_flag { member.offset >> 24 } else { 0 };
  208. size as usize
  209. }
  210. pub(crate) fn types_are_compatible(
  211. local_btf: &Btf,
  212. root_local_id: u32,
  213. target_btf: &Btf,
  214. root_target_id: u32,
  215. ) -> Result<bool, BtfError> {
  216. let mut local_id = root_local_id;
  217. let mut target_id = root_target_id;
  218. let local_ty = local_btf.type_by_id(local_id)?;
  219. let target_ty = target_btf.type_by_id(target_id)?;
  220. if local_ty.kind()? != target_ty.kind()? {
  221. return Ok(false);
  222. }
  223. for _ in 0..MAX_RESOLVE_DEPTH {
  224. local_id = local_btf.resolve_type(local_id)?;
  225. target_id = target_btf.resolve_type(target_id)?;
  226. let local_ty = local_btf.type_by_id(local_id)?;
  227. let target_ty = target_btf.type_by_id(target_id)?;
  228. if local_ty.kind()? != target_ty.kind()? {
  229. return Ok(false);
  230. }
  231. use BtfType::*;
  232. match local_ty {
  233. Unknown | Struct(_, _) | Union(_, _) | Enum(_, _) | Fwd(_) => return Ok(true),
  234. Int(_, local_off) => {
  235. if let Int(_, target_off) = target_ty {
  236. return Ok(*local_off == 0 && *target_off == 0);
  237. }
  238. }
  239. Ptr(l_ty) => {
  240. if let Ptr(t_ty) = target_ty {
  241. // Safety: union
  242. unsafe {
  243. local_id = l_ty.__bindgen_anon_1.type_;
  244. target_id = t_ty.__bindgen_anon_1.type_;
  245. }
  246. continue;
  247. }
  248. }
  249. Array(l_ty, _) => {
  250. if let Array(t_ty, _) = target_ty {
  251. // Safety: union
  252. unsafe {
  253. local_id = l_ty.__bindgen_anon_1.type_;
  254. target_id = t_ty.__bindgen_anon_1.type_;
  255. }
  256. continue;
  257. }
  258. }
  259. FuncProto(l_ty, l_params) => {
  260. if let FuncProto(t_ty, t_params) = target_ty {
  261. if l_params.len() != t_params.len() {
  262. return Ok(false);
  263. }
  264. for (l_param, t_param) in l_params.iter().zip(t_params.iter()) {
  265. let local_id = local_btf.resolve_type(l_param.type_)?;
  266. let target_id = target_btf.resolve_type(t_param.type_)?;
  267. if !types_are_compatible(local_btf, local_id, target_btf, target_id)? {
  268. return Ok(false);
  269. }
  270. }
  271. // Safety: union
  272. unsafe {
  273. local_id = l_ty.__bindgen_anon_1.type_;
  274. target_id = t_ty.__bindgen_anon_1.type_;
  275. }
  276. continue;
  277. }
  278. }
  279. _ => panic!("this shouldn't be reached"),
  280. }
  281. }
  282. Err(BtfError::MaximumTypeDepthReached { type_id: local_id })
  283. }
  284. pub(crate) fn fields_are_compatible(
  285. local_btf: &Btf,
  286. mut local_id: u32,
  287. target_btf: &Btf,
  288. mut target_id: u32,
  289. ) -> Result<bool, BtfError> {
  290. for _ in 0..MAX_RESOLVE_DEPTH {
  291. local_id = local_btf.resolve_type(local_id)?;
  292. target_id = target_btf.resolve_type(target_id)?;
  293. let local_ty = local_btf.type_by_id(local_id)?;
  294. let target_ty = target_btf.type_by_id(target_id)?;
  295. if local_ty.is_composite() && target_ty.is_composite() {
  296. return Ok(true);
  297. }
  298. if local_ty.kind()? != target_ty.kind()? {
  299. return Ok(false);
  300. }
  301. use BtfType::*;
  302. match local_ty {
  303. Fwd(_) | Enum(_, _) => {
  304. let flavorless_name =
  305. |name: &str| name.splitn(2, "___").next().unwrap().to_string();
  306. let local_name = flavorless_name(&*local_btf.type_name(local_ty)?.unwrap());
  307. let target_name = flavorless_name(&*target_btf.type_name(target_ty)?.unwrap());
  308. return Ok(local_name == target_name);
  309. }
  310. Int(_, local_off) => {
  311. let local_off = (local_off >> 16) & 0xFF;
  312. if let Int(_, target_off) = target_ty {
  313. let target_off = (target_off >> 16) & 0xFF;
  314. return Ok(local_off == 0 && target_off == 0);
  315. }
  316. }
  317. Ptr(_) => return Ok(true),
  318. Array(l_ty, _) => {
  319. if let Array(t_ty, _) = target_ty {
  320. // Safety: union
  321. unsafe {
  322. local_id = l_ty.__bindgen_anon_1.type_;
  323. target_id = t_ty.__bindgen_anon_1.type_;
  324. }
  325. continue;
  326. }
  327. }
  328. _ => panic!("this shouldn't be reached"),
  329. }
  330. }
  331. Err(BtfError::MaximumTypeDepthReached { type_id: local_id })
  332. }
  333. impl std::fmt::Debug for btf_type {
  334. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  335. f.debug_struct("btf_type")
  336. .field("name_off", &self.name_off)
  337. .field("info", &self.info)
  338. .field("__bindgen_anon_1", &self.__bindgen_anon_1)
  339. .finish()
  340. }
  341. }
  342. impl std::fmt::Debug for btf_type__bindgen_ty_1 {
  343. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  344. // Safety: union
  345. f.debug_struct("btf_type__bindgen_ty_1")
  346. .field("size", unsafe { &self.size })
  347. .field("type_", unsafe { &self.type_ })
  348. .finish()
  349. }
  350. }