add symbols

master
Ales Katona 4 years ago
parent 9c4765ca95
commit 2183422e3d
Signed by: almindor
GPG Key ID: 2F773149BF38B48F

@ -1,11 +1,9 @@
mod lazy;
mod loadable; mod loadable;
mod output; mod output;
mod relocatable; mod relocatable;
mod section; mod section;
mod symbol; mod symbol;
pub use lazy::*;
pub use loadable::*; pub use loadable::*;
pub use output::*; pub use output::*;
pub use relocatable::*; pub use relocatable::*;

@ -1,8 +0,0 @@
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;
}

@ -34,11 +34,12 @@ impl SegmentSections {
// TODO: use attributes for field section names, indexes etc. // TODO: use attributes for field section names, indexes etc.
#[derive(Default)] #[derive(Default)]
pub struct Loadable { pub struct Loadable {
pub start_offset: Option<u64>,
text: SegmentSections, text: SegmentSections,
rodata: SegmentSections, rodata: SegmentSections,
data: SegmentSections, data: SegmentSections,
bss: SegmentSections, bss: SegmentSections,
pub start_offset: Option<u64>,
} }
impl Loadable { impl Loadable {

@ -3,7 +3,7 @@ use std::{fmt::Display, path::PathBuf};
use crate::error::Error; use crate::error::Error;
use super::Section; use super::{Section, Symbol};
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
// index into section of given object stored in the linker // index into section of given object stored in the linker
@ -28,7 +28,10 @@ impl DataIndex {
} }
} }
pub type BSI<'iter> = Box<dyn Iterator<Item = Result<Section, Error>> + 'iter>; pub type SectionIterBox<'iter> = Box<dyn Iterator<Item = Result<Section, Error>> + 'iter>;
pub type SymbolIterBox<'iter> = Box<dyn Iterator<Item = Symbol> + 'iter>;
/// Contains all the needed getters to construct a final /// Contains all the needed getters to construct a final
/// mushed and relocated executable from an object file /// mushed and relocated executable from an object file
pub trait Relocatable: Display + Sized { pub trait Relocatable: Display + Sized {
@ -37,7 +40,9 @@ pub trait Relocatable: Display + Sized {
fn origin(&self) -> &Path; // not same as section's path since this one's supposed to be cannonical fn origin(&self) -> &Path; // not same as section's path since this one's supposed to be cannonical
fn sections(&self) -> BSI; fn sections(&self) -> SectionIterBox;
fn section_data(&self, section_index: DataIndex) -> Result<&[u8], Error>; fn section_data(&self, section_index: DataIndex) -> Result<&[u8], Error>;
fn symbols(&self) -> SymbolIterBox;
} }

@ -1,14 +1,13 @@
#[derive(Debug, Default)] #[derive(Clone, Copy)]
pub struct Symbol<'a> { pub enum Binding {
pub index: u32, Local,
pub str_ref: Option<&'a str>, Global,
Weak,
} }
impl Symbol<'_> { pub struct Symbol {
pub fn new(index: u32) -> Self { pub name: String,
Self { pub binding: Binding,
index, pub address: u64,
str_ref: None, pub size: u64,
}
}
} }

@ -1,13 +1,11 @@
use std::path::PathBuf; use std::path::PathBuf;
use crate::common::{Lazy, Symbol};
use crate::error::Error; use crate::error::Error;
use crate::linker::Linker; use crate::linker::Linker;
mod object; mod object;
mod output; mod output;
use elf_utilities::file::ELF64;
pub use object::*; pub use object::*;
pub use output::*; pub use output::*;
@ -17,13 +15,3 @@ impl Linker<ElfObject, ElfOutput> {
Ok(Self::new(ElfOutput::new(destination)?)) Ok(Self::new(ElfOutput::new(destination)?))
} }
} }
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 {
self.str_ref.is_some()
}
}

@ -4,9 +4,14 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use crate::common::{DataIndex, Relocatable, Section, SectionInfo}; use crate::common::{Binding, DataIndex, Relocatable, Section, SectionInfo, Symbol, SymbolIterBox};
use crate::{common::BSI, error::Error}; use crate::{common::SectionIterBox, error::Error};
use elf_utilities::{file::ELF64, parser::read_elf64}; use elf_utilities::{
file::ELF64,
parser::read_elf64,
section::{Contents64, Type},
symbol::{Bind, Symbol64},
};
pub struct ElfObject { pub struct ElfObject {
object_index: usize, object_index: usize,
@ -45,9 +50,7 @@ impl Relocatable for ElfObject {
&self.origin &self.origin
} }
fn sections(&self) -> BSI { fn sections(&self) -> SectionIterBox {
use elf_utilities::section::{Contents64, Type};
let iter = self let iter = self
.elf .elf
.sections .sections
@ -95,7 +98,6 @@ impl Relocatable for ElfObject {
} }
fn section_data(&self, index: DataIndex) -> Result<&[u8], Error> { fn section_data(&self, index: DataIndex) -> Result<&[u8], Error> {
use elf_utilities::section::Contents64;
let section = &self.elf.sections[index.section_index]; let section = &self.elf.sections[index.section_index];
match &section.contents { match &section.contents {
@ -103,6 +105,39 @@ impl Relocatable for ElfObject {
_ => Err(Error::InvalidSectionData), _ => Err(Error::InvalidSectionData),
} }
} }
fn symbols(&self) -> SymbolIterBox {
if let Some(strtab_section) = self
.elf
.first_section_by(|s64| s64.header.get_type() == Type::StrTab && s64.name == ".strtab")
{
let strtab = match &strtab_section.contents {
Contents64::Raw(bytes) => bytes,
_ => panic!("Unexpected strtab content type"),
};
let iter = self
.elf
.sections
.iter()
.filter_map(move |s| match &s.contents {
Contents64::Symbols(symbols) => {
Some(symbols.iter().filter_map(move |sym| match sym.get_bind() {
Bind::Global | Bind::Local | Bind::Weak => {
Some(make_symbol(sym, strtab))
}
_ => None,
}))
}
_ => None,
})
.flatten();
Box::new(iter)
} else {
Box::new(std::iter::empty())
}
}
} }
impl Display for ElfObject { impl Display for ElfObject {
@ -123,13 +158,34 @@ impl Display for ElfObject {
} }
} }
// impl TryFrom<PathBuf> for ElfObject { fn make_symbol(s64: &Symbol64, strtab: &Vec<u8>) -> Symbol {
// type Error = Error; let binding = match s64.get_bind() {
Bind::Global => Binding::Global,
Bind::Local => Binding::Local,
Bind::Weak => Binding::Weak,
_ => panic!("Unexpected binding type encountered on symbol"), // this is screened!
};
Symbol {
name: parse_strtab_name(&strtab, s64.st_name),
binding,
address: s64.st_value,
size: s64.st_size,
}
}
// fn try_from(path: PathBuf) -> Result<Self, Self::Error> { fn parse_strtab_name(strtab: &Vec<u8>, idx: u32) -> String {
// Self::new(path) let bytes: Vec<u8> = strtab
// } .iter()
// } .skip(idx as usize)
.take_while(|byte| **byte != 0x00)
.copied()
.collect();
std::str::from_utf8(&bytes)
.expect("Symbol name parse")
.to_string()
}
fn is_relocatable(elf: &ELF64) -> Result<(), Error> { fn is_relocatable(elf: &ELF64) -> Result<(), Error> {
use elf_utilities::header::Type; use elf_utilities::header::Type;

@ -1,8 +1,4 @@
use std::{ use std::{fmt::Display, path::PathBuf};
fmt::Display,
io::ErrorKind,
path::{Path, PathBuf},
};
use crate::{ use crate::{
common::{DataIndex, Loadable, Output, Relocatable}, common::{DataIndex, Loadable, Output, Relocatable},
@ -33,35 +29,33 @@ where
} }
pub fn add_relocatable(&mut self, origin: PathBuf) -> Result<(), Error> { pub fn add_relocatable(&mut self, origin: PathBuf) -> Result<(), Error> {
self.relocatables.push(R::new( let r = R::new(origin, DataIndex::for_object(self.relocatables.len()))?;
origin,
DataIndex::for_object(self.relocatables.len()), // TODO: parallelize?
)?); for s in r.sections() {
self.loadable.process_section(s?)?;
}
self.relocatables.push(r);
Ok(()) Ok(())
} }
pub fn link(mut self) -> Result<PathBuf, Error> { pub fn link(mut self) -> Result<PathBuf, Error> {
for r in self.relocatables.iter() {
for s in r.sections() {
self.loadable.process_section(s?)?;
}
}
self.loadable.start_offset = Some(4096); // TODO: get from .start symbol location self.loadable.start_offset = Some(4096); // TODO: get from .start symbol location
self.output.finalize(&self.relocatables, &self.loadable) self.output.finalize(&self.relocatables, &self.loadable)
} }
pub fn object_path(origin: &Path) -> Result<PathBuf, Error> { // pub fn object_path(origin: &Path) -> Result<PathBuf, Error> {
let mut dest = std::fs::canonicalize(origin)?; // let mut dest = std::fs::canonicalize(origin)?;
if !dest.pop() { // if !dest.pop() {
let err = std::io::Error::new(ErrorKind::Other, "Destination path invalid"); // let err = std::io::Error::new(ErrorKind::Other, "Destination path invalid");
Err(Error::IOError(Box::new(err))) // Err(Error::IOError(Box::new(err)))
} else { // } else {
dest.push("rld.out"); // dest.push("rld.out");
Ok(dest) // Ok(dest)
} // }
} // }
} }
impl<R, O> Display for Linker<R, O> impl<R, O> Display for Linker<R, O>

Loading…
Cancel
Save