Export constants for flags to be used with calls

This should make use of the target-specific `Library::open` calls
significantly more palatable.
This commit is contained in:
Simonas Kazlauskas
2020-08-23 01:51:12 +03:00
committed by Simonas Kazlauskas
parent 55b466d91f
commit 23c25400da
6 changed files with 403 additions and 12 deletions
+7
View File
@@ -22,6 +22,13 @@ features = [
"libloaderapi",
]
[target.'cfg(unix)'.dependencies.cfg-if]
version = "0.1"
[dev-dependencies]
libc = "0.2"
static_assertions = "1.1"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
+3 -2
View File
@@ -6,8 +6,9 @@
/// Release 0.6.3 (2020-08-22)
///
/// * Improve documentation, allowing to view all of the os-specific functionality from
/// documentation generated for any target.
/// * Add [`os::windows::Library::this`].
/// documentation generated for any target;
/// * Add [`os::windows::Library::this`];
/// * Added constants to use with OS-specific `Library::open`.
///
/// [`os::windows::Library::this`]: crate::os::windows::Library::this
+230
View File
@@ -0,0 +1,230 @@
use std::os::raw::c_int;
/// Perform lazy binding.
///
/// Relocations shall be performed at an implementation-defined time, ranging from the time
/// of the [`Library::open`] call until the first reference to a given symbol occurs.
/// Specifying `RTLD_LAZY` should improve performance on implementations supporting dynamic
/// symbol binding since a process might not reference all of the symbols in an executable
/// object file. And, for systems supporting dynamic symbol resolution for normal process
/// execution, this behavior mimics the normal handling of process execution.
///
/// Conflicts with [`RTLD_NOW`].
///
/// [`Library::open`]: crate::os::unix::Library::open
pub const RTLD_LAZY: c_int = posix::RTLD_LAZY;
/// Perform eager binding.
///
/// All necessary relocations shall be performed when the executable object file is first
/// loaded. This may waste some processing if relocations are performed for symbols
/// that are never referenced. This behavior may be useful for applications that need to
/// know that all symbols referenced during execution will be available before
/// [`Library::open`] returns.
///
/// Conflicts with [`RTLD_LAZY`].
///
/// [`Library::open`]: crate::os::unix::Library::open
pub const RTLD_NOW: c_int = posix::RTLD_NOW;
/// Make loaded symbols available for resolution globally.
///
/// The executable object file's symbols shall be made available for relocation processing of any
/// other executable object file. In addition, calls to [`Library::get`] on `Library` obtained from
/// [`Library::this`] allows executable object files loaded with this mode to be searched.
///
/// [`Library::this`]: crate::os::unix::Library::this
/// [`Library::get`]: crate::os::unix::Library::get
pub const RTLD_GLOBAL: c_int = posix::RTLD_GLOBAL;
/// Load symbols into an isolated namespace.
///
/// The executable object file's symbols shall not be made available for relocation processing of
/// any other executable object file. This mode of operation is most appropriate for e.g. plugins.
pub const RTLD_LOCAL: c_int = posix::RTLD_LOCAL;
#[cfg(docsrs)]
mod posix {
use super::c_int;
pub(super) const RTLD_LAZY: c_int = !0;
pub(super) const RTLD_NOW: c_int = !0;
pub(super) const RTLD_GLOBAL: c_int = !0;
pub(super) const RTLD_LOCAL: c_int = !0;
}
#[cfg(not(docsrs))]
mod posix {
extern crate cfg_if;
use self::cfg_if::cfg_if;
use super::c_int;
cfg_if! {
if #[cfg(target_os = "haiku")] {
pub(super) const RTLD_LAZY: c_int = 0;
} else if #[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "emscripten",
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "openbsd",
target_os = "netbsd",
target_os = "solaris",
target_os = "illumos",
target_env = "uclibc",
target_env = "newlib",
target_os = "fuchsia",
target_os = "redox",
))] {
pub(super) const RTLD_LAZY: c_int = 1;
} else {
compile_error!(
"Target has no known `RTLD_LAZY` value. Please submit an issue or PR adding it."
);
}
}
cfg_if! {
if #[cfg(target_os = "haiku")] {
pub(super) const RTLD_NOW: c_int = 1;
} else if #[cfg(any(
target_os = "linux",
all(target_os = "android", target_pointer_width = "64"),
target_os = "emscripten",
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "openbsd",
target_os = "netbsd",
target_os = "solaris",
target_os = "illumos",
target_env = "uclibc",
target_env = "newlib",
target_os = "fuchsia",
target_os = "redox",
))] {
pub(super) const RTLD_NOW: c_int = 2;
} else if #[cfg(all(target_os = "android",target_pointer_width = "32"))] {
pub(super) const RTLD_NOW: c_int = 0;
} else {
compile_error!(
"Target has no known `RTLD_NOW` value. Please submit an issue or PR adding it."
);
}
}
cfg_if! {
if #[cfg(any(
target_os = "haiku",
all(target_os = "android",target_pointer_width = "32"),
))] {
pub(super) const RTLD_GLOBAL: c_int = 2;
} else if #[cfg(any(
target_env = "uclibc",
all(target_os = "linux", target_arch = "mips"),
all(target_os = "linux", target_arch = "mips64"),
))] {
pub(super) const RTLD_GLOBAL: c_int = 4;
} else if #[cfg(any(
target_os = "macos",
target_os = "ios",
))] {
pub(super) const RTLD_GLOBAL: c_int = 8;
} else if #[cfg(any(
target_os = "linux",
all(target_os = "android", target_pointer_width = "64"),
target_os = "emscripten",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "openbsd",
target_os = "netbsd",
target_os = "solaris",
target_os = "illumos",
target_env = "newlib",
target_os = "fuchsia",
target_os = "redox",
))] {
pub(super) const RTLD_GLOBAL: c_int = 0x100;
} else {
compile_error!(
"Target has no known `RTLD_GLOBAL` value. Please submit an issue or PR adding it."
);
}
}
cfg_if! {
if #[cfg(target_os = "netbsd")] {
pub(super) const RTLD_LOCAL: c_int = 0x200;
} else if #[cfg(any(
target_os = "macos",
target_os = "ios",
))] {
pub(super) const RTLD_LOCAL: c_int = 4;
} else if #[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "emscripten",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "openbsd",
target_os = "haiku",
target_os = "solaris",
target_os = "illumos",
target_env = "uclibc",
target_env = "newlib",
target_os = "fuchsia",
target_os = "redox",
))] {
pub(super) const RTLD_LOCAL: c_int = 0;
} else {
compile_error!(
"Target has no known `RTLD_LOCAL` value. Please submit an issue or PR adding it."
);
}
}
}
// Other constants that exist but are not bound because they are platform-specific (non-posix)
// extensions. Some of these constants are only relevant to `dlsym` or `dlmopen` calls.
//
// RTLD_CONFGEN
// RTLD_DEFAULT
// RTLD_DI_CONFIGADDR
// RTLD_DI_LINKMAP
// RTLD_DI_LMID
// RTLD_DI_ORIGIN
// RTLD_DI_PROFILENAME
// RTLD_DI_PROFILEOUT
// RTLD_DI_SERINFO
// RTLD_DI_SERINFOSIZE
// RTLD_DI_TLS_DATA
// RTLD_DI_TLS_MODID
// RTLD_FIRST
// RTLD_GROUP
// RTLD_NEXT
// RTLD_PARENT
// RTLD_PROBE
// RTLD_SELF
// RTLD_WORLD
// RTLD_NODELETE
// RTLD_NOLOAD
// RTLD_DEEPBIND
+3 -7
View File
@@ -3,7 +3,7 @@
#[cfg(all(docsrs, not(unix)))]
mod unix_imports {
}
#[cfg(unix)]
#[cfg(any(not(docsrs), unix))]
mod unix_imports {
pub(super) use std::os::unix::ffi::OsStrExt;
}
@@ -13,7 +13,9 @@ use util::{ensure_compatible_types, cstr_cow_from_bytes};
use std::ffi::{CStr, OsStr};
use std::{fmt, marker, mem, ptr};
use std::os::raw;
pub use self::consts::*;
mod consts;
// dl* family of functions did not have enough thought put into it.
//
@@ -385,7 +387,6 @@ impl<T> fmt::Debug for Symbol<T> {
}
// Platform specific things
extern {
fn dlopen(filename: *const raw::c_char, flags: raw::c_int) -> *mut raw::c_void;
fn dlclose(handle: *mut raw::c_void) -> raw::c_int;
@@ -394,11 +395,6 @@ extern {
fn dladdr(addr: *mut raw::c_void, info: *mut DlInfo) -> raw::c_int;
}
#[cfg(not(target_os="android"))]
const RTLD_NOW: raw::c_int = 2;
#[cfg(target_os="android")]
const RTLD_NOW: raw::c_int = 0;
#[repr(C)]
struct DlInfo {
dli_fname: *const raw::c_char,
+147 -3
View File
@@ -3,11 +3,27 @@
#[cfg(all(docsrs, not(windows)))]
mod windows_imports {
pub(super) enum WORD {}
pub(super) enum DWORD {}
pub(super) struct DWORD;
pub(super) enum HMODULE {}
pub(super) enum FARPROC {}
pub(super) mod consts {
use super::DWORD;
pub(crate) const LOAD_IGNORE_CODE_AUTHZ_LEVEL: DWORD = DWORD;
pub(crate) const LOAD_LIBRARY_AS_DATAFILE: DWORD = DWORD;
pub(crate) const LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE: DWORD = DWORD;
pub(crate) const LOAD_LIBRARY_AS_IMAGE_RESOURCE: DWORD = DWORD;
pub(crate) const LOAD_LIBRARY_SEARCH_APPLICATION_DIR: DWORD = DWORD;
pub(crate) const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: DWORD = DWORD;
pub(crate) const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: DWORD = DWORD;
pub(crate) const LOAD_LIBRARY_SEARCH_SYSTEM32: DWORD = DWORD;
pub(crate) const LOAD_LIBRARY_SEARCH_USER_DIRS: DWORD = DWORD;
pub(crate) const LOAD_WITH_ALTERED_SEARCH_PATH: DWORD = DWORD;
pub(crate) const LOAD_LIBRARY_REQUIRE_SIGNED_TARGET: DWORD = DWORD;
pub(crate) const LOAD_LIBRARY_SAFE_CURRENT_DIRS: DWORD = DWORD;
}
}
#[cfg(windows)]
#[cfg(any(not(docsrs), windows))]
mod windows_imports {
extern crate winapi;
pub(super) use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
@@ -16,11 +32,27 @@ mod windows_imports {
pub(super) use self::winapi::um::{errhandlingapi, libloaderapi};
pub(super) use std::os::windows::ffi::{OsStrExt, OsStringExt};
pub(super) const SEM_FAILCE: DWORD = 1;
pub(super) mod consts {
pub(crate) use super::winapi::um::libloaderapi::{
LOAD_IGNORE_CODE_AUTHZ_LEVEL,
LOAD_LIBRARY_AS_DATAFILE,
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE,
LOAD_LIBRARY_AS_IMAGE_RESOURCE,
LOAD_LIBRARY_SEARCH_APPLICATION_DIR,
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR,
LOAD_LIBRARY_SEARCH_SYSTEM32,
LOAD_LIBRARY_SEARCH_USER_DIRS,
LOAD_WITH_ALTERED_SEARCH_PATH,
LOAD_LIBRARY_REQUIRE_SIGNED_TARGET,
LOAD_LIBRARY_SAFE_CURRENT_DIRS,
};
}
}
use self::windows_imports::*;
use util::{ensure_compatible_types, cstr_cow_from_bytes};
use std::ffi::{OsStr, OsString};
use std::{fmt, io, marker, mem, ptr};
use std::sync::atomic::{AtomicBool, Ordering};
@@ -348,3 +380,115 @@ where F: FnOnce() -> Option<T> {
}
})
}
/// Do not check AppLocker rules or apply Software Restriction Policies for the DLL.
///
/// This action applies only to the DLL being loaded and not to its dependencies. This value is
/// recommended for use in setup programs that must run extracted DLLs during installation.
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
pub const LOAD_IGNORE_CODE_AUTHZ_LEVEL: DWORD = consts::LOAD_IGNORE_CODE_AUTHZ_LEVEL;
/// Map the file into the calling process virtual address space as if it were a data file.
///
/// Nothing is done to execute or prepare to execute the mapped file. Therefore, you cannot call
/// functions like [`Library::get`] with this DLL. Using this value causes writes to read-only
/// memory to raise an access violation. Use this flag when you want to load a DLL only to extract
/// messages or resources from it.
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
pub const LOAD_LIBRARY_AS_DATAFILE: DWORD = consts::LOAD_LIBRARY_AS_DATAFILE;
/// Map the file into the calling process virtual address space as if it were a data file.
///
/// Similar to [`LOAD_LIBRARY_AS_DATAFILE`], except that the DLL file is opened with exclusive
/// write access for the calling process. Other processes cannot open the DLL file for write access
/// while it is in use. However, the DLL can still be opened by other processes.
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
pub const LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE: DWORD = consts::LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE;
/// Map the file into the process virtual address space as an image file.
///
/// The loader does not load the static imports or perform the other usual initialization steps.
/// Use this flag when you want to load a DLL only to extract messages or resources from it.
///
/// Unless the application depends on the file having the in-memory layout of an image, this value
/// should be used with either [`LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE`] or
/// [`LOAD_LIBRARY_AS_DATAFILE`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
pub const LOAD_LIBRARY_AS_IMAGE_RESOURCE: DWORD = consts::LOAD_LIBRARY_AS_IMAGE_RESOURCE;
/// Search application's installation directory for the DLL and its dependencies.
///
/// Directories in the standard search path are not searched. This value cannot be combined with
/// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
pub const LOAD_LIBRARY_SEARCH_APPLICATION_DIR: DWORD = consts::LOAD_LIBRARY_SEARCH_APPLICATION_DIR;
/// Search default directories when looking for the DLL and its dependencies.
///
/// This value is a combination of [`LOAD_LIBRARY_SEARCH_APPLICATION_DIR`],
/// [`LOAD_LIBRARY_SEARCH_SYSTEM32`], and [`LOAD_LIBRARY_SEARCH_USER_DIRS`]. Directories in the
/// standard search path are not searched. This value cannot be combined with
/// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: DWORD = consts::LOAD_LIBRARY_SEARCH_DEFAULT_DIRS;
/// Directory that contains the DLL is temporarily added to the beginning of the list of
/// directories that are searched for the DLLs dependencies.
///
/// Directories in the standard search path are not searched.
///
/// The `filename` parameter must specify a fully qualified path. This value cannot be combined
/// with [`LOAD_WITH_ALTERED_SEARCH_PATH`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
pub const LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR: DWORD = consts::LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;
/// Search `%windows%\system32` for the DLL and its dependencies.
///
/// Directories in the standard search path are not searched. This value cannot be combined with
/// [`LOAD_WITH_ALTERED_SEARCH_PATH`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
pub const LOAD_LIBRARY_SEARCH_SYSTEM32: DWORD = consts::LOAD_LIBRARY_SEARCH_SYSTEM32;
/// Directories added using the `AddDllDirectory` or the `SetDllDirectory` function are searched
/// for the DLL and its dependencies.
///
/// If more than one directory has been added, the order in which the directories are searched is
/// unspecified. Directories in the standard search path are not searched. This value cannot be
/// combined with [`LOAD_WITH_ALTERED_SEARCH_PATH`].
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
pub const LOAD_LIBRARY_SEARCH_USER_DIRS: DWORD = consts::LOAD_LIBRARY_SEARCH_USER_DIRS;
/// If `filename specifies an absolute path, the system uses the alternate file search strategy
/// discussed in the [Remarks section] to find associated executable modules that the specified
/// module causes to be loaded.
///
/// If this value is used and `filename` specifies a relative path, the behavior is undefined.
///
/// If this value is not used, or if `filename` does not specify a path, the system uses the
/// standard search strategy discussed in the [Remarks section] to find associated executable
/// modules that the specified module causes to be loaded.
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
///
/// [Remarks]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#remarks
pub const LOAD_WITH_ALTERED_SEARCH_PATH: DWORD = consts::LOAD_WITH_ALTERED_SEARCH_PATH;
/// Specifies that the digital signature of the binary image must be checked at load time.
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
pub const LOAD_LIBRARY_REQUIRE_SIGNED_TARGET: DWORD = consts::LOAD_LIBRARY_REQUIRE_SIGNED_TARGET;
/// Allow loading a DLL for execution from the current directory only if it is under a directory in
/// the Safe load list.
///
/// See [flag documentation on MSDN](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw#parameters).
pub const LOAD_LIBRARY_SAFE_CURRENT_DIRS: DWORD = consts::LOAD_LIBRARY_SAFE_CURRENT_DIRS;
+13
View File
@@ -0,0 +1,13 @@
extern crate libloading;
extern crate libc;
extern crate static_assertions;
#[cfg(all(test, unix))]
mod unix {
use super::static_assertions::const_assert_eq;
const_assert_eq!(libloading::os::unix::RTLD_LOCAL, libc::RTLD_LOCAL);
const_assert_eq!(libloading::os::unix::RTLD_GLOBAL, libc::RTLD_GLOBAL);
const_assert_eq!(libloading::os::unix::RTLD_NOW, libc::RTLD_NOW);
const_assert_eq!(libloading::os::unix::RTLD_LAZY, libc::RTLD_LAZY);
}