blob: 98b3a0381ca4ad08c4e94f47807bf1e33e1c6449 [file]
//
// Copyright (C) 2025 The Android Open-Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::library_loader::{LinkerNamespace, LoadedLibrary, NamespaceFactory};
use std::sync::OnceLock;
struct PreloadedLib {
namespace: LinkerNamespace,
_library: LoadedLibrary,
_library_name: String,
library_paths: String,
allowed_lib_dirs: String,
}
static PRELOAD_INFO: OnceLock<PreloadedLib> = OnceLock::new();
/// Preload the specified lib.
///
/// # Safety
///
/// The caller must ensure that initialization routine of the library is safe.
#[allow(clippy::too_many_arguments)]
pub unsafe fn preload_lib(
library_name: &str,
library_paths: &str,
allowed_lib_dirs: &str,
target_sdk_version: i32,
is_shared: bool,
zip_paths: &str,
native_shared_lib_path: &str,
preload_func: Option<&str>,
) {
let namespace = NamespaceFactory::create_linker_namespace(
target_sdk_version,
is_shared,
zip_paths,
library_paths,
allowed_lib_dirs,
native_shared_lib_path,
)
.expect("failed to create namespace");
let library =
// SAFETY: We are assuming the caller has specified valid library name and namespace parameters.
unsafe { LoadedLibrary::new(library_name, &namespace) }.expect("failed to load library");
if let Some(preload_func) = preload_func {
let preload_fun_handle =
library.find_symbol(preload_func).expect("failed to find preload func");
// SAFETY: The caller guarantees that the symbol pointed to by `preload_func`
// has the correct signature (takes no arguments, returns nothing).
// Null-check of the handle is performed in `find_symbol`.
let preload_fn: extern "C" fn() = unsafe { std::mem::transmute(preload_fun_handle) };
preload_fn();
}
let _ = PRELOAD_INFO.set(PreloadedLib {
namespace,
_library: library,
_library_name: library_name.to_owned(),
library_paths: library_paths.to_owned(),
allowed_lib_dirs: allowed_lib_dirs.to_owned(),
});
}
/// Return the previously registered LinkerNamespace if it exists.
pub fn reuse_namespace(library_paths: &str, allowed_lib_dirs: &str) -> Option<LinkerNamespace> {
PRELOAD_INFO
.get()
.filter(|lib| {
lib.library_paths == library_paths && lib.allowed_lib_dirs == allowed_lib_dirs
})
.map(|lib| lib.namespace.clone())
}