From 02aa400c5ce26eca523f9604bfb2e962ef68fe74 Mon Sep 17 00:00:00 2001 From: oddcoder <ahmedsoliman@oddcoder.com> Date: Sun, 5 Jul 2020 20:57:24 +0200 Subject: [PATCH] Add callbacks to ld.so version of Linker's function It is fact that ld.so has libc statially linked into it. Normally we wouldn't need ld.so functionality once the program is finalyl loaded, but with the next few patches, we will have dlopen which will reuse the same ld.so functionality. The problem is that it seams that huge part of the code is possible not referntially transparent. That is, it is not impossible that some of the functions have internals states. So when using the struct Linker that is initialized by ld.so's copy of libc. we must access it using the same copy even if both copies are identical. For example in dlopen if you do linker.load_library(..). That would segfault because it is using the function from libc not ld.so So I don't truly undestand why should this be needed, but after long hours of being stuck I thought maybe.. maybe that is the issue and indeed it turned out to be so. --- src/ld_so/callbacks.rs | 53 ++++++++++++++++++++++++++++++++++++++++++ src/ld_so/mod.rs | 2 +- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/ld_so/callbacks.rs diff --git a/src/ld_so/callbacks.rs b/src/ld_so/callbacks.rs new file mode 100644 index 00000000..22c6920a --- /dev/null +++ b/src/ld_so/callbacks.rs @@ -0,0 +1,53 @@ +use super::linker::{Linker, DSO}; +use alloc::boxed::Box; +use goblin::error::Result; + +pub struct LinkerCallbacks { + pub unload: Box<dyn Fn(&mut Linker, usize)>, + pub load_library: Box<dyn Fn(&mut Linker, &str) -> Result<usize>>, + pub link: + Box<dyn Fn(&mut Linker, Option<&str>, Option<DSO>, Option<usize>) -> Result<Option<usize>>>, + pub get_sym: Box<dyn Fn(&Linker, &str, Option<usize>) -> Option<usize>>, + pub run_init: Box<dyn Fn(&Linker, Option<usize>) -> Result<()>>, + pub run_fini: Box<dyn Fn(&Linker, Option<usize>) -> Result<()>>, +} + +impl LinkerCallbacks { + pub fn new() -> LinkerCallbacks { + LinkerCallbacks { + unload: Box::new(unload), + load_library: Box::new(load_library), + link: Box::new(link), + get_sym: Box::new(get_sym), + run_init: Box::new(run_init), + run_fini: Box::new(run_fini), + } + } +} + +fn unload(linker: &mut Linker, libspace: usize) { + linker.unload(libspace) +} + +fn load_library(linker: &mut Linker, name: &str) -> Result<usize> { + linker.load_library(name) +} + +fn link( + linker: &mut Linker, + primary_opt: Option<&str>, + dso: Option<DSO>, + libspace: Option<usize>, +) -> Result<Option<usize>> { + linker.link(primary_opt, dso, libspace) +} + +fn get_sym(linker: &Linker, name: &str, libspace: Option<usize>) -> Option<usize> { + linker.get_sym(name, libspace) +} +fn run_init(linker: &Linker, libspace: Option<usize>) -> Result<()> { + linker.run_init(libspace) +} +fn run_fini(linker: &Linker, libspace: Option<usize>) -> Result<()> { + linker.run_fini(libspace) +} diff --git a/src/ld_so/mod.rs b/src/ld_so/mod.rs index e6857e96..efaf6bc5 100644 --- a/src/ld_so/mod.rs +++ b/src/ld_so/mod.rs @@ -5,12 +5,12 @@ use crate::start::Stack; pub const PAGE_SIZE: usize = 4096; mod access; +pub mod callbacks; pub mod debug; mod library; pub mod linker; pub mod start; pub mod tcb; - pub fn static_init(sp: &'static Stack) { let mut phdr_opt = None; let mut phent_opt = None; -- GitLab