elf_sections.rs 10 KB

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