1use num_traits::{FromPrimitive, ToPrimitive};
2use std::io::{Read, Write};
3use std::io::BufWriter;
4use error::Error;
5use types;
6
7#[derive(Debug,Clone)]
8pub struct Header {
9 pub ident_magic: [u8; 4],
10 pub ident_class: types::Class,
11 pub ident_endianness: types::Endianness,
12 pub ident_version: u8, pub ident_abi: types::Abi,
14 pub ident_abiversion: u8,
15
16 pub etype: types::ElfType,
17 pub machine: types::Machine,
18 pub version: u32, pub entry: u64, pub phoff: u64, pub shoff: u64, pub flags: types::HeaderFlags,
23 pub ehsize: u16, pub phentsize: u16, pub phnum: u16, pub shentsize: u16, pub shnum: u16, pub shstrndx: u16, }
30
31impl Default for Header {
32 fn default() -> Self {
33 Header {
34 ident_magic: [0x7F, 0x45, 0x4c, 0x46],
35 ident_class: types::Class::Class64,
36 ident_endianness: types::Endianness::LittleEndian,
37 ident_version: 1,
38 ident_abi: types::Abi::SYSV,
39 ident_abiversion: 0,
40 etype: types::ElfType::default(),
41 machine: types::Machine::default(),
42 version: 1,
43 entry: 0,
44 phoff: 0,
45 shoff: 0,
46 flags: types::HeaderFlags::default(),
47 ehsize: 0,
48 phentsize: 0,
49 phnum: 0,
50 shentsize: 0,
51 shnum: 0,
52 shstrndx: 0,
53 }
54 }
55}
56
57
58impl Header {
59 pub fn from_reader<R>(io: &mut R) -> Result<Header, Error>
60 where
61 R: Read,
62 {
63 let mut r = Header::default();
64 let mut b = [0; 16];
65 if let Err(_) = io.read_exact(&mut b) {
66 return Err(Error::InvalidMagic);
67 }
68 r.ident_magic.clone_from_slice(&b[0..4]);
69
70 if r.ident_magic != [0x7F, 0x45, 0x4c, 0x46] {
71 return Err(Error::InvalidMagic);
72 }
73
74 r.ident_class = match types::Class::from_u8(b[4]) {
75 Some(v) => v,
76 None => return Err(Error::InvalidIdentClass(b[4])),
77 };
78
79 r.ident_endianness = match types::Endianness::from_u8(b[5]) {
80 Some(v) => v,
81 None => return Err(Error::InvalidEndianness(b[5])),
82 };
83
84 r.ident_version = b[6];
85 if r.ident_version != 1 {
86 return Err(Error::InvalidIdentVersion(b[6]));
87 }
88
89 r.ident_abi = match types::Abi::from_u8(b[7]) {
90 Some(v) => v,
91 None => return Err(Error::InvalidAbi(b[7])),
92 };
93
94 r.ident_abiversion = b[8];
95
96 elf_dispatch_endianness!(r => {
97
98 let reb = read_u16(io)?;
99 r.etype = match types::ElfType::from_u16(reb) {
100 Some(v) => v,
101 None => return Err(Error::InvalidElfType(reb)),
102 };
103
104 let reb = read_u16(io)?;
105 r.machine = match types::Machine::from_u16(reb) {
106 Some(v) => v,
107 None => return Err(Error::InvalidMachineType(reb)),
108 };
109
110 r.version = read_u32(io)?;
111 if r.version != 1 {
112 return Err(Error::InvalidVersion(r.version));
113 }
114
115
116 elf_dispatch_uclass!(r => {
117 r.entry = read_uclass(io)?;
118 r.phoff = read_uclass(io)?;
119 r.shoff = read_uclass(io)?;
120 });
121
122 let reb = io.read_u32::<DispatchedEndian>()?;
123 r.flags = types::HeaderFlags::from_bits_truncate(reb);
124 r.ehsize = read_u16(io)?;
130 r.phentsize = read_u16(io)?;
131 r.phnum = read_u16(io)?;
132 r.shentsize = read_u16(io)?;
133 r.shnum = read_u16(io)?;
134 r.shstrndx = read_u16(io)?;
135 });
136
137 Ok(r)
138 }
139
140 pub fn to_writer<R>(&self, io: &mut R) -> Result<(), Error>
141 where
142 R: Write,
143 {
144 let mut w = BufWriter::new(io);
145 w.write(&self.ident_magic)?;
146 w.write(&[self.ident_class.to_u8().unwrap()])?;
147 w.write(&[self.ident_endianness.to_u8().unwrap()])?;
148 w.write(&[self.ident_version.to_u8().unwrap()])?;
149 w.write(&[self.ident_abi.to_u8().unwrap()])?;
150 w.write(&[0; 8])?;
151
152 elf_write_u16!(self, w, self.etype.to_u16().unwrap())?;
153 elf_write_u16!(self, w, self.machine.to_u16().unwrap())?;
154 elf_write_u32!(self, w, self.version.to_u32().unwrap())?;
155 elf_write_uclass!(self, w, self.entry.to_u64().unwrap())?;
156 elf_write_uclass!(self, w, self.phoff.to_u64().unwrap())?;
157 elf_write_uclass!(self, w, self.shoff.to_u64().unwrap())?;
158 elf_write_u32!(self, w, self.flags.bits())?;
159 elf_write_u16!(self, w, self.ehsize.to_u16().unwrap())?;
160 elf_write_u16!(self, w, self.phentsize.to_u16().unwrap())?;
161 elf_write_u16!(self, w, self.phnum.to_u16().unwrap())?;
162 elf_write_u16!(self, w, self.shentsize.to_u16().unwrap())?;
163 elf_write_u16!(self, w, self.shnum.to_u16().unwrap())?;
164 elf_write_u16!(self, w, self.shstrndx.to_u16().unwrap())?;
165
166 Ok(())
167 }
168
169 pub fn size(&self) -> usize {
170 16 + 2 + 2 + 4 + match self.ident_class {
171 types::Class::Class32 => 4 + 4 + 4,
172 types::Class::Class64 => 8 + 8 + 8,
173 } + 4 + 2 + 2 + 2 + 2 + 2 + 2
174 }
175}