Improve error handling

This commit is contained in:
Edwin Cheng 2020-04-11 14:53:13 +08:00
parent 5fc8f90a21
commit 31d163aa3b

View file

@ -7,28 +7,35 @@ use goblin::{mach::Mach, Object};
use libloading::Library; use libloading::Library;
use ra_proc_macro::ProcMacroKind; use ra_proc_macro::ProcMacroKind;
static NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; use std::io::Error as IoError;
use std::io::ErrorKind as IoErrorKind;
fn get_symbols_from_lib(file: &Path) -> Option<Vec<String>> { const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
let buffer = std::fs::read(file).ok()?;
let object = Object::parse(&buffer).ok()?;
return match object { fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> IoError {
IoError::new(IoErrorKind::InvalidData, e)
}
fn get_symbols_from_lib(file: &Path) -> Result<Vec<String>, IoError> {
let buffer = std::fs::read(file)?;
let object = Object::parse(&buffer).map_err(invalid_data_err)?;
match object {
Object::Elf(elf) => { Object::Elf(elf) => {
let symbols = elf.dynstrtab.to_vec().ok()?; let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?;
let names = symbols.iter().map(|s| s.to_string()).collect(); let names = symbols.iter().map(|s| s.to_string()).collect();
Some(names) Ok(names)
} }
Object::PE(pe) => { Object::PE(pe) => {
let symbol_names = let symbol_names =
pe.exports.iter().flat_map(|s| s.name).map(|n| n.to_string()).collect(); pe.exports.iter().flat_map(|s| s.name).map(|n| n.to_string()).collect();
Some(symbol_names) Ok(symbol_names)
} }
Object::Mach(mach) => match mach { Object::Mach(mach) => match mach {
Mach::Binary(binary) => { Mach::Binary(binary) => {
let exports = binary.exports().ok()?; let exports = binary.exports().map_err(invalid_data_err)?;
let names = exports let names = exports
.iter() .into_iter()
.map(|s| { .map(|s| {
// In macos doc: // In macos doc:
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
@ -37,26 +44,25 @@ fn get_symbols_from_lib(file: &Path) -> Option<Vec<String>> {
if s.name.starts_with("_") { if s.name.starts_with("_") {
s.name[1..].to_string() s.name[1..].to_string()
} else { } else {
s.name.to_string() s.name
} }
}) })
.collect(); .collect();
Some(names) Ok(names)
} }
Mach::Fat(_) => None, Mach::Fat(_) => Ok(vec![]),
}, },
Object::Archive(_) | Object::Unknown(_) => None, Object::Archive(_) | Object::Unknown(_) => Ok(vec![]),
}; }
} }
fn is_derive_registrar_symbol(symbol: &str) -> bool { fn is_derive_registrar_symbol(symbol: &str) -> bool {
symbol.contains(NEW_REGISTRAR_SYMBOL) symbol.contains(NEW_REGISTRAR_SYMBOL)
} }
fn find_registrar_symbol(file: &Path) -> Option<String> { fn find_registrar_symbol(file: &Path) -> Result<Option<String>, IoError> {
let symbols = get_symbols_from_lib(file)?; let symbols = get_symbols_from_lib(file)?;
Ok(symbols.into_iter().find(|s| is_derive_registrar_symbol(s)))
symbols.iter().find(|s| is_derive_registrar_symbol(s)).map(|s| s.clone())
} }
/// Loads dynamic library in platform dependent manner. /// Loads dynamic library in platform dependent manner.
@ -92,14 +98,14 @@ struct ProcMacroLibraryLibloading {
} }
impl ProcMacroLibraryLibloading { impl ProcMacroLibraryLibloading {
fn open(file: &Path) -> Result<Self, String> { fn open(file: &Path) -> Result<Self, IoError> {
let symbol_name = find_registrar_symbol(file) let symbol_name = find_registrar_symbol(file)?
.ok_or(format!("Cannot find registrar symbol in file {:?}", file))?; .ok_or(invalid_data_err(format!("Cannot find registrar symbol in file {:?}", file)))?;
let lib = load_library(file).map_err(|e| e.to_string())?; let lib = load_library(file).map_err(invalid_data_err)?;
let exported_macros = { let exported_macros = {
let macros: libloading::Symbol<&&[bridge::client::ProcMacro]> = let macros: libloading::Symbol<&&[bridge::client::ProcMacro]> =
unsafe { lib.get(symbol_name.as_bytes()) }.map_err(|e| e.to_string())?; unsafe { lib.get(symbol_name.as_bytes()) }.map_err(invalid_data_err)?;
macros.to_vec() macros.to_vec()
}; };
@ -122,7 +128,7 @@ impl Expander {
let lib = let lib =
lib.as_ref().canonicalize().expect(&format!("Cannot canonicalize {:?}", lib.as_ref())); lib.as_ref().canonicalize().expect(&format!("Cannot canonicalize {:?}", lib.as_ref()));
let library = ProcMacroLibraryImpl::open(&lib)?; let library = ProcMacroLibraryImpl::open(&lib).map_err(|e| e.to_string())?;
libs.push(library); libs.push(library);
Ok(Expander { libs }) Ok(Expander { libs })