add xmas-elf support together with elf-utils
							parent
							
								
									951358daac
								
							
						
					
					
						commit
						0e1c83bbed
					
				| @ -1,3 +1,5 @@ | |||||||
| mod elf; | mod elf; | ||||||
|  | mod xelf; | ||||||
| 
 | 
 | ||||||
| pub use elf::*; | 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