elf_sections.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. use crate::header::Tag;
  2. use core::fmt::{Debug, Formatter};
  3. /// This tag contains section header table from an ELF kernel.
  4. ///
  5. /// The sections iterator is provided via the `sections` method.
  6. #[derive(Debug)]
  7. pub struct ElfSectionsTag {
  8. inner: *const ElfSectionsTagInner,
  9. offset: usize,
  10. }
  11. pub unsafe fn elf_sections_tag(tag: &Tag, offset: usize) -> ElfSectionsTag {
  12. assert_eq!(9, tag.typ);
  13. let es = ElfSectionsTag {
  14. inner: (tag as *const Tag).offset(1) as *const ElfSectionsTagInner,
  15. offset,
  16. };
  17. assert!((es.get().entry_size * es.get().shndx) <= tag.size);
  18. es
  19. }
  20. #[derive(Clone, Copy, Debug)]
  21. #[repr(C, packed)] // only repr(C) would add unwanted padding at the end
  22. struct ElfSectionsTagInner {
  23. number_of_sections: u32,
  24. entry_size: u32,
  25. shndx: u32, // string table
  26. }
  27. impl ElfSectionsTag {
  28. /// Get an iterator of loaded ELF sections.
  29. ///
  30. /// # Examples
  31. ///
  32. /// ```ignore
  33. /// if let Some(elf_tag) = boot_info.elf_sections_tag() {
  34. /// let mut total = 0;
  35. /// for section in elf_tag.sections() {
  36. /// println!("Section: {:?}", section);
  37. /// total += 1;
  38. /// }
  39. /// }
  40. /// ```
  41. pub fn sections(&self) -> ElfSectionIter {
  42. let string_section_offset = (self.get().shndx * self.get().entry_size) as isize;
  43. let string_section_ptr =
  44. unsafe { self.first_section().offset(string_section_offset) as *const _ };
  45. ElfSectionIter {
  46. current_section: self.first_section(),
  47. remaining_sections: self.get().number_of_sections,
  48. entry_size: self.get().entry_size,
  49. string_section: string_section_ptr,
  50. offset: self.offset,
  51. }
  52. }
  53. fn first_section(&self) -> *const u8 {
  54. (unsafe { self.inner.offset(1) }) as *const _
  55. }
  56. fn get(&self) -> &ElfSectionsTagInner {
  57. unsafe { &*self.inner }
  58. }
  59. }
  60. /// An iterator over some ELF sections.
  61. #[derive(Clone)]
  62. pub struct ElfSectionIter {
  63. current_section: *const u8,
  64. remaining_sections: u32,
  65. entry_size: u32,
  66. string_section: *const u8,
  67. offset: usize,
  68. }
  69. impl Iterator for ElfSectionIter {
  70. type Item = ElfSection;
  71. fn next(&mut self) -> Option<ElfSection> {
  72. while self.remaining_sections != 0 {
  73. let section = ElfSection {
  74. inner: self.current_section,
  75. string_section: self.string_section,
  76. entry_size: self.entry_size,
  77. offset: self.offset,
  78. };
  79. self.current_section = unsafe { self.current_section.offset(self.entry_size as isize) };
  80. self.remaining_sections -= 1;
  81. if section.section_type() != ElfSectionType::Unused {
  82. return Some(section);
  83. }
  84. }
  85. None
  86. }
  87. }
  88. impl Debug for ElfSectionIter {
  89. fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
  90. let mut debug = f.debug_list();
  91. self.clone().for_each(|ref e| {
  92. debug.entry(e);
  93. });
  94. debug.finish()
  95. }
  96. }
  97. impl Default for ElfSectionIter {
  98. fn default() -> Self {
  99. Self {
  100. current_section: core::ptr::null(),
  101. remaining_sections: 0,
  102. entry_size: 0,
  103. string_section: core::ptr::null(),
  104. offset: 0,
  105. }
  106. }
  107. }
  108. /// A single generic ELF Section.
  109. #[derive(Debug)]
  110. pub struct ElfSection {
  111. inner: *const u8,
  112. string_section: *const u8,
  113. entry_size: u32,
  114. offset: usize,
  115. }
  116. #[derive(Clone, Copy, Debug)]
  117. #[repr(C, packed)]
  118. struct ElfSectionInner32 {
  119. name_index: u32,
  120. typ: u32,
  121. flags: u32,
  122. addr: u32,
  123. offset: u32,
  124. size: u32,
  125. link: u32,
  126. info: u32,
  127. addralign: u32,
  128. entry_size: u32,
  129. }
  130. #[derive(Clone, Copy, Debug)]
  131. #[repr(C, packed)]
  132. struct ElfSectionInner64 {
  133. name_index: u32,
  134. typ: u32,
  135. flags: u64,
  136. addr: u64,
  137. offset: u64,
  138. size: u64,
  139. link: u32,
  140. info: u32,
  141. addralign: u64,
  142. entry_size: u64,
  143. }
  144. impl ElfSection {
  145. /// Get the section type as a `ElfSectionType` enum variant.
  146. pub fn section_type(&self) -> ElfSectionType {
  147. match self.get().typ() {
  148. 0 => ElfSectionType::Unused,
  149. 1 => ElfSectionType::ProgramSection,
  150. 2 => ElfSectionType::LinkerSymbolTable,
  151. 3 => ElfSectionType::StringTable,
  152. 4 => ElfSectionType::RelaRelocation,
  153. 5 => ElfSectionType::SymbolHashTable,
  154. 6 => ElfSectionType::DynamicLinkingTable,
  155. 7 => ElfSectionType::Note,
  156. 8 => ElfSectionType::Uninitialized,
  157. 9 => ElfSectionType::RelRelocation,
  158. 10 => ElfSectionType::Reserved,
  159. 11 => ElfSectionType::DynamicLoaderSymbolTable,
  160. 0x6000_0000..=0x6FFF_FFFF => ElfSectionType::EnvironmentSpecific,
  161. 0x7000_0000..=0x7FFF_FFFF => ElfSectionType::ProcessorSpecific,
  162. _ => panic!(),
  163. }
  164. }
  165. /// Get the "raw" section type as a `u32`
  166. pub fn section_type_raw(&self) -> u32 {
  167. self.get().typ()
  168. }
  169. /// Read the name of the section.
  170. pub fn name(&self) -> &str {
  171. use core::{slice, str};
  172. let name_ptr = unsafe { self.string_table().offset(self.get().name_index() as isize) };
  173. let strlen = {
  174. let mut len = 0;
  175. while unsafe { *name_ptr.offset(len) } != 0 {
  176. len += 1;
  177. }
  178. len as usize
  179. };
  180. str::from_utf8(unsafe { slice::from_raw_parts(name_ptr, strlen) }).unwrap()
  181. }
  182. /// Get the physical start address of the section.
  183. pub fn start_address(&self) -> u64 {
  184. self.get().addr()
  185. }
  186. /// Get the physical end address of the section.
  187. ///
  188. /// This is the same as doing `section.start_address() + section.size()`
  189. pub fn end_address(&self) -> u64 {
  190. self.get().addr() + self.get().size()
  191. }
  192. /// Get the section's size in bytes.
  193. pub fn size(&self) -> u64 {
  194. self.get().size()
  195. }
  196. /// Get the section's address alignment constraints.
  197. ///
  198. /// That is, the value of `start_address` must be congruent to 0,
  199. /// modulo the value of `addrlign`. Currently, only 0 and positive
  200. /// integral powers of two are allowed. Values 0 and 1 mean the section has no
  201. /// alignment constraints.
  202. pub fn addralign(&self) -> u64 {
  203. self.get().addralign()
  204. }
  205. /// Get the section's flags.
  206. pub fn flags(&self) -> ElfSectionFlags {
  207. ElfSectionFlags::from_bits_truncate(self.get().flags())
  208. }
  209. /// Check if the `ALLOCATED` flag is set in the section flags.
  210. pub fn is_allocated(&self) -> bool {
  211. self.flags().contains(ElfSectionFlags::ALLOCATED)
  212. }
  213. fn get(&self) -> &dyn ElfSectionInner {
  214. match self.entry_size {
  215. 40 => unsafe { &*(self.inner as *const ElfSectionInner32) },
  216. 64 => unsafe { &*(self.inner as *const ElfSectionInner64) },
  217. _ => panic!(),
  218. }
  219. }
  220. unsafe fn string_table(&self) -> *const u8 {
  221. let addr = match self.entry_size {
  222. 40 => (*(self.string_section as *const ElfSectionInner32)).addr as usize,
  223. 64 => (*(self.string_section as *const ElfSectionInner64)).addr as usize,
  224. _ => panic!(),
  225. };
  226. (addr + self.offset) as *const _
  227. }
  228. }
  229. trait ElfSectionInner {
  230. fn name_index(&self) -> u32;
  231. fn typ(&self) -> u32;
  232. fn flags(&self) -> u64;
  233. fn addr(&self) -> u64;
  234. fn size(&self) -> u64;
  235. fn addralign(&self) -> u64;
  236. }
  237. impl ElfSectionInner for ElfSectionInner32 {
  238. fn name_index(&self) -> u32 {
  239. self.name_index
  240. }
  241. fn typ(&self) -> u32 {
  242. self.typ
  243. }
  244. fn flags(&self) -> u64 {
  245. self.flags.into()
  246. }
  247. fn addr(&self) -> u64 {
  248. self.addr.into()
  249. }
  250. fn size(&self) -> u64 {
  251. self.size.into()
  252. }
  253. fn addralign(&self) -> u64 {
  254. self.addralign.into()
  255. }
  256. }
  257. impl ElfSectionInner for ElfSectionInner64 {
  258. fn name_index(&self) -> u32 {
  259. self.name_index
  260. }
  261. fn typ(&self) -> u32 {
  262. self.typ
  263. }
  264. fn flags(&self) -> u64 {
  265. self.flags
  266. }
  267. fn addr(&self) -> u64 {
  268. self.addr
  269. }
  270. fn size(&self) -> u64 {
  271. self.size
  272. }
  273. fn addralign(&self) -> u64 {
  274. self.addralign
  275. }
  276. }
  277. /// An enum abstraction over raw ELF section types.
  278. #[derive(PartialEq, Eq, Debug, Copy, Clone)]
  279. #[repr(u32)]
  280. pub enum ElfSectionType {
  281. /// This value marks the section header as inactive; it does not have an
  282. /// associated section. Other members of the section header have undefined
  283. /// values.
  284. Unused = 0,
  285. /// The section holds information defined by the program, whose format and
  286. /// meaning are determined solely by the program.
  287. ProgramSection = 1,
  288. /// This section holds a linker symbol table.
  289. LinkerSymbolTable = 2,
  290. /// The section holds a string table.
  291. StringTable = 3,
  292. /// The section holds relocation entries with explicit addends, such as type
  293. /// Elf32_Rela for the 32-bit class of object files. An object file may have
  294. /// multiple relocation sections.
  295. RelaRelocation = 4,
  296. /// The section holds a symbol hash table.
  297. SymbolHashTable = 5,
  298. /// The section holds dynamic linking tables.
  299. DynamicLinkingTable = 6,
  300. /// This section holds information that marks the file in some way.
  301. Note = 7,
  302. /// A section of this type occupies no space in the file but otherwise resembles
  303. /// `ProgramSection`. Although this section contains no bytes, the
  304. /// sh_offset member contains the conceptual file offset.
  305. Uninitialized = 8,
  306. /// The section holds relocation entries without explicit addends, such as type
  307. /// Elf32_Rel for the 32-bit class of object files. An object file may have
  308. /// multiple relocation sections.
  309. RelRelocation = 9,
  310. /// This section type is reserved but has unspecified semantics.
  311. Reserved = 10,
  312. /// This section holds a dynamic loader symbol table.
  313. DynamicLoaderSymbolTable = 11,
  314. /// Values in this inclusive range (`[0x6000_0000, 0x6FFF_FFFF)`) are
  315. /// reserved for environment-specific semantics.
  316. EnvironmentSpecific = 0x6000_0000,
  317. /// Values in this inclusive range (`[0x7000_0000, 0x7FFF_FFFF)`) are
  318. /// reserved for processor-specific semantics.
  319. ProcessorSpecific = 0x7000_0000,
  320. }
  321. bitflags! {
  322. /// ELF Section bitflags.
  323. pub struct ElfSectionFlags: u64 {
  324. /// The section contains data that should be writable during program execution.
  325. const WRITABLE = 0x1;
  326. /// The section occupies memory during the process execution.
  327. const ALLOCATED = 0x2;
  328. /// The section contains executable machine instructions.
  329. const EXECUTABLE = 0x4;
  330. // plus environment-specific use at 0x0F000000
  331. // plus processor-specific use at 0xF0000000
  332. }
  333. }