initial commit
commit
0d7f5a3206
@ -0,0 +1,3 @@
|
|||||||
|
/target
|
||||||
|
|
||||||
|
/assets
|
@ -0,0 +1,62 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.81"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "page_size"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rld"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"page_size",
|
||||||
|
"xmas-elf",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
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"
|
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "rld"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Ales Katona <ales@katona.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
xmas-elf = "0.7.0"
|
||||||
|
page_size = "0.4.2"
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,15 @@
|
|||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
IOError(std::io::Error),
|
||||||
|
InvalidObjectType(u32),
|
||||||
|
StringError(&'static str),
|
||||||
|
MissingSectionHeader(&'static str),
|
||||||
|
MissingSectionData(&'static str),
|
||||||
|
InvalidSectionData,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for Error {
|
||||||
|
fn from(err: std::io::Error) -> Self {
|
||||||
|
Self::IOError(err)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
mod elf;
|
||||||
|
|
||||||
|
pub use elf::*;
|
@ -0,0 +1,71 @@
|
|||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
use crate::error::Error;
|
||||||
|
use crate::parts::{Lazy, Relocatable, Symbol, Text};
|
||||||
|
use xmas_elf::header::Type as ElfType;
|
||||||
|
use xmas_elf::sections::*;
|
||||||
|
use xmas_elf::ElfFile;
|
||||||
|
|
||||||
|
impl<'a> Lazy<&'a str, ElfFile<'a>> for Symbol<'a> {
|
||||||
|
fn value(&self, src: &ElfFile<'a>) -> Result<&'a str, Error> {
|
||||||
|
src.get_string(self.index)
|
||||||
|
.map_err(|e| Error::StringError(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolved(&self) -> bool {
|
||||||
|
self.str_ref.is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<SectionData<'a>> for Text<'a> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(data: SectionData<'a>) -> Result<Self, Error> {
|
||||||
|
match data {
|
||||||
|
SectionData::Undefined(bytes) => Ok(Text { bytes }),
|
||||||
|
_ => Err(Error::InvalidSectionData), // TODO: more context needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Relocatable<'a> {
|
||||||
|
pub fn from_elf(origin: &'a str, elf: &'a ElfFile) -> Result<Self, Error> {
|
||||||
|
is_relocatable(elf)?;
|
||||||
|
let mut result = Relocatable::new(origin);
|
||||||
|
|
||||||
|
for header in elf.section_iter() {
|
||||||
|
// .text sections > 0 only
|
||||||
|
if is_text_section(elf, &header)? {
|
||||||
|
let data = header
|
||||||
|
.get_data(&elf)
|
||||||
|
.map_err(|e| Error::MissingSectionData(e))?;
|
||||||
|
|
||||||
|
result.texts.push(Text::try_from(data)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_text_section(elf: &ElfFile, header: &SectionHeader) -> Result<bool, Error> {
|
||||||
|
let name = header.get_name(&elf).unwrap_or("null");
|
||||||
|
let h_type = header
|
||||||
|
.get_type()
|
||||||
|
.map_err(|e| Error::MissingSectionHeader(e))?;
|
||||||
|
|
||||||
|
Ok(h_type == ShType::ProgBits
|
||||||
|
&& header.flags() == (SHF_EXECINSTR | SHF_ALLOC)
|
||||||
|
&& name.starts_with(".text")
|
||||||
|
&& header.size() > 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use crate::error::Error;
|
||||||
|
use crate::parts::Relocatable;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct LinkState<'a> {
|
||||||
|
relocatables: Vec<Relocatable<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LinkState<'a> {
|
||||||
|
pub fn add_relocatable(&mut self, relocatable: Relocatable<'a>) -> Result<(), Error> {
|
||||||
|
self.relocatables.push(relocatable);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LinkState<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
writeln!(f, "===Relocatables===")?;
|
||||||
|
|
||||||
|
for r in self.relocatables.iter() {
|
||||||
|
writeln!(f, "{}", r)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
use std::fs;
|
||||||
|
use xmas_elf::ElfFile;
|
||||||
|
|
||||||
|
mod error;
|
||||||
|
mod formats;
|
||||||
|
mod linker;
|
||||||
|
mod parts;
|
||||||
|
|
||||||
|
use linker::LinkState;
|
||||||
|
use parts::Relocatable;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut args = std::env::args().peekable();
|
||||||
|
|
||||||
|
// can this miss?
|
||||||
|
args.next().unwrap();
|
||||||
|
|
||||||
|
let mut contents: Vec<(String, Vec<u8>)> = Vec::new();
|
||||||
|
let mut parsed: Vec<(&str, ElfFile)> = Vec::new();
|
||||||
|
let mut linker = LinkState::default();
|
||||||
|
|
||||||
|
while args.peek().is_some() {
|
||||||
|
let fpath = args.next().expect("Unexpected peek-a-boo");
|
||||||
|
let raw = fs::read(&fpath).expect("Error reading file");
|
||||||
|
contents.push((fpath, raw));
|
||||||
|
}
|
||||||
|
|
||||||
|
for data in contents.iter() {
|
||||||
|
let elf = ElfFile::new(&data.1).expect("Error parsing ELF file");
|
||||||
|
parsed.push((&data.0, elf));
|
||||||
|
}
|
||||||
|
|
||||||
|
for elf in parsed.iter() {
|
||||||
|
let relocatable = Relocatable::from_elf(elf.0, &elf.1).unwrap();
|
||||||
|
linker.add_relocatable(relocatable).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{}", linker);
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
mod lazy;
|
||||||
|
mod relocatable;
|
||||||
|
mod symbol;
|
||||||
|
mod segments;
|
||||||
|
|
||||||
|
pub use lazy::*;
|
||||||
|
pub use relocatable::*;
|
||||||
|
pub use symbol::*;
|
||||||
|
pub use segments::*;
|
@ -0,0 +1,9 @@
|
|||||||
|
use crate::error::Error;
|
||||||
|
|
||||||
|
pub trait Lazy<VALUE, SOURCE> {
|
||||||
|
/// Resolve VALUE, blocking load from the SOURCE
|
||||||
|
fn value(&self, src: &SOURCE) -> Result<VALUE, Error>;
|
||||||
|
|
||||||
|
/// Check if already resolved
|
||||||
|
fn resolved(&self) -> bool;
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
use crate::parts::{Symbol, Text, Data, Bss};
|
||||||
|
|
||||||
|
/// Contains all the needed references to construct a final
|
||||||
|
/// mushed and relocated executable from an object file
|
||||||
|
pub struct Relocatable<'a> {
|
||||||
|
pub origin: &'a str,
|
||||||
|
pub symbols: Vec<Symbol<'a>>,
|
||||||
|
pub texts: Vec<Text<'a>>,
|
||||||
|
pub data: Vec<Data<'a>>,
|
||||||
|
pub bss: Vec<Bss<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Relocatable<'a> {
|
||||||
|
pub fn new(origin: &'a str) -> Self {
|
||||||
|
Self {
|
||||||
|
origin,
|
||||||
|
symbols: Vec::new(),
|
||||||
|
texts: Vec::new(),
|
||||||
|
data: Vec::new(),
|
||||||
|
bss: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Relocatable<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"==={}===\nSymbols:\n{:?}\nTexts:\n??",
|
||||||
|
self.origin, self.symbols //, self.texts
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
|
||||||
|
pub struct Text<'a> {
|
||||||
|
pub bytes: &'a [u8],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Data<'a> {
|
||||||
|
pub bytes: &'a [u8],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Bss<'a> {
|
||||||
|
pub bytes: &'a [u8],
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Symbol<'a> {
|
||||||
|
pub index: u32,
|
||||||
|
pub str_ref: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Symbol<'_> {
|
||||||
|
pub fn new(index: u32) -> Self {
|
||||||
|
Self {
|
||||||
|
index,
|
||||||
|
str_ref: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue