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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
//! qld is a fast, parallel linker that accepts GNU ld, gold, lld and mold
//! command lines, and can also be driven as a library.
//!
//! # Status
//!
//! Pre-alpha. The pipeline is being implemented milestone by milestone; see
//! `ROADMAP.md`. Nothing outside this crate's root re-exports should be
//! considered stable, and the root API will not be stable until 1.0.
//!
//! # Library use
//!
//! Build [`LinkOptions`] by hand or from a command line ([`parse_gnu`]), and
//! call [`link`]. Diagnostics go to a [`DiagnosticSink`] of your choice.
//! Inputs can be byte buffers ([`InputKind::bytes`], [`MemoryFiles`]), the
//! output can come back as bytes ([`link_to_memory`], [`OutputBuffer`]), a
//! link can be cancelled from another thread ([`CancelToken`]), and it runs
//! in the caller's rayon pool, as it is, when called inside
//! [`rayon::ThreadPool::install`].
//!
//! A link built with [`LinkOptions::new`] is hermetic and silent: the
//! process never exits, nothing is written to its standard output or
//! standard error, and no environment variable is read.
//! [`LinkOptions::use_process_defaults`] opts into all three, and
//! [`parse_gnu`] applies it, because it describes the link the `qld` binary
//! runs.
//!
//! ```no_run
//! use qld::{InputAttrs, InputKind, LinkOptions, OutputKind};
//! use qld::diag::Collect;
//!
//! # let object: Vec<u8> = Vec::new();
//! let mut options = LinkOptions::new();
//! options.kind = OutputKind::StaticExecutable;
//! options.push_input(InputKind::bytes("main.o", object), InputAttrs::default());
//! let diagnostics = Collect::new();
//! let image: Vec<u8> = qld::link_to_memory(&options, &diagnostics)?;
//! # Ok::<(), qld::Error>(())
//! ```
//!
//! The `examples/` directory has complete programs: `link_argv`,
//! `in_memory`, `custom_sink`, `rayon_pool` and `cancel`.
//!
//! # Layout
//!
//! Modules follow the link pipeline described in `docs/architecture.md`:
//!
//! | Module | Role |
//! | --- | --- |
//! | [`args`] | Option model and the argv front ends |
//! | [`input`] | Mapping input files, identifying formats, archives |
//! | [`symbols`] | String interning and the global symbol table |
//! | [`passes`] | Format-neutral passes: GC, ICF, section merging |
//! | [`script`] | GNU linker script parser and evaluator |
//! | [`output`] | Output file writer and post-write steps |
//! | [`elf`], [`coff`], [`macho`] | Format backends |
//! | [`arch`] | Instruction-level helpers shared across formats |
//! | [`debug`] | DWARF handling: compression, indexes, line lookup |
//! | [`demangle`] | Itanium C++ and Rust symbol demangling for diagnostics |
//! | [`hints`] | Suggestions for undefined symbols: missing `-l`, versions, near misses |
//! | [`plugin`] | LTO plugin host (feature `plugin`) |
//!
//! Format backends own their own symbol precedence and layout rules. The
//! shared modules must not depend on a backend.
//!
//! Only [`args`], [`diag`], [`error`] and [`target`] are documented; the
//! other modules are public for qld's own tests and tools, and are not
//! covered by semantic versioning.
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ScriptError;
pub use ;
/// Program name used to prefix diagnostics.
pub const PROGRAM_NAME: &str = "qld";
/// Version string, printed by `--version` and `-v`.
///
/// Build systems detect a GNU-compatible linker by looking for `GNU` in this
/// output, so the wording must not change. See `docs/compatibility.md`.
/// Runs a link described by `options`.
///
/// With [`LinkOptions::threads`] (`--threads`), parallel stages run in a
/// rayon pool of that size, created for the duration of the link. Without
/// it, the format driver chooses: outside any pool the ELF driver sizes one
/// from the input, because small links run faster on few threads. To run in
/// a pool you already own, call `link` (or a format driver such as
/// [`elf::link`](fn@elf::link)) inside your pool's `install`: that pool is
/// then used as it is, whatever its size, and the driver creates none of its
/// own.
///
/// A successful link runs [`LinkOptions::on_output_complete`] once the
/// output is complete: the ELF driver runs it before freeing its data and
/// unmapping the inputs, and `link` runs it before returning `Ok` if the
/// driver did not.
///
/// # Example
///
/// ```no_run
/// use qld::diag::Stderr;
///
/// let args = ["ld", "-o", "hello", "crt1.o", "hello.o", "-lc"];
/// if let qld::ParseOutcome::Link(options) = qld::parse_gnu(&args)? {
/// qld::link(&options, &Stderr::new(qld::PROGRAM_NAME))?;
/// }
/// # Ok::<(), qld::Error>(())
/// ```
///
/// # Errors
///
/// Returns any fatal error from the link, including
/// [`Error::Unimplemented`] for targets and features not supported yet,
/// [`Error::Reported`] when errors were reported to `diagnostics`, and
/// [`Error::Cancelled`] when [`LinkOptions::cancel`] was cancelled.
/// Runs a link described by `options` and returns the output image instead
/// of writing [`LinkOptions::output`], which then only names the output.
///
/// This is [`link`] with a fresh [`OutputBuffer`] in
/// [`LinkOptions::output_buffer`]. Side outputs (`-Map`,
/// `--dependency-file`) are still written as files.
///
/// # Errors
///
/// As [`link`].