master
Ales Katona 4 years ago
parent ef7f942349
commit a6eb022b91
Signed by: almindor
GPG Key ID: 2F773149BF38B48F

@ -3,7 +3,7 @@ use std::iter::once;
use crate::error::Error;
use crate::{
common::{Relocatable, Section, SectionInfo, SymbolIndex},
common::{Relocatable, Section, SectionInfo, SymbolIndex, Symbols},
error::LinkError,
};
@ -42,7 +42,7 @@ pub struct Loadable {
rodata: SegmentSections,
data: SegmentSections,
bss: SegmentSections,
symbol_map: HashMap<String, Vec<SymbolIndex>>,
symbol_map: HashMap<String, Symbols>,
}
impl Loadable {
@ -57,29 +57,35 @@ impl Loadable {
Ok(())
}
pub fn process_symbol<R>(&mut self, index: usize, object: &R) -> Result<(), Error>
pub fn process_symbol<R>(&mut self, si: SymbolIndex, objects: &[R]) -> Result<(), Error>
where
R: Relocatable,
{
if !object.symbol_needs_resolving(index) {
let object = objects
.get(si.object_index)
.ok_or(Error::InvalidSectionIndex)?;
if !object.symbol_needs_resolving(si.symbol_index) {
return Ok(()); // local symbols are not stored
}
let name = object.symbol_name(index)?;
eprintln!("NAME: {}", name);
let name = object.symbol_name(si.symbol_index)?;
eprintln!("NAME: {}/{:?}", name, object.symbol_value(si.symbol_index)?);
let si = SymbolIndex {
object_index: object.object_index(),
symbol_index: index,
symbol_index: si.symbol_index,
};
if let Some(existing) = self.symbol_map.get_mut(name) {
existing.push(si);
existing.push(si, objects)
} else {
self.symbol_map.insert(name.to_owned(), vec![si]);
}
let mut symbols = Symbols::default();
symbols.push(si, objects)?;
self.symbol_map.insert(name.to_owned(), symbols);
Ok(())
Ok(())
}
}
pub fn segment_sections(&self) -> impl Iterator<Item = &SegmentSections> {

@ -23,6 +23,10 @@ pub trait Relocatable: Display + Sized {
fn symbol_name(&self, index: usize) -> Result<&str, Error>;
fn symbol_value(&self, index: usize) -> Result<&[u8], Error>;
fn symbol_file_offset(&self, index: usize) -> Result<usize, Error>;
fn symbol_needs_resolving(&self, index: usize) -> bool;
fn bytes(&self, offset: u64, size: u64) -> Result<&[u8], Error>;

@ -1,7 +1,92 @@
use std::fmt::Debug;
#[derive(Default, Debug)]
use crate::error::{Error, LinkError, Trace, LE_GLOBAL_SYMBOL_DUPLICATE};
use super::Relocatable;
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub struct SymbolIndex {
pub object_index: usize,
pub symbol_index: usize,
}
#[derive(Default)]
pub struct Symbols {
indexes: Vec<SymbolIndex>,
value_index: Option<usize>,
}
impl Symbols {
pub fn push<R>(&mut self, si: SymbolIndex, objects: &[R]) -> Result<(), Error>
where
R: Relocatable,
{
let object = objects
.get(si.object_index)
.ok_or(Error::InvalidSymbolIndex)?;
let value = object.symbol_value(si.symbol_index)?;
self.indexes.push(si);
if value.len() > 0 {
if let Some(existing) = self.value_index {
let osi = self
.indexes
.get(existing)
.ok_or(Error::InvalidSymbolIndex)?;
Self::duplicate_symbol_error(si, *osi, objects)
} else {
self.value_index = Some(self.indexes.len() - 1);
Ok(())
}
} else {
Ok(())
}
}
pub fn value<'o, R>(&self, object: &'o R) -> Result<&'o [u8], Error>
where
R: Relocatable,
{
self.value_index.map_or(Ok(&[]), |v| {
object.symbol_value(self.indexes[v].symbol_index)
})
}
fn duplicate_symbol_error<R>(
si: SymbolIndex,
osi: SymbolIndex,
objects: &[R],
) -> Result<(), Error>
where
R: Relocatable,
{
let object = objects
.get(si.object_index)
.ok_or(Error::InvalidSymbolIndex)?;
let other = objects
.get(osi.object_index)
.ok_or(Error::InvalidObjectIndex)?;
let mut traces = Vec::new();
traces.push(Trace {
origin: object.origin().into(),
offset: object.symbol_file_offset(si.symbol_index)?,
source_info: None,
});
traces.push(Trace {
origin: other.origin().into(),
offset: other.symbol_file_offset(osi.symbol_index)?,
source_info: None,
});
let link_error = LinkError {
code: LE_GLOBAL_SYMBOL_DUPLICATE,
message: "duplicate global symbol found".into(),
traces,
};
Err(Error::LinkingError(link_error))
}
}

@ -9,7 +9,9 @@ pub const LE_GLOBAL_SYMBOL_DUPLICATE: u32 = 10001;
pub enum Error {
IOError(Box<dyn std::error::Error>),
DataError(PathBuf), // generic "something wrong with data" error, not specific to parsing
InvalidObjectIndex,
InvalidObjectType(u32),
InvalidSectionIndex,
InvalidSectionName,
InvalidSymbolIndex,
InvalidSymbolName,
@ -23,7 +25,7 @@ pub enum Error {
#[derive(Debug, Default)]
pub struct Trace {
pub origin: PathBuf,
pub offset: u64, // 0 indicates unknown/invalid
pub offset: usize, // 0 indicates unknown/invalid
pub source_info: Option<Box<dyn SourceInfo>>,
}
@ -41,11 +43,13 @@ impl Error {
match self {
Error::IOError(_) => 100,
Error::DataError(_) => 800,
Error::InvalidObjectType(_) => 200,
Error::InvalidSectionName => 300,
Error::InvalidSymbolIndex => 325,
Error::InvalidSymbolName => 350,
Error::InvalidSectionData => 400,
Error::InvalidObjectIndex => 200,
Error::InvalidObjectType(_) => 201,
Error::InvalidSectionIndex => 300,
Error::InvalidSectionName => 301,
Error::InvalidSectionData => 302,
Error::InvalidSymbolIndex => 400,
Error::InvalidSymbolName => 401,
Error::ParseError(_) => 500,
Error::TryFromIntError => 600,
Error::InvalidInput => 700,
@ -79,11 +83,13 @@ impl Display for Error {
match self {
Error::IOError(err) => write!(f, "IO error: {}", err),
Error::DataError(origin) => write!(f, "Data error in {:?}", origin),
Error::InvalidObjectIndex => write!(f, "Invalid section index"),
Error::InvalidObjectType(ot) => write!(f, "Invalid object type: {}", ot),
Error::InvalidSectionIndex => write!(f, "Invalid section index"),
Error::InvalidSectionName => write!(f, "Invalid section name"),
Error::InvalidSectionData => write!(f, "Invalid section data"),
Error::InvalidSymbolIndex => write!(f, "Invalid symbol index"),
Error::InvalidSymbolName => write!(f, "Invalid symbol name"),
Error::InvalidSectionData => write!(f, "Invalid section data"),
Error::ParseError(err) => write!(f, "Parse error: {}", err),
Error::TryFromIntError => write!(f, "Integer conversion error"),
Error::InvalidInput => write!(f, "Input object invalid"),

@ -48,6 +48,23 @@ impl ElfObject {
Ok(result)
}
fn resolve_symbol_value(&self, symbol_index: usize) -> Result<&[u8], Error> {
if let Some((_, s64)) = self.symbols.get(symbol_index) {
if s64.st_size == 0 {
Ok(&[])
} else if let Some(shdr) = self.shdrs.get(s64.st_shndx as usize) {
let start: usize = (shdr.sh_offset + s64.st_value) as usize;
let end: usize = start + s64.st_size as usize;
Ok(&self.data[start..end])
} else {
Err(Error::InvalidSectionIndex)
}
} else {
Err(Error::InvalidSymbolIndex)
}
}
fn resolve_name(&self, name_idx: usize, sh_index: usize) -> Result<&str, Error> {
if name_idx == 0 {
let error = if sh_index == self.ehdr.e_shstrndx.into() {
@ -194,6 +211,22 @@ impl Relocatable for ElfObject {
}
}
fn symbol_value(&self, index: usize) -> Result<&[u8], Error> {
self.resolve_symbol_value(index)
}
fn symbol_file_offset(&self, index: usize) -> Result<usize, Error> {
let (sh_index, s64) = self.symbols.get(index).ok_or(Error::InvalidSymbolIndex)?;
let shdr = self
.shdrs
.get(*sh_index)
.ok_or(Error::InvalidSectionIndex)?;
let sh_offset: usize = shdr.sh_offset as usize;
Ok(sh_offset)
}
fn symbol_needs_resolving(&self, index: usize) -> bool {
match self.symbols[index].1.get_bind() {
Bind::Global | Bind::Weak => true,

@ -10,7 +10,7 @@ where
R: Relocatable,
O: Output<R>,
{
relocatables: Vec<R>,
objects: Vec<R>,
loadable: Loadable,
output: O,
}
@ -22,21 +22,21 @@ where
{
pub fn new(output: O) -> Self {
Self {
relocatables: Vec::new(),
objects: Vec::new(),
loadable: Loadable::default(),
output,
}
}
pub fn add_relocatable(&mut self, origin: PathBuf) -> Result<(), Error> {
let r = R::new(origin, self.relocatables.len())?;
let r = R::new(origin, self.objects.len())?;
// TODO: parallelize?
for section in r.sections() {
self.loadable.process_section(section?)?;
}
self.relocatables.push(r);
self.objects.push(r);
Ok(())
}
@ -45,15 +45,19 @@ where
self.process_symbols()?;
self.loadable.set_start_offset(4096); // TODO: get from .start symbol location
self.output.finalize(&self.relocatables, &self.loadable)
self.output.finalize(&self.objects, &self.loadable)
}
fn process_symbols(&mut self) -> Result<(), Error> {
for r in &self.relocatables {
for r in &self.objects {
let symbol_count = r.symbol_count();
for i in 0..symbol_count {
self.loadable.process_symbol(i, r)?;
let si = SymbolIndex {
object_index: r.object_index(),
symbol_index: i,
};
self.loadable.process_symbol(si, &self.objects)?;
}
}
@ -69,7 +73,7 @@ where
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "===Relocatables===")?;
for r in self.relocatables.iter() {
for r in self.objects.iter() {
write!(f, "{}", r)?;
}

Loading…
Cancel
Save