obj.rs 84 KB

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