use elf-utilities for ELF64

master
Ales Katona 4 years ago
parent 21096384d8
commit 951358daac
Signed by: almindor
GPG Key ID: 2F773149BF38B48F

119
Cargo.lock generated

@ -1,5 +1,32 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # 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]] [[package]]
name = "libc" name = "libc"
version = "0.2.81" version = "0.2.81"
@ -16,14 +43,89 @@ dependencies = [
"winapi", "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]] [[package]]
name = "rld" name = "rld"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"elf-utilities",
"page_size", "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]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@ -45,18 +147,3 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 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"

@ -7,5 +7,5 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
xmas-elf = "0.7.0" elf-utilities = "0.2.8"
page_size = "0.4.2" page_size = "0.4.2"

@ -1,13 +1,13 @@
mod lazy; mod lazy;
mod output;
mod relocatable; mod relocatable;
mod section; mod section;
mod storage; mod storage;
mod symbol; mod symbol;
mod output;
pub use lazy::*; pub use lazy::*;
pub use output::*;
pub use relocatable::*; pub use relocatable::*;
pub use section::*; pub use section::*;
pub use storage::*; pub use storage::*;
pub use symbol::*; pub use symbol::*;
pub use output::*;

@ -1,5 +1,5 @@
use crate::error::Error;
use super::Section; use super::Section;
use crate::error::Error;
pub trait Output { pub trait Output {
fn allocate(&mut self, size: u64) -> Result<u64, Error>; fn allocate(&mut self, size: u64) -> Result<u64, Error>;
@ -21,4 +21,4 @@ impl Output for DummyOutput {
eprintln!("Appending section: {}", section); eprintln!("Appending section: {}", section);
Ok(()) Ok(())
} }
} }

@ -46,10 +46,3 @@ impl Display for Section<'_> {
} }
} }
} }
pub enum SectionIterResult<'data> {
Ok(Section<'data>),
Err(Error),
Skip,
None,
}

@ -7,10 +7,10 @@ use std::{
pub enum Error { pub enum Error {
IOError(std::io::Error), IOError(std::io::Error),
InvalidObjectType(u32), InvalidObjectType(u32),
StringError(&'static str),
MissingSectionHeader(&'static str), MissingSectionHeader(&'static str),
MissingSectionData(&'static str), MissingSectionData(&'static str),
InvalidSectionData, InvalidSectionData,
ParseError(Box<dyn std::error::Error>),
LinkingError(Trace), LinkingError(Trace),
} }

@ -1,14 +1,10 @@
use crate::common::{Lazy, Symbol}; use crate::common::{Lazy, Symbol};
use crate::linker::Linker;
use crate::error::Error; use crate::error::Error;
use xmas_elf::ElfFile; use crate::linker::Linker;
mod object; mod object;
mod section;
mod section_iter;
use section_iter::SectionIter; use elf_utilities::file::ELF64;
pub use object::ElfObject; pub use object::ElfObject;
impl Linker<'_> { impl Linker<'_> {
@ -18,10 +14,9 @@ impl Linker<'_> {
} }
} }
impl<'data> Lazy<&'data str, ElfFile<'data>> for Symbol<'data> { impl<'data> Lazy<&'data str, ELF64> for Symbol<'data> {
fn value(&self, src: &ElfFile<'data>) -> Result<&'data str, Error> { fn value(&self, src: &ELF64) -> Result<&'data str, Error> {
src.get_string(self.index) Err(Error::InvalidSectionData) // TODO
.map_err(|e| Error::StringError(e))
} }
fn resolved(&self) -> bool { fn resolved(&self) -> bool {

@ -3,22 +3,26 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use crate::common::{Relocatable, Storage}; use crate::common::{Relocatable, Section, SectionInfo, Storage};
use crate::{common::BSI, error::Error}; use crate::{common::BSI, error::Error};
use xmas_elf::header::Type as ElfType; use elf_utilities::{file::ELF64, parser::read_elf64};
use xmas_elf::ElfFile;
use super::SectionIter; pub struct ElfObject {
pub struct ElfObject<'data> {
origin: PathBuf, origin: PathBuf,
elf: ElfFile<'data>, elf: ELF64,
} }
impl<'data> ElfObject<'data> { impl ElfObject {
pub fn new(storage: &'data mut Storage) -> Result<Self, Error> { pub fn new(storage: &mut Storage) -> Result<Self, Error> {
let origin = storage.origin()?; 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)?; is_relocatable(&elf)?;
let result = ElfObject { origin, 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 { fn origin(&self) -> &Path {
&self.origin &self.origin
} }
fn sections(&self) -> BSI<'_> { fn sections(&self) -> BSI<'_> {
Box::new(SectionIter { use elf_utilities::section::{Contents64, Type};
elf: &self.elf,
iter: self.elf.section_iter(), 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 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!( write!(
f, f,
@ -58,11 +96,11 @@ impl Display for ElfObject<'_> {
} }
} }
fn is_relocatable(elf: &ElfFile) -> Result<(), Error> { fn is_relocatable(elf: &ELF64) -> Result<(), Error> {
let raw_type = elf.header.pt2.type_(); use elf_utilities::header::Type;
let elf_type: ElfType = raw_type.as_type();
if elf_type != ElfType::Relocatable { if elf.ehdr.get_type() != Type::Rel {
return Err(Error::InvalidObjectType(raw_type.0.into())); return Err(Error::InvalidObjectType(elf.ehdr.e_type.into()));
} }
Ok(()) Ok(())

@ -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<Box<dyn Iterator<Item = u8> + '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<Cloned<std::slice::Iter<'file, u8>>, 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
}
}

@ -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<Section<'data>, Error>;
fn next(&mut self) -> Option<Self::Item> {
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)),
}
}
}

@ -1,6 +1,9 @@
use std::fmt::Display; use std::fmt::Display;
use crate::{common::{Output, Relocatable}, error::Error}; use crate::{
common::{Output, Relocatable},
error::Error,
};
pub struct Linker<'data> { pub struct Linker<'data> {
relocatables: Vec<Box<dyn Relocatable + 'data>>, relocatables: Vec<Box<dyn Relocatable + 'data>>,
@ -8,15 +11,10 @@ pub struct Linker<'data> {
impl<'data> Linker<'data> { impl<'data> Linker<'data> {
pub fn new(relocatables: Vec<Box<dyn Relocatable + 'data>>) -> Self { pub fn new(relocatables: Vec<Box<dyn Relocatable + 'data>>) -> Self {
Self { Self { relocatables }
relocatables,
}
} }
pub fn add_relocatable( pub fn add_relocatable(&mut self, relocatable: Box<dyn Relocatable + 'data>) {
&mut self,
relocatable: Box<dyn Relocatable + 'data>,
) {
self.relocatables.push(relocatable); self.relocatables.push(relocatable);
} }

@ -3,7 +3,7 @@ mod error;
mod formats; mod formats;
mod linker; mod linker;
use common::{Storage, DummyOutput}; use common::{DummyOutput, Storage};
use formats::ElfObject; use formats::ElfObject;
use linker::Linker; use linker::Linker;

Loading…
Cancel
Save