1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

use super::super::nom::{IResult, ErrorKind, le_u8};

use super::super::{Fault, nom_bullshit};

/*
 * LE/BE doesn't matter when reading bytes
 * individual bytes
 */
use super::abi::{ElfAbi, Abi, parse_elf_abi};
use super::endian::{ElfEndian, Endian, parse_elf_endian};
use super::class::{ElfClass, Class, parse_elf_class};
use super::traits::{ElfMagicNumber};

/// Data extracted from magic numbers
#[derive(Copy,Clone,Debug,Hash)]
pub struct ElfMagicNumbers {
    class: ElfClass,
    endian: ElfEndian,
    abi: ElfAbi,
    abi_version: u8,
}
impl Abi for ElfMagicNumbers {
    #[inline(always)]
    fn get_abi(&self) -> ElfAbi {
        self.abi.clone()
    }
}
impl Endian for ElfMagicNumbers {
    #[inline(always)]
    fn get_endian(&self) -> ElfEndian {
        self.endian.clone()
    }
}
impl Class for ElfMagicNumbers {
    #[inline(always)]
    fn get_class(&self) -> ElfClass {
        self.class.clone()
    }
}
impl ElfMagicNumber for ElfMagicNumbers {
    #[inline(always)]
    fn get_abi_version(&self) -> u8 {
        self.abi_version.clone()
    }
}

named!(check_magic<&[u8],&[u8],u32>,
    add_return_error!(ErrorKind::Custom(1u32),
    tag!(b"\x7F\x45\x4C\x46")
));

named!(pub parse_elf_magic<&[u8],ElfMagicNumbers,u32>, do_parse!(
    check_magic >>
    class: parse_elf_class >>
    endian: parse_elf_endian >> 
    take!(1) >>
    abi: parse_elf_abi >>
    abi_version: le_u8 >>
    take!(7) >>
    ( ElfMagicNumbers{
        class, endian, abi, abi_version
    })
));

#[test]
fn test_check_magic() {

    //passing test
    let dut0 = b"\x7F\x45\x4C\x46\xDE\xAD\xBE\xEF";
    let (rem,var) = match check_magic(dut0) {
        IResult::Done(x,y) => (x,y),
        IResult::Incomplete(n) => panic!("check magic failed {:?}",n),
        IResult::Error(e) => panic!("check magic failed {:?}",e)
    };
    assert_eq!(rem.len(), 4);
    assert_eq!(rem, b"\xDE\xAD\xBE\xEF");
    assert_eq!(var.len(), 4);
    assert_eq!(var, b"\x7F\x45\x4C\x46");
    
    //failing test
    let dut1 = b"\x00\x45\x4C\x46\xDE\xAD\xBE\xEF";
    match check_magic(dut1) {
        IResult::Done(_,_) => panic!("check magic should fail"),
        IResult::Incomplete(n) => panic!("check magic wrong error {:?}",n),
        IResult::Error(e) => {
            match nom_bullshit(e) {
                ErrorKind::Custom(1u32) => { }
                ErrorKind::Custom(x) => panic!("check magic wrong error code {:?}", x),
                e => panic!("check magic wrong error code {:?}", e)
            }
        }
    };
}

#[test]
fn test_parse_elf_magic() {

    //passing test
    let dut0: &[u8] = b"\x7F\x45\x4C\x46\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
    let (rem, magic) = match parse_elf_magic(dut0) {
        IResult::Done(x,m) => (x,m),
        IResult::Incomplete(n) => panic!("check_version failed {:?}",n),
        IResult::Error(e) => panic!("check_version failed {:?}",e)
    };
    //check remainer
    assert_eq!(rem.len(), 1);
    assert_eq!(rem[0],0);

    //check values
    assert_eq!(magic.get_abi(), ElfAbi::SystemV);
    assert_eq!(magic.get_endian(), ElfEndian::Little);
    assert_eq!(magic.get_class(), ElfClass::Bits64);
    assert_eq!(magic.get_abi_version(), 0);
}