add xmas-elf support together with elf-utils
							parent
							
								
									951358daac
								
							
						
					
					
						commit
						0e1c83bbed
					
				| @ -1,3 +1,5 @@ | ||||
| mod elf; | ||||
| mod xelf; | ||||
| 
 | ||||
| pub use elf::*; | ||||
| pub use xelf::*; | ||||
|  | ||||
| @ -0,0 +1,26 @@ | ||||
| use crate::common::{Lazy, Symbol}; | ||||
| use crate::error::Error; | ||||
| use crate::linker::Linker; | ||||
| use xmas_elf::ElfFile; | ||||
| 
 | ||||
| mod object; | ||||
| 
 | ||||
| pub use object::XElfObject; | ||||
| 
 | ||||
| impl Linker<'_> { | ||||
|     // shortcut to avoid turbofish
 | ||||
|     pub fn xelf() -> Self { | ||||
|         Self::new(Vec::new()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<'data> Lazy<&'data str, ElfFile<'data>> for Symbol<'data> { | ||||
|     fn value(&self, src: &ElfFile<'data>) -> Result<&'data str, Error> { | ||||
|         src.get_string(self.index) | ||||
|             .map_err(|e| Error::MissingSectionData(e)) | ||||
|     } | ||||
| 
 | ||||
|     fn resolved(&self) -> bool { | ||||
|         self.str_ref.is_some() | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,113 @@ | ||||
| use std::{ | ||||
|     convert::TryFrom, | ||||
|     fmt::Display, | ||||
|     path::{Path, PathBuf}, | ||||
| }; | ||||
| 
 | ||||
| use crate::common::{Relocatable, Section, SectionInfo, Storage}; | ||||
| use crate::{common::BSI, error::Error}; | ||||
| use xmas_elf::{ElfFile, sections::{SectionData, SectionHeader}}; | ||||
| use xmas_elf::{header::Type as ElfType, sections::ShType}; | ||||
| 
 | ||||
| pub struct XElfObject<'data> { | ||||
|     origin: PathBuf, | ||||
|     elf: ElfFile<'data>, | ||||
| } | ||||
| 
 | ||||
| impl<'data> XElfObject<'data> { | ||||
|     pub fn new(storage: &'data mut Storage) -> Result<Self, Error> { | ||||
|         let origin = storage.origin()?; | ||||
|         let elf = ElfFile::new(storage.bytes()?).map_err(|_| Error::InvalidObjectType(0))?; | ||||
| 
 | ||||
|         is_relocatable(&elf)?; | ||||
|         let result = XElfObject { origin, elf }; | ||||
| 
 | ||||
|         Ok(result) | ||||
|     } | ||||
| 
 | ||||
|     fn data(&self, h: &SectionHeader<'data>) -> Result<std::slice::Iter<'data, u8>, Error> { | ||||
|         match h.get_data(&self.elf) { | ||||
|             Ok(SectionData::Undefined(ba)) => Ok(ba.iter()), | ||||
|             Ok(_) => Err(Error::InvalidSectionData), | ||||
|             Err(_) => Err(Error::InvalidSectionData), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Relocatable for XElfObject<'_> { | ||||
|     fn origin(&self) -> &Path { | ||||
|         &self.origin | ||||
|     } | ||||
| 
 | ||||
|     fn sections(&self) -> BSI<'_> { | ||||
|         let iter = self.elf.section_iter().filter_map(move |h| { | ||||
|             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(&self.elf).unwrap_or("null"); | ||||
|                         if h.size() > 0 { | ||||
|                             match self.data(&h) { | ||||
|                                 Ok(data_iter) => { | ||||
|                                     let si = SectionInfo { | ||||
|                                         size: h.size(), | ||||
|                                         data: Some(Box::new(data_iter.copied())), | ||||
|                                         offset: h.offset(), | ||||
|                                     }; | ||||
|         
 | ||||
|                                     match Section::try_from((s_name, si)) { | ||||
|                                         Ok(s) => Some(Ok(s)), | ||||
|                                         Err(Error::InvalidSectionName) => None, // skip
 | ||||
|                                         Err(err) => Some(Err(err)), | ||||
|                                     } | ||||
|                                 } | ||||
|                                 Err(err) => Some(Err(err)), | ||||
|                             } | ||||
|                         } else { | ||||
|                             None | ||||
|                         } | ||||
|                     } | ||||
|                     // bss
 | ||||
|                     ShType::NoBits => Some(Ok(Section::Bss(SectionInfo { | ||||
|                         size: h.size(), | ||||
|                         data: None, | ||||
|                         offset: h.offset(), | ||||
|                     }))), | ||||
|                     _ => None, | ||||
|                 }, | ||||
|                 Err(err) => Some(Err(err)), | ||||
|             }; | ||||
|         }); | ||||
| 
 | ||||
|         Box::new(iter) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Display for XElfObject<'_> { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         write!( | ||||
|             f, | ||||
|             "==={:?}===\n>Symbols:\n{}\n>Sections:\n", | ||||
|             self.origin().file_name().unwrap(), | ||||
|             "TODO" | ||||
|         )?; | ||||
| 
 | ||||
|         for section in self.sections() { | ||||
|             let u = section.unwrap(); | ||||
|             write!(f, "{}", u)?; | ||||
|         } | ||||
| 
 | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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(()) | ||||
| } | ||||
					Loading…
					
					
				
		Reference in New Issue