obj.rs 94 KB

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