Skip to main content

LinkOptions

Struct LinkOptions 

Source
#[non_exhaustive]
pub struct LinkOptions {
Show 152 fields pub flavor: Flavor, pub target: Option<Target>, pub endian: Option<Endianness>, pub output: Option<PathBuf>, pub output_format: Option<OutputFormat>, pub kind: OutputKind, pub inputs: Vec<InputSpec>, pub search_paths: Vec<PathBuf>, pub nostdlib: bool, pub sysroot: Option<PathBuf>, pub default_script: Option<PathBuf>, pub entry: Option<String>, pub soname: Option<String>, pub dynamic_linker: Option<PathBuf>, pub no_dynamic_linker: bool, pub rpaths: Vec<PathBuf>, pub rpath_links: Vec<PathBuf>, pub new_dtags: Option<bool>, pub undefined: Vec<String>, pub undefined_glob: Vec<String>, pub require_defined: Vec<String>, pub defsym: Vec<(String, String)>, pub wrap: Vec<String>, pub init: Option<String>, pub fini: Option<String>, pub auxiliary: Vec<String>, pub filter: Vec<String>, pub gc_sections: bool, pub print_gc_sections: bool, pub gc_keep_exported: bool, pub why_live: Vec<String>, pub icf: IcfMode, pub print_icf_sections: bool, pub keep_unique: Vec<String>, pub ignore_data_address_equality: bool, pub ignore_function_address_equality: bool, pub strip: StripMode, pub discard: DiscardMode, pub retain_symbols_file: Option<PathBuf>, pub build_id: BuildId, pub hash_style: HashStyle, pub eh_frame_hdr: bool, pub export_dynamic: bool, pub export_dynamic_symbols: Vec<String>, pub export_dynamic_symbol_lists: Vec<PathBuf>, pub dynamic_lists: Vec<PathBuf>, pub dynamic_list_data: bool, pub dynamic_list_cpp_new: bool, pub dynamic_list_cpp_typeinfo: bool, pub exclude_libs: Vec<String>, pub version_scripts: Vec<PathBuf>, pub undefined_version: Option<bool>, pub default_symver: bool, pub symbolic: SymbolicMode, pub no_undefined: Option<bool>, pub allow_shlib_undefined: Option<bool>, pub unresolved_symbols: Option<UnresolvedSymbols>, pub warn_unresolved_symbols: bool, pub ignore_unresolved_symbols: Vec<String>, pub allow_multiple_definition: bool, pub warn_common: bool, pub warn_backrefs: bool, pub warn_backrefs_exclude: Vec<String>, pub warn_textrel: bool, pub error_textrel: bool, pub bind_now: bool, pub relro: bool, pub separate_code: Option<SeparateCode>, pub rosegment: Option<bool>, pub exec_stack: ExecStack, pub gnu_stack: bool, pub stack_size: Option<u64>, pub max_page_size: Option<u64>, pub common_page_size: Option<u64>, pub copy_relocs: bool, pub combine_relocs: bool, pub pack_relative_relocs: bool, pub gnu_tls_tag: bool, pub gnu2_tls_tag: bool, pub apply_dynamic_relocs: bool, pub dynamic_flags: DynamicFlags, pub start_stop_gc: Option<bool>, pub start_stop_visibility: Option<Visibility>, pub keep_text_section_prefix: bool, pub dynamic_undefined_weak: Option<bool>, pub extern_protected_data: bool, pub mark_plt: bool, pub section_header: bool, pub memory_seal: bool, pub dead_reloc_in_nonalloc: Vec<(String, u64)>, pub x86: X86Features, pub fix_cortex_a53_843419: bool, pub aarch64: Aarch64Features, pub spare_dynamic_tags: Option<u64>, pub emit_relocs: bool, pub define_common: bool, pub magic: MagicMode, pub relax: bool, pub merge_exidx_entries: bool, pub relax_gp: bool, pub image_base: Option<u64>, pub section_starts: Vec<(String, u64)>, pub text_segment: Option<u64>, pub rodata_segment: Option<u64>, pub ldata_segment: Option<u64>, pub orphan_handling: OrphanHandling, pub sort_section: SortSection, pub compress_debug_sections: DebugCompression, pub package_metadata: Option<String>, pub symbol_ordering_file: Option<PathBuf>, pub no_warn_symbol_ordering: bool, pub call_graph_profile_sort: Option<CallGraphSort>, pub call_graph_ordering_file: Option<PathBuf>, pub print_symbol_order: Option<PathBuf>, pub gdb_index: bool, pub s390_pgste: bool, pub debug_names: bool, pub separate_debug_file: Option<Option<PathBuf>>, pub dependency_file: Option<PathBuf>, pub dependent_libraries: bool, pub optimize: u8, pub threads: Option<usize>, pub map_file: Option<PathBuf>, pub print_map: bool, pub cref: bool, pub trace: bool, pub trace_symbols: Vec<String>, pub verbose: bool, pub demangle: bool, pub fatal_warnings: bool, pub no_warnings: bool, pub error_limit: Option<u64>, pub color: ColorChoice, pub noinhibit_exec: bool, pub pe: PeArgs, pub darwin: DarwinArgs, pub plugins: Vec<(PathBuf, Vec<String>)>, pub plugin_save_temps: bool, pub exit_on_plugin_fatal: bool, pub fork: bool, pub on_output_complete: Option<OutputCompleteHook>, pub input_provider: Option<Arc<dyn InputProvider>>, pub output_buffer: Option<OutputBuffer>, pub cancel: Option<CancelToken>, pub map_output: Option<TextOutput>, pub timing: Option<TextOutput>, pub env_run_path: Vec<PathBuf>, pub env_library_path: Vec<PathBuf>, pub zero_ar_date: bool, pub output_backing: Option<OutputBacking>, pub ignored: Vec<OsString>, pub warnings: Vec<String>,
}
Expand description

Everything a link is configured by.

Construct one with LinkOptions::new and the builder methods, or parse argv with crate::args::parse_gnu.

Fields typed Option<bool> distinguish “not given” (None, meaning the target’s or output kind’s default applies) from an explicit choice.

LinkOptions::default is LinkOptions::new: both describe the link GNU ld performs when the command line says nothing, so the ten options GNU ld has on by default (-z relro, --demangle, --relax, …) are on in both.

The struct is #[non_exhaustive]: qld adds fields as it implements more options, so build one with LinkOptions::new and assign the fields you need.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§flavor: Flavor

Command-line dialect this was parsed from.

§target: Option<Target>

Target, when it was given explicitly (-m). Otherwise it is inferred from the first object input.

§endian: Option<Endianness>

Endianness forced with -EB / -EL.

§output: Option<PathBuf>

Output path (-o). None means the flavor’s default (a.out).

§output_format: Option<OutputFormat>

Output format (--oformat), such as binary or elf64-x86-64.

§kind: OutputKind

What kind of output to produce.

§inputs: Vec<InputSpec>

Inputs, in command-line order.

§search_paths: Vec<PathBuf>

Library search paths (-L), in order.

§nostdlib: bool

-nostdlib: ignore SEARCH_DIR commands in linker scripts.

§sysroot: Option<PathBuf>

--sysroot.

§default_script: Option<PathBuf>

--default-script / -dT: used when no -T script is given.

§entry: Option<String>

Entry point (-e).

§soname: Option<String>

-soname / -install_name.

§dynamic_linker: Option<PathBuf>

Program interpreter (--dynamic-linker).

§no_dynamic_linker: bool

--no-dynamic-linker: omit PT_INTERP (used for static PIE).

§rpaths: Vec<PathBuf>

-rpath entries, in order.

§rpath_links: Vec<PathBuf>

-rpath-link entries, in order.

§new_dtags: Option<bool>

--enable-new-dtags (Some(true), DT_RUNPATH) or --disable-new-dtags (Some(false), DT_RPATH).

§undefined: Vec<String>

Symbols required to be defined (-u, --undefined).

§undefined_glob: Vec<String>

--undefined-glob patterns.

§require_defined: Vec<String>

--require-defined symbols: like -u, but an error if undefined.

§defsym: Vec<(String, String)>

--defsym assignments, in order.

§wrap: Vec<String>

--wrap symbols.

§init: Option<String>

-init symbol (DT_INIT).

§fini: Option<String>

-fini symbol (DT_FINI).

§auxiliary: Vec<String>

-f / --auxiliary names (DT_AUXILIARY).

§filter: Vec<String>

-F / --filter names (DT_FILTER).

§gc_sections: bool

Remove unreferenced sections (--gc-sections).

§print_gc_sections: bool

--print-gc-sections.

§gc_keep_exported: bool

--gc-keep-exported: exported symbols are GC roots.

§why_live: Vec<String>

--why-live symbol patterns.

§icf: IcfMode

Identical code folding (--icf).

§print_icf_sections: bool

--print-icf-sections.

§keep_unique: Vec<String>

--keep-unique symbols, never folded by ICF.

§ignore_data_address_equality: bool

--ignore-data-address-equality.

§ignore_function_address_equality: bool

--ignore-function-address-equality.

§strip: StripMode

Strip level.

§discard: DiscardMode

Local symbol discarding (-x, -X, --discard-none).

§retain_symbols_file: Option<PathBuf>

--retain-symbols-file.

§build_id: BuildId

Build ID generation.

§hash_style: HashStyle

Dynamic symbol hash tables to emit.

§eh_frame_hdr: bool

--eh-frame-hdr: create .eh_frame_hdr and PT_GNU_EH_FRAME.

§export_dynamic: bool

Export all symbols from an executable (--export-dynamic).

§export_dynamic_symbols: Vec<String>

--export-dynamic-symbol patterns.

§export_dynamic_symbol_lists: Vec<PathBuf>

--export-dynamic-symbol-list files.

§dynamic_lists: Vec<PathBuf>

--dynamic-list files.

§dynamic_list_data: bool

--dynamic-list-data: add every defined data symbol to the dynamic list.

§dynamic_list_cpp_new: bool

--dynamic-list-cpp-new: add operator new and operator delete to the dynamic list.

§dynamic_list_cpp_typeinfo: bool

--dynamic-list-cpp-typeinfo: add the C++ type information symbols to the dynamic list.

§exclude_libs: Vec<String>

--exclude-libs archive names (ALL is kept as a name).

§version_scripts: Vec<PathBuf>

--version-script files.

§undefined_version: Option<bool>

--undefined-version (Some(true)) or --no-undefined-version (Some(false)).

§default_symver: bool

--default-symver: version exported symbols with the soname.

§symbolic: SymbolicMode

-Bsymbolic and variants.

§no_undefined: Option<bool>

--no-undefined / -z defs (Some(true)) or -z undefs (Some(false)): whether undefined symbols in regular objects are errors even for shared output.

§allow_shlib_undefined: Option<bool>

--allow-shlib-undefined (Some(true)) or --no-allow-shlib-undefined (Some(false)).

§unresolved_symbols: Option<UnresolvedSymbols>

--unresolved-symbols=.

§warn_unresolved_symbols: bool

--warn-unresolved-symbols: report unresolved symbols as warnings.

§ignore_unresolved_symbols: Vec<String>

--ignore-unresolved-symbol names.

§allow_multiple_definition: bool

--allow-multiple-definition / -z muldefs.

§warn_common: bool

--warn-common.

§warn_backrefs: bool

--warn-backrefs.

§warn_backrefs_exclude: Vec<String>

--warn-backrefs-exclude patterns.

§warn_textrel: bool

--warn-textrel: warn when the output needs DT_TEXTREL.

§error_textrel: bool

-z text: make DT_TEXTREL an error.

§bind_now: bool

Resolve all dynamic symbols at load time (-z now).

§relro: bool

-z relro (default) / -z norelro.

§separate_code: Option<SeparateCode>

-z separate-code and friends. None means the target default.

§rosegment: Option<bool>

--rosegment (Some(true)) / --no-rosegment (Some(false)).

§exec_stack: ExecStack

-z execstack / -z noexecstack.

§gnu_stack: bool

-z nognustack clears this: omit PT_GNU_STACK.

§stack_size: Option<u64>

-z stack-size=: the PT_GNU_STACK size.

§max_page_size: Option<u64>

-z max-page-size=.

§common_page_size: Option<u64>

-z common-page-size=.

§copy_relocs: bool

-z copyreloc (default) / -z nocopyreloc.

§combine_relocs: bool

-z combreloc (default) / -z nocombreloc.

§pack_relative_relocs: bool

-z pack-relative-relocs or --pack-dyn-relocs=relr: emit DT_RELR.

§gnu_tls_tag: bool

--gnu-tls-tag (default) / --no-gnu-tls-tag: add the GLIBC_ABI_GNU_TLS version dependency to an output that keeps GNU general-dynamic or local-dynamic TLS, when a needed library defines that version.

§gnu2_tls_tag: bool

--gnu2-tls-tag (default) / --no-gnu2-tls-tag: the same for GLIBC_ABI_GNU2_TLS and TLS descriptors.

§apply_dynamic_relocs: bool

--apply-dynamic-relocs: also write addends into the output.

§dynamic_flags: DynamicFlags

DT_FLAGS / DT_FLAGS_1 bits from -z keywords.

§start_stop_gc: Option<bool>

-z start-stop-gc (Some(true)) / -z nostart-stop-gc.

§start_stop_visibility: Option<Visibility>

-z start-stop-visibility=. None when the keyword was not given, which leaves the linker’s own default.

§keep_text_section_prefix: bool

-z keep-text-section-prefix.

§dynamic_undefined_weak: Option<bool>

-z dynamic-undefined-weak (Some(true)) / -z nodynamic-undefined-weak.

§extern_protected_data: bool

-z noextern-protected-data clears this.

§mark_plt: bool

-z mark-plt.

§section_header: bool

-z sectionheader (default) / -z nosectionheader.

§memory_seal: bool

-z memory-seal.

§dead_reloc_in_nonalloc: Vec<(String, u64)>

-z dead-reloc-in-nonalloc=<glob>=<value> rules, in command-line order: the value written for a relocation in a non-allocated section whose name matches the glob, when its target section was discarded. Later rules take precedence.

§x86: X86Features

x86 CET and ISA-level options.

§fix_cortex_a53_843419: bool

--fix-cortex-a53-843419.

§aarch64: Aarch64Features

AArch64 BTI, PAC and erratum options.

§spare_dynamic_tags: Option<u64>

--spare-dynamic-tags.

§emit_relocs: bool

-q / --emit-relocs: keep relocations in the output.

§define_common: bool

-d, -dc, -dp: allocate common symbols even for -r.

§magic: MagicMode

-n / -N.

§relax: bool

--relax (default) / --no-relax.

§merge_exidx_entries: bool

Arm --merge-exidx-entries (default) / --no-merge-exidx-entries: drop .ARM.exidx entries that repeat the one before.

§relax_gp: bool

RISC-V --relax-gp: relax absolute accesses within 2 KiB of __global_pointer$ to gp-relative ones (off by default, as in lld).

§image_base: Option<u64>

--image-base.

§section_starts: Vec<(String, u64)>

--section-start, -Ttext, -Tdata, -Tbss: section addresses, in order.

§text_segment: Option<u64>

-Ttext-segment.

§rodata_segment: Option<u64>

-Trodata-segment.

§ldata_segment: Option<u64>

-Tldata-segment.

§orphan_handling: OrphanHandling

--orphan-handling=.

§sort_section: SortSection

--sort-section=.

§compress_debug_sections: DebugCompression

--compress-debug-sections=.

§package_metadata: Option<String>

--package-metadata=: contents of .note.package.

§symbol_ordering_file: Option<PathBuf>

--symbol-ordering-file: order input sections by the symbols listed in this file (lld).

§no_warn_symbol_ordering: bool

--no-warn-symbol-ordering: do not warn about symbols of the ordering file that cannot be ordered.

§call_graph_profile_sort: Option<CallGraphSort>

--call-graph-profile-sort=: how to order sections by call graph profile. None when not given: qld then orders only with --call-graph-ordering-file (lld also sorts by default when an input has a .llvm.call-graph-profile section).

§call_graph_ordering_file: Option<PathBuf>

--call-graph-ordering-file: call graph edges (from to weight).

§print_symbol_order: Option<PathBuf>

--print-symbol-order=: write the symbol order the call graph sort chose to this file.

§gdb_index: bool

--gdb-index: write a .gdb_index section.

§s390_pgste: bool

--s390-pgste: add an empty PT_S390_PGSTE segment, which tells the Linux kernel to allocate page tables with the guest storage extension (s390x only).

§debug_names: bool

--debug-names: write a merged .debug_names section.

§separate_debug_file: Option<Option<PathBuf>>

--separate-debug-file[=FILE]: write the debug sections to FILE (Some(None): the output path plus .dbg) and link it from the output with .gnu_debuglink, as mold does.

§dependency_file: Option<PathBuf>

--dependency-file.

§dependent_libraries: bool

--dependent-libraries (default) / --no-dependent-libraries.

§optimize: u8

Optimization level (-O).

§threads: Option<usize>

Thread count (--threads). Some(n) runs the link in a pool of n threads that crate::link creates for it.

None, the default, leaves the choice to the format driver: the ELF driver sizes a pool from the input (small links run faster on few threads), at most 16 threads and at most the available parallelism. Called inside a rayon pool of your own (rayon::ThreadPool::install), a link with None runs in that pool and creates none, however large it is.

§map_file: Option<PathBuf>

Write a link map to this path (-Map).

§print_map: bool

-M / --print-map: write the link map to stdout.

§cref: bool

--cref: add a cross-reference table to the map.

§trace: bool

-t / --trace: print each input file as it is processed.

§trace_symbols: Vec<String>

-y / --trace-symbol names.

§verbose: bool

--verbose.

§demangle: bool

Demangle symbol names in diagnostics (--demangle, on by default).

§fatal_warnings: bool

--fatal-warnings.

§no_warnings: bool

-w / --no-warnings.

§error_limit: Option<u64>

--error-limit. Some(0) means no limit.

§color: ColorChoice

--color-diagnostics.

§noinhibit_exec: bool

--noinhibit-exec: write the output even after errors.

§pe: PeArgs

The PE/COFF options of GNU ld’s MinGW emulations. Only PE links read them.

§darwin: DarwinArgs

The Apple ld64 options that have no GNU equivalent. Only Mach-O links read them.

§plugins: Vec<(PathBuf, Vec<String>)>

LTO plugin paths (-plugin) and their options (-plugin-opt).

§plugin_save_temps: bool

-plugin-save-temps: keep the files an LTO plugin generates.

§exit_on_plugin_fatal: bool

Exit the process when an LTO plugin reports a fatal error, as GNU ld does. The qld binary sets this; library callers get an error instead, and accept that a plugin may not expect to be called again.

§fork: bool

--fork (the default) / --no-fork: whether the qld binary runs the link in a child process and returns as soon as the output is complete, leaving the child to free memory and unmap the inputs. Only the binary reads it (on Unix); the library never forks.

§on_output_complete: Option<OutputCompleteHook>

Called once when a successful link’s output is complete; see OutputCompleteHook. None by default. The qld binary sets it in the child process of --fork to let its parent exit early.

§input_provider: Option<Arc<dyn InputProvider>>

Files that exist only in memory, looked up by path before the file system: inputs named by path, -l libraries found in the search directories, INPUT/GROUP entries of input scripts, and thin archive members. None by default (only the file system). See MemoryFiles and InputProvider.

The ELF driver uses it. Files read outside the input list (-T scripts, version scripts, dynamic lists) still come from the file system; so do all inputs of PE and Mach-O links.

§output_buffer: Option<OutputBuffer>

Hand the output image to this buffer instead of writing the output file; see OutputBuffer. None by default.

§cancel: Option<CancelToken>

Stop the link with an error once this token is cancelled; see CancelToken. None by default.

§map_output: Option<TextOutput>

Receives the link map of -M / --print-map, and the --cref table when no -Map file was named. None by default, which drops that text: a library link writes nothing to the process’s standard output. See LinkOptions::use_process_defaults.

§timing: Option<TextOutput>

Receives one line per pipeline stage with the time it took, the way QLD_TIMING asks the qld binary for. None by default, which measures nothing. See LinkOptions::use_process_defaults.

§env_run_path: Vec<PathBuf>

LD_RUN_PATH, split into directories: searched for the dependencies of shared libraries when no -rpath was given, as GNU ld does. Empty by default; a library link reads no environment of its own. See LinkOptions::use_process_defaults.

§env_library_path: Vec<PathBuf>

LD_LIBRARY_PATH, split into directories: searched for the dependencies of shared libraries, as GNU ld does. Empty by default. See LinkOptions::use_process_defaults.

§zero_ar_date: bool

Record zero modification times in a Mach-O debug map, for reproducible output; ZERO_AR_DATE in the environment asks ld64, lld and the qld binary for it. Off by default. See LinkOptions::use_process_defaults.

§output_backing: Option<OutputBacking>

How the output image is held while it is written. None, the default, leaves the choice to the writer; QLD_OUTPUT_BACKING sets it for the qld binary. See LinkOptions::use_process_defaults.

§ignored: Vec<OsString>

Options that were recognized but have no effect yet, kept so that --verbose and tests can report them.

§warnings: Vec<String>

Warnings produced while parsing the command line (for example an unknown -z keyword), in command-line order. The driver emits them to its diagnostic sink.

Implementations§

Source§

impl LinkOptions

Source

pub fn new() -> Self

Creates the options of a link whose command line said nothing: every field at the default GNU ld uses.

Examples found in repository?
examples/rayon_pool.rs (line 23)
22fn link(value: u8) -> qld::Result<Vec<u8>> {
23    let mut options = LinkOptions::new();
24    options.kind = OutputKind::StaticExecutable;
25    options.push_input(
26        InputKind::bytes("main.o", objects::main_object()),
27        InputAttrs::default(),
28    );
29    options.push_input(
30        InputKind::bytes("answer.o", objects::answer_object(value)),
31        InputAttrs::default(),
32    );
33    let buffer = OutputBuffer::new();
34    options.output_buffer = Some(buffer.clone());
35    qld::link(&options, &Collect::new())?;
36    buffer
37        .take()
38        .ok_or_else(|| qld::Error::Internal("no output".into()))
39}
More examples
Hide additional examples
examples/custom_sink.rs (line 91)
89fn main() {
90    // `main.o` calls `answer`, which nothing defines.
91    let mut options = LinkOptions::new();
92    options.kind = OutputKind::StaticExecutable;
93    options.output_buffer = Some(OutputBuffer::new());
94    options.push_input(
95        InputKind::bytes("main.o", objects::main_object()),
96        InputAttrs::default(),
97    );
98
99    let sink = JsonLines::default();
100    let result = qld::link(&options, &sink);
101    print!("{}", sink.render());
102    match result {
103        Ok(()) => println!("linked"),
104        Err(qld::Error::Reported { errors }) => {
105            println!("the link failed with {errors} error(s) reported above");
106        }
107        Err(error) => println!("the link failed: {error}"),
108    }
109}
examples/link_map.rs (line 24)
23fn main() -> qld::Result<()> {
24    let mut options = LinkOptions::new();
25    options.kind = OutputKind::StaticExecutable;
26    options.push_input(
27        InputKind::bytes("main.o", objects::main_object()),
28        InputAttrs::default(),
29    );
30    options.push_input(
31        InputKind::bytes("answer.o", objects::answer_object(42)),
32        InputAttrs::default(),
33    );
34
35    // `-M` and `--cref`, into a string instead of standard output.
36    options.print_map = true;
37    options.cref = true;
38    let map = Arc::new(Mutex::new(String::new()));
39    let collected = Arc::clone(&map);
40    options.map_output = Some(TextOutput::new(move |text| {
41        collected.lock().unwrap().push_str(text);
42    }));
43
44    let image = qld::link_to_memory(&options, &Collect::new())?;
45    let map = map.lock().unwrap();
46    println!("linked {} bytes, {} of map", image.len(), map.len());
47    for line in map.lines().take(8) {
48        println!("  {line}");
49    }
50
51    // What the same options would take from the process, if asked.
52    let mut as_the_binary = options.clone();
53    as_the_binary.use_process_defaults();
54    println!(
55        "\nhermetic: map_output {}, LD_LIBRARY_PATH {} entries, timing {}",
56        if options.map_output.is_some() {
57            "set by this program"
58        } else {
59            "unset"
60        },
61        options.env_library_path.len(),
62        if options.timing.is_some() {
63            "on"
64        } else {
65            "off"
66        },
67    );
68    println!(
69        "as the binary: LD_LIBRARY_PATH {} entries, timing {}",
70        as_the_binary.env_library_path.len(),
71        if as_the_binary.timing.is_some() {
72            "on"
73        } else {
74            "off"
75        },
76    );
77    Ok(())
78}
examples/cancel.rs (line 64)
42fn main() -> qld::Result<()> {
43    let mut args = std::env::args().skip(1);
44    if let Some(limit) = args.next() {
45        let limit = Duration::from_millis(limit.parse().unwrap_or(1000));
46        let argv: Vec<String> = std::iter::once("ld".to_string()).chain(args).collect();
47        let qld::ParseOutcome::Link(options) = qld::parse_gnu(&argv)? else {
48            return Ok(());
49        };
50        let start = Instant::now();
51        let result = link_with_deadline(*options, limit);
52        match &result {
53            Ok(()) => eprintln!("linked in {:?}", start.elapsed()),
54            Err(error) if CancelToken::is_cancellation(error) => {
55                eprintln!("{error} after {:?}", start.elapsed());
56            }
57            Err(_) => {}
58        }
59        return result;
60    }
61
62    // Without arguments: link the in-memory demo program twice, once with
63    // plenty of time and once cancelled before it starts.
64    let mut options = LinkOptions::new();
65    options.kind = OutputKind::StaticExecutable;
66    options.push_input(
67        InputKind::bytes("main.o", objects::main_object()),
68        InputAttrs::default(),
69    );
70    options.push_input(
71        InputKind::bytes("answer.o", objects::answer_object(42)),
72        InputAttrs::default(),
73    );
74    let buffer = OutputBuffer::new();
75    options.output_buffer = Some(buffer.clone());
76
77    link_with_deadline(options.clone(), Duration::from_secs(10))?;
78    println!(
79        "with a 10 s deadline: linked {} bytes",
80        buffer.take().map_or(0, |b| b.len())
81    );
82
83    let token = CancelToken::new();
84    token.cancel();
85    options.cancel = Some(token);
86    match qld::link(&options, &Stderr::new(qld::PROGRAM_NAME)) {
87        Err(error) if CancelToken::is_cancellation(&error) => {
88            println!(
89                "cancelled before it started: {error}; output empty: {}",
90                !buffer.is_filled()
91            );
92        }
93        other => println!("unexpected: {other:?}"),
94    }
95    Ok(())
96}
examples/in_memory.rs (line 31)
25fn main() -> qld::Result<()> {
26    // Object code from a compiler or JIT in the same process.
27    let main_o = objects::main_object();
28    let answer_o = objects::answer_object(42);
29
30    // 1. Buffers as inputs, the output into a buffer.
31    let mut options = LinkOptions::new();
32    options.kind = OutputKind::StaticExecutable;
33    options.push_input(
34        InputKind::bytes("main.o", main_o.clone()),
35        InputAttrs::default(),
36    );
37    options.push_input(
38        InputKind::bytes("answer.o", answer_o.clone()),
39        InputAttrs::default(),
40    );
41    let buffer = OutputBuffer::new();
42    options.output_buffer = Some(buffer.clone());
43    let diagnostics = Collect::new();
44    qld::link(&options, &diagnostics)?;
45    let first = buffer.take().expect("a successful link fills the buffer");
46    report("buffers", &first);
47
48    // 2. A command line whose files live in memory: `main.o`, and
49    //    `libanswer.a` in a search directory that does not exist on disk.
50    let library = objects::archive(&[("answer.o", &answer_o, &["answer"])]);
51    let files = MemoryFiles::new()
52        .with("main.o", main_o)
53        .with("/virtual/lib/libanswer.a", library);
54    let argv = ["ld", "-static", "-L/virtual/lib", "main.o", "-lanswer"];
55    let qld::ParseOutcome::Link(options) = qld::parse_gnu(&argv)? else {
56        unreachable!("a link command line");
57    };
58    let mut options = *options;
59    options.input_provider = Some(Arc::new(files));
60    let buffer = OutputBuffer::new();
61    options.output_buffer = Some(buffer.clone());
62    qld::link(&options, &diagnostics)?;
63    let second = buffer.take().expect("a successful link fills the buffer");
64    report("memory files", &second);
65    assert_eq!(first, second, "same program either way");
66
67    for diagnostic in diagnostics.take_sorted() {
68        eprintln!("{}: {}", diagnostic.severity, diagnostic.message);
69    }
70    if let Some(path) = std::env::args_os().nth(1) {
71        std::fs::write(&path, &first).map_err(|error| qld::Error::io(&path, error))?;
72        #[cfg(unix)]
73        {
74            use std::os::unix::fs::PermissionsExt;
75            std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o755))
76                .map_err(|error| qld::Error::io(&path, error))?;
77        }
78        println!("wrote {} (it exits with status 42)", path.to_string_lossy());
79    }
80    Ok(())
81}
Source

pub fn use_process_defaults(&mut self)

Makes these options describe a link run the way the qld binary runs one, by taking from the process what a library link must be told explicitly.

Nothing else in qld reads the environment or writes to standard output or standard error, so a LinkOptions that never went through this method describes a hermetic, silent link. parse_gnu and parse_darwin call it, because they parse a command line the way the binary does; parse_gnu_with, parse_darwin_with and LinkOptions::new do not.

It sets:

  • map_output to standard output, where GNU ld writes the map of -M and a --cref table with no -Map file;
  • timing to standard error when QLD_TIMING is set in the environment;
  • env_run_path from LD_RUN_PATH and env_library_path from LD_LIBRARY_PATH, which GNU ld also searches;
  • zero_ar_date from ZERO_AR_DATE, which ld64 and lld also read;
  • output_backing from QLD_OUTPUT_BACKING, a benchmarking knob.
Examples found in repository?
examples/link_map.rs (line 53)
23fn main() -> qld::Result<()> {
24    let mut options = LinkOptions::new();
25    options.kind = OutputKind::StaticExecutable;
26    options.push_input(
27        InputKind::bytes("main.o", objects::main_object()),
28        InputAttrs::default(),
29    );
30    options.push_input(
31        InputKind::bytes("answer.o", objects::answer_object(42)),
32        InputAttrs::default(),
33    );
34
35    // `-M` and `--cref`, into a string instead of standard output.
36    options.print_map = true;
37    options.cref = true;
38    let map = Arc::new(Mutex::new(String::new()));
39    let collected = Arc::clone(&map);
40    options.map_output = Some(TextOutput::new(move |text| {
41        collected.lock().unwrap().push_str(text);
42    }));
43
44    let image = qld::link_to_memory(&options, &Collect::new())?;
45    let map = map.lock().unwrap();
46    println!("linked {} bytes, {} of map", image.len(), map.len());
47    for line in map.lines().take(8) {
48        println!("  {line}");
49    }
50
51    // What the same options would take from the process, if asked.
52    let mut as_the_binary = options.clone();
53    as_the_binary.use_process_defaults();
54    println!(
55        "\nhermetic: map_output {}, LD_LIBRARY_PATH {} entries, timing {}",
56        if options.map_output.is_some() {
57            "set by this program"
58        } else {
59            "unset"
60        },
61        options.env_library_path.len(),
62        if options.timing.is_some() {
63            "on"
64        } else {
65            "off"
66        },
67    );
68    println!(
69        "as the binary: LD_LIBRARY_PATH {} entries, timing {}",
70        as_the_binary.env_library_path.len(),
71        if as_the_binary.timing.is_some() {
72            "on"
73        } else {
74            "off"
75        },
76    );
77    Ok(())
78}
Source

pub fn output_complete(&self)

Runs the on_output_complete hook, if there is one and it has not run yet.

Link drivers call this once the output of a successful link is complete, and crate::link calls it before returning Ok for drivers that did not.

Source

pub fn check_cancelled(&self) -> Result<()>

Returns an error if the link was cancelled through LinkOptions::cancel. Link drivers call this between stages.

§Errors

CancelToken::error once the token is cancelled.

Source

pub fn output_path(&self) -> PathBuf

Returns the output path, or the flavor’s default.

Source

pub fn is_pic(&self) -> bool

Whether the output is position-independent.

Source

pub fn is_dynamic(&self) -> bool

Whether the output links against shared libraries at run time.

Source

pub fn push_input(&mut self, kind: InputKind, attrs: InputAttrs)

Appends an input with the given attributes.

Examples found in repository?
examples/rayon_pool.rs (lines 25-28)
22fn link(value: u8) -> qld::Result<Vec<u8>> {
23    let mut options = LinkOptions::new();
24    options.kind = OutputKind::StaticExecutable;
25    options.push_input(
26        InputKind::bytes("main.o", objects::main_object()),
27        InputAttrs::default(),
28    );
29    options.push_input(
30        InputKind::bytes("answer.o", objects::answer_object(value)),
31        InputAttrs::default(),
32    );
33    let buffer = OutputBuffer::new();
34    options.output_buffer = Some(buffer.clone());
35    qld::link(&options, &Collect::new())?;
36    buffer
37        .take()
38        .ok_or_else(|| qld::Error::Internal("no output".into()))
39}
More examples
Hide additional examples
examples/custom_sink.rs (lines 94-97)
89fn main() {
90    // `main.o` calls `answer`, which nothing defines.
91    let mut options = LinkOptions::new();
92    options.kind = OutputKind::StaticExecutable;
93    options.output_buffer = Some(OutputBuffer::new());
94    options.push_input(
95        InputKind::bytes("main.o", objects::main_object()),
96        InputAttrs::default(),
97    );
98
99    let sink = JsonLines::default();
100    let result = qld::link(&options, &sink);
101    print!("{}", sink.render());
102    match result {
103        Ok(()) => println!("linked"),
104        Err(qld::Error::Reported { errors }) => {
105            println!("the link failed with {errors} error(s) reported above");
106        }
107        Err(error) => println!("the link failed: {error}"),
108    }
109}
examples/link_map.rs (lines 26-29)
23fn main() -> qld::Result<()> {
24    let mut options = LinkOptions::new();
25    options.kind = OutputKind::StaticExecutable;
26    options.push_input(
27        InputKind::bytes("main.o", objects::main_object()),
28        InputAttrs::default(),
29    );
30    options.push_input(
31        InputKind::bytes("answer.o", objects::answer_object(42)),
32        InputAttrs::default(),
33    );
34
35    // `-M` and `--cref`, into a string instead of standard output.
36    options.print_map = true;
37    options.cref = true;
38    let map = Arc::new(Mutex::new(String::new()));
39    let collected = Arc::clone(&map);
40    options.map_output = Some(TextOutput::new(move |text| {
41        collected.lock().unwrap().push_str(text);
42    }));
43
44    let image = qld::link_to_memory(&options, &Collect::new())?;
45    let map = map.lock().unwrap();
46    println!("linked {} bytes, {} of map", image.len(), map.len());
47    for line in map.lines().take(8) {
48        println!("  {line}");
49    }
50
51    // What the same options would take from the process, if asked.
52    let mut as_the_binary = options.clone();
53    as_the_binary.use_process_defaults();
54    println!(
55        "\nhermetic: map_output {}, LD_LIBRARY_PATH {} entries, timing {}",
56        if options.map_output.is_some() {
57            "set by this program"
58        } else {
59            "unset"
60        },
61        options.env_library_path.len(),
62        if options.timing.is_some() {
63            "on"
64        } else {
65            "off"
66        },
67    );
68    println!(
69        "as the binary: LD_LIBRARY_PATH {} entries, timing {}",
70        as_the_binary.env_library_path.len(),
71        if as_the_binary.timing.is_some() {
72            "on"
73        } else {
74            "off"
75        },
76    );
77    Ok(())
78}
examples/cancel.rs (lines 66-69)
42fn main() -> qld::Result<()> {
43    let mut args = std::env::args().skip(1);
44    if let Some(limit) = args.next() {
45        let limit = Duration::from_millis(limit.parse().unwrap_or(1000));
46        let argv: Vec<String> = std::iter::once("ld".to_string()).chain(args).collect();
47        let qld::ParseOutcome::Link(options) = qld::parse_gnu(&argv)? else {
48            return Ok(());
49        };
50        let start = Instant::now();
51        let result = link_with_deadline(*options, limit);
52        match &result {
53            Ok(()) => eprintln!("linked in {:?}", start.elapsed()),
54            Err(error) if CancelToken::is_cancellation(error) => {
55                eprintln!("{error} after {:?}", start.elapsed());
56            }
57            Err(_) => {}
58        }
59        return result;
60    }
61
62    // Without arguments: link the in-memory demo program twice, once with
63    // plenty of time and once cancelled before it starts.
64    let mut options = LinkOptions::new();
65    options.kind = OutputKind::StaticExecutable;
66    options.push_input(
67        InputKind::bytes("main.o", objects::main_object()),
68        InputAttrs::default(),
69    );
70    options.push_input(
71        InputKind::bytes("answer.o", objects::answer_object(42)),
72        InputAttrs::default(),
73    );
74    let buffer = OutputBuffer::new();
75    options.output_buffer = Some(buffer.clone());
76
77    link_with_deadline(options.clone(), Duration::from_secs(10))?;
78    println!(
79        "with a 10 s deadline: linked {} bytes",
80        buffer.take().map_or(0, |b| b.len())
81    );
82
83    let token = CancelToken::new();
84    token.cancel();
85    options.cancel = Some(token);
86    match qld::link(&options, &Stderr::new(qld::PROGRAM_NAME)) {
87        Err(error) if CancelToken::is_cancellation(&error) => {
88            println!(
89                "cancelled before it started: {error}; output empty: {}",
90                !buffer.is_filled()
91            );
92        }
93        other => println!("unexpected: {other:?}"),
94    }
95    Ok(())
96}
examples/in_memory.rs (lines 33-36)
25fn main() -> qld::Result<()> {
26    // Object code from a compiler or JIT in the same process.
27    let main_o = objects::main_object();
28    let answer_o = objects::answer_object(42);
29
30    // 1. Buffers as inputs, the output into a buffer.
31    let mut options = LinkOptions::new();
32    options.kind = OutputKind::StaticExecutable;
33    options.push_input(
34        InputKind::bytes("main.o", main_o.clone()),
35        InputAttrs::default(),
36    );
37    options.push_input(
38        InputKind::bytes("answer.o", answer_o.clone()),
39        InputAttrs::default(),
40    );
41    let buffer = OutputBuffer::new();
42    options.output_buffer = Some(buffer.clone());
43    let diagnostics = Collect::new();
44    qld::link(&options, &diagnostics)?;
45    let first = buffer.take().expect("a successful link fills the buffer");
46    report("buffers", &first);
47
48    // 2. A command line whose files live in memory: `main.o`, and
49    //    `libanswer.a` in a search directory that does not exist on disk.
50    let library = objects::archive(&[("answer.o", &answer_o, &["answer"])]);
51    let files = MemoryFiles::new()
52        .with("main.o", main_o)
53        .with("/virtual/lib/libanswer.a", library);
54    let argv = ["ld", "-static", "-L/virtual/lib", "main.o", "-lanswer"];
55    let qld::ParseOutcome::Link(options) = qld::parse_gnu(&argv)? else {
56        unreachable!("a link command line");
57    };
58    let mut options = *options;
59    options.input_provider = Some(Arc::new(files));
60    let buffer = OutputBuffer::new();
61    options.output_buffer = Some(buffer.clone());
62    qld::link(&options, &diagnostics)?;
63    let second = buffer.take().expect("a successful link fills the buffer");
64    report("memory files", &second);
65    assert_eq!(first, second, "same program either way");
66
67    for diagnostic in diagnostics.take_sorted() {
68        eprintln!("{}: {}", diagnostic.severity, diagnostic.message);
69    }
70    if let Some(path) = std::env::args_os().nth(1) {
71        std::fs::write(&path, &first).map_err(|error| qld::Error::io(&path, error))?;
72        #[cfg(unix)]
73        {
74            use std::os::unix::fs::PermissionsExt;
75            std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o755))
76                .map_err(|error| qld::Error::io(&path, error))?;
77        }
78        println!("wrote {} (it exits with status 42)", path.to_string_lossy());
79    }
80    Ok(())
81}
Source

pub fn resolve_sysroot(&self, path: &Path) -> PathBuf

Resolves a path that may start with = or $SYSROOT against LinkOptions::sysroot, as GNU ld does for -L, -T, -rpath-link and script INPUTs.

Paths without the prefix are returned unchanged. When there is no sysroot the prefix is simply removed. This is a pure string operation; it does not touch the file system.

Trait Implementations§

Source§

impl Clone for LinkOptions

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for LinkOptions

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for LinkOptions

Source§

fn default() -> Self

Identical to LinkOptions::new.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.