elfkit/
header.rs

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, // 1
13    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, //1
19    pub entry:      u64, //program counter starts here
20    pub phoff:      u64, //offset of program header table
21    pub shoff:      u64, //offset of section header table
22    pub flags:      types::HeaderFlags,
23    pub ehsize:     u16, //size of this header (who cares?)
24    pub phentsize:  u16, //the size of a program header table entry
25    pub phnum:      u16, //the number of entries in the program header table
26    pub shentsize:  u16, //the size of a section header table entry
27    pub shnum:      u16, //the number of entries in the section header table
28    pub shstrndx:   u16, //where to find section names
29}
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.flags = match types::HeaderFlags::from_bits(reb) {
125            //    Some(v) => v,
126            //    None => return Err(Error::InvalidHeaderFlags(reb)),
127            //};
128
129            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}