obj.rs 84 KB

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