obj.rs 79 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494
  1. //! Object file loading, parsing, and relocation.
  2. use alloc::{
  3. borrow::ToOwned,
  4. collections::BTreeMap,
  5. ffi::CString,
  6. string::{String, ToString},
  7. vec::Vec,
  8. };
  9. use core::{ffi::CStr, mem, ptr, str::FromStr};
  10. use log::debug;
  11. use object::{
  12. read::{Object as ElfObject, ObjectSection, Section as ObjSection},
  13. Endianness, ObjectSymbol, ObjectSymbolTable, RelocationTarget, SectionIndex, SectionKind,
  14. SymbolKind,
  15. };
  16. use crate::{
  17. btf::BtfFeatures,
  18. generated::{BPF_CALL, BPF_JMP, BPF_K},
  19. maps::{BtfMap, LegacyMap, Map, MINIMUM_MAP_SIZE},
  20. relocation::*,
  21. util::HashMap,
  22. };
  23. #[cfg(not(feature = "std"))]
  24. use crate::std;
  25. use crate::{
  26. btf::{Btf, BtfError, BtfExt, BtfType},
  27. generated::{bpf_insn, bpf_map_info, bpf_map_type::BPF_MAP_TYPE_ARRAY, BPF_F_RDONLY_PROG},
  28. maps::{bpf_map_def, BtfMapDef, PinningType},
  29. programs::{CgroupSockAddrAttachType, CgroupSockAttachType, CgroupSockoptAttachType},
  30. };
  31. use core::slice::from_raw_parts_mut;
  32. use crate::btf::{Array, DataSecEntry, FuncSecInfo, LineSecInfo};
  33. const KERNEL_VERSION_ANY: u32 = 0xFFFF_FFFE;
  34. /// Features implements BPF and BTF feature detection
  35. #[derive(Default, Debug)]
  36. #[allow(missing_docs)]
  37. pub struct Features {
  38. bpf_name: bool,
  39. bpf_probe_read_kernel: bool,
  40. bpf_perf_link: bool,
  41. bpf_global_data: bool,
  42. bpf_cookie: bool,
  43. btf: Option<BtfFeatures>,
  44. }
  45. impl Features {
  46. #[doc(hidden)]
  47. pub fn new(
  48. bpf_name: bool,
  49. bpf_probe_read_kernel: bool,
  50. bpf_perf_link: bool,
  51. bpf_global_data: bool,
  52. bpf_cookie: bool,
  53. btf: Option<BtfFeatures>,
  54. ) -> Self {
  55. Self {
  56. bpf_name,
  57. bpf_probe_read_kernel,
  58. bpf_perf_link,
  59. bpf_global_data,
  60. bpf_cookie,
  61. btf,
  62. }
  63. }
  64. /// Returns whether BPF program names are supported.
  65. pub fn bpf_name(&self) -> bool {
  66. self.bpf_name
  67. }
  68. /// Returns whether the bpf_probe_read_kernel helper is supported.
  69. pub fn bpf_probe_read_kernel(&self) -> bool {
  70. self.bpf_probe_read_kernel
  71. }
  72. /// Returns whether bpf_links are supported for Kprobes/Uprobes/Tracepoints.
  73. pub fn bpf_perf_link(&self) -> bool {
  74. self.bpf_perf_link
  75. }
  76. /// Returns whether BPF program global data is supported.
  77. pub fn bpf_global_data(&self) -> bool {
  78. self.bpf_global_data
  79. }
  80. /// Returns whether BPF program cookie is supported.
  81. pub fn bpf_cookie(&self) -> bool {
  82. self.bpf_cookie
  83. }
  84. /// If BTF is supported, returns which BTF features are supported.
  85. pub fn btf(&self) -> Option<&BtfFeatures> {
  86. self.btf.as_ref()
  87. }
  88. }
  89. /// The loaded object file representation
  90. #[derive(Clone)]
  91. pub struct Object {
  92. /// The endianness
  93. pub endianness: Endianness,
  94. /// Program license
  95. pub license: CString,
  96. /// Kernel version
  97. pub kernel_version: Option<u32>,
  98. /// Program BTF
  99. pub btf: Option<Btf>,
  100. /// Program BTF.ext
  101. pub btf_ext: Option<BtfExt>,
  102. /// Referenced maps
  103. pub maps: HashMap<String, Map>,
  104. /// A hash map of programs, using the program names parsed
  105. /// in [ProgramSection]s as keys.
  106. pub programs: HashMap<String, Program>,
  107. /// Functions
  108. pub functions: BTreeMap<(usize, u64), Function>,
  109. pub(crate) relocations: HashMap<SectionIndex, HashMap<u64, Relocation>>,
  110. pub(crate) symbol_table: HashMap<usize, Symbol>,
  111. pub(crate) section_infos: HashMap<String, (SectionIndex, u64)>,
  112. // symbol_offset_by_name caches symbols that could be referenced from a
  113. // BTF VAR type so the offsets can be fixed up
  114. pub(crate) symbol_offset_by_name: HashMap<String, u64>,
  115. }
  116. /// An eBPF program
  117. #[derive(Debug, Clone)]
  118. pub struct Program {
  119. /// The license
  120. pub license: CString,
  121. /// The kernel version
  122. pub kernel_version: Option<u32>,
  123. /// The section containing the program
  124. pub section: ProgramSection,
  125. /// The section index of the program
  126. pub section_index: usize,
  127. /// The address of the program
  128. pub address: u64,
  129. }
  130. impl Program {
  131. /// The key used by [Object::functions]
  132. pub fn function_key(&self) -> (usize, u64) {
  133. (self.section_index, self.address)
  134. }
  135. }
  136. /// An eBPF function
  137. #[derive(Debug, Clone)]
  138. pub struct Function {
  139. /// The address
  140. pub address: u64,
  141. /// The function name
  142. pub name: String,
  143. /// The section index
  144. pub section_index: SectionIndex,
  145. /// The section offset
  146. pub section_offset: usize,
  147. /// The eBPF byte code instructions
  148. pub instructions: Vec<bpf_insn>,
  149. /// The function info
  150. pub func_info: FuncSecInfo,
  151. /// The line info
  152. pub line_info: LineSecInfo,
  153. /// Function info record size
  154. pub func_info_rec_size: usize,
  155. /// Line info record size
  156. pub line_info_rec_size: usize,
  157. }
  158. /// Section types containing eBPF programs
  159. ///
  160. /// # Section Name Parsing
  161. ///
  162. /// Section types are parsed from the section name strings.
  163. ///
  164. /// In order for Aya to treat a section as a [ProgramSection],
  165. /// there are a few requirements:
  166. /// - The section must be an executable code section.
  167. /// - The section name must conform to [Program Types and ELF Sections].
  168. ///
  169. /// [Program Types and ELF Sections]: https://docs.kernel.org/bpf/libbpf/program_types.html
  170. ///
  171. /// ## Program Name
  172. ///
  173. /// Each section name is parsed into a section type and a program name.
  174. ///
  175. /// Generally speaking,
  176. /// - if the section name does not contain any slashes,
  177. /// then the program name is just that section name;
  178. /// - if there are some slashes, the name is `section_name.rsplitn(2, '/')[0]`,
  179. /// - except for tracepoint programs, for which the name is
  180. /// `section_name.splitn(2, '/')[1]`.
  181. ///
  182. /// ```rust
  183. /// use aya_obj::ProgramSection;
  184. /// use std::str::FromStr;
  185. ///
  186. /// assert_eq!(
  187. /// ProgramSection::from_str("kprobe/do_unlinkat")
  188. /// .unwrap().name(),
  189. /// "do_unlinkat",
  190. /// );
  191. /// assert_eq!(
  192. /// ProgramSection::from_str("tracepoint/syscalls/sys_enter_openat")
  193. /// .unwrap().name(),
  194. /// "syscalls/sys_enter_openat",
  195. /// );
  196. /// ```
  197. ///
  198. /// The program name will be used in [Object] as references to each program.
  199. ///
  200. /// # Unsupported Sections
  201. ///
  202. /// Currently, the following section names are not supported yet:
  203. /// - `flow_dissector`: `BPF_PROG_TYPE_FLOW_DISSECTOR`
  204. /// - `ksyscall+` or `kretsyscall+`
  205. /// - `uprobe.s+` or `uretprobe.s+`
  206. /// - `usdt+`
  207. /// - `kprobe.multi+` or `kretprobe.multi+`: `BPF_TRACE_KPROBE_MULTI`
  208. /// - `lsm_cgroup+`
  209. /// - `lwt_in`, `lwt_out`, `lwt_seg6local`, `lwt_xmit`
  210. /// - `raw_tp.w+`, `raw_tracepoint.w+`
  211. /// - `action`
  212. /// - `sk_reuseport/migrate`, `sk_reuseport`
  213. /// - `syscall`
  214. /// - `struct_ops+`
  215. /// - `fmod_ret+`, `fmod_ret.s+`
  216. /// - `fentry.s+`, `fexit.s+`
  217. /// - `iter+`, `iter.s+`
  218. /// - `xdp.frags/cpumap`, `xdp/cpumap`
  219. /// - `xdp.frags/devmap`, `xdp/devmap`
  220. #[derive(Debug, Clone)]
  221. #[allow(missing_docs)]
  222. pub enum ProgramSection {
  223. KRetProbe {
  224. name: String,
  225. },
  226. KProbe {
  227. name: String,
  228. },
  229. UProbe {
  230. name: String,
  231. },
  232. URetProbe {
  233. name: String,
  234. },
  235. TracePoint {
  236. name: String,
  237. },
  238. SocketFilter {
  239. name: String,
  240. },
  241. Xdp {
  242. name: String,
  243. frags: bool,
  244. },
  245. SkMsg {
  246. name: String,
  247. },
  248. SkSkbStreamParser {
  249. name: String,
  250. },
  251. SkSkbStreamVerdict {
  252. name: String,
  253. },
  254. SockOps {
  255. name: String,
  256. },
  257. SchedClassifier {
  258. name: String,
  259. },
  260. CgroupSkb {
  261. name: String,
  262. },
  263. CgroupSkbIngress {
  264. name: String,
  265. },
  266. CgroupSkbEgress {
  267. name: String,
  268. },
  269. CgroupSockAddr {
  270. name: String,
  271. attach_type: CgroupSockAddrAttachType,
  272. },
  273. CgroupSysctl {
  274. name: String,
  275. },
  276. CgroupSockopt {
  277. name: String,
  278. attach_type: CgroupSockoptAttachType,
  279. },
  280. LircMode2 {
  281. name: String,
  282. },
  283. PerfEvent {
  284. name: String,
  285. },
  286. RawTracePoint {
  287. name: String,
  288. },
  289. Lsm {
  290. name: String,
  291. sleepable: bool,
  292. },
  293. BtfTracePoint {
  294. name: String,
  295. },
  296. FEntry {
  297. name: String,
  298. },
  299. FExit {
  300. name: String,
  301. },
  302. Extension {
  303. name: String,
  304. },
  305. SkLookup {
  306. name: String,
  307. },
  308. CgroupSock {
  309. name: String,
  310. attach_type: CgroupSockAttachType,
  311. },
  312. CgroupDevice {
  313. name: String,
  314. },
  315. }
  316. impl ProgramSection {
  317. /// Returns the program name
  318. pub fn name(&self) -> &str {
  319. match self {
  320. ProgramSection::KRetProbe { name } => name,
  321. ProgramSection::KProbe { name } => name,
  322. ProgramSection::UProbe { name } => name,
  323. ProgramSection::URetProbe { name } => name,
  324. ProgramSection::TracePoint { name } => name,
  325. ProgramSection::SocketFilter { name } => name,
  326. ProgramSection::Xdp { name, .. } => name,
  327. ProgramSection::SkMsg { name } => name,
  328. ProgramSection::SkSkbStreamParser { name } => name,
  329. ProgramSection::SkSkbStreamVerdict { name } => name,
  330. ProgramSection::SockOps { name } => name,
  331. ProgramSection::SchedClassifier { name } => name,
  332. ProgramSection::CgroupSkb { name, .. } => name,
  333. ProgramSection::CgroupSkbIngress { name, .. } => name,
  334. ProgramSection::CgroupSkbEgress { name, .. } => name,
  335. ProgramSection::CgroupSockAddr { name, .. } => name,
  336. ProgramSection::CgroupSysctl { name } => name,
  337. ProgramSection::CgroupSockopt { name, .. } => name,
  338. ProgramSection::LircMode2 { name } => name,
  339. ProgramSection::PerfEvent { name } => name,
  340. ProgramSection::RawTracePoint { name } => name,
  341. ProgramSection::Lsm { name, .. } => name,
  342. ProgramSection::BtfTracePoint { name } => name,
  343. ProgramSection::FEntry { name } => name,
  344. ProgramSection::FExit { name } => name,
  345. ProgramSection::Extension { name } => name,
  346. ProgramSection::SkLookup { name } => name,
  347. ProgramSection::CgroupSock { name, .. } => name,
  348. ProgramSection::CgroupDevice { name } => name,
  349. }
  350. }
  351. }
  352. impl FromStr for ProgramSection {
  353. type Err = ParseError;
  354. fn from_str(section: &str) -> Result<ProgramSection, ParseError> {
  355. use ProgramSection::*;
  356. // parse the common case, eg "xdp/program_name" or
  357. // "sk_skb/stream_verdict/program_name"
  358. let mut parts = section.rsplitn(2, '/').collect::<Vec<_>>();
  359. if parts.len() == 1 {
  360. parts.push(parts[0]);
  361. }
  362. let kind = parts[1];
  363. let name = parts[0].to_owned();
  364. Ok(match kind {
  365. "kprobe" => KProbe { name },
  366. "kretprobe" => KRetProbe { name },
  367. "uprobe" => UProbe { name },
  368. "uretprobe" => URetProbe { name },
  369. "xdp" => Xdp { name, frags: false },
  370. "xdp.frags" => Xdp { name, frags: true },
  371. "tp_btf" => BtfTracePoint { name },
  372. _ if kind.starts_with("tracepoint") || kind.starts_with("tp") => {
  373. // tracepoint sections are named `tracepoint/category/event_name`,
  374. // and we want to parse the name as "category/event_name"
  375. let name = section.splitn(2, '/').last().unwrap().to_owned();
  376. TracePoint { name }
  377. }
  378. "socket" => SocketFilter { name },
  379. "sk_msg" => SkMsg { name },
  380. "sk_skb" => match &*name {
  381. "stream_parser" => SkSkbStreamParser { name },
  382. "stream_verdict" => SkSkbStreamVerdict { name },
  383. _ => {
  384. return Err(ParseError::InvalidProgramSection {
  385. section: section.to_owned(),
  386. })
  387. }
  388. },
  389. "sk_skb/stream_parser" => SkSkbStreamParser { name },
  390. "sk_skb/stream_verdict" => SkSkbStreamVerdict { name },
  391. "sockops" => SockOps { name },
  392. "classifier" => SchedClassifier { name },
  393. "cgroup_skb" => match &*name {
  394. "ingress" => CgroupSkbIngress { name },
  395. "egress" => CgroupSkbEgress { name },
  396. _ => {
  397. return Err(ParseError::InvalidProgramSection {
  398. section: section.to_owned(),
  399. })
  400. }
  401. },
  402. "cgroup_skb/ingress" => CgroupSkbIngress { name },
  403. "cgroup_skb/egress" => CgroupSkbEgress { name },
  404. "cgroup/skb" => CgroupSkb { name },
  405. "cgroup/sock" => CgroupSock {
  406. name,
  407. attach_type: CgroupSockAttachType::default(),
  408. },
  409. "cgroup/sysctl" => CgroupSysctl { name },
  410. "cgroup/dev" => CgroupDevice { name },
  411. "cgroup/getsockopt" => CgroupSockopt {
  412. name,
  413. attach_type: CgroupSockoptAttachType::Get,
  414. },
  415. "cgroup/setsockopt" => CgroupSockopt {
  416. name,
  417. attach_type: CgroupSockoptAttachType::Set,
  418. },
  419. "cgroup" => match &*name {
  420. "skb" => CgroupSkb { name },
  421. "sysctl" => CgroupSysctl { name },
  422. "dev" => CgroupDevice { name },
  423. "getsockopt" | "setsockopt" => {
  424. if let Ok(attach_type) = CgroupSockoptAttachType::try_from(name.as_str()) {
  425. CgroupSockopt { name, attach_type }
  426. } else {
  427. return Err(ParseError::InvalidProgramSection {
  428. section: section.to_owned(),
  429. });
  430. }
  431. }
  432. "sock" => CgroupSock {
  433. name,
  434. attach_type: CgroupSockAttachType::default(),
  435. },
  436. "post_bind4" | "post_bind6" | "sock_create" | "sock_release" => {
  437. if let Ok(attach_type) = CgroupSockAttachType::try_from(name.as_str()) {
  438. CgroupSock { name, attach_type }
  439. } else {
  440. return Err(ParseError::InvalidProgramSection {
  441. section: section.to_owned(),
  442. });
  443. }
  444. }
  445. _ => {
  446. if let Ok(attach_type) = CgroupSockAddrAttachType::try_from(name.as_str()) {
  447. CgroupSockAddr { name, attach_type }
  448. } else {
  449. return Err(ParseError::InvalidProgramSection {
  450. section: section.to_owned(),
  451. });
  452. }
  453. }
  454. },
  455. "cgroup/post_bind4" => CgroupSock {
  456. name,
  457. attach_type: CgroupSockAttachType::PostBind4,
  458. },
  459. "cgroup/post_bind6" => CgroupSock {
  460. name,
  461. attach_type: CgroupSockAttachType::PostBind6,
  462. },
  463. "cgroup/sock_create" => CgroupSock {
  464. name,
  465. attach_type: CgroupSockAttachType::SockCreate,
  466. },
  467. "cgroup/sock_release" => CgroupSock {
  468. name,
  469. attach_type: CgroupSockAttachType::SockRelease,
  470. },
  471. "cgroup/bind4" => CgroupSockAddr {
  472. name,
  473. attach_type: CgroupSockAddrAttachType::Bind4,
  474. },
  475. "cgroup/bind6" => CgroupSockAddr {
  476. name,
  477. attach_type: CgroupSockAddrAttachType::Bind6,
  478. },
  479. "cgroup/connect4" => CgroupSockAddr {
  480. name,
  481. attach_type: CgroupSockAddrAttachType::Connect4,
  482. },
  483. "cgroup/connect6" => CgroupSockAddr {
  484. name,
  485. attach_type: CgroupSockAddrAttachType::Connect6,
  486. },
  487. "cgroup/getpeername4" => CgroupSockAddr {
  488. name,
  489. attach_type: CgroupSockAddrAttachType::GetPeerName4,
  490. },
  491. "cgroup/getpeername6" => CgroupSockAddr {
  492. name,
  493. attach_type: CgroupSockAddrAttachType::GetPeerName6,
  494. },
  495. "cgroup/getsockname4" => CgroupSockAddr {
  496. name,
  497. attach_type: CgroupSockAddrAttachType::GetSockName4,
  498. },
  499. "cgroup/getsockname6" => CgroupSockAddr {
  500. name,
  501. attach_type: CgroupSockAddrAttachType::GetSockName6,
  502. },
  503. "cgroup/sendmsg4" => CgroupSockAddr {
  504. name,
  505. attach_type: CgroupSockAddrAttachType::UDPSendMsg4,
  506. },
  507. "cgroup/sendmsg6" => CgroupSockAddr {
  508. name,
  509. attach_type: CgroupSockAddrAttachType::UDPSendMsg6,
  510. },
  511. "cgroup/recvmsg4" => CgroupSockAddr {
  512. name,
  513. attach_type: CgroupSockAddrAttachType::UDPRecvMsg4,
  514. },
  515. "cgroup/recvmsg6" => CgroupSockAddr {
  516. name,
  517. attach_type: CgroupSockAddrAttachType::UDPRecvMsg6,
  518. },
  519. "lirc_mode2" => LircMode2 { name },
  520. "perf_event" => PerfEvent { name },
  521. "raw_tp" | "raw_tracepoint" => RawTracePoint { name },
  522. "lsm" => Lsm {
  523. name,
  524. sleepable: false,
  525. },
  526. "lsm.s" => Lsm {
  527. name,
  528. sleepable: true,
  529. },
  530. "fentry" => FEntry { name },
  531. "fexit" => FExit { name },
  532. "freplace" => Extension { name },
  533. "sk_lookup" => SkLookup { name },
  534. _ => {
  535. return Err(ParseError::InvalidProgramSection {
  536. section: section.to_owned(),
  537. })
  538. }
  539. })
  540. }
  541. }
  542. impl Object {
  543. /// Parses the binary data as an object file into an [Object]
  544. pub fn parse(data: &[u8]) -> Result<Object, ParseError> {
  545. let obj = object::read::File::parse(data).map_err(ParseError::ElfError)?;
  546. let endianness = obj.endianness();
  547. let license = if let Some(section) = obj.section_by_name("license") {
  548. parse_license(Section::try_from(&section)?.data)?
  549. } else {
  550. CString::new("GPL").unwrap()
  551. };
  552. let kernel_version = if let Some(section) = obj.section_by_name("version") {
  553. parse_version(Section::try_from(&section)?.data, endianness)?
  554. } else {
  555. None
  556. };
  557. let mut bpf_obj = Object::new(endianness, license, kernel_version);
  558. if let Some(symbol_table) = obj.symbol_table() {
  559. for symbol in symbol_table.symbols() {
  560. let name = symbol
  561. .name()
  562. .ok()
  563. .map(String::from)
  564. .ok_or(BtfError::InvalidSymbolName)?;
  565. let sym = Symbol {
  566. index: symbol.index().0,
  567. name: Some(name.clone()),
  568. section_index: symbol.section().index().map(|i| i.0),
  569. address: symbol.address(),
  570. size: symbol.size(),
  571. is_definition: symbol.is_definition(),
  572. kind: symbol.kind(),
  573. };
  574. bpf_obj.symbol_table.insert(symbol.index().0, sym);
  575. if symbol.is_global() || symbol.kind() == SymbolKind::Data {
  576. bpf_obj.symbol_offset_by_name.insert(name, symbol.address());
  577. }
  578. }
  579. }
  580. // .BTF and .BTF.ext sections must be parsed first
  581. // as they're required to prepare function and line information
  582. // when parsing program sections
  583. if let Some(s) = obj.section_by_name(".BTF") {
  584. bpf_obj.parse_section(Section::try_from(&s)?)?;
  585. if let Some(s) = obj.section_by_name(".BTF.ext") {
  586. bpf_obj.parse_section(Section::try_from(&s)?)?;
  587. }
  588. }
  589. for s in obj.sections() {
  590. if let Ok(name) = s.name() {
  591. if name == ".BTF" || name == ".BTF.ext" {
  592. continue;
  593. }
  594. }
  595. bpf_obj.parse_section(Section::try_from(&s)?)?;
  596. }
  597. Ok(bpf_obj)
  598. }
  599. fn new(endianness: Endianness, license: CString, kernel_version: Option<u32>) -> Object {
  600. Object {
  601. endianness,
  602. license,
  603. kernel_version,
  604. btf: None,
  605. btf_ext: None,
  606. maps: HashMap::new(),
  607. programs: HashMap::new(),
  608. functions: BTreeMap::new(),
  609. relocations: HashMap::new(),
  610. symbol_table: HashMap::new(),
  611. section_infos: HashMap::new(),
  612. symbol_offset_by_name: HashMap::new(),
  613. }
  614. }
  615. /// Patches map data
  616. pub fn patch_map_data(
  617. &mut self,
  618. globals: HashMap<&str, (&[u8], bool)>,
  619. ) -> Result<(), ParseError> {
  620. let symbols: HashMap<String, &Symbol> = self
  621. .symbol_table
  622. .iter()
  623. .filter(|(_, s)| s.name.is_some())
  624. .map(|(_, s)| (s.name.as_ref().unwrap().clone(), s))
  625. .collect();
  626. for (name, (data, must_exist)) in globals {
  627. if let Some(symbol) = symbols.get(name) {
  628. if data.len() as u64 != symbol.size {
  629. return Err(ParseError::InvalidGlobalData {
  630. name: name.to_string(),
  631. sym_size: symbol.size,
  632. data_size: data.len(),
  633. });
  634. }
  635. let (_, map) = self
  636. .maps
  637. .iter_mut()
  638. // assumption: there is only one map created per section where we're trying to
  639. // patch data. this assumption holds true for the .rodata section at least
  640. .find(|(_, m)| symbol.section_index == Some(m.section_index()))
  641. .ok_or_else(|| ParseError::MapNotFound {
  642. index: symbol.section_index.unwrap_or(0),
  643. })?;
  644. let start = symbol.address as usize;
  645. let end = start + symbol.size as usize;
  646. if start > end || end > map.data().len() {
  647. return Err(ParseError::InvalidGlobalData {
  648. name: name.to_string(),
  649. sym_size: symbol.size,
  650. data_size: data.len(),
  651. });
  652. }
  653. map.data_mut().splice(start..end, data.iter().cloned());
  654. } else if must_exist {
  655. return Err(ParseError::SymbolNotFound {
  656. name: name.to_owned(),
  657. });
  658. }
  659. }
  660. Ok(())
  661. }
  662. fn parse_btf(&mut self, section: &Section) -> Result<(), BtfError> {
  663. self.btf = Some(Btf::parse(section.data, self.endianness)?);
  664. Ok(())
  665. }
  666. fn parse_btf_ext(&mut self, section: &Section) -> Result<(), BtfError> {
  667. self.btf_ext = Some(BtfExt::parse(
  668. section.data,
  669. self.endianness,
  670. self.btf.as_ref().unwrap(),
  671. )?);
  672. Ok(())
  673. }
  674. fn parse_program(&self, section: &Section) -> Result<(Program, Function), ParseError> {
  675. let prog_sec = ProgramSection::from_str(section.name)?;
  676. let name = prog_sec.name().to_owned();
  677. let (func_info, line_info, func_info_rec_size, line_info_rec_size) =
  678. if let Some(btf_ext) = &self.btf_ext {
  679. let func_info = btf_ext.func_info.get(section.name);
  680. let line_info = btf_ext.line_info.get(section.name);
  681. (
  682. func_info,
  683. line_info,
  684. btf_ext.func_info_rec_size(),
  685. btf_ext.line_info_rec_size(),
  686. )
  687. } else {
  688. (FuncSecInfo::default(), LineSecInfo::default(), 0, 0)
  689. };
  690. let function = Function {
  691. name,
  692. address: section.address,
  693. section_index: section.index,
  694. section_offset: 0,
  695. instructions: copy_instructions(section.data)?,
  696. func_info,
  697. line_info,
  698. func_info_rec_size,
  699. line_info_rec_size,
  700. };
  701. Ok((
  702. Program {
  703. license: self.license.clone(),
  704. kernel_version: self.kernel_version,
  705. section: prog_sec,
  706. section_index: function.section_index.0,
  707. address: function.address,
  708. },
  709. function,
  710. ))
  711. }
  712. fn parse_text_section(&mut self, section: Section) -> Result<(), ParseError> {
  713. let mut symbols_by_address = HashMap::new();
  714. for sym in self.symbol_table.values() {
  715. if sym.is_definition
  716. && sym.kind == SymbolKind::Text
  717. && sym.section_index == Some(section.index.0)
  718. {
  719. if symbols_by_address.contains_key(&sym.address) {
  720. return Err(ParseError::SymbolTableConflict {
  721. section_index: section.index.0,
  722. address: sym.address,
  723. });
  724. }
  725. symbols_by_address.insert(sym.address, sym);
  726. }
  727. }
  728. let mut offset = 0;
  729. while offset < section.data.len() {
  730. let address = section.address + offset as u64;
  731. let sym = symbols_by_address
  732. .get(&address)
  733. .ok_or(ParseError::UnknownSymbol {
  734. section_index: section.index.0,
  735. address,
  736. })?;
  737. if sym.size == 0 {
  738. return Err(ParseError::InvalidSymbol {
  739. index: sym.index,
  740. name: sym.name.clone(),
  741. });
  742. }
  743. let (func_info, line_info, func_info_rec_size, line_info_rec_size) =
  744. if let Some(btf_ext) = &self.btf_ext {
  745. let bytes_offset = offset as u32 / INS_SIZE as u32;
  746. let section_size_bytes = sym.size as u32 / INS_SIZE as u32;
  747. let mut func_info = btf_ext.func_info.get(section.name);
  748. func_info.func_info.retain(|f| f.insn_off == bytes_offset);
  749. let mut line_info = btf_ext.line_info.get(section.name);
  750. line_info.line_info.retain(|l| {
  751. l.insn_off >= bytes_offset
  752. && l.insn_off < (bytes_offset + section_size_bytes)
  753. });
  754. (
  755. func_info,
  756. line_info,
  757. btf_ext.func_info_rec_size(),
  758. btf_ext.line_info_rec_size(),
  759. )
  760. } else {
  761. (FuncSecInfo::default(), LineSecInfo::default(), 0, 0)
  762. };
  763. self.functions.insert(
  764. (section.index.0, sym.address),
  765. Function {
  766. address,
  767. name: sym.name.clone().unwrap(),
  768. section_index: section.index,
  769. section_offset: offset,
  770. instructions: copy_instructions(
  771. &section.data[offset..offset + sym.size as usize],
  772. )?,
  773. func_info,
  774. line_info,
  775. func_info_rec_size,
  776. line_info_rec_size,
  777. },
  778. );
  779. offset += sym.size as usize;
  780. }
  781. if !section.relocations.is_empty() {
  782. self.relocations.insert(
  783. section.index,
  784. section
  785. .relocations
  786. .into_iter()
  787. .map(|rel| (rel.offset, rel))
  788. .collect(),
  789. );
  790. }
  791. Ok(())
  792. }
  793. fn parse_btf_maps(
  794. &mut self,
  795. section: &Section,
  796. symbols: HashMap<String, Symbol>,
  797. ) -> Result<(), ParseError> {
  798. if self.btf.is_none() {
  799. return Err(ParseError::NoBTF);
  800. }
  801. let btf = self.btf.as_ref().unwrap();
  802. for t in btf.types() {
  803. if let BtfType::DataSec(datasec) = &t {
  804. let type_name = match btf.type_name(t) {
  805. Ok(name) => name,
  806. _ => continue,
  807. };
  808. if type_name == section.name {
  809. // each btf_var_secinfo contains a map
  810. for info in &datasec.entries {
  811. let (map_name, def) = parse_btf_map_def(btf, info)?;
  812. let symbol_index = symbols
  813. .get(&map_name)
  814. .ok_or_else(|| ParseError::SymbolNotFound {
  815. name: map_name.to_string(),
  816. })?
  817. .index;
  818. self.maps.insert(
  819. map_name,
  820. Map::Btf(BtfMap {
  821. def,
  822. section_index: section.index.0,
  823. symbol_index,
  824. data: Vec::new(),
  825. }),
  826. );
  827. }
  828. }
  829. }
  830. }
  831. Ok(())
  832. }
  833. fn parse_section(&mut self, section: Section) -> Result<(), ParseError> {
  834. let mut parts = section.name.rsplitn(2, '/').collect::<Vec<_>>();
  835. parts.reverse();
  836. if parts.len() == 1
  837. && (parts[0] == "xdp"
  838. || parts[0] == "sk_msg"
  839. || parts[0] == "sockops"
  840. || parts[0] == "classifier")
  841. {
  842. parts.push(parts[0]);
  843. }
  844. self.section_infos
  845. .insert(section.name.to_owned(), (section.index, section.size));
  846. match section.kind {
  847. BpfSectionKind::Data | BpfSectionKind::Rodata | BpfSectionKind::Bss => {
  848. self.maps
  849. .insert(section.name.to_string(), parse_data_map_section(&section)?);
  850. }
  851. BpfSectionKind::Text => self.parse_text_section(section)?,
  852. BpfSectionKind::Btf => self.parse_btf(&section)?,
  853. BpfSectionKind::BtfExt => self.parse_btf_ext(&section)?,
  854. BpfSectionKind::BtfMaps => {
  855. let symbols: HashMap<String, Symbol> = self
  856. .symbol_table
  857. .values()
  858. .filter(|s| {
  859. if let Some(idx) = s.section_index {
  860. idx == section.index.0 && s.name.is_some()
  861. } else {
  862. false
  863. }
  864. })
  865. .cloned()
  866. .map(|s| (s.name.as_ref().unwrap().to_string(), s))
  867. .collect();
  868. self.parse_btf_maps(&section, symbols)?
  869. }
  870. BpfSectionKind::Maps => {
  871. // take out self.maps so we can borrow the iterator below
  872. // without cloning or collecting
  873. let mut maps = mem::take(&mut self.maps);
  874. // extract the symbols for the .maps section, we'll need them
  875. // during parsing
  876. let symbols = self.symbol_table.values().filter(|s| {
  877. s.section_index
  878. .map(|idx| idx == section.index.0)
  879. .unwrap_or(false)
  880. });
  881. let res = parse_maps_section(&mut maps, &section, symbols);
  882. // put the maps back
  883. self.maps = maps;
  884. res?
  885. }
  886. BpfSectionKind::Program => {
  887. let (program, function) = self.parse_program(&section)?;
  888. self.functions.insert(program.function_key(), function);
  889. self.programs
  890. .insert(program.section.name().to_owned(), program);
  891. if !section.relocations.is_empty() {
  892. self.relocations.insert(
  893. section.index,
  894. section
  895. .relocations
  896. .into_iter()
  897. .map(|rel| (rel.offset, rel))
  898. .collect(),
  899. );
  900. }
  901. }
  902. BpfSectionKind::Undefined | BpfSectionKind::License | BpfSectionKind::Version => {}
  903. }
  904. Ok(())
  905. }
  906. /// Sanitize BPF functions.
  907. pub fn sanitize_functions(&mut self, features: &Features) {
  908. for function in self.functions.values_mut() {
  909. function.sanitize(features);
  910. }
  911. }
  912. }
  913. fn insn_is_helper_call(ins: &bpf_insn) -> bool {
  914. let klass = (ins.code & 0x07) as u32;
  915. let op = (ins.code & 0xF0) as u32;
  916. let src = (ins.code & 0x08) as u32;
  917. klass == BPF_JMP && op == BPF_CALL && src == BPF_K && ins.src_reg() == 0 && ins.dst_reg() == 0
  918. }
  919. const BPF_FUNC_PROBE_READ: i32 = 4;
  920. const BPF_FUNC_PROBE_READ_STR: i32 = 45;
  921. const BPF_FUNC_PROBE_READ_USER: i32 = 112;
  922. const BPF_FUNC_PROBE_READ_KERNEL: i32 = 113;
  923. const BPF_FUNC_PROBE_READ_USER_STR: i32 = 114;
  924. const BPF_FUNC_PROBE_READ_KERNEL_STR: i32 = 115;
  925. impl Function {
  926. fn sanitize(&mut self, features: &Features) {
  927. for inst in &mut self.instructions {
  928. if !insn_is_helper_call(inst) {
  929. continue;
  930. }
  931. match inst.imm {
  932. BPF_FUNC_PROBE_READ_USER | BPF_FUNC_PROBE_READ_KERNEL
  933. if !features.bpf_probe_read_kernel =>
  934. {
  935. inst.imm = BPF_FUNC_PROBE_READ;
  936. }
  937. BPF_FUNC_PROBE_READ_USER_STR | BPF_FUNC_PROBE_READ_KERNEL_STR
  938. if !features.bpf_probe_read_kernel =>
  939. {
  940. inst.imm = BPF_FUNC_PROBE_READ_STR;
  941. }
  942. _ => {}
  943. }
  944. }
  945. }
  946. }
  947. // Parses multiple map definition contained in a single `maps` section (which is
  948. // different from `.maps` which is used for BTF). We can tell where each map is
  949. // based on the symbol table.
  950. fn parse_maps_section<'a, I: Iterator<Item = &'a Symbol>>(
  951. maps: &mut HashMap<String, Map>,
  952. section: &Section,
  953. symbols: I,
  954. ) -> Result<(), ParseError> {
  955. let mut have_symbols = false;
  956. // each symbol in the section is a separate map
  957. for (i, sym) in symbols.enumerate() {
  958. let start = sym.address as usize;
  959. let end = start + sym.size as usize;
  960. let data = &section.data[start..end];
  961. let name = sym
  962. .name
  963. .as_ref()
  964. .ok_or(ParseError::MapSymbolNameNotFound { i })?;
  965. let def = parse_map_def(name, data)?;
  966. maps.insert(
  967. name.to_string(),
  968. Map::Legacy(LegacyMap {
  969. section_index: section.index.0,
  970. section_kind: section.kind,
  971. symbol_index: Some(sym.index),
  972. def,
  973. data: Vec::new(),
  974. }),
  975. );
  976. have_symbols = true;
  977. }
  978. if !have_symbols {
  979. return Err(ParseError::NoSymbolsForMapsSection);
  980. }
  981. Ok(())
  982. }
  983. /// Errors caught during parsing the object file
  984. #[derive(Debug, thiserror::Error)]
  985. #[allow(missing_docs)]
  986. pub enum ParseError {
  987. #[error("error parsing ELF data")]
  988. ElfError(object::read::Error),
  989. /// Error parsing BTF object
  990. #[error("BTF error")]
  991. BtfError(#[from] BtfError),
  992. #[error("invalid license `{data:?}`: missing NULL terminator")]
  993. MissingLicenseNullTerminator { data: Vec<u8> },
  994. #[error("invalid license `{data:?}`")]
  995. InvalidLicense { data: Vec<u8> },
  996. #[error("invalid kernel version `{data:?}`")]
  997. InvalidKernelVersion { data: Vec<u8> },
  998. #[error("error parsing section with index {index}")]
  999. SectionError {
  1000. index: usize,
  1001. error: object::read::Error,
  1002. },
  1003. #[error("unsupported relocation target")]
  1004. UnsupportedRelocationTarget,
  1005. #[error("invalid program section `{section}`")]
  1006. InvalidProgramSection { section: String },
  1007. #[error("invalid program code")]
  1008. InvalidProgramCode,
  1009. #[error("error parsing map `{name}`")]
  1010. InvalidMapDefinition { name: String },
  1011. #[error("two or more symbols in section `{section_index}` have the same address {address:#X}")]
  1012. SymbolTableConflict { section_index: usize, address: u64 },
  1013. #[error("unknown symbol in section `{section_index}` at address {address:#X}")]
  1014. UnknownSymbol { section_index: usize, address: u64 },
  1015. #[error("invalid symbol, index `{index}` name: {}", .name.as_ref().unwrap_or(&"[unknown]".into()))]
  1016. InvalidSymbol { index: usize, name: Option<String> },
  1017. #[error("symbol {name} has size `{sym_size}`, but provided data is of size `{data_size}`")]
  1018. InvalidGlobalData {
  1019. name: String,
  1020. sym_size: u64,
  1021. data_size: usize,
  1022. },
  1023. #[error("symbol with name {name} not found in the symbols table")]
  1024. SymbolNotFound { name: String },
  1025. #[error("map for section with index {index} not found")]
  1026. MapNotFound { index: usize },
  1027. #[error("the map number {i} in the `maps` section doesn't have a symbol name")]
  1028. MapSymbolNameNotFound { i: usize },
  1029. #[error("no symbols for `maps` section, can't parse maps")]
  1030. NoSymbolsForMapsSection,
  1031. /// No BTF parsed for object
  1032. #[error("no BTF parsed for object")]
  1033. NoBTF,
  1034. }
  1035. /// The kind of an ELF section.
  1036. #[derive(Debug, Copy, Clone, Eq, PartialEq)]
  1037. pub enum BpfSectionKind {
  1038. /// Undefined
  1039. Undefined,
  1040. /// `maps`
  1041. Maps,
  1042. /// `.maps`
  1043. BtfMaps,
  1044. /// A program section
  1045. Program,
  1046. /// `.data`
  1047. Data,
  1048. /// `.rodata`
  1049. Rodata,
  1050. /// `.bss`
  1051. Bss,
  1052. /// `.text`
  1053. Text,
  1054. /// `.BTF`
  1055. Btf,
  1056. /// `.BTF.ext`
  1057. BtfExt,
  1058. /// `license`
  1059. License,
  1060. /// `version`
  1061. Version,
  1062. }
  1063. impl BpfSectionKind {
  1064. fn from_name(name: &str) -> BpfSectionKind {
  1065. if name.starts_with("license") {
  1066. BpfSectionKind::License
  1067. } else if name.starts_with("version") {
  1068. BpfSectionKind::Version
  1069. } else if name.starts_with("maps") {
  1070. BpfSectionKind::Maps
  1071. } else if name.starts_with(".maps") {
  1072. BpfSectionKind::BtfMaps
  1073. } else if name.starts_with(".text") {
  1074. BpfSectionKind::Text
  1075. } else if name.starts_with(".bss") {
  1076. BpfSectionKind::Bss
  1077. } else if name.starts_with(".data") {
  1078. BpfSectionKind::Data
  1079. } else if name.starts_with(".rodata") {
  1080. BpfSectionKind::Rodata
  1081. } else if name == ".BTF" {
  1082. BpfSectionKind::Btf
  1083. } else if name == ".BTF.ext" {
  1084. BpfSectionKind::BtfExt
  1085. } else {
  1086. BpfSectionKind::Undefined
  1087. }
  1088. }
  1089. }
  1090. #[derive(Debug)]
  1091. struct Section<'a> {
  1092. index: SectionIndex,
  1093. kind: BpfSectionKind,
  1094. address: u64,
  1095. name: &'a str,
  1096. data: &'a [u8],
  1097. size: u64,
  1098. relocations: Vec<Relocation>,
  1099. }
  1100. impl<'data, 'file, 'a> TryFrom<&'a ObjSection<'data, 'file>> for Section<'a> {
  1101. type Error = ParseError;
  1102. fn try_from(section: &'a ObjSection) -> Result<Section<'a>, ParseError> {
  1103. let index = section.index();
  1104. let map_err = |error| ParseError::SectionError {
  1105. index: index.0,
  1106. error,
  1107. };
  1108. let name = section.name().map_err(map_err)?;
  1109. let kind = match BpfSectionKind::from_name(name) {
  1110. BpfSectionKind::Undefined => {
  1111. if section.kind() == SectionKind::Text && section.size() > 0 {
  1112. BpfSectionKind::Program
  1113. } else {
  1114. BpfSectionKind::Undefined
  1115. }
  1116. }
  1117. k => k,
  1118. };
  1119. Ok(Section {
  1120. index,
  1121. kind,
  1122. address: section.address(),
  1123. name,
  1124. data: section.data().map_err(map_err)?,
  1125. size: section.size(),
  1126. relocations: section
  1127. .relocations()
  1128. .map(|(offset, r)| {
  1129. Ok(Relocation {
  1130. symbol_index: match r.target() {
  1131. RelocationTarget::Symbol(index) => index.0,
  1132. _ => return Err(ParseError::UnsupportedRelocationTarget),
  1133. },
  1134. offset,
  1135. size: r.size(),
  1136. })
  1137. })
  1138. .collect::<Result<Vec<_>, _>>()?,
  1139. })
  1140. }
  1141. }
  1142. fn parse_license(data: &[u8]) -> Result<CString, ParseError> {
  1143. if data.len() < 2 {
  1144. return Err(ParseError::InvalidLicense {
  1145. data: data.to_vec(),
  1146. });
  1147. }
  1148. if data[data.len() - 1] != 0 {
  1149. return Err(ParseError::MissingLicenseNullTerminator {
  1150. data: data.to_vec(),
  1151. });
  1152. }
  1153. Ok(CStr::from_bytes_with_nul(data)
  1154. .map_err(|_| ParseError::InvalidLicense {
  1155. data: data.to_vec(),
  1156. })?
  1157. .to_owned())
  1158. }
  1159. fn parse_version(data: &[u8], endianness: object::Endianness) -> Result<Option<u32>, ParseError> {
  1160. let data = match data.len() {
  1161. 4 => data.try_into().unwrap(),
  1162. _ => {
  1163. return Err(ParseError::InvalidKernelVersion {
  1164. data: data.to_vec(),
  1165. })
  1166. }
  1167. };
  1168. let v = match endianness {
  1169. object::Endianness::Big => u32::from_be_bytes(data),
  1170. object::Endianness::Little => u32::from_le_bytes(data),
  1171. };
  1172. Ok(if v == KERNEL_VERSION_ANY {
  1173. None
  1174. } else {
  1175. Some(v)
  1176. })
  1177. }
  1178. // Gets an integer value from a BTF map defintion K/V pair.
  1179. // type_id should be a PTR to an ARRAY.
  1180. // the value is encoded in the array nr_elems field.
  1181. fn get_map_field(btf: &Btf, type_id: u32) -> Result<u32, BtfError> {
  1182. let pty = match &btf.type_by_id(type_id)? {
  1183. BtfType::Ptr(pty) => pty,
  1184. other => {
  1185. return Err(BtfError::UnexpectedBtfType {
  1186. type_id: other.btf_type().unwrap_or(0),
  1187. })
  1188. }
  1189. };
  1190. // Safety: union
  1191. let arr = match &btf.type_by_id(pty.btf_type)? {
  1192. BtfType::Array(Array { array, .. }) => array,
  1193. other => {
  1194. return Err(BtfError::UnexpectedBtfType {
  1195. type_id: other.btf_type().unwrap_or(0),
  1196. })
  1197. }
  1198. };
  1199. Ok(arr.len)
  1200. }
  1201. // Parsed '.bss' '.data' and '.rodata' sections. These sections are arrays of
  1202. // bytes and are relocated based on their section index.
  1203. fn parse_data_map_section(section: &Section) -> Result<Map, ParseError> {
  1204. let (def, data) = match section.kind {
  1205. BpfSectionKind::Bss | BpfSectionKind::Data | BpfSectionKind::Rodata => {
  1206. let def = bpf_map_def {
  1207. map_type: BPF_MAP_TYPE_ARRAY as u32,
  1208. key_size: mem::size_of::<u32>() as u32,
  1209. // We need to use section.size here since
  1210. // .bss will always have data.len() == 0
  1211. value_size: section.size as u32,
  1212. max_entries: 1,
  1213. map_flags: if section.kind == BpfSectionKind::Rodata {
  1214. BPF_F_RDONLY_PROG
  1215. } else {
  1216. 0
  1217. },
  1218. ..Default::default()
  1219. };
  1220. (def, section.data.to_vec())
  1221. }
  1222. _ => unreachable!(),
  1223. };
  1224. Ok(Map::Legacy(LegacyMap {
  1225. section_index: section.index.0,
  1226. section_kind: section.kind,
  1227. // Data maps don't require symbols to be relocated
  1228. symbol_index: None,
  1229. def,
  1230. data,
  1231. }))
  1232. }
  1233. fn parse_map_def(name: &str, data: &[u8]) -> Result<bpf_map_def, ParseError> {
  1234. if data.len() < MINIMUM_MAP_SIZE {
  1235. return Err(ParseError::InvalidMapDefinition {
  1236. name: name.to_owned(),
  1237. });
  1238. }
  1239. if data.len() < mem::size_of::<bpf_map_def>() {
  1240. let mut map_def = bpf_map_def::default();
  1241. unsafe {
  1242. let map_def_ptr =
  1243. from_raw_parts_mut(&mut map_def as *mut bpf_map_def as *mut u8, data.len());
  1244. map_def_ptr.copy_from_slice(data);
  1245. }
  1246. Ok(map_def)
  1247. } else {
  1248. Ok(unsafe { ptr::read_unaligned(data.as_ptr() as *const bpf_map_def) })
  1249. }
  1250. }
  1251. fn parse_btf_map_def(btf: &Btf, info: &DataSecEntry) -> Result<(String, BtfMapDef), BtfError> {
  1252. let ty = match btf.type_by_id(info.btf_type)? {
  1253. BtfType::Var(var) => var,
  1254. other => {
  1255. return Err(BtfError::UnexpectedBtfType {
  1256. type_id: other.btf_type().unwrap_or(0),
  1257. })
  1258. }
  1259. };
  1260. let map_name = btf.string_at(ty.name_offset)?;
  1261. let mut map_def = BtfMapDef::default();
  1262. // Safety: union
  1263. let root_type = btf.resolve_type(ty.btf_type)?;
  1264. let s = match btf.type_by_id(root_type)? {
  1265. BtfType::Struct(s) => s,
  1266. other => {
  1267. return Err(BtfError::UnexpectedBtfType {
  1268. type_id: other.btf_type().unwrap_or(0),
  1269. })
  1270. }
  1271. };
  1272. for m in &s.members {
  1273. match btf.string_at(m.name_offset)?.as_ref() {
  1274. "type" => {
  1275. map_def.map_type = get_map_field(btf, m.btf_type)?;
  1276. }
  1277. "key" => {
  1278. if let BtfType::Ptr(pty) = btf.type_by_id(m.btf_type)? {
  1279. // Safety: union
  1280. let t = pty.btf_type;
  1281. map_def.key_size = btf.type_size(t)? as u32;
  1282. map_def.btf_key_type_id = t;
  1283. } else {
  1284. return Err(BtfError::UnexpectedBtfType {
  1285. type_id: m.btf_type,
  1286. });
  1287. }
  1288. }
  1289. "key_size" => {
  1290. map_def.key_size = get_map_field(btf, m.btf_type)?;
  1291. }
  1292. "value" => {
  1293. if let BtfType::Ptr(pty) = btf.type_by_id(m.btf_type)? {
  1294. let t = pty.btf_type;
  1295. map_def.value_size = btf.type_size(t)? as u32;
  1296. map_def.btf_value_type_id = t;
  1297. } else {
  1298. return Err(BtfError::UnexpectedBtfType {
  1299. type_id: m.btf_type,
  1300. });
  1301. }
  1302. }
  1303. "value_size" => {
  1304. map_def.value_size = get_map_field(btf, m.btf_type)?;
  1305. }
  1306. "max_entries" => {
  1307. map_def.max_entries = get_map_field(btf, m.btf_type)?;
  1308. }
  1309. "map_flags" => {
  1310. map_def.map_flags = get_map_field(btf, m.btf_type)?;
  1311. }
  1312. "pinning" => {
  1313. let pinning = get_map_field(btf, m.btf_type)?;
  1314. map_def.pinning = PinningType::try_from(pinning).unwrap_or_else(|_| {
  1315. debug!("{} is not a valid pin type. using PIN_NONE", pinning);
  1316. PinningType::None
  1317. });
  1318. }
  1319. other => {
  1320. debug!("skipping unknown map section: {}", other);
  1321. continue;
  1322. }
  1323. }
  1324. }
  1325. Ok((map_name.to_string(), map_def))
  1326. }
  1327. /// Parses a [bpf_map_info] into a [Map].
  1328. pub fn parse_map_info(info: bpf_map_info, pinned: PinningType) -> Map {
  1329. if info.btf_key_type_id != 0 {
  1330. Map::Btf(BtfMap {
  1331. def: BtfMapDef {
  1332. map_type: info.type_,
  1333. key_size: info.key_size,
  1334. value_size: info.value_size,
  1335. max_entries: info.max_entries,
  1336. map_flags: info.map_flags,
  1337. pinning: pinned,
  1338. btf_key_type_id: info.btf_key_type_id,
  1339. btf_value_type_id: info.btf_value_type_id,
  1340. },
  1341. section_index: 0,
  1342. symbol_index: 0,
  1343. data: Vec::new(),
  1344. })
  1345. } else {
  1346. Map::Legacy(LegacyMap {
  1347. def: bpf_map_def {
  1348. map_type: info.type_,
  1349. key_size: info.key_size,
  1350. value_size: info.value_size,
  1351. max_entries: info.max_entries,
  1352. map_flags: info.map_flags,
  1353. pinning: pinned,
  1354. id: info.id,
  1355. },
  1356. section_index: 0,
  1357. symbol_index: None,
  1358. section_kind: BpfSectionKind::Undefined,
  1359. data: Vec::new(),
  1360. })
  1361. }
  1362. }
  1363. /// Copies a block of eBPF instructions
  1364. pub fn copy_instructions(data: &[u8]) -> Result<Vec<bpf_insn>, ParseError> {
  1365. if data.len() % mem::size_of::<bpf_insn>() > 0 {
  1366. return Err(ParseError::InvalidProgramCode);
  1367. }
  1368. let instructions = data
  1369. .chunks_exact(mem::size_of::<bpf_insn>())
  1370. .map(|d| unsafe { ptr::read_unaligned(d.as_ptr() as *const bpf_insn) })
  1371. .collect::<Vec<_>>();
  1372. Ok(instructions)
  1373. }
  1374. #[cfg(test)]
  1375. mod tests {
  1376. use alloc::vec;
  1377. use matches::assert_matches;
  1378. use object::Endianness;
  1379. use super::*;
  1380. use crate::maps::PinningType;
  1381. fn fake_section<'a>(kind: BpfSectionKind, name: &'a str, data: &'a [u8]) -> Section<'a> {
  1382. Section {
  1383. index: SectionIndex(0),
  1384. kind,
  1385. address: 0,
  1386. name,
  1387. data,
  1388. size: data.len() as u64,
  1389. relocations: Vec::new(),
  1390. }
  1391. }
  1392. fn fake_ins() -> bpf_insn {
  1393. bpf_insn {
  1394. code: 0,
  1395. _bitfield_align_1: [],
  1396. _bitfield_1: bpf_insn::new_bitfield_1(0, 0),
  1397. off: 0,
  1398. imm: 0,
  1399. }
  1400. }
  1401. fn fake_sym(obj: &mut Object, section_index: usize, address: u64, name: &str, size: u64) {
  1402. let idx = obj.symbol_table.len();
  1403. obj.symbol_table.insert(
  1404. idx + 1,
  1405. Symbol {
  1406. index: idx + 1,
  1407. section_index: Some(section_index),
  1408. name: Some(name.to_string()),
  1409. address,
  1410. size,
  1411. is_definition: false,
  1412. kind: SymbolKind::Data,
  1413. },
  1414. );
  1415. }
  1416. fn bytes_of<T>(val: &T) -> &[u8] {
  1417. // Safety: This is for testing only
  1418. unsafe { crate::util::bytes_of(val) }
  1419. }
  1420. #[test]
  1421. fn test_parse_generic_error() {
  1422. assert!(matches!(
  1423. Object::parse(&b"foo"[..]),
  1424. Err(ParseError::ElfError(_))
  1425. ))
  1426. }
  1427. #[test]
  1428. fn test_parse_license() {
  1429. assert!(matches!(
  1430. parse_license(b""),
  1431. Err(ParseError::InvalidLicense { .. })
  1432. ));
  1433. assert!(matches!(
  1434. parse_license(b"\0"),
  1435. Err(ParseError::InvalidLicense { .. })
  1436. ));
  1437. assert!(matches!(
  1438. parse_license(b"GPL"),
  1439. Err(ParseError::MissingLicenseNullTerminator { .. })
  1440. ));
  1441. assert_eq!(parse_license(b"GPL\0").unwrap().to_str().unwrap(), "GPL");
  1442. }
  1443. #[test]
  1444. fn test_parse_version() {
  1445. assert!(matches!(
  1446. parse_version(b"", Endianness::Little),
  1447. Err(ParseError::InvalidKernelVersion { .. })
  1448. ));
  1449. assert!(matches!(
  1450. parse_version(b"123", Endianness::Little),
  1451. Err(ParseError::InvalidKernelVersion { .. })
  1452. ));
  1453. assert!(matches!(
  1454. parse_version(&0xFFFF_FFFEu32.to_le_bytes(), Endianness::Little),
  1455. Ok(None)
  1456. ));
  1457. assert!(matches!(
  1458. parse_version(&0xFFFF_FFFEu32.to_be_bytes(), Endianness::Big),
  1459. Ok(None)
  1460. ));
  1461. assert!(matches!(
  1462. parse_version(&1234u32.to_le_bytes(), Endianness::Little),
  1463. Ok(Some(1234))
  1464. ));
  1465. }
  1466. #[test]
  1467. fn test_parse_map_def_error() {
  1468. assert!(matches!(
  1469. parse_map_def("foo", &[]),
  1470. Err(ParseError::InvalidMapDefinition { .. })
  1471. ));
  1472. }
  1473. #[test]
  1474. fn test_parse_map_short() {
  1475. let def = bpf_map_def {
  1476. map_type: 1,
  1477. key_size: 2,
  1478. value_size: 3,
  1479. max_entries: 4,
  1480. map_flags: 5,
  1481. id: 0,
  1482. pinning: PinningType::None,
  1483. };
  1484. assert_eq!(
  1485. parse_map_def("foo", &bytes_of(&def)[..MINIMUM_MAP_SIZE]).unwrap(),
  1486. def
  1487. );
  1488. }
  1489. #[test]
  1490. fn test_parse_map_def() {
  1491. let def = bpf_map_def {
  1492. map_type: 1,
  1493. key_size: 2,
  1494. value_size: 3,
  1495. max_entries: 4,
  1496. map_flags: 5,
  1497. id: 6,
  1498. pinning: PinningType::ByName,
  1499. };
  1500. assert_eq!(parse_map_def("foo", bytes_of(&def)).unwrap(), def);
  1501. }
  1502. #[test]
  1503. fn test_parse_map_def_with_padding() {
  1504. let def = bpf_map_def {
  1505. map_type: 1,
  1506. key_size: 2,
  1507. value_size: 3,
  1508. max_entries: 4,
  1509. map_flags: 5,
  1510. id: 6,
  1511. pinning: PinningType::ByName,
  1512. };
  1513. let mut buf = [0u8; 128];
  1514. unsafe { ptr::write_unaligned(buf.as_mut_ptr() as *mut _, def) };
  1515. assert_eq!(parse_map_def("foo", &buf).unwrap(), def);
  1516. }
  1517. #[test]
  1518. fn test_parse_map_data() {
  1519. let map_data = b"map data";
  1520. assert!(matches!(
  1521. parse_data_map_section(
  1522. &fake_section(
  1523. BpfSectionKind::Data,
  1524. ".bss",
  1525. map_data,
  1526. ),
  1527. ),
  1528. Ok(Map::Legacy(LegacyMap {
  1529. section_index: 0,
  1530. section_kind: BpfSectionKind::Data,
  1531. symbol_index: None,
  1532. def: bpf_map_def {
  1533. map_type: _map_type,
  1534. key_size: 4,
  1535. value_size,
  1536. max_entries: 1,
  1537. map_flags: 0,
  1538. id: 0,
  1539. pinning: PinningType::None,
  1540. },
  1541. data,
  1542. })) if data == map_data && value_size == map_data.len() as u32
  1543. ))
  1544. }
  1545. fn fake_obj() -> Object {
  1546. Object::new(Endianness::Little, CString::new("GPL").unwrap(), None)
  1547. }
  1548. #[test]
  1549. fn sanitizes_empty_btf_files_to_none() {
  1550. let mut obj = fake_obj();
  1551. obj.parse_section(fake_section(
  1552. BpfSectionKind::Btf,
  1553. ".BTF",
  1554. &[
  1555. 159, 235, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
  1556. ],
  1557. ))
  1558. .unwrap();
  1559. obj.parse_section(fake_section(
  1560. BpfSectionKind::BtfExt,
  1561. ".BTF.ext",
  1562. &[
  1563. 159, 235, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0,
  1564. 0, 0, 16, 0, 0, 0,
  1565. ],
  1566. ))
  1567. .unwrap();
  1568. let btf = obj.fixup_and_sanitize_btf(&BtfFeatures::default()).unwrap();
  1569. assert!(btf.is_none());
  1570. }
  1571. #[test]
  1572. fn test_parse_program_error() {
  1573. let obj = fake_obj();
  1574. assert_matches!(
  1575. obj.parse_program(&fake_section(
  1576. BpfSectionKind::Program,
  1577. "kprobe/foo",
  1578. &42u32.to_ne_bytes(),
  1579. )),
  1580. Err(ParseError::InvalidProgramCode)
  1581. );
  1582. }
  1583. #[test]
  1584. fn test_parse_program() {
  1585. let obj = fake_obj();
  1586. assert_matches!(
  1587. obj.parse_program(&fake_section(BpfSectionKind::Program,"kprobe/foo", bytes_of(&fake_ins()))),
  1588. Ok((Program {
  1589. license,
  1590. kernel_version: None,
  1591. section: ProgramSection::KProbe { .. },
  1592. .. }, Function {
  1593. name,
  1594. address: 0,
  1595. section_index: SectionIndex(0),
  1596. section_offset: 0,
  1597. instructions,
  1598. ..})) if license.to_string_lossy() == "GPL" && name == "foo" && instructions.len() == 1
  1599. );
  1600. }
  1601. #[test]
  1602. fn test_parse_section_map() {
  1603. let mut obj = fake_obj();
  1604. fake_sym(&mut obj, 0, 0, "foo", mem::size_of::<bpf_map_def>() as u64);
  1605. assert_matches!(
  1606. obj.parse_section(fake_section(
  1607. BpfSectionKind::Maps,
  1608. "maps/foo",
  1609. bytes_of(&bpf_map_def {
  1610. map_type: 1,
  1611. key_size: 2,
  1612. value_size: 3,
  1613. max_entries: 4,
  1614. map_flags: 5,
  1615. ..Default::default()
  1616. })
  1617. )),
  1618. Ok(())
  1619. );
  1620. assert!(obj.maps.get("foo").is_some());
  1621. }
  1622. #[test]
  1623. fn test_parse_section_multiple_maps() {
  1624. let mut obj = fake_obj();
  1625. fake_sym(&mut obj, 0, 0, "foo", mem::size_of::<bpf_map_def>() as u64);
  1626. fake_sym(&mut obj, 0, 28, "bar", mem::size_of::<bpf_map_def>() as u64);
  1627. fake_sym(&mut obj, 0, 60, "baz", mem::size_of::<bpf_map_def>() as u64);
  1628. let def = &bpf_map_def {
  1629. map_type: 1,
  1630. key_size: 2,
  1631. value_size: 3,
  1632. max_entries: 4,
  1633. map_flags: 5,
  1634. ..Default::default()
  1635. };
  1636. let map_data = bytes_of(def).to_vec();
  1637. let mut buf = vec![];
  1638. buf.extend(&map_data);
  1639. buf.extend(&map_data);
  1640. // throw in some padding
  1641. buf.extend([0, 0, 0, 0]);
  1642. buf.extend(&map_data);
  1643. assert_matches!(
  1644. obj.parse_section(fake_section(BpfSectionKind::Maps, "maps", buf.as_slice(),)),
  1645. Ok(())
  1646. );
  1647. assert!(obj.maps.get("foo").is_some());
  1648. assert!(obj.maps.get("bar").is_some());
  1649. assert!(obj.maps.get("baz").is_some());
  1650. for map in obj.maps.values() {
  1651. if let Map::Legacy(m) = map {
  1652. assert_eq!(&m.def, def);
  1653. } else {
  1654. panic!("expected a BTF map")
  1655. }
  1656. }
  1657. }
  1658. #[test]
  1659. fn test_parse_section_data() {
  1660. let mut obj = fake_obj();
  1661. assert_matches!(
  1662. obj.parse_section(fake_section(BpfSectionKind::Data, ".bss", b"map data")),
  1663. Ok(())
  1664. );
  1665. assert!(obj.maps.get(".bss").is_some());
  1666. assert_matches!(
  1667. obj.parse_section(fake_section(BpfSectionKind::Data, ".rodata", b"map data")),
  1668. Ok(())
  1669. );
  1670. assert!(obj.maps.get(".rodata").is_some());
  1671. assert_matches!(
  1672. obj.parse_section(fake_section(
  1673. BpfSectionKind::Data,
  1674. ".rodata.boo",
  1675. b"map data"
  1676. )),
  1677. Ok(())
  1678. );
  1679. assert!(obj.maps.get(".rodata.boo").is_some());
  1680. assert_matches!(
  1681. obj.parse_section(fake_section(BpfSectionKind::Data, ".data", b"map data")),
  1682. Ok(())
  1683. );
  1684. assert!(obj.maps.get(".data").is_some());
  1685. assert_matches!(
  1686. obj.parse_section(fake_section(BpfSectionKind::Data, ".data.boo", b"map data")),
  1687. Ok(())
  1688. );
  1689. assert!(obj.maps.get(".data.boo").is_some());
  1690. }
  1691. #[test]
  1692. fn test_parse_section_kprobe() {
  1693. let mut obj = fake_obj();
  1694. assert_matches!(
  1695. obj.parse_section(fake_section(
  1696. BpfSectionKind::Program,
  1697. "kprobe/foo",
  1698. bytes_of(&fake_ins())
  1699. )),
  1700. Ok(())
  1701. );
  1702. assert_matches!(
  1703. obj.programs.get("foo"),
  1704. Some(Program {
  1705. section: ProgramSection::KProbe { .. },
  1706. ..
  1707. })
  1708. );
  1709. }
  1710. #[test]
  1711. fn test_parse_section_uprobe() {
  1712. let mut obj = fake_obj();
  1713. assert_matches!(
  1714. obj.parse_section(fake_section(
  1715. BpfSectionKind::Program,
  1716. "uprobe/foo",
  1717. bytes_of(&fake_ins())
  1718. )),
  1719. Ok(())
  1720. );
  1721. assert_matches!(
  1722. obj.programs.get("foo"),
  1723. Some(Program {
  1724. section: ProgramSection::UProbe { .. },
  1725. ..
  1726. })
  1727. );
  1728. }
  1729. #[test]
  1730. fn test_parse_section_trace_point() {
  1731. let mut obj = fake_obj();
  1732. assert_matches!(
  1733. obj.parse_section(fake_section(
  1734. BpfSectionKind::Program,
  1735. "tracepoint/foo",
  1736. bytes_of(&fake_ins())
  1737. )),
  1738. Ok(())
  1739. );
  1740. assert_matches!(
  1741. obj.programs.get("foo"),
  1742. Some(Program {
  1743. section: ProgramSection::TracePoint { .. },
  1744. ..
  1745. })
  1746. );
  1747. assert_matches!(
  1748. obj.parse_section(fake_section(
  1749. BpfSectionKind::Program,
  1750. "tp/foo/bar",
  1751. bytes_of(&fake_ins())
  1752. )),
  1753. Ok(())
  1754. );
  1755. assert_matches!(
  1756. obj.programs.get("foo/bar"),
  1757. Some(Program {
  1758. section: ProgramSection::TracePoint { .. },
  1759. ..
  1760. })
  1761. );
  1762. }
  1763. #[test]
  1764. fn test_parse_section_socket_filter() {
  1765. let mut obj = fake_obj();
  1766. assert_matches!(
  1767. obj.parse_section(fake_section(
  1768. BpfSectionKind::Program,
  1769. "socket/foo",
  1770. bytes_of(&fake_ins())
  1771. )),
  1772. Ok(())
  1773. );
  1774. assert_matches!(
  1775. obj.programs.get("foo"),
  1776. Some(Program {
  1777. section: ProgramSection::SocketFilter { .. },
  1778. ..
  1779. })
  1780. );
  1781. }
  1782. #[test]
  1783. fn test_parse_section_xdp() {
  1784. let mut obj = fake_obj();
  1785. assert_matches!(
  1786. obj.parse_section(fake_section(
  1787. BpfSectionKind::Program,
  1788. "xdp/foo",
  1789. bytes_of(&fake_ins())
  1790. )),
  1791. Ok(())
  1792. );
  1793. assert_matches!(
  1794. obj.programs.get("foo"),
  1795. Some(Program {
  1796. section: ProgramSection::Xdp { frags: false, .. },
  1797. ..
  1798. })
  1799. );
  1800. }
  1801. #[test]
  1802. fn test_parse_section_xdp_frags() {
  1803. let mut obj = fake_obj();
  1804. assert_matches!(
  1805. obj.parse_section(fake_section(
  1806. BpfSectionKind::Program,
  1807. "xdp.frags/foo",
  1808. bytes_of(&fake_ins())
  1809. )),
  1810. Ok(())
  1811. );
  1812. assert_matches!(
  1813. obj.programs.get("foo"),
  1814. Some(Program {
  1815. section: ProgramSection::Xdp { frags: true, .. },
  1816. ..
  1817. })
  1818. );
  1819. }
  1820. #[test]
  1821. fn test_parse_section_raw_tp() {
  1822. let mut obj = fake_obj();
  1823. assert_matches!(
  1824. obj.parse_section(fake_section(
  1825. BpfSectionKind::Program,
  1826. "raw_tp/foo",
  1827. bytes_of(&fake_ins())
  1828. )),
  1829. Ok(())
  1830. );
  1831. assert_matches!(
  1832. obj.programs.get("foo"),
  1833. Some(Program {
  1834. section: ProgramSection::RawTracePoint { .. },
  1835. ..
  1836. })
  1837. );
  1838. assert_matches!(
  1839. obj.parse_section(fake_section(
  1840. BpfSectionKind::Program,
  1841. "raw_tracepoint/bar",
  1842. bytes_of(&fake_ins())
  1843. )),
  1844. Ok(())
  1845. );
  1846. assert_matches!(
  1847. obj.programs.get("bar"),
  1848. Some(Program {
  1849. section: ProgramSection::RawTracePoint { .. },
  1850. ..
  1851. })
  1852. );
  1853. }
  1854. #[test]
  1855. fn test_parse_section_lsm() {
  1856. let mut obj = fake_obj();
  1857. assert_matches!(
  1858. obj.parse_section(fake_section(
  1859. BpfSectionKind::Program,
  1860. "lsm/foo",
  1861. bytes_of(&fake_ins())
  1862. )),
  1863. Ok(())
  1864. );
  1865. assert_matches!(
  1866. obj.programs.get("foo"),
  1867. Some(Program {
  1868. section: ProgramSection::Lsm {
  1869. sleepable: false,
  1870. ..
  1871. },
  1872. ..
  1873. })
  1874. );
  1875. }
  1876. #[test]
  1877. fn test_parse_section_lsm_sleepable() {
  1878. let mut obj = fake_obj();
  1879. assert_matches!(
  1880. obj.parse_section(fake_section(
  1881. BpfSectionKind::Program,
  1882. "lsm.s/foo",
  1883. bytes_of(&fake_ins())
  1884. )),
  1885. Ok(())
  1886. );
  1887. assert_matches!(
  1888. obj.programs.get("foo"),
  1889. Some(Program {
  1890. section: ProgramSection::Lsm {
  1891. sleepable: true,
  1892. ..
  1893. },
  1894. ..
  1895. })
  1896. );
  1897. }
  1898. #[test]
  1899. fn test_parse_section_btf_tracepoint() {
  1900. let mut obj = fake_obj();
  1901. assert_matches!(
  1902. obj.parse_section(fake_section(
  1903. BpfSectionKind::Program,
  1904. "tp_btf/foo",
  1905. bytes_of(&fake_ins())
  1906. )),
  1907. Ok(())
  1908. );
  1909. assert_matches!(
  1910. obj.programs.get("foo"),
  1911. Some(Program {
  1912. section: ProgramSection::BtfTracePoint { .. },
  1913. ..
  1914. })
  1915. );
  1916. }
  1917. #[test]
  1918. fn test_parse_section_skskb_unnamed() {
  1919. let mut obj = fake_obj();
  1920. assert_matches!(
  1921. obj.parse_section(fake_section(
  1922. BpfSectionKind::Program,
  1923. "sk_skb/stream_parser",
  1924. bytes_of(&fake_ins())
  1925. )),
  1926. Ok(())
  1927. );
  1928. assert_matches!(
  1929. obj.programs.get("stream_parser"),
  1930. Some(Program {
  1931. section: ProgramSection::SkSkbStreamParser { .. },
  1932. ..
  1933. })
  1934. );
  1935. }
  1936. #[test]
  1937. fn test_parse_section_skskb_named() {
  1938. let mut obj = fake_obj();
  1939. assert_matches!(
  1940. obj.parse_section(fake_section(
  1941. BpfSectionKind::Program,
  1942. "sk_skb/stream_parser/my_parser",
  1943. bytes_of(&fake_ins())
  1944. )),
  1945. Ok(())
  1946. );
  1947. assert_matches!(
  1948. obj.programs.get("my_parser"),
  1949. Some(Program {
  1950. section: ProgramSection::SkSkbStreamParser { .. },
  1951. ..
  1952. })
  1953. );
  1954. }
  1955. #[test]
  1956. fn test_parse_section_fentry() {
  1957. let mut obj = fake_obj();
  1958. assert_matches!(
  1959. obj.parse_section(fake_section(
  1960. BpfSectionKind::Program,
  1961. "fentry/foo",
  1962. bytes_of(&fake_ins())
  1963. )),
  1964. Ok(())
  1965. );
  1966. assert_matches!(
  1967. obj.programs.get("foo"),
  1968. Some(Program {
  1969. section: ProgramSection::FEntry { .. },
  1970. ..
  1971. })
  1972. );
  1973. }
  1974. #[test]
  1975. fn test_parse_section_fexit() {
  1976. let mut obj = fake_obj();
  1977. assert_matches!(
  1978. obj.parse_section(fake_section(
  1979. BpfSectionKind::Program,
  1980. "fexit/foo",
  1981. bytes_of(&fake_ins())
  1982. )),
  1983. Ok(())
  1984. );
  1985. assert_matches!(
  1986. obj.programs.get("foo"),
  1987. Some(Program {
  1988. section: ProgramSection::FExit { .. },
  1989. ..
  1990. })
  1991. );
  1992. }
  1993. #[test]
  1994. fn test_parse_section_cgroup_skb_ingress_unnamed() {
  1995. let mut obj = fake_obj();
  1996. assert_matches!(
  1997. obj.parse_section(fake_section(
  1998. BpfSectionKind::Program,
  1999. "cgroup_skb/ingress",
  2000. bytes_of(&fake_ins())
  2001. )),
  2002. Ok(())
  2003. );
  2004. assert_matches!(
  2005. obj.programs.get("ingress"),
  2006. Some(Program {
  2007. section: ProgramSection::CgroupSkbIngress { .. },
  2008. ..
  2009. })
  2010. );
  2011. }
  2012. #[test]
  2013. fn test_parse_section_cgroup_skb_ingress_named() {
  2014. let mut obj = fake_obj();
  2015. assert_matches!(
  2016. obj.parse_section(fake_section(
  2017. BpfSectionKind::Program,
  2018. "cgroup_skb/ingress/foo",
  2019. bytes_of(&fake_ins())
  2020. )),
  2021. Ok(())
  2022. );
  2023. assert_matches!(
  2024. obj.programs.get("foo"),
  2025. Some(Program {
  2026. section: ProgramSection::CgroupSkbIngress { .. },
  2027. ..
  2028. })
  2029. );
  2030. }
  2031. #[test]
  2032. fn test_parse_section_cgroup_skb_no_direction_unamed() {
  2033. let mut obj = fake_obj();
  2034. assert_matches!(
  2035. obj.parse_section(fake_section(
  2036. BpfSectionKind::Program,
  2037. "cgroup/skb",
  2038. bytes_of(&fake_ins())
  2039. )),
  2040. Ok(())
  2041. );
  2042. assert_matches!(
  2043. obj.programs.get("skb"),
  2044. Some(Program {
  2045. section: ProgramSection::CgroupSkb { .. },
  2046. ..
  2047. })
  2048. );
  2049. }
  2050. #[test]
  2051. fn test_parse_section_cgroup_skb_no_direction_named() {
  2052. let mut obj = fake_obj();
  2053. assert_matches!(
  2054. obj.parse_section(fake_section(
  2055. BpfSectionKind::Program,
  2056. "cgroup/skb/foo",
  2057. bytes_of(&fake_ins())
  2058. )),
  2059. Ok(())
  2060. );
  2061. assert_matches!(
  2062. obj.programs.get("foo"),
  2063. Some(Program {
  2064. section: ProgramSection::CgroupSkb { .. },
  2065. ..
  2066. })
  2067. );
  2068. }
  2069. #[test]
  2070. fn test_parse_section_sock_addr_named() {
  2071. let mut obj = fake_obj();
  2072. assert_matches!(
  2073. obj.parse_section(fake_section(
  2074. BpfSectionKind::Program,
  2075. "cgroup/connect4/foo",
  2076. bytes_of(&fake_ins())
  2077. )),
  2078. Ok(())
  2079. );
  2080. assert_matches!(
  2081. obj.programs.get("foo"),
  2082. Some(Program {
  2083. section: ProgramSection::CgroupSockAddr {
  2084. attach_type: CgroupSockAddrAttachType::Connect4,
  2085. ..
  2086. },
  2087. ..
  2088. })
  2089. );
  2090. }
  2091. #[test]
  2092. fn test_parse_section_sock_addr_unnamed() {
  2093. let mut obj = fake_obj();
  2094. assert_matches!(
  2095. obj.parse_section(fake_section(
  2096. BpfSectionKind::Program,
  2097. "cgroup/connect4",
  2098. bytes_of(&fake_ins())
  2099. )),
  2100. Ok(())
  2101. );
  2102. assert_matches!(
  2103. obj.programs.get("connect4"),
  2104. Some(Program {
  2105. section: ProgramSection::CgroupSockAddr {
  2106. attach_type: CgroupSockAddrAttachType::Connect4,
  2107. ..
  2108. },
  2109. ..
  2110. })
  2111. );
  2112. }
  2113. #[test]
  2114. fn test_parse_section_sockopt_named() {
  2115. let mut obj = fake_obj();
  2116. assert_matches!(
  2117. obj.parse_section(fake_section(
  2118. BpfSectionKind::Program,
  2119. "cgroup/getsockopt/foo",
  2120. bytes_of(&fake_ins())
  2121. )),
  2122. Ok(())
  2123. );
  2124. assert_matches!(
  2125. obj.programs.get("foo"),
  2126. Some(Program {
  2127. section: ProgramSection::CgroupSockopt {
  2128. attach_type: CgroupSockoptAttachType::Get,
  2129. ..
  2130. },
  2131. ..
  2132. })
  2133. );
  2134. }
  2135. #[test]
  2136. fn test_parse_section_sockopt_unnamed() {
  2137. let mut obj = fake_obj();
  2138. assert_matches!(
  2139. obj.parse_section(fake_section(
  2140. BpfSectionKind::Program,
  2141. "cgroup/getsockopt",
  2142. bytes_of(&fake_ins())
  2143. )),
  2144. Ok(())
  2145. );
  2146. assert_matches!(
  2147. obj.programs.get("getsockopt"),
  2148. Some(Program {
  2149. section: ProgramSection::CgroupSockopt {
  2150. attach_type: CgroupSockoptAttachType::Get,
  2151. ..
  2152. },
  2153. ..
  2154. })
  2155. );
  2156. }
  2157. #[test]
  2158. fn test_patch_map_data() {
  2159. let mut obj = fake_obj();
  2160. obj.maps.insert(
  2161. ".rodata".to_owned(),
  2162. Map::Legacy(LegacyMap {
  2163. def: bpf_map_def {
  2164. map_type: BPF_MAP_TYPE_ARRAY as u32,
  2165. key_size: mem::size_of::<u32>() as u32,
  2166. value_size: 3,
  2167. max_entries: 1,
  2168. map_flags: BPF_F_RDONLY_PROG,
  2169. id: 1,
  2170. pinning: PinningType::None,
  2171. },
  2172. section_index: 1,
  2173. section_kind: BpfSectionKind::Rodata,
  2174. symbol_index: Some(1),
  2175. data: vec![0, 0, 0],
  2176. }),
  2177. );
  2178. obj.symbol_table.insert(
  2179. 1,
  2180. Symbol {
  2181. index: 1,
  2182. section_index: Some(1),
  2183. name: Some("my_config".to_owned()),
  2184. address: 0,
  2185. size: 3,
  2186. is_definition: true,
  2187. kind: SymbolKind::Data,
  2188. },
  2189. );
  2190. let test_data: &[u8] = &[1, 2, 3];
  2191. obj.patch_map_data(HashMap::from([
  2192. ("my_config", (test_data, true)),
  2193. ("optional_variable", (test_data, false)),
  2194. ]))
  2195. .unwrap();
  2196. let map = obj.maps.get(".rodata").unwrap();
  2197. assert_eq!(test_data, map.data());
  2198. }
  2199. #[test]
  2200. fn test_parse_btf_map_section() {
  2201. let mut obj = fake_obj();
  2202. fake_sym(&mut obj, 0, 0, "map_1", 0);
  2203. fake_sym(&mut obj, 0, 0, "map_2", 0);
  2204. // generated from:
  2205. // objcopy --dump-section .BTF=test.btf ./target/bpfel-unknown-none/debug/multimap-btf.bpf.o
  2206. // hexdump -v -e '7/1 "0x%02X, " 1/1 " 0x%02X,\n"' test.btf
  2207. let data: &[u8] = &[
  2208. 0x9F, 0xEB, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x01,
  2209. 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0xCC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2210. 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  2211. 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
  2212. 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
  2213. 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  2214. 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2215. 0x00, 0x02, 0x06, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
  2216. 0x07, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00,
  2217. 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  2218. 0x09, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0A, 0x00,
  2219. 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
  2220. 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0C, 0x00,
  2221. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
  2222. 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
  2223. 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
  2224. 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x05, 0x00,
  2225. 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  2226. 0x80, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xC0, 0x00,
  2227. 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0D, 0x00, 0x00, 0x00,
  2228. 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x20, 0x00,
  2229. 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2230. 0x4A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4E, 0x00,
  2231. 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
  2232. 0x0B, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
  2233. 0x00, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  2234. 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
  2235. 0x00, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
  2236. 0x70, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x12, 0x00, 0x00, 0x00, 0xB0, 0x01,
  2237. 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01,
  2238. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00,
  2239. 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB5, 0x01, 0x00, 0x00,
  2240. 0x00, 0x00, 0x00, 0x0E, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xBE, 0x01,
  2241. 0x00, 0x00, 0x02, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00,
  2242. 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
  2243. 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xC4, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0F,
  2244. 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
  2245. 0x00, 0x00, 0x00, 0x69, 0x6E, 0x74, 0x00, 0x5F, 0x5F, 0x41, 0x52, 0x52, 0x41, 0x59,
  2246. 0x5F, 0x53, 0x49, 0x5A, 0x45, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x5F, 0x00, 0x5F,
  2247. 0x5F, 0x75, 0x33, 0x32, 0x00, 0x75, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20,
  2248. 0x69, 0x6E, 0x74, 0x00, 0x5F, 0x5F, 0x75, 0x36, 0x34, 0x00, 0x75, 0x6E, 0x73, 0x69,
  2249. 0x67, 0x6E, 0x65, 0x64, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x20, 0x6C, 0x6F, 0x6E, 0x67,
  2250. 0x00, 0x74, 0x79, 0x70, 0x65, 0x00, 0x6B, 0x65, 0x79, 0x00, 0x76, 0x61, 0x6C, 0x75,
  2251. 0x65, 0x00, 0x6D, 0x61, 0x78, 0x5F, 0x65, 0x6E, 0x74, 0x72, 0x69, 0x65, 0x73, 0x00,
  2252. 0x6D, 0x61, 0x70, 0x5F, 0x31, 0x00, 0x6D, 0x61, 0x70, 0x5F, 0x32, 0x00, 0x63, 0x74,
  2253. 0x78, 0x00, 0x62, 0x70, 0x66, 0x5F, 0x70, 0x72, 0x6F, 0x67, 0x00, 0x74, 0x72, 0x61,
  2254. 0x63, 0x65, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x00, 0x2F, 0x76, 0x61, 0x72, 0x2F, 0x68,
  2255. 0x6F, 0x6D, 0x65, 0x2F, 0x64, 0x61, 0x76, 0x65, 0x2F, 0x64, 0x65, 0x76, 0x2F, 0x61,
  2256. 0x79, 0x61, 0x2D, 0x72, 0x73, 0x2F, 0x61, 0x79, 0x61, 0x2F, 0x74, 0x65, 0x73, 0x74,
  2257. 0x2F, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2D, 0x65,
  2258. 0x62, 0x70, 0x66, 0x2F, 0x73, 0x72, 0x63, 0x2F, 0x62, 0x70, 0x66, 0x2F, 0x6D, 0x75,
  2259. 0x6C, 0x74, 0x69, 0x6D, 0x61, 0x70, 0x2D, 0x62, 0x74, 0x66, 0x2E, 0x62, 0x70, 0x66,
  2260. 0x2E, 0x63, 0x00, 0x69, 0x6E, 0x74, 0x20, 0x62, 0x70, 0x66, 0x5F, 0x70, 0x72, 0x6F,
  2261. 0x67, 0x28, 0x76, 0x6F, 0x69, 0x64, 0x20, 0x2A, 0x63, 0x74, 0x78, 0x29, 0x00, 0x09,
  2262. 0x5F, 0x5F, 0x75, 0x33, 0x32, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x3D, 0x20, 0x30, 0x3B,
  2263. 0x00, 0x09, 0x5F, 0x5F, 0x75, 0x36, 0x34, 0x20, 0x74, 0x77, 0x65, 0x6E, 0x74, 0x79,
  2264. 0x5F, 0x66, 0x6F, 0x75, 0x72, 0x20, 0x3D, 0x20, 0x32, 0x34, 0x3B, 0x00, 0x09, 0x5F,
  2265. 0x5F, 0x75, 0x36, 0x34, 0x20, 0x66, 0x6F, 0x72, 0x74, 0x79, 0x5F, 0x74, 0x77, 0x6F,
  2266. 0x20, 0x3D, 0x20, 0x34, 0x32, 0x3B, 0x00, 0x20, 0x20, 0x20, 0x20, 0x62, 0x70, 0x66,
  2267. 0x5F, 0x6D, 0x61, 0x70, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5F, 0x65, 0x6C,
  2268. 0x65, 0x6D, 0x28, 0x26, 0x6D, 0x61, 0x70, 0x5F, 0x31, 0x2C, 0x20, 0x26, 0x6B, 0x65,
  2269. 0x79, 0x2C, 0x20, 0x26, 0x74, 0x77, 0x65, 0x6E, 0x74, 0x79, 0x5F, 0x66, 0x6F, 0x75,
  2270. 0x72, 0x2C, 0x20, 0x42, 0x50, 0x46, 0x5F, 0x41, 0x4E, 0x59, 0x29, 0x3B, 0x00, 0x20,
  2271. 0x20, 0x20, 0x20, 0x62, 0x70, 0x66, 0x5F, 0x6D, 0x61, 0x70, 0x5F, 0x75, 0x70, 0x64,
  2272. 0x61, 0x74, 0x65, 0x5F, 0x65, 0x6C, 0x65, 0x6D, 0x28, 0x26, 0x6D, 0x61, 0x70, 0x5F,
  2273. 0x32, 0x2C, 0x20, 0x26, 0x6B, 0x65, 0x79, 0x2C, 0x20, 0x26, 0x66, 0x6F, 0x72, 0x74,
  2274. 0x79, 0x5F, 0x74, 0x77, 0x6F, 0x2C, 0x20, 0x42, 0x50, 0x46, 0x5F, 0x41, 0x4E, 0x59,
  2275. 0x29, 0x3B, 0x00, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x30, 0x3B, 0x00,
  2276. 0x63, 0x68, 0x61, 0x72, 0x00, 0x5F, 0x6C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x00,
  2277. 0x2E, 0x6D, 0x61, 0x70, 0x73, 0x00, 0x6C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x00,
  2278. ];
  2279. let btf_section = fake_section(BpfSectionKind::Btf, ".BTF", data);
  2280. obj.parse_section(btf_section).unwrap();
  2281. let map_section = fake_section(BpfSectionKind::BtfMaps, ".maps", &[]);
  2282. obj.parse_section(map_section).unwrap();
  2283. let map = obj.maps.get("map_1").unwrap();
  2284. if let Map::Btf(m) = map {
  2285. assert_eq!(m.def.key_size, 4);
  2286. assert_eq!(m.def.value_size, 8);
  2287. assert_eq!(m.def.max_entries, 1);
  2288. } else {
  2289. panic!("expected a BTF map")
  2290. }
  2291. }
  2292. }