elfkit 0.0.7

an elf parser and manipulation library in pure rust
Documentation
use std::io::{Read, Write};
use {Error, Header, SectionContent};
use types;
use num_traits::{FromPrimitive, ToPrimitive};

#[derive(Debug, Clone)]
pub enum DynamicContent {
    None,
    String((Vec<u8>,Option<u64>)),
    Address(u64),
    Flags1(types::DynamicFlags1),
}

impl Default for DynamicContent{
    fn default() -> Self {
        DynamicContent::None
    }
}

#[derive(Debug, Clone, Default)]
pub struct Dynamic {
    pub dhtype: types::DynamicType,
    pub content: DynamicContent,
}

impl Dynamic {
    pub fn entsize(eh: &Header) -> usize {
        match eh.ident_class {
            types::Class::Class64 => 16,
            types::Class::Class32 => 8,
        }
    }

    pub fn from_reader<R>(
        mut io: R,
        linked: Option<&SectionContent>,
        eh: &Header,
    ) -> Result<SectionContent, Error>
    where
        R: Read,
    {
        let strtab = match linked {
            None => None,
            Some(&SectionContent::Strtab(ref s)) => Some(s),
            any => return Err(Error::LinkedSectionIsNotStrtab{
                during: "reading dynamic",
                link: any.map(|v|v.clone()),
            }),
        };

        let mut r = Vec::new();

        while let Ok(tag) = elf_read_uclass!(eh, io) {
            let val = elf_read_uclass!(eh, io)?;

            match types::DynamicType::from_u64(tag) {
                None => return Err(Error::InvalidDynamicType(tag)),
                Some(types::DynamicType::NULL) => {
                    r.push(Dynamic {
                        dhtype: types::DynamicType::NULL,
                        content: DynamicContent::None,
                    });
                    break;
                },
                Some(types::DynamicType::RPATH) => {
                    r.push(Dynamic {
                        dhtype: types::DynamicType::RPATH,
                        content: DynamicContent::String(match strtab {
                            None => (Vec::default(),None),
                            Some(s) => (s.get(val as usize), Some(val)),
                        }),
                    });
                },
                Some(types::DynamicType::NEEDED) => {
                    r.push(Dynamic {
                        dhtype: types::DynamicType::NEEDED,
                        content: DynamicContent::String(match strtab {
                            None => (Vec::default(),None),
                            Some(s) => (s.get(val as usize), Some(val)),
                        }),
                    });
                },
                Some(types::DynamicType::FLAGS_1) => {
                    r.push(Dynamic {
                        dhtype: types::DynamicType::FLAGS_1,
                        content: DynamicContent::Flags1(
                            match types::DynamicFlags1::from_bits(val) {
                                Some(v) => v,
                                None => return Err(Error::InvalidDynamicFlags1(val)),
                            },
                        ),
                    });
                },
                Some(x) => {
                    r.push(Dynamic {
                        dhtype: x,
                        content: DynamicContent::Address(val),
                    });
                }
            };
        }

        Ok(SectionContent::Dynamic(r))
    }
    pub fn to_writer<W>(
        &self,
        mut io: W,
        eh: &Header,
    ) -> Result<(usize), Error>
    where
        W: Write,
    {
        elf_write_uclass!(eh, io, self.dhtype.to_u64().unwrap())?;

        match self.content {
            DynamicContent::None => {
                elf_write_uclass!(eh, io, 0)?;
            }
            DynamicContent::String(ref s) => match s.1 {
                Some(val) => elf_write_uclass!(eh, io, val)?,
                None      => return Err(Error::WritingNotSynced),
            },
            DynamicContent::Address(ref v) => {
                elf_write_uclass!(eh, io, *v)?;
            }
            DynamicContent::Flags1(ref v) => {
                elf_write_uclass!(eh, io, v.bits())?;
            }
        }
        Ok(Dynamic::entsize(eh))
    }

    pub fn sync(&mut self, linked: Option<&mut SectionContent>, _: &Header) -> Result<(), Error> {
        match self.content {
            DynamicContent::String(ref mut s) => match linked {
                Some(&mut SectionContent::Strtab(ref mut strtab)) => {
                    s.1 = Some(strtab.insert(&s.0) as u64);
                }
                any => return Err(Error::LinkedSectionIsNotStrtab{
                    during: "syncing dynamic",
                    link: any.map(|v|v.clone()),
                }),
            },
            DynamicContent::None => {}
            DynamicContent::Address(_) => {}
            DynamicContent::Flags1(_) => {}
        }
        Ok(())
    }
}