[go: up one dir, main page]

auxv/
lib.rs

1//! # Just what is the auxiliary vector?
2//!
3//! The auxiliary vector (aka auxv) is some memory near the start of a running ELF program's stack.
4//! Specifically, it's a sequence of pairs of either 64 bit or 32 bit unsigned ints. The two
5//! components of the pair form a key and a value. This data is mostly there to help things
6//! like runtime linkers, but sometimes it's useful for other reasons. It is ELF-specific; it does
7//! not exist in, say, Mach-O.
8//!
9//! On most Unixy systems, you can have the linker print out the contents of the aux vector by
10//! setting an environment variable when running a command like `LD_SHOW_AUXV=1 cat /dev/null`.
11//!
12//! The keys used in the aux vector are defined in various header files and typically prefixed with
13//! `AT_`. Some of the data there is not available from any other source, like `AT_HWCAP` and
14//! `AT_HWCAP2`. These expose bit vectors of architecture-dependent hardware capability information.
15//! On ARM, for instance, the bit `1 << 12` in the value for `AT_HWCAP` will be set if the CPU
16//! supports NEON, and `1 << 3` will be set in the value for `AT_HWCAP2` if the CPU supports
17//! SHA-256 acceleration. Handy, if you're doing that sort of thing.
18//!
19//! Other keys are typically not used directly by programs, like `AT_UID`: the real user id is
20//! great and all, but you'd pobably call [`getuid(2)`](https://linux.die.net/man/2/getuid) in C or
21//! `libc::getuid` from Rust instead.
22//!
23//! For most people, probably the most interesting data in auxv is for `AT_HWCAP` or `AT_HWCAP2`
24//! so those have constants defined in `auxv`, but you can of course use any other key as well;
25//! you'll just have to look up the appropriate number.
26//!
27//! More info on the auxiliary vector:
28//!
29//! - http://articles.manugarg.com/aboutelfauxiliaryvectors.html
30//! - http://phrack.org/issues/58/5.html
31//! - See `include/uapi/linux/auxvec.h` in the Linux source (or `getauxval(3)`) for defined keys,
32//!   as well as other header files for architecture-specific types.
33//! - See `fs/binfmt_elf.c` in the Linux source for how the vector is generated.
34//! - Searching for `AT_` in your OS of choice is likely to yield some good leads on the available
35//!   constants and how it's generated.
36//!
37//! # Reading the auxiliary vector
38//!
39//! Unfortunately, there is no one best option for how to access the aux vector.
40//!
41//! - [`getauxval(3)`](https://linux.die.net/man/3/getauxval) is available in glibc 2.16+, Android
42//!   libc (Bionic) since Android 4,3, and musl 1.1.0+. Since it is a non-standard extension, if
43//!   you're not using those libc implementations (e.g. you're using uclibc, etc), this will
44//!   not be available. Also, if you're on glibc older than 2.19, or Bionic before March 2015,
45//!   `getauxval` is unable to express the concept of "not found" and will instead "find" the value 0.
46//! - `/proc/self/auxv` exposes the contents of the aux vector, but it only exists on Linux.
47//!   Furthermore, the OS may be configured to not allow access to it (see `proc(5)`).
48//! - Navigating the ELF stack layout manually is also (sometimes) possible. There isn't a
49//!   standardized way of jumping directly to auxv in the stack, but we can start at the `environ`
50//!   pointer (which is specified in POSIX) and navigate from there. This will work on any ELF
51//!   OS, but it is `unsafe` and only is possible if the environment has not been modified since
52//!   the process started.
53//!
54//! This library lets you use all of these options, so chances are pretty good that at least one of
55//! them will work in any given host. See each submodule for details on how and when to use it.
56//!
57//! For most users, it would be best practice to try the `getauxval` way first, and then try the
58//! procfs way if `getauxval` is not available at runtime. You should only try the stack crawling
59//! way if you are sure that it is safe; see its docs for details.
60//!
61//! See the `examples` dir for examples of each way of accessing auxv.
62//!
63//! ## Auxv type width
64//!
65//! `AuxvType` is selected at compile time to be either `u32` or `u64` depending on the pointer
66//! width of the system. This type is used for the key and value.
67
68// The key/value pairs in auxv are either Elf32_auxv_t or Elf64_auxv_t.
69// If this is an LP64 system (a "long" is 64 bits) then it seems that
70// these entries will be Elf64_auxv_t (2x 64 bits). Fortunately,
71// Unixen in general are LP64 (when on 64 bit), and ELF only exists
72// on Unixen, which means we can simply use pointer width to detect 32
73// vs 64 bit. Furthermore, some of the things auxv holds are pointers
74// (e.g. AT_BASe and AT_EXECFN), so value has to be able to hold a
75// pointer, and the key is always the same width as the value.
76/// The type used in auxv keys and values.
77#[cfg(target_pointer_width="32")]
78pub type AuxvType = u32;
79/// The type used in auxv keys and values.
80#[cfg(target_pointer_width="64")]
81pub type AuxvType = u64;
82
83// from [linux]/include/uapi/linux/auxvec.h. First 32 bits of HWCAP
84// even on platforms where unsigned long is 64 bits.
85pub const AT_HWCAP: AuxvType = 16;
86pub const AT_HWCAP2: AuxvType = 26;
87
88/// An auxv key-value pair.
89#[derive(Debug, PartialEq)]
90pub struct AuxvPair {
91    pub key: AuxvType,
92    pub value: AuxvType,
93}
94
95pub mod getauxval;
96pub mod procfs;
97pub mod stack;