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 output;
mod relocatable;
mod section;
mod symbol;
pub use lazy::*;
pub use loadable::*;
pub use output::*;
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.
#[derive(Default)]
pub struct Loadable {
pub start_offset: Option<u64>,
text: SegmentSections,
rodata: SegmentSections,
data: SegmentSections,
bss: SegmentSections,
pub start_offset: Option<u64>,
}
impl Loadable {

@ -3,7 +3,7 @@ use std::{fmt::Display, path::PathBuf};
use crate::error::Error;
use super::Section;
use super::{Section, Symbol};
#[derive(Clone, Copy)]
// 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
/// mushed and relocated executable from an object file
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 sections(&self) -> BSI;
fn sections(&self) -> SectionIterBox;
fn section_data(&self, section_index: DataIndex) -> Result<&[u8], Error>;
fn symbols(&self) -> SymbolIterBox;
}

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

@ -1,13 +1,11 @@
use std::path::PathBuf;
use crate::common::{Lazy, Symbol};
use crate::error::Error;
use crate::linker::Linker;
mod object;
mod output;
use elf_utilities::file::ELF64;
pub use object::*;
pub use output::*;
@ -17,13 +15,3 @@ impl Linker<ElfObject, ElfOutput> {
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},
};
use crate::common::{DataIndex, Relocatable, Section, SectionInfo};
use crate::{common::BSI, error::Error};
use elf_utilities::{file::ELF64, parser::read_elf64};
use crate::common::{Binding, DataIndex, Relocatable, Section, SectionInfo, Symbol, SymbolIterBox};
use crate::{common::SectionIterBox, error::Error};
use elf_utilities::{
file::ELF64,
parser::read_elf64,
section::{Contents64, Type},
symbol::{Bind, Symbol64},
};
pub struct ElfObject {
object_index: usize,
@ -45,9 +50,7 @@ impl Relocatable for ElfObject {
&self.origin
}
fn sections(&self) -> BSI {
use elf_utilities::section::{Contents64, Type};
fn sections(&self) -> SectionIterBox {
let iter = self
.elf
.sections
@ -95,7 +98,6 @@ impl Relocatable for ElfObject {
}
fn section_data(&self, index: DataIndex) -> Result<&[u8], Error> {
use elf_utilities::section::Contents64;
let section = &self.elf.sections[index.section_index];
match &section.contents {
@ -103,6 +105,39 @@ impl Relocatable for ElfObject {
_ => 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 {
@ -123,13 +158,34 @@ impl Display for ElfObject {
}
}
// impl TryFrom<PathBuf> for ElfObject {
// type Error = Error;
fn make_symbol(s64: &Symbol64, strtab: &Vec<u8>) -> Symbol {
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> {
// Self::new(path)
// }
// }
fn parse_strtab_name(strtab: &Vec<u8>, idx: u32) -> String {
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> {
use elf_utilities::header::Type;

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

Loading…
Cancel
Save