diff --git a/Cargo.lock b/Cargo.lock index 7d8745d..9fc70ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,32 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "bincode" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" +dependencies = [ + "byteorder", + "serde", +] + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "elf-utilities" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54d8c636efdbcd4303b00c23f8fad4e93b1ca8607687fbe9a8a660eef7ba2dc1" +dependencies = [ + "bincode", + "serde", + "thiserror", +] + [[package]] name = "libc" version = "0.2.81" @@ -16,14 +43,89 @@ dependencies = [ "winapi", ] +[[package]] +name = "proc-macro2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rld" version = "0.1.0" dependencies = [ + "elf-utilities", "page_size", - "xmas-elf", ] +[[package]] +name = "serde" +version = "1.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "thiserror" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + [[package]] name = "winapi" version = "0.3.9" @@ -45,18 +147,3 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "xmas-elf" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74de9a366f6ab8c405fa6b371d9ac24943921fa14b3d64afcb202065c405f11" -dependencies = [ - "zero", -] - -[[package]] -name = "zero" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5" diff --git a/Cargo.toml b/Cargo.toml index 50686f2..1816eee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,5 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -xmas-elf = "0.7.0" +elf-utilities = "0.2.8" page_size = "0.4.2" \ No newline at end of file diff --git a/src/common.rs b/src/common.rs index 0cba7ca..143634f 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,13 +1,13 @@ mod lazy; +mod output; mod relocatable; mod section; mod storage; mod symbol; -mod output; pub use lazy::*; +pub use output::*; pub use relocatable::*; pub use section::*; pub use storage::*; pub use symbol::*; -pub use output::*; \ No newline at end of file diff --git a/src/common/output.rs b/src/common/output.rs index 0be740a..d92c4a9 100644 --- a/src/common/output.rs +++ b/src/common/output.rs @@ -1,5 +1,5 @@ -use crate::error::Error; use super::Section; +use crate::error::Error; pub trait Output { fn allocate(&mut self, size: u64) -> Result; @@ -21,4 +21,4 @@ impl Output for DummyOutput { eprintln!("Appending section: {}", section); Ok(()) } -} \ No newline at end of file +} diff --git a/src/common/section.rs b/src/common/section.rs index 365d1f2..be1ca33 100644 --- a/src/common/section.rs +++ b/src/common/section.rs @@ -46,10 +46,3 @@ impl Display for Section<'_> { } } } - -pub enum SectionIterResult<'data> { - Ok(Section<'data>), - Err(Error), - Skip, - None, -} diff --git a/src/error.rs b/src/error.rs index fc13a63..dbb422e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,10 +7,10 @@ use std::{ pub enum Error { IOError(std::io::Error), InvalidObjectType(u32), - StringError(&'static str), MissingSectionHeader(&'static str), MissingSectionData(&'static str), InvalidSectionData, + ParseError(Box), LinkingError(Trace), } diff --git a/src/formats/elf.rs b/src/formats/elf.rs index 6f46303..2ebf472 100644 --- a/src/formats/elf.rs +++ b/src/formats/elf.rs @@ -1,14 +1,10 @@ - use crate::common::{Lazy, Symbol}; -use crate::linker::Linker; use crate::error::Error; -use xmas_elf::ElfFile; +use crate::linker::Linker; mod object; -mod section; -mod section_iter; -use section_iter::SectionIter; +use elf_utilities::file::ELF64; pub use object::ElfObject; impl Linker<'_> { @@ -18,10 +14,9 @@ impl Linker<'_> { } } -impl<'data> Lazy<&'data str, ElfFile<'data>> for Symbol<'data> { - fn value(&self, src: &ElfFile<'data>) -> Result<&'data str, Error> { - src.get_string(self.index) - .map_err(|e| Error::StringError(e)) +impl<'data> Lazy<&'data str, ELF64> for Symbol<'data> { + fn value(&self, src: &ELF64) -> Result<&'data str, Error> { + Err(Error::InvalidSectionData) // TODO } fn resolved(&self) -> bool { diff --git a/src/formats/elf/object.rs b/src/formats/elf/object.rs index f88aada..fadc500 100644 --- a/src/formats/elf/object.rs +++ b/src/formats/elf/object.rs @@ -3,22 +3,26 @@ use std::{ path::{Path, PathBuf}, }; -use crate::common::{Relocatable, Storage}; +use crate::common::{Relocatable, Section, SectionInfo, Storage}; use crate::{common::BSI, error::Error}; -use xmas_elf::header::Type as ElfType; -use xmas_elf::ElfFile; +use elf_utilities::{file::ELF64, parser::read_elf64}; -use super::SectionIter; - -pub struct ElfObject<'data> { +pub struct ElfObject { origin: PathBuf, - elf: ElfFile<'data>, + elf: ELF64, } -impl<'data> ElfObject<'data> { - pub fn new(storage: &'data mut Storage) -> Result { +impl ElfObject { + pub fn new(storage: &mut Storage) -> Result { let origin = storage.origin()?; - let elf = ElfFile::new(storage.bytes()?).map_err(|_| Error::InvalidObjectType(0))?; + let str_origin = origin + .as_path() + .to_str() + .ok_or(Error::InvalidObjectType(404))?; + let elf = match read_elf64(str_origin) { + Ok(val) => val, + Err(err) => return Err(Error::ParseError(err)), + }; is_relocatable(&elf)?; let result = ElfObject { origin, elf }; @@ -27,20 +31,54 @@ impl<'data> ElfObject<'data> { } } -impl Relocatable for ElfObject<'_> { +impl Relocatable for ElfObject { fn origin(&self) -> &Path { &self.origin } fn sections(&self) -> BSI<'_> { - Box::new(SectionIter { - elf: &self.elf, - iter: self.elf.section_iter(), - }) + use elf_utilities::section::{Contents64, Type}; + + let iter = self + .elf + .sections + .iter() + .filter_map(|s| match s.header.get_type() { + Type::ProgBits => { + if s.header.sh_size > 0 + && (s.name.starts_with(".text") + || s.name.starts_with(".rodata") + || s.name.starts_with(".data")) + { + if let Some(di) = match &s.contents { + Contents64::Raw(v) => Some(v.iter()), + _ => None, + } { + Some(Ok(Section::Text(SectionInfo { + size: s.header.sh_size, + data: Some(Box::new(di.copied())), + offset: s.header.sh_offset, + }))) + } else { + Some(Err(Error::InvalidSectionData)) + } + } else { + None + } + } + Type::NoBits => Some(Ok(Section::Bss(SectionInfo { + size: 0, + data: None, + offset: s.header.sh_offset, + }))), + _ => None, + }); + + Box::new(iter) } } -impl Display for ElfObject<'_> { +impl Display for ElfObject { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, @@ -58,11 +96,11 @@ impl Display for ElfObject<'_> { } } -fn is_relocatable(elf: &ElfFile) -> Result<(), Error> { - let raw_type = elf.header.pt2.type_(); - let elf_type: ElfType = raw_type.as_type(); - if elf_type != ElfType::Relocatable { - return Err(Error::InvalidObjectType(raw_type.0.into())); +fn is_relocatable(elf: &ELF64) -> Result<(), Error> { + use elf_utilities::header::Type; + + if elf.ehdr.get_type() != Type::Rel { + return Err(Error::InvalidObjectType(elf.ehdr.e_type.into())); } Ok(()) diff --git a/src/formats/elf/section.rs b/src/formats/elf/section.rs deleted file mode 100644 index 174b984..0000000 --- a/src/formats/elf/section.rs +++ /dev/null @@ -1,110 +0,0 @@ -use std::iter::Cloned; - -use crate::{ - common::{Section, SectionInfo, SectionIterResult}, - error::Error, -}; -use xmas_elf::{ - sections::{SectionData, SectionHeader, SectionIter as ElfIter, ShType}, - ElfFile, -}; - -impl<'data> Section<'data> { - pub fn iterate( - elf: &'data ElfFile<'data>, - iter: &mut ElfIter<'data, 'data>, - ) -> SectionIterResult<'data> { - if let Some(h) = iter.next() { - let h_result = h.get_type().map_err(|e| Error::MissingSectionHeader(e)); - return match h_result { - Ok(h_type) => match h_type { - // text, [ro]data - ShType::ProgBits => { - let s_name = h.get_name(&elf).unwrap_or("null"); - match section_data_to_iterator(elf, h) { - Ok(i) => Section::from_name(s_name, &h, Some(Box::new(i))), - Err(err) => SectionIterResult::Err(err), - } - } - // bss - ShType::NoBits => { - let si = SectionInfo { - size: h.size(), - data: None, - offset: h.offset(), - }; - let s = Section::Bss(si); - SectionIterResult::Ok(s) - } - _ => SectionIterResult::Skip, - }, - Err(err) => SectionIterResult::Err(err), - }; - } - - SectionIterResult::None - } - - fn from_name( - name: &str, - header: &SectionHeader, - data: Option + 'data>>, - ) -> SectionIterResult<'data> { - if name.starts_with(".text") { - if header.size() == 0 { - return SectionIterResult::Skip; // empty texts - } - let iter = match data { - Some(i) => i, - None => return SectionIterResult::Err(Error::MissingSectionData(".text")), - }; - let si = SectionInfo { - size: header.size(), - data: Some(iter), - offset: header.offset(), - }; - return SectionIterResult::Ok(Section::Text(si)); - } else if name.starts_with(".rodata") || name.starts_with(".data") { - if header.size() == 0 { - return SectionIterResult::Skip; // empty data - } - let iter = match data { - Some(i) => i, - None => return SectionIterResult::Err(Error::MissingSectionData(".data")), - }; - let si = SectionInfo { - size: header.size(), - data: Some(iter), - offset: header.offset(), - }; - return SectionIterResult::Ok(Section::Data(si)); - } else if name.starts_with(".bss") { - let si = SectionInfo { - size: header.size(), - data: None, - offset: header.offset(), - }; - return SectionIterResult::Ok(Section::Bss(si)); - } - - SectionIterResult::Skip - } -} - -fn section_data_to_iterator<'file>( - elf: &'file ElfFile, - header: SectionHeader<'file>, -) -> Result>, Error> { - let data = header - .get_data(&elf) - .map_err(|e| Error::MissingSectionData(e))?; - - match data { - SectionData::Empty => Ok(([]).iter().cloned()), - SectionData::Undefined(bytes) => { - let iter = bytes.iter().cloned(); - Ok(iter) - } - _ => Err(Error::InvalidSectionData), // TODO: more context needed - } -} diff --git a/src/formats/elf/section_iter.rs b/src/formats/elf/section_iter.rs deleted file mode 100644 index 8b00325..0000000 --- a/src/formats/elf/section_iter.rs +++ /dev/null @@ -1,24 +0,0 @@ -use crate::{ - common::{Section, SectionIterResult}, - error::Error, -}; -use xmas_elf::sections::SectionIter as ElfIter; -use xmas_elf::ElfFile; - -pub struct SectionIter<'data> { - pub elf: &'data ElfFile<'data>, - pub iter: ElfIter<'data, 'data>, -} - -impl<'data> Iterator for SectionIter<'data> { - type Item = Result, Error>; - - fn next(&mut self) -> Option { - match Section::iterate(&self.elf, &mut self.iter) { - SectionIterResult::Err(err) => Some(Err(err)), - SectionIterResult::None => None, - SectionIterResult::Skip => self.next(), - SectionIterResult::Ok(r) => Some(Ok(r)), - } - } -} diff --git a/src/linker.rs b/src/linker.rs index bac47e7..aa5a5cb 100644 --- a/src/linker.rs +++ b/src/linker.rs @@ -1,6 +1,9 @@ use std::fmt::Display; -use crate::{common::{Output, Relocatable}, error::Error}; +use crate::{ + common::{Output, Relocatable}, + error::Error, +}; pub struct Linker<'data> { relocatables: Vec>, @@ -8,15 +11,10 @@ pub struct Linker<'data> { impl<'data> Linker<'data> { pub fn new(relocatables: Vec>) -> Self { - Self { - relocatables, - } + Self { relocatables } } - pub fn add_relocatable( - &mut self, - relocatable: Box, - ) { + pub fn add_relocatable(&mut self, relocatable: Box) { self.relocatables.push(relocatable); } diff --git a/src/main.rs b/src/main.rs index 0c6e762..df03c31 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ mod error; mod formats; mod linker; -use common::{Storage, DummyOutput}; +use common::{DummyOutput, Storage}; use formats::ElfObject; use linker::Linker;