1#![no_std]
2#![crate_name = "elfloader"]
3#![crate_type = "lib"]
4
5#[cfg(test)]
6#[macro_use]
7extern crate std;
8#[cfg(test)]
9extern crate env_logger;
10
11mod binary;
12pub use binary::ElfBinary;
13
14pub mod arch;
15pub use arch::RelocationType;
16
17use core::fmt;
18use core::iter::Filter;
19
20use bitflags::bitflags;
21use xmas_elf::dynamic::*;
22use xmas_elf::program::ProgramIter;
23
24pub use xmas_elf::header::Machine;
25pub use xmas_elf::program::{Flags, ProgramHeader, ProgramHeader64};
26pub use xmas_elf::sections::{Rel, Rela};
27pub use xmas_elf::symbol_table::{Entry, Entry64};
28pub use xmas_elf::{P32, P64};
29
30pub type LoadableHeaders<'a, 'b> = Filter<ProgramIter<'a, 'b>, fn(&ProgramHeader) -> bool>;
32pub type PAddr = u64;
33pub type VAddr = u64;
34
35#[allow(dead_code)]
39pub struct RelocationEntry {
40 pub rtype: RelocationType,
41 pub offset: u64,
42 pub index: u32,
43 pub addend: Option<u64>,
44}
45
46#[derive(PartialEq, Clone, Debug)]
47pub enum ElfLoaderErr {
48 ElfParser { source: &'static str },
49 OutOfMemory,
50 SymbolTableNotFound,
51 UnsupportedElfFormat,
52 UnsupportedElfVersion,
53 UnsupportedEndianness,
54 UnsupportedAbi,
55 UnsupportedElfType,
56 UnsupportedSectionData,
57 UnsupportedArchitecture,
58 UnsupportedRelocationEntry,
59}
60
61impl From<&'static str> for ElfLoaderErr {
62 fn from(source: &'static str) -> Self {
63 ElfLoaderErr::ElfParser { source }
64 }
65}
66
67impl fmt::Display for ElfLoaderErr {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 match self {
70 ElfLoaderErr::ElfParser { source } => write!(f, "Error in ELF parser: {}", source),
71 ElfLoaderErr::OutOfMemory => write!(f, "Out of memory"),
72 ElfLoaderErr::SymbolTableNotFound => write!(f, "No symbol table in the ELF file"),
73 ElfLoaderErr::UnsupportedElfFormat => write!(f, "ELF format not supported"),
74 ElfLoaderErr::UnsupportedElfVersion => write!(f, "ELF version not supported"),
75 ElfLoaderErr::UnsupportedEndianness => write!(f, "ELF endianness not supported"),
76 ElfLoaderErr::UnsupportedAbi => write!(f, "ELF ABI not supported"),
77 ElfLoaderErr::UnsupportedElfType => write!(f, "ELF type not supported"),
78 ElfLoaderErr::UnsupportedSectionData => write!(f, "Can't handle this section data"),
79 ElfLoaderErr::UnsupportedArchitecture => write!(f, "Unsupported Architecture"),
80 ElfLoaderErr::UnsupportedRelocationEntry => {
81 write!(f, "Can't handle relocation entry")
82 }
83 }
84 }
85}
86
87bitflags! {
88 #[derive(Default)]
89 pub struct DynamicFlags1: u64 {
90 const NOW = FLAG_1_NOW;
91 const GLOBAL = FLAG_1_GLOBAL;
92 const GROUP = FLAG_1_GROUP;
93 const NODELETE = FLAG_1_NODELETE;
94 const LOADFLTR = FLAG_1_LOADFLTR;
95 const INITFIRST = FLAG_1_INITFIRST;
96 const NOOPEN = FLAG_1_NOOPEN;
97 const ORIGIN = FLAG_1_ORIGIN;
98 const DIRECT = FLAG_1_DIRECT;
99 const TRANS = FLAG_1_TRANS;
100 const INTERPOSE = FLAG_1_INTERPOSE;
101 const NODEFLIB = FLAG_1_NODEFLIB;
102 const NODUMP = FLAG_1_NODUMP;
103 const CONFALT = FLAG_1_CONFALT;
104 const ENDFILTEE = FLAG_1_ENDFILTEE;
105 const DISPRELDNE = FLAG_1_DISPRELDNE;
106 const DISPRELPND = FLAG_1_DISPRELPND;
107 const NODIRECT = FLAG_1_NODIRECT;
108 const IGNMULDEF = FLAG_1_IGNMULDEF;
109 const NOKSYMS = FLAG_1_NOKSYMS;
110 const NOHDR = FLAG_1_NOHDR;
111 const EDITED = FLAG_1_EDITED;
112 const NORELOC = FLAG_1_NORELOC;
113 const SYMINTPOSE = FLAG_1_SYMINTPOSE;
114 const GLOBAUDIT = FLAG_1_GLOBAUDIT;
115 const SINGLETON = FLAG_1_SINGLETON;
116 const STUB = FLAG_1_STUB;
117 const PIE = FLAG_1_PIE;
118 }
119}
120
121pub struct DynamicInfo {
123 pub flags1: DynamicFlags1,
124 pub rela: u64,
125 pub rela_size: u64,
126}
127
128pub trait ElfLoader {
135 fn allocate(&mut self, load_headers: LoadableHeaders) -> Result<(), ElfLoaderErr>;
137
138 fn load(&mut self, flags: Flags, base: VAddr, region: &[u8]) -> Result<(), ElfLoaderErr>;
142
143 fn relocate(&mut self, entry: RelocationEntry) -> Result<(), ElfLoaderErr>;
146
147 fn tls(
149 &mut self,
150 _tdata_start: VAddr,
151 _tdata_length: u64,
152 _total_size: u64,
153 _align: u64,
154 ) -> Result<(), ElfLoaderErr> {
155 Ok(())
156 }
157
158 fn make_readonly(&mut self, _base: VAddr, _size: usize) -> Result<(), ElfLoaderErr> {
165 Ok(())
166 }
167}
168
169#[cfg(doctest)]
170mod test_readme {
171 macro_rules! external_doc_test {
172 ($x:expr) => {
173 #[doc = $x]
174 extern "C" {}
175 };
176 }
177
178 external_doc_test!(include_str!("../README.md"));
179}