obj.rs 85 KB

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