<commit_before>//
//  SOS: the Stupid Operating System
//  by <NAME> (<EMAIL>)
//
//  Copyright (c) 2015-2017 <NAME>
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use super::{ElfResult, ElfWord, Section, section};

use core::{fmt, mem};

pub trait Header {
    type Word: ElfWord;

    /// Attempt to extract an ELF file header from a slice of bytes.
    /// TODO: should this be a From impl maybe?
    //          - eliza, 03/08/2017
    fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self>;

    /// Attempt to extract a section header from a slice of bytes.
    /// TODO: can/should the index be `usize`?
    //          - eliza, 03/08/2017
    fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>;

    // Field accessors -------------------------------------------
    fn ident(&self) -> Ident;
    fn get_type(&self) -> Type;
    fn machine(&self) -> Machine;
    /// Offset of the program entry point
    fn entry_point(&self) -> usize;
    /// Offset of the start of program headers
    fn ph_offset(&self) -> usize;
    /// Offset of the start of [section header]s.
    ///
    /// [section header]: ../section/struct.Header.html
    fn sh_offset(&self) -> usize;
    /// TODO: can this return the flags type?
    //          - eliza, 03/08/2017
    fn flags(&self) -> u32;
    fn sh_str_idx(&self) -> usize;

}

/// An ELF file header
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct HeaderRepr<W: ElfWord> {
    /// the ELF [file identifier](struct.Ident.html)
    pub ident: Ident
  , elftype: TypeRepr
  , pub machine: Machine
  , /// Program entry point
    /// TODO: getters for turning these into `usize`?
    //          - eliza, 03/08/2017
    entry_point: W
  , /// Offset for start of program headers
    ph_offset: W
  , /// Offset for start of [section header]s.
    /// [section header]: ../section/struct.Header.html
    sh_offset: W
  , pub flags: u32
  , pub header_size: u16
  , pub ph_entry_size: u16
  , pub ph_count: u16
  , pub sh_entry_size: u16
  , pub sh_count: u16
  , /// Index of the section header string table
    sh_str_idx: u16
}

/// FIXME(style): generate more stuff with macros/use `macro_attr` to derive
///               these...
//                  - eliza, 03/08/2017
macro_rules! impl_getters {
    ($(#[$attr:meta])* pub fn $name:ident(&self) -> $ty:ident; $($rest:tt)*) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ($(#[$attr:meta])* fn $name:ident(&self) -> $ty:ident; $($rest:tt)*) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ( $(#[$attr:meta])* pub fn $name: ident (&self)-> $ty: ident; ) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
    };
    ( $(#[$attr:meta])* fn $name: ident (&self)-> $ty: ident; ) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
    };
    () => {};
}


impl Header for HeaderRepr<u64> {
    type Word = u64;

    /// Attempt to extract an ELF file header from a slice of bytes.
    /// TODO: can this also be macro-generated?
    ///         - eliza, 03/08/2017
    fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self> {
        if input.len() < mem::size_of::<Self>() {
            Err("Input too short to extract ELF header")
        } else {
            unsafe { Ok(&super::extract_from_slice::<Self>(input, 0, 1)[0]) }
        }
    }

    /// Attempt to extract a section header from a slice of bytes.
    /// TODO: can this also be macro-generated?
    ///         - eliza, 03/08/2017
    fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>
    {
        if idx < section::SHN_LORESERVE {
            Err("Cannot parse reserved section.")
        } else {
            let start: u64// start offset for section
                = self.sh_offset + idx as u64 * self.sh_entry_size as u64;
            let end: u64 // end offset for section
                = start + self.sh_entry_size as u64;
            let raw
                = &input[start as usize .. end as usize];

            match self.ident.class {
                Class::None => Err("Invalid ELF class (ELFCLASSNONE).")
              , Class::Elf32 => Err("Cannot parse 32-bit section from 64-bit \
                                     ELF file.")
              , Class::Elf64 => unsafe {
                    Ok(&*(raw as *const [u8] as *const u8 as *const Section))
                }
            }
        }
    }

    #[inline] fn get_type(&self) -> Type { self.elftype.as_type() }

    impl_getters! {
        #[doc = "Index for the start of [section header]s. \
                 [section header]: ../section/struct.Header.html"]
        fn sh_offset(&self) -> usize;
        #[doc = "Index for the start of program headers"]
        fn ph_offset(&self) -> usize;
        #[doc = "Index for the program entry point"]
        fn entry_point(&self) -> usize;
        #[doc = "Index of the section header [string table] \
                 [string table]: ../section/struct.StrTable.html"]
        fn sh_str_idx(&self) -> usize;
        fn flags(&self) -> u32;
        fn ident(&self) -> Ident;
        fn machine(&self) -> Machine;
    }

}

impl Header for HeaderRepr<u32> {

    type Word = u32;
    /// Attempt to extract an ELF file header from a slice of bytes.
    fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self> {
        if input.len() < mem::size_of::<Self>() {
            Err("Input too short to extract ELF header")
        } else {
            unsafe { Ok(&super::extract_from_slice::<Self>(input, 0, 1)[0]) }
        }
    }

    /// Attempt to extract a section header from a slice of bytes.
    fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>
    {
        if idx < section::SHN_LORESERVE {
            Err("Cannot parse reserved section.")
        } else {
            let start: u32// start offset for section
                = self.sh_offset + idx as u32 * self.sh_entry_size as u32;
            let end: u32 // end offset for section
                = start + self.sh_entry_size as u32;
            let raw
                = &input[start as usize .. end as usize];

            match self.ident.class {
                Class::None => Err("Invalid ELF class (ELFCLASSNONE).")
              , Class::Elf32 => unsafe {
                    Ok(&*(raw as *const [u8] as *const u8 as *const Section))
                }
              , Class::Elf64 => Err("Cannot parse 64-bit section from 32-bit \
                                     ELF file.")
            }
        }
    }

    #[inline] fn get_type(&self) -> Type { self.elftype.as_type() }

    impl_getters! {
        #[doc = "Index for the start of [section header]s. \
                 [section header]: ../section/struct.Header.html"]
        fn sh_offset(&self) -> usize;
        #[doc = "Index for the start of program headers"]
        fn ph_offset(&self) -> usize;
        #[doc = "Index for the program entry point"]
        fn entry_point(&self) -> usize;
        #[doc = "Index of the section header [string table] \
                 [string table]: ../section/struct.StrTable.html"]
        fn sh_str_idx(&self) -> usize;
        fn flags(&self) -> u32;
        fn ident(&self) -> Ident;
        fn machine(&self) -> Machine;
    }

}
<commit_msg>feat(elf): add getters for more file header fields<commit_after>//
//  SOS: the Stupid Operating System
//  by <NAME> (<EMAIL>)
//
//  Copyright (c) 2015-2017 <NAME>
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use super::{ElfResult, ElfWord, Section, section};

use core::{fmt, mem};

pub trait Header {
    type Word: ElfWord;

    /// Attempt to extract an ELF file header from a slice of bytes.
    /// TODO: should this be a From impl maybe?
    //          - eliza, 03/08/2017
    fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self>;

    /// Attempt to extract a section header from a slice of bytes.
    /// TODO: can/should the index be `usize`?
    //          - eliza, 03/08/2017
    fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>;

    // Field accessors -------------------------------------------
    fn ident(&self) -> Ident;
    fn get_type(&self) -> Type;
    fn machine(&self) -> Machine;
    /// Offset of the program entry point
    fn entry_point(&self) -> usize;
    /// Offset of the start of program headers
    fn ph_offset(&self) -> usize;
    /// Number of program headers.
    fn ph_count(&self) -> usize;
    /// Size of a program header.
    /// TODO: add function for using this and `ph_count` to make a memrange
    ///       representing the program header entries?
    //          - eliza, 03/08/2017
    fn ph_entry_size(&self) -> usize;
    /// Offset of the start of [section header]s.
    ///
    /// [section header]: ../section/struct.Header.html
    fn sh_offset(&self) -> usize;
    /// Number of [section header]s.
    ///
    /// [section header]: ../section/struct.Header.html
    fn sh_count(&self) -> usize;
    /// Size of a [section header].
    ///
    /// [section header]: ../section/struct.Header.html
    /// TODO: add function for using this and `sh_count` to make a memrange
    ///       representing the section header entries?
    //          - eliza, 03/08/2017
    fn sh_entry_size(&self) -> usize;
    /// TODO: can this return the flags type?
    //          - eliza, 03/08/2017
    fn flags(&self) -> u32;
    /// Index of the section header [string table].
    ///
    /// [string table]: ../section/struct.StrTable.html"]
    fn sh_str_idx(&self) -> usize;

}

/// An ELF file header
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct HeaderRepr<W: ElfWord> {
    /// the ELF [file identifier](struct.Ident.html)
    pub ident: Ident
  , elftype: TypeRepr
  , pub machine: Machine
  , /// Program entry point
    /// TODO: getters for turning these into `usize`?
    //          - eliza, 03/08/2017
    entry_point: W
  , /// Offset for start of program headers
    ph_offset: W
  , /// Offset for start of [section header]s.
    /// [section header]: ../section/struct.Header.html
    sh_offset: W
  , pub flags: u32
  , pub header_size: u16
  , pub ph_entry_size: u16
  , pub ph_count: u16
  , pub sh_entry_size: u16
  , pub sh_count: u16
  , /// Index of the section header string table
    sh_str_idx: u16
}

/// FIXME(style): generate more stuff with macros/use `macro_attr` to derive
///               these...
//                  - eliza, 03/08/2017
macro_rules! impl_getters {
    ($(#[$attr:meta])* pub fn $name:ident(&self) -> $ty:ident; $($rest:tt)*) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ($(#[$attr:meta])* fn $name:ident(&self) -> $ty:ident; $($rest:tt)*) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ( $(#[$attr:meta])* pub fn $name: ident (&self)-> $ty: ident; ) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
    };
    ( $(#[$attr:meta])* fn $name: ident (&self)-> $ty: ident; ) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
    };
    () => {};
}


impl Header for HeaderRepr<u64> {
    type Word = u64;

    /// Attempt to extract an ELF file header from a slice of bytes.
    /// TODO: can this also be macro-generated?
    ///         - eliza, 03/08/2017
    fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self> {
        if input.len() < mem::size_of::<Self>() {
            Err("Input too short to extract ELF header")
        } else {
            unsafe { Ok(&super::extract_from_slice::<Self>(input, 0, 1)[0]) }
        }
    }

    /// Attempt to extract a section header from a slice of bytes.
    /// TODO: can this also be macro-generated?
    ///         - eliza, 03/08/2017
    fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>
    {
        if idx < section::SHN_LORESERVE {
            Err("Cannot parse reserved section.")
        } else {
            let start: u64// start offset for section
                = self.sh_offset + idx as u64 * self.sh_entry_size as u64;
            let end: u64 // end offset for section
                = start + self.sh_entry_size as u64;
            let raw
                = &input[start as usize .. end as usize];

            match self.ident.class {
                Class::None => Err("Invalid ELF class (ELFCLASSNONE).")
              , Class::Elf32 => Err("Cannot parse 32-bit section from 64-bit \
                                     ELF file.")
              , Class::Elf64 => unsafe {
                    Ok(&*(raw as *const [u8] as *const u8 as *const Section))
                }
            }
        }
    }

    #[inline] fn get_type(&self) -> Type { self.elftype.as_type() }

    impl_getters! {
        #[doc = "Index for the start of [section header]s. \
                 [section header]: ../section/struct.Header.html"]
        fn sh_offset(&self) -> usize;
        fn sh_entry_size(&self) -> usize;
        fn sh_count(&self) -> usize;

        #[doc = "Index for the start of program headers"]
        fn ph_offset(&self) -> usize;
        fn ph_entry_size(&self) -> usize;
        fn ph_count(&self) -> usize;

        #[doc = "Index for the program entry point"]
        fn entry_point(&self) -> usize;
        #[doc = "Index of the section header [string table] \
                 [string table]: ../section/struct.StrTable.html"]
        fn sh_str_idx(&self) -> usize;
        fn flags(&self) -> u32;
        fn ident(&self) -> Ident;
        fn machine(&self) -> Machine;
    }

}

impl Header for HeaderRepr<u32> {

    type Word = u32;
    /// Attempt to extract an ELF file header from a slice of bytes.
    fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self> {
        if input.len() < mem::size_of::<Self>() {
            Err("Input too short to extract ELF header")
        } else {
            unsafe { Ok(&super::extract_from_slice::<Self>(input, 0, 1)[0]) }
        }
    }

    /// Attempt to extract a section header from a slice of bytes.
    fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>
    {
        if idx < section::SHN_LORESERVE {
            Err("Cannot parse reserved section.")
        } else {
            let start: u32// start offset for section
                = self.sh_offset + idx as u32 * self.sh_entry_size as u32;
            let end: u32 // end offset for section
                = start + self.sh_entry_size as u32;
            let raw
                = &input[start as usize .. end as usize];

            match self.ident.class {
                Class::None => Err("Invalid ELF class (ELFCLASSNONE).")
              , Class::Elf32 => unsafe {
                    Ok(&*(raw as *const [u8] as *const u8 as *const Section))
                }
              , Class::Elf64 => Err("Cannot parse 64-bit section from 32-bit \
                                     ELF file.")
            }
        }
    }

    #[inline] fn get_type(&self) -> Type { self.elftype.as_type() }

    impl_getters! {
        #[doc = "Index for the start of [section header]s. \
                 [section header]: ../section/struct.Header.html"]
        fn sh_offset(&self) -> usize;
        fn sh_entry_size(&self) -> usize;
        fn sh_count(&self) -> usize;

        #[doc = "Index for the start of program headers"]
        fn ph_offset(&self) -> usize;
        fn ph_entry_size(&self) -> usize;
        fn ph_count(&self) -> usize;

        #[doc = "Index for the program entry point"]
        fn entry_point(&self) -> usize;
        #[doc = "Index of the section header [string table] \
                 [string table]: ../section/struct.StrTable.html"]
        fn sh_str_idx(&self) -> usize;
        fn flags(&self) -> u32;
        fn ident(&self) -> Ident;
        fn machine(&self) -> Machine;
    }

}

{'fraction_non_alphanumeric': 0.1560619872379216, 'fraction_numerical': 0.01920388939532057, 'mean_word_length': 1.8436149991359945, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 157, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6461626', 'n_tokens_mistral': 5345, 'n_tokens_neox': 5145, 'n_words': 1573}