1use crate::error::{Error, Result};
2use crate::types::{Array, BaseType, Field, Float, Integer, Struct, Type, TypeDatabase};
3
4use btf::{
5 Array as BtfArray, Btf, Float as BtfFloat, Integer as BtfInteger, Struct as BtfStruct,
6 Type as BtfType,
7};
8
9use std::collections::HashMap;
10
11impl TypeDatabase {
12 fn add_btf_void(&mut self, name: Option<&str>, num_refs: u32) -> Result<usize> {
19 let new_type = Type {
20 base_type: BaseType::Void,
21 num_refs,
22 };
23
24 self.add_type(name, &new_type)
25 }
26
27 fn add_btf_integer(
35 &mut self,
36 name: Option<&str>,
37 integer: &BtfInteger,
38 num_refs: u32,
39 ) -> Result<usize> {
40 let base_type = BaseType::Integer(Integer {
41 used_bits: integer.used_bits,
42 bits: integer.bits,
43 is_signed: integer.is_signed,
44 });
45
46 let new_type = Type {
47 base_type,
48 num_refs,
49 };
50
51 self.add_type(name, &new_type)
52 }
53
54 fn add_btf_float(
62 &mut self,
63 name: Option<&str>,
64 float: &BtfFloat,
65 num_refs: u32,
66 ) -> Result<usize> {
67 let base_type = BaseType::Float(Float { bits: float.bits });
68
69 let new_type = Type {
70 base_type,
71 num_refs,
72 };
73
74 self.add_type(name, &new_type)
75 }
76
77 fn add_btf_array(
85 &mut self,
86 name: Option<&str>,
87 array: &BtfArray,
88 num_refs: u32,
89 ) -> Result<usize> {
90 let btf_id_name = format!(".btf.{}", array.elem_type_id);
91 let element_type_id = self
92 .get_type_id_by_name(&btf_id_name)
93 .ok_or(Error::NoConversion)?;
94 let base_type = BaseType::Array(Array::create(self, element_type_id, array.num_elements)?);
95 let new_type = Type {
96 base_type,
97 num_refs,
98 };
99 self.add_type(name, &new_type)
100 }
101
102 fn add_btf_struct(
110 &mut self,
111 name: Option<&str>,
112 structure: &BtfStruct,
113 num_refs: u32,
114 ) -> Result<usize> {
115 let mut size = 0;
116 let mut fields = HashMap::with_capacity(structure.members.len());
117 for (i, member) in structure.members.iter().enumerate() {
118 let btf_id_name = format!(".btf.{}", member.type_id);
119 let type_id = self
120 .get_type_id_by_name(&btf_id_name)
121 .ok_or(Error::NoConversion)?;
122 let field = Field {
123 offset: member.offset,
124 type_id,
125 };
126
127 let field_type = self
128 .get_type_by_name(&btf_id_name)
129 .ok_or(Error::NoConversion)?;
130 let field_size = (member.offset + field_type.get_size() * 8) / 8;
131 if field_size > size {
132 size = field_size;
133 }
134
135 if let Some(member_name) = &member.name {
136 fields.insert(member_name.to_string(), field);
137 } else {
138 let member_name = format!("{}", i);
139 fields.insert(member_name, field);
140 }
141 }
142
143 let base_type = BaseType::Struct(Struct { size, fields });
144 let new_type = Type {
145 base_type,
146 num_refs,
147 };
148 self.add_type(name, &new_type)
149 }
150
151 fn add_btf_type(
159 &mut self,
160 name: Option<&str>,
161 btf_type: &BtfType,
162 num_refs: u32,
163 ) -> Result<usize> {
164 match btf_type {
165 BtfType::Integer(integer) => self.add_btf_integer(name, integer, num_refs),
166 BtfType::Float(float) => self.add_btf_float(name, float, num_refs),
167 BtfType::Array(array) => self.add_btf_array(name, array, num_refs),
168 BtfType::Struct(structure) => self.add_btf_struct(name, structure, num_refs),
169 _ => self.add_btf_void(name, num_refs),
170 }
171 }
172
173 pub fn add_btf_types(&mut self, btf: &Btf) -> Result<()> {
196 for i in 0..btf.get_types().len() {
198 let btf_id_name = format!(".btf.{}", i);
199 self.add_btf_void(Some(&btf_id_name), 0)?;
200 }
201
202 for (i, btf_type) in btf.get_types().iter().enumerate() {
203 let btf_id_name = format!(".btf.{}", i);
204 self.add_btf_type(Some(&btf_id_name), &btf_type.base_type, btf_type.num_refs)?;
205 self.add_btf_type(
206 btf_type.name.as_deref(),
207 &btf_type.base_type,
208 btf_type.num_refs,
209 )?;
210 }
211
212 Ok(())
213 }
214}