dustlink is the Dust Programming Language internal linker project.
- Platform-agnostic linker architecture (not XDV-specific).
- Dust source (
.ds) linker pipeline. - Host runtime implementation for object ingestion and file emission.
- Compatibility-oriented CLI surface for gcc/ld/lld workflows.
dustlink is not a backend pass-through wrapper.
src/main.ds routes directly into Dust linker modules.
- Object ingestion:
- ELF64 relocatable objects
- COFF 64-bit objects (
x86_64andarm64machine IDs) - Mach-O 64-bit objects (
x86_64andarm64CPU IDs)
- Archive ingestion:
.aand.libsearch/ingest via-L/-land--library-path/--library- deterministic search order: explicit
-Lpaths, then-rpath-link(dynamic mode), then target/sysroot default library roots - dynamic-mode
-lresolution prefers shared objects (.so/.dylib/.dll) before static archives - static-mode
-lresolution uses static archives only - exact-name
-l:<file>token support
- Output writers:
- ELF executable
- flat binary
- MBR image
- PE executable (multi-section, section-per-chunk emission)
- Mach-O executable (multi-section segment/section emission)
- machine/cpu selection follows resolved target architecture (
x86_64vsaarch64/arm64) - PE compatibility-state toggles (
/NOENTRY,/DYNAMICBASE,/NXCOMPAT,/LARGEADDRESSAWARE) are emitted into real PE header fields
- Script application:
-T <script>/--script <script>- directive support:
ENTRY,OUTPUT,OUTPUT_FORMAT,OUTPUT_ARCH,TARGET,SEARCH_DIR,INPUT,GROUP,AS_NEEDED,NO_AS_NEEDED,EXTERN,PROVIDE,PROVIDE_HIDDEN,INCLUDE,ASSERT - compatibility blocks:
PHDRS,VERSION(block-shape validated) - script expression coverage for
ORIGIN(...),LENGTH(...),ADDR(...),LOADADDR(...),SIZEOF(...),ALIGN(...), plus additive/subtractive arithmetic - script expression coverage also includes unary,
*,/,%, shifts, and bitwise operators - direct script symbol assignments (
SYMBOL = <expr>) are supported - unknown script directive heads are rejected (no silent acceptance)
SECTIONScoverage: location-counter assignment (. = <expr>), output-address forms (.text <expr> : { ... }), andAT(<expr>)load-address captureSEARCH_DIR(=...)resolves through configured--sysrootwhen presentINPUTfamily token handling recognizes-Land-lforms- block-aware script statement splitting for multi-line
MEMORY/SECTIONSblocks ENTRY(symbol)now registers required-symbol intent when symbol resolution is deferred
- Link-mode controls:
--gc-sections/--no-gc-sections(GC-aware alloc section selection)--allow-multiple-definition--defsym name=value--target=<triple>/-m<emulation>target selection--sysroot,-rpath/--rpath, and-rpath-link/--rpath-link- dynamic-unresolved policy controls:
--no-undefined,--error-unresolved-symbols,--allow-shlib-undefined,--no-allow-shlib-undefined - dynamic-tag controls:
--enable-new-dtags/--disable-new-dtags - transitive
DT_NEEDEDpolicy controls:--copy-dt-needed-entries/--no-copy-dt-needed-entries - compatibility-state controls:
--hash-style,--threads,--thread-count,--eh-frame-hdr,--fatal-warnings,--color-diagnostics,--print-gc-sections,--icf=* - broader compatibility controls:
--version-script,--dynamic-list,--trace-symbol,--print-map,--start-lib,--end-lib,--emit-relocs,--strip-all lld-linkcompatibility controls:/OUT:,/ENTRY:,/MACHINE:,/LIBPATH:,/DEFAULTLIB:,/MAP[:file],/DLL,/SUBSYSTEM:,/OPT:,/WX,/NOENTRY,/DYNAMICBASE,/NXCOMPAT,/LARGEADDRESSAWARE- shared-object symbol ingestion for exported symbol resolution across ELF, PE, COFF, and Mach-O metadata paths
- Target IDs are architecture-aware:
nonex86_64-linux,x86_64-windows,x86_64-macosaarch64-linux,aarch64-windows,aarch64-macos
- CLI target parsing preserves architecture for both
x86_64andaarch64/arm64aliases. - CLI target parsing also accepts musl triples, Windows GNU triples, and bare-metal
*-none[-elf]aliases. - ELF object validator machine coverage includes
EM_X86_64andEM_AARCH64. - relocation application is machine-aware per ingested object via runtime
object.machine. - COFF and Mach-O object ingestion now use refined machine-aware relocation-kind mapping during relocation record ingest.
- Core relocation set includes:
R_X86_64_NONE,R_X86_64_64,R_X86_64_PC32,R_X86_64_PLT32R_X86_64_GLOB_DAT,R_X86_64_JUMP_SLOT,R_X86_64_RELATIVER_X86_64_GOTPCREL,R_X86_64_32,R_X86_64_32SR_X86_64_GOTPCRELX,R_X86_64_REX_GOTPCRELX- AArch64 core + instruction forms:
R_AARCH64_NONE,R_AARCH64_ABS64,R_AARCH64_ABS32,R_AARCH64_PREL64,R_AARCH64_PREL32R_AARCH64_CALL26,R_AARCH64_JUMP26,R_AARCH64_CONDBR19,R_AARCH64_TSTBR14R_AARCH64_LD_PREL_LO19,R_AARCH64_ADR_PREL_LO21,R_AARCH64_ADR_PREL_PG_HI21,R_AARCH64_ADR_PREL_PG_HI21_NCR_AARCH64_ADD_ABS_LO12_NC,R_AARCH64_LDST8/16/32/64/128_ABS_LO12_NC- MOVW families:
R_AARCH64_MOVW_UABS_*,R_AARCH64_MOVW_SABS_*,R_AARCH64_MOVW_PREL_*
- AArch64 TLS relocation coverage:
TLSGD/TLSLD/TLSDESCinstruction-form relocation IDs are recognized by ELF ingest and relocation validationR_AARCH64_TLS_DTPMOD,R_AARCH64_TLS_DTPREL,R_AARCH64_TLS_TPRELare applied for non-shared links using host-runtime TLS layout metadata helpers- shared-link AArch64 TLS data reloc handling is partially differentiated:
TLS_DTPRELresolves from TLS layout metadata, shared-linkTLS_TPRELis rejected as invalid, and shared-linkTLS_DTPMODremains unsupported - TLSLE/TLSLD low12 offset instruction forms (
*_ADD_*_LO12_NC,*_LDST64_*_LO12_NC,*_LDST128_*_LO12_NC) are applied in non-shared links using host-runtime TLS offset helpers R_AARCH64_TLSDESC_CALLis applied as a validatedBLRpreserve relocation- host TLS synthetic descriptor/GOT planning ABI is available and now used in relocation application (
reserve,count,slot address,reloc-value) for stagedTLSGD/TLSLD/TLSDESCdescriptor-sequence implementation - descriptor-sequence instruction relocations (
TLSGD/TLSLD/TLSDESC) now patch against host-planned synthetic slot addresses in the emitted load image (staged semantics; full TLSDESC runtime parity still incomplete) - ELF host writer now materializes a synthetic AArch64 TLS descriptor/GOT-like slot region and emits minimal synthetic
.rela.dynmetadata (DT_SYMTAB,DT_SYMENT,DT_RELA*) for reserved descriptor-sequence slots - initial descriptor-sequence relaxation scope is limited to deterministic synthetic-slot reuse/coalescing (including TLSLD module-slot coalescing); full instruction-sequence rewrite relaxations remain pending
Primary options:
-o,--output-e,--entry,--entry-point--image-base-Ttext-T,--script--oformat(elf64,binary,mbr,pe,macho64plus aliases)-L,--library-path-l,--library--sysroot-rpath,--rpath-rpath-link,--rpath-link-Map,--Map,--map-file-s,--strip-debug--gc-sections--no-gc-sections--allow-multiple-definition--defsym/--defsym=<name=value>--build-id/--build-id=<none|fast|md5|sha1|uuid|0x...>--target/--target=<triple>-m/-m<emulation>-z/-z<...>(relro,norelro,now,lazy,execstack,noexecstack,defs,undefs, plus accepted compatibility tokenstext,notext,origin)-u,--undefined,--require-defined--no-undefined,--error-unresolved-symbols--allow-shlib-undefined--no-allow-shlib-undefined--enable-new-dtags,--disable-new-dtags--copy-dt-needed-entries,--no-copy-dt-needed-entries--start-group,--end-group--version-script,--dynamic-list,--trace-symbol--print-map,--start-lib,--end-lib--emit-relocs,--strip-alllld-linkcompatibility spellings:/OUT:<path>,/ENTRY:<symbol|addr>,/MACHINE:<arch>/LIBPATH:<dir>,/DEFAULTLIB:<name>,/MAPor/MAP:<path>/DLL,/SUBSYSTEM:<kind>,/OPT:<token>,/WX,/WX:NO/NOENTRY,/DYNAMICBASE,/NXCOMPAT,/LARGEADDRESSAWARE
--help,--version
Compatibility spellings for common ld/lld flags are accepted.
Core linker-affecting paths (--target/-m, --defsym, --build-id, -z, required-symbol flags, sysroot/rpath/rpath-link, dynamic policy flags, group/static/shared toggles, and hash/thread/icf-related compatibility controls) are wired to internal linker state.
lld-link compatibility controls /NOENTRY, /DYNAMICBASE, /NXCOMPAT, and /LARGEADDRESSAWARE are now state-wired into PE writer behavior.
Additional soft-compatibility families (--warn-*, --time-trace*, --lto-*, and /GUARD:*-style slash families) are accepted to reduce false hard-fail paths during lld-profile migrations.
These compatibility no-op paths now emit diagnostics, and become hard failures when --fatal-warnings (or /WX) is enabled.
--dependency-fileis now state-wired and emits a depfile after successful links.--emit-relocsis now state-wired and expands map-row output with relocation rows.--hash-stylenow affects ELF dynamic-tag emission (DT_HASH/DT_GNU_HASH) in Dust runtime host writer output.--print-gc-sectionsnow prints section-drop diagnostics during GC-aware alloc-section selection.- Unsupported flag/target failures now emit explicit diagnostics instead of returning only status codes.
- AArch64 ELF relocation coverage now includes instruction bitfield patching (
ADR_PREL_LO21, MOVW families,LD/STlo12 variants, branch/literal forms) and stricter TLS-family handling:TLSDESC_CALLnow validatesBLRinstruction encoding instead of acting as a generic no-op- AArch64 TLS data relocs (
TLS_DTPMOD/TLS_DTPREL/TLS_TPREL) now use host-runtime TLS layout metadata for non-shared links - TLS descriptor-sequence instruction relocations now route through the host synthetic-slot reloc-value helper and patch against materialized synthetic slot addresses (staged semantics)
- reserved TLS descriptor-sequence synthetic slots are now materialized in ELF load images and emit minimal synthetic
.rela.dynmetadata (DT_SYMTAB,DT_SYMENT,DT_RELA*) - descriptor-sequence staged relaxation behavior now includes deterministic synthetic-slot reuse/coalescing (including TLSLD module-slot coalescing); full instruction rewrite relaxations remain pending
- Shared-library ingest now propagates shared-object ingest failures directly (no Dust-side
ERR_NOT_IMPLEMENTED_YETswallow path). - Host shared-object ingest now treats unknown/unsupported payload formats as
ERR_INVALID_FORMATinstead of silently succeeding. - Host shared-object ingest now also rejects cross-target / wrong-ABI / wrong-kind shared inputs before symbol ingest (ELF requires target machine +
ET_DYN; PE requires Windows target + DLL + matching machine; Mach-O requires macOS target + matching CPU + dylib file type). - Host shared-object ingest now filters non-exported metadata entries during symbol ingestion (ELF hidden/internal dynsyms and Mach-O private extern/debug symbols are skipped).
- Needed-library recording now prefers embedded shared-library names when available (
DT_SONAME, PE export DLL name, Mach-O install name) instead of filename-only normalization. dustlinknow patches AArch64 TLS descriptor-sequence instruction relocs through host synthetic-slot helpers and emits staged synthetic slot/dynamic metadata in ELF outputs, preserving future parity work without changing relocation discovery flow.
dustlink builds independently of the Dust compiler's Rust runtime shim.
The host runtime is provided by src/hostlinker_shim.c (C).
# Using the Makefile (requires `dust` compiler in PATH)
make
# Or manually:
mkdir -p target
dust obj src --out target/dustlink_core.o
cc -Wall -O2 -c src/hostlinker_shim.c -o target/hostlinker_shim.o
cc -o target/dustlink target/dustlink_core.o target/hostlinker_shim.o -lmWhen building through the Dust compiler, the C shim is automatically compiled and linked — no Rust runtime dependency:
dust build src --out target/dust/dustlinkdustlink has advanced beyond initial ELF-only behavior, but it is not yet full lld parity across every flag/script/cross-format semantic.
See changelog.md for detailed change history.