1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! Reading one symbol out of a shared object.
//!
//! This exists for exactly one caller - `CrateLoader::dlsym_proc_macros`, which needs the
//! `__rustc_proc_macro_decls_*__` static out of a proc-macro crate's `.dylib`. Upstream reaches
//! it through `libloading`; that crate is `std`, so the three libc calls it wraps are made here
//! directly.
//!
//! # `dlopen` in a `no_std` process is not a `std` dependency
//!
//! The shared object on the other side of this call was compiled against the host's real
//! `std` and carries its own copy of it. That is fine and it is not the ban being broken: the
//! ban is on this compiler's own link line, which a link-line check reads directly. The
//! loaded object contributes nothing to it. It is opened `RTLD_LOCAL` so its symbols - its
//! allocator shim, its panic runtime, its lang items - stay in its own namespace and cannot be
//! bound to by anything already in this process.
//!
//! The two runtimes never share an allocation, either. That is what `proc_macro::bridge` is
//! for: every buffer that crosses carries its own `reserve` and `drop` function pointers, so
//! memory allocated on one side is only ever freed by the side that allocated it.
//!
//! # Why the bindings are declared here
//!
//! `ekostd` is the operating system for this tree and this belongs in it. It is published to
//! crates.io and consumed from the registry, so it cannot be edited from here; `libc` already
//! supplies the declarations and this crate already depends on it. `libc::dladdr` is used the
//! same way in `crate::rustc_session::filesearch`.
use ;
use Vec;
use CStr;
use Path;
use crate;
/// Which of the two calls failed, so the caller can say which in the diagnostic.
pub
/// Open `path` and read the value of the symbol named `sym_name` out of it, as a `T`.
///
/// # The indirection is easy to get wrong, so it is spelled out
///
/// `dlsym` returns the *address of the item*. The item here is a `static`, so that address is a
/// pointer to a `T` and the value wanted is what is at it - hence the `read` rather than a
/// transmute of the address itself. `libloading::Symbol<T>` gets the same answer by the opposite
/// route, transmuting the address to `T` and leaving the caller to write one more `*`; the two
/// spellings agree because upstream asks for a `*const &[ProcMacro]` where this asks for a
/// `&[ProcMacro]`.
///
/// # Safety
///
/// `T` must be the type of the symbol in the object at `path`. Nothing here can check that, and
/// there is no version tag on a `.dylib` to check it against: the guarantee comes from
/// `proc_macro::bridge` being a deliberately stable ABI, and from the `Client` type on this side
/// being byte-identical to the one the object was compiled with.
///
/// The returned value borrows from an object that is never unloaded, which is why `'static` is
/// available to the caller.
pub unsafe
/// The pending `dlerror` message, if there is one.