4
0

obj.rs 84 KB

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