LD.LLD(1)
๐ธ NAME ๐ธ
okay so bestie, you're reading the General Commands Manual entry for ld.lld(1) โ the ELF linker from the LLVM project, and she is literally that girl ๐
โจ.
โจ SYNOPSIS โจ
ld.lld [options] objfile ...
๐ฆ DESCRIPTION ๐ฆ
So a linker takes one or more object files, archive files, and library files, and combines them into an output file โ which can be an executable, a shared library, or another object file. It relocates code and data from the input files and resolves symbol references between them. That's the whole vibe ๐ซถ.
ld.lld is a drop-in replacement for the GNU BFD and gold linkers. It accepts most of the same command line arguments and linker scripts as GNU linkers. No cap.
Right now ld.lld supports i386, x86-64, ARM, AArch64, LoongArch, PowerPC32, PowerPC64, MIPS32, MIPS64, RISC-V, AMDGPU, Hexagon, and SPARC V9 targets. It acts as a Microsoft link.exe-compatible linker if invoked as lld-link, and as macOS's ld if invoked as ld.ld64. All these targets are always supported however ld.lld was built, so you can always use ld.lld as a native linker as well as a cross linker. Iconic behavior, honestly ๐.
๐ OPTIONS ๐
Many options have both a single-letter and long form. When using the long form options other than those beginning with the letter o, you may specify them using either one or two dashes preceding the option name. Long options beginning with o require two dashes to avoid confusion with the -o path option. Dash lore, but make it useful ๐.
--allow-multiple-definitionโ don't error if a symbol is defined multiple times. The first definition will be used. Periodt.--allow-shlib-undefinedโ allow unresolved references in shared libraries. This option is enabled by default when linking a shared library.--apply-dynamic-relocsโ apply link-time values for dynamic relocations.--as-neededโ only setDT_NEEDEDfor shared libraries if used.--auxiliary=valueโ set theDT_AUXILIARYfield to the specified name.--Bdynamic,--dyโ link against shared libraries.--Bstatic,--static,--dnโ do not link against shared libraries.-Bno-symbolicโ don't bind default visibility defined symbols locally for-shared(default).-Bsymbolicโ bind default visibility defined symbols locally for-shared. Also set theDF_SYMBOLICflag.-Bsymbolic-non-weakโ bind default visibility definedSTB_GLOBALsymbols locally for-shared.-Bsymbolic-functionsโ bind default visibility defined function symbols locally for-shared.-Bsymbolic-non-weak-functionsโ bind default visibility definedSTB_GLOBALfunction symbols locally for-shared.--be8โ write a Big Endian ELF file using BE8 format (AArch32only).--branch-to-branchโ enable the branch-to-branch optimizations: a branch whose target is another branch instruction is rewritten to point to the latter branch target (AArch64andX86_64only), and CFI jump table entries are replaced with the function body where possible (X86_64only). Enabled by default at-O2.--build-id=valueโ generate a build ID note.valuemay be one offast,md5,sha1,tree,uuid,0xhex-string, andnone.treeis an alias forsha1. Build-IDs of typefast,md5,sha1, andtreeare calculated from the object contents.fastis not intended to be cryptographically secure.--build-idโ synonym for--build-id=sha1.--call-graph-profile-sort=algorithmโalgorithmmay be:noneโ ignore call graph profile.hfsortโ use hfsort.cdsortโ use cdsort (default).
--color-diagnostics=valueโ use colors in diagnostics.valuemay be one ofalways,auto, andnever.autoenables color if and only if output is to a terminal.--color-diagnosticsโ alias for--color-diagnostics=auto.--compress-debug-sections=valueโ compress DWARF debug sections. The sections remain uncompressed if compressed content would be larger.valuemay be:noneโ no compression.zlibโ the default compression level is1(fastest), as the debug info usually compresses well at that level.zstdโ use the default compression level in zstd.
--compress-sections=section-glob={none,zlib,zstd}[:level]โ compress output sections that match the glob and do not have theSHF_ALLOCflag. The matched sections remain uncompressed if compressed content would be larger. The compression level islevel(if specified) or a default speed-focused level. This is like a generalized--compress-debug-sections.--crefโ output cross reference table. If-Mapis specified, print to the map file.--debug-namesโ generate a merged.debug_namessection.--default-script=file,-dT fileโ in the absence of--script, read this default linker script.--defsym=symbol=expressionโ define a symbol alias.expressionmay be another symbol or a linker script expression. For example,--defsym=foo=baror--defsym=foo=bar+0x100.--demangleโ demangle symbol names.--disable-new-dtagsโ disable new dynamic tags.--discard-all,-xโ delete all local symbols.--discard-locals,-Xโ delete temporary local symbols.--discard-noneโ keep all symbols in the symbol table.--dynamic-linker=valueโ specify the dynamic linker to be used for a dynamically linked executable. This is recorded in an ELF segment of typePT_INTERP.--dynamic-list=fileโ similar to--export-dynamic-symbol-list. When creating a shared object, implies-Bsymbolicbut does not setDF_SYMBOLIC.--EBโ select the big-endian format in theOUTPUT_FORMATcommand.--ELโ select the little-endian format in theOUTPUT_FORMATcommand.--eh-frame-hdrโ request creation of.eh_frame_hdrsection andPT_GNU_EH_FRAMEsegment header.--emit-relocs,-qโ generate relocations in the output.--enable-new-dtagsโ enable new dynamic tags.--enable-non-contiguous-regionsโ spill input sections to later matching output sections to avoid memory region overflow.--end-libโ end a grouping of objects that should be treated as if they were together in an archive.--entry=entryโ name of entry point symbol.--error-limit=valueโ maximum number of errors to emit before stopping. Avalueof zero indicates that there is no limit.--error-unresolved-symbolsโ report unresolved symbols as errors.--error-handing-script=script_pathโ call scriptscript_pathupon some error, withtagas first argument, and an extra parameter as second argument. The script is expected to return0on success. Any other value is considered a generic error.tagmay bemissing-libfollowed by the name of the missing library, orundefined-symbolfollowed by the name of the undefined symbol. Yes bestie, that's the exact spelling in the manual โ copy it exactly ๐ซถ.--execute-onlyโ mark executable sections unreadable. This option is currently only supported onAArch64.--exclude-libs=valueโ exclude static libraries from automatic export.--export-dynamic,-Eโ put symbols in the dynamic symbol table.--export-dynamic-symbol=globโ (executable) put matched non-local defined symbols to the dynamic symbol table. (shared object) references to matched non-localSTV_DEFAULTsymbols shouldn't be bound to definitions within the shared object even if they would otherwise be due to-Bsymbolic,-Bsymbolic-functions, or--dynamic-list.--export-dynamic-symbol-list=fileโ read a list of dynamic symbol patterns fromfile. Apply--export-dynamic-symbolon each pattern.--fatal-warningsโ treat warnings as errors.--filter=value,-F valueโ set theDT_FILTERfield to the specifiedvalue.--fini=symbolโ specify a finalizer function.--force-group-allocationโ only meaningful for-r. Section groups are discarded. If two section group members are placed to the same output section, combine their relocations as well.--format=input-format,-b input-formatโ specify the format of the inputs following this option.input-formatmay be one ofbinary,elf, anddefault.defaultis a synonym forelf.--gc-sectionsโ enable garbage collection of unused sections.--gdb-indexโ generate.gdb_indexsection.--hash-style=valueโ specify hash style.valuemay besysv,gnu, orboth.bothis the default.--helpโ print a help message.--icf=allโ enable identical code folding.--icf=safeโ enable safe identical code folding.--icf=noneโ disable identical code folding.--ignore-data-address-equalityโ ignore address equality of data. C/C++ requires each data to have a unique address. This option allows lld to do unsafe optimization that breaks the requirement: create copies of read-only data or merge two or more read-only data that happen to have the same value. Unsafe optimization alert, bestie โ it literally breaks the requirement.--ignore-function-address-equalityโ ignore address equality of functions. This option allows non-PIC calls to a function with non-default visibility in a shared object. The function may have different addresses within the executable and within the shared object.--image-base=valueโ set the base address tovalue.--init=symbolโ specify an initializer function.--keep-unique=symbolโ do not foldsymbolduring ICF.-l libName,--library=libNameโ root name of library to use.-L dir,--library-path=dirโ add a directory to the library search path.--lto-aa-pipeline=valueโ AA pipeline to run during LTO. Used in conjunction with--lto-newpm-passes.--lto-newpm-passes=valueโ passes to run during LTO.--lto-Oopt-levelโ optimization level for LTO.--lto-partitions=valueโ number of LTO codegen partitions.-m valueโ set target emulation.--Map=file,-M fileโ print a link map tofile.--nmagic,-nโ do not page align sections, link against static libraries.--no-allow-shlib-undefinedโ nope, we are not letting shared libraries have loose unresolved references lying around. ๐ This one's on by default when you're linking an executable, so the vibes stay clean automatically.--no-as-neededโ always setDT_NEEDEDfor shared libraries. Like, yes bestie, you are needed, we're writing it down. ๐--no-color-diagnosticsโ no colors in diagnostics. monochrome era, very demure. ๐ค--no-demangleโ don't demangle symbol names. you get the raw mangled names, no glow-up. ๐ญ--no-dynamic-linkerโ inhibits output of an.interpsection. no interp bestie, we're not doing that today.--no-fortran-commonโ don't go searching archive members for definitions to overrideCOMMONsymbols. fortran girlies, this one's for you ๐ซถ--no-gc-sectionsโ disables garbage collection of unused sections. nothing gets collected, it all stays, hoarder core. ๐--no-gnu-uniqueโ disablesSTB_GNU_UNIQUEsymbol binding. un-uniqued. ๐--no-merge-exidx-entriesโ disables merging.ARM.exidxentries. keep 'em separated โจ--no-nmagicโ page align sections. (yes the name is confusing, it's giving chaotic but it's literally just page-aligning, trust ๐ง)--no-omagicโ don't set the text data sections to be writable, and page align sections. so: not writable, but still page aligned. โจ--no-relaxโ disables target-specific relaxations. for x86-64 this specifically kills theR_X86_64_GOTPCRELXandR_X86_64_REX_GOTPCRELXGOT optimization. unclench, no relaxing allowed ๐ซ--no-rosegmentโ do not put read-only non-executable sections in their own segment. they gotta share, it's giving communal living ๐--undefined-versionโ do not report version scripts that refer to undefined symbols. snitches get silence ๐คซ--no-undefinedโ report unresolved symbols even if the linker is creating a shared library. normally shared libs get a pass, but not today. ๐ฅ--no-warn-mismatchโ do not reject unknown section types. live and let live, lowkey.--no-warn-symbol-orderingโ do not warn about problems with the symbol ordering file or call graph profile. warnings cancelled ๐--no-warnings,-wโ suppress warnings AND cancel--fatal-warnings. double homicide of the warning system, iconic. ๐--no-whole-archiveโ restores the default behavior of loading archive members. back to normal, we're so back. ๐--no-pie,--no-pic-executableโ do not create a position independent executable. fixed addresses, no PIE for you ๐ฅงโ--noinhibit-execโ retain the executable output file whenever it's still usable. even if stuff went sideways, if the file works, we keep it. bestie's resilient ๐ซถ--nostdlibโ only search directories specified on the command line. no default paths, main character energy only. ๐-opath โ write the output executable, library, or object to path. if you don't specify it,a.outis used as a default. (yes,a.out, the OG name, we love a classic ๐)-Ovalueโ optimize the output file. value may be:0โ disable string merging.1โ enable string merging.2โ enable string tail merging and branch-to-branch optimization.
-O1 is the default. โจ
--oformat=formatโ specify the format for the output object file. the only supported format isbinary, which produces output with no ELF header. raw and unbothered. ๐ฆ--omagic,-Nโ set the text and data sections to be readable and writable, do not page align sections, and link against static libraries. the "handle with care" combo ngl โ ๏ธ--opt-remarks-filenamefile โ write optimization remarks in YAML format to file. receipts, but YAML. ๐งพ--opt-remarks-passespass-regex โ filter optimization remarks by only allowing the passes matching pass-regex. selective hearing, but for passes ๐--opt-remarks-with-hotnessโ include hotness information in the optimization remarks file. yes, hotness. ๐ฅ slay.--orphan-handling=modeโ control how orphan sections are handled. an orphan section is one not specifically mentioned in a linker script (poor thing, unclaimed ๐ญ). mode may be:placeโ place orphan sections in suitable output sections.warnโ place orphan sections as forplace, and also report a warning.errorโ place orphan sections as forplace, and also report an error.
place is the default. ๐ซถ
--pack-dyn-relocs=formatโ pack dynamic relocations in the given format. format may be:noneโ do not pack. dynamic relocations are encoded inSHT_REL(A).androidโ pack dynamic relocations inSHT_ANDROID_REL(A).relrโ pack relative relocations inSHT_RELR, and the rest of dynamic relocations inSHT_REL(A).android+relrโ pack relative relocations inSHT_RELR, and the rest of dynamic relocations inSHT_ANDROID_REL(A).
none is the default. and heads up: if --use-android-relr-tags is specified, use SHT_ANDROID_RELR instead of SHT_RELR. ๐
--package-metadataโ emit a percent-encoded string to the.note.packagesection. for example,%25decodes to a single%. iykyk โจ--pic-veneerโ always generate position independent thunks. pico de gallo but make it position independent. ๐ฎ--pie,--pic-executableโ create a position independent executable. ๐ฅงโจ--power10-stubs=modeโ whether to use Power10 instructions in call stubs forR_PPC64_REL24_NOTOCand TOC/NOTOC interworking. mode may be:yesโ (default) use.autoโ currently the same asyes.noโ don't use.
--print-gc-sectionsโ list removed unused sections. naming and shaming the discarded ๐--print-gc-sections=fileโ list removed unused sections to the specified file. same energy, but it goes in a file ๐--print-icf-sectionsโ list identical folded sections. twin reveal ๐ช--print-mapโ print a link map to the standard output. map girlie ๐บ๏ธ--print-archive-stats=fileโ write archive usage statistics to the specified file. prints the numbers of members and fetched members for each archive. stats era ๐--push-stateโ save the current state of--as-needed,--static, and--whole-archive. save file energy ๐พ--pop-stateโ restore the states saved by--push-state. load file energy ๐--randomize-section-padding=seedโ randomly insert padding between input sections and at the start of each segment using the given seed. padding gets inserted into output sections with names matching these patterns:.bss,.data,.data.rel.ro,.lbss,.ldata,.lrodata,.ltext,.rodataand.text*. chaos, but seeded. ๐ฒ---relax-gpโ enable global pointer relaxation for RISC-V. (yes that's three dashes, that's literally how it's written, don't come for me ๐)--relocatable,-rโ create a relocatable object file. ๐งฉ--remap-inputs=from-glob=to-fileโ input files matching from-glob are mapped to to-file. use/dev/nullto ignore an input file entirely (ghosting, but technical ๐ซฅ).--remap-inputs-file=fileโ remap input files based on patterns in file. each line in the remap file is of the formatfrom-glob=to-fileor a comment starting with#. ๐--reproduce=pathโ write a tar file to path, containing all the input files needed to reproduce the link, a text file calledresponse.txtcontaining the command line options, and a text file calledversion.txtcontaining the output ofld.lld --version. the archive, when unpacked, can be used to re-run the linker with the same options and input files. literally a time capsule bestie ๐ฐ๏ธ--retain-symbols-file=fileโ keep only the symbols listed in file in the static symbol table, along with symbols referenced by emitted relocations. this does not affect the dynamic symbol table. read that twice, it matters ๐--rpath=value,-Rvalue โ add aDT_RUNPATHto the output. path girlie ๐ค๏ธ--rsp-quoting=valueโ quoting style for response files. the supported values arewindowsandposix. pick your fighter ๐ฅ--script=file,-Tfile โ read linker script from file. if multiple linker scripts are given, they are processed as if they were concatenated in the order they appeared on the command line. order matters, don't shuffle ๐--section-start=section=addressโ set address of section. ๐--shared,--Bsharableโ build a shared object. sharing is caring ๐ซถ--shuffle-sections=seedโ shuffle matched sections using the given seed before mapping them to the output sections. if-1, reverse the section order. if0, use a random seed. spotify shuffle but for sections ๐--soname=value,-hvalue โ setDT_SONAMEto value. name tag, but ELF ๐ท๏ธ--sort-commonโ this option is ignored for GNU compatibility. it's giving ghosted, bestie ๐ซฅ--sort-section=valueโ specifies sections sorting rule when linkerscript is used. ๐--start-libโ start a grouping of objects that should be treated as if they were together in an archive. squad assembly ๐ซ--strip-all,-sโ strip all symbols. implies--strip-debug. everything off, nothing left ๐--strip-debug,-Sโ strip debugging information. bye debug info, you won't be missed (you will, but still) ๐--symbol-ordering-file=fileโ lay out sections in the order specified by file. โจ--sysroot=valueโ set the system root. ๐ก--target1-absโ interpretR_ARM_TARGET1asR_ARM_ABS32. ๐--target1-relโ interpretR_ARM_TARGET1asR_ARM_REL32. ๐--target2=typeโ interpretR_ARM_TARGET2as type, where type is one ofrel,abs, orgot-rel. ๐ฏ--Tbss=valueโ same as--section-startwith.bssas the sectionname. ๐--Tdata=valueโ same as--section-startwith.dataas the sectionname. ๐--Ttext=valueโ same as--section-startwith.textas the sectionname. ๐--thinlto-cache-dir=valueโ path to ThinLTO cached object file directory. cache storage, bestie ๐๏ธ--thinlto-cache-policy=valueโ pruning policy for the ThinLTO cache. โ๏ธ--thinlto-jobs=valueโ number of ThinLTO jobs. ๐ผ--threads=Nโ number of threads.all(default) means all of concurrent threads supported.1disables multi-threading. go parallel or go home ๐โโ๏ธ--fat-lto-objectsโ use the.llvm.ltosection, which contains LLVM bitcode, in fat LTO object files to perform LTO. thicc objects, immaculate vibes ๐--no-fat-lto-objectsโ ignore the.llvm.ltosection in relocatable object files (default). โจ--time-traceโ record time trace. โฑ๏ธ--time-trace-file=fileโ write time trace output to file. ๐--time-trace-granularity=valueโ minimum time granularity (in microseconds) traced by the time profiler. very precise, very demure ๐ฌ--traceโ print the names of the input files. roll call ๐ข--trace-symbol=symbol,-ysymbol โ trace references to symbol. following it around like a detective ๐--undefined=symbol,-usymbol โ if symbol is not defined after symbol resolution, and there's a static library that contains an object file defining the symbol, load the member to include the object file in the output file. pulling the one object file out of the archive, very "i just need this one thing" ๐--undefined-glob=patternโ synonym for--undefined, except it takes a glob pattern. in a glob pattern,*matches zero or more characters,?matches any single character, and[...]matches the characters within brackets. all symbols that match a given pattern are handled as if they were given as arguments of--undefined. ๐ฏ--uniqueโ creates a separate output section for every orphan input section. everybody gets their own room ๐ช--unresolved-symbols=valueโ determine how to handle unresolved symbols. value may be:report-allโ reports unresolved symbols. That's the default, bestie โจignore-in-object-filesโ only complains about unresolved symbols that live in shared libraries ๐ignore-in-shared-libsโ the flip side: only complains about unresolved symbols that live in object files ๐ignore-allโ doesn't report unresolved symbols at all. silence is golden ๐--use-android-relr-tagsโ use theSHT_ANDROID_RELR/DT_ANDROID_RELR*tags instead ofSHT_RELR/DT_RELR*. like, the Android-flavoured version of the same thing ๐-v,-Vโ print the version number and then keep going with the link if you actually gave it object files ๐ซถ--versionโ print the version number and dip out. that's it, that's the whole job ๐--verboseโ verbose mode. she talks more ๐ฃ๏ธ- *
--version-script=file* โ read the version script fromfile๐ --warn-backrefsโ warns you about reverse or cyclic dependencies to or between static archives. use it to keep your linker invocation compatible with traditional Unix-like linkers, no cap ๐ฅ- *
--warn-backrefs-exclude=glob* โ a glob describing an archive (or an object file inside--start-lib) that should get ignored for--warn-backrefs. like a VIP list but for not being warned about ๐ --warn-commonโ warn about duplicate common symbols ๐ฏโโ๏ธ--warn-ifunc-textrelโ warns about using ifunc symbols together with text relocations. okay so storytime: older glibc (2.28 and earlier) had a bug where the segment containing ifunc symbols gets marked as not executable when they're relocated. so likeโฆ the program compiles and links successfully (slay?) but then gives a segmentation fault the moment the instruction pointer reaches an ifunc symbol ๐ญ. use-warn-ifunc-textrelto letlldgive you a warning if your code may include ifunc symbols, may do text relocations, and is being linked with an older glibc version. otherwise there's literally no need to use it, because the default value does not give a warning. this flag got introduced in late 2018, has no counterpart inldandgoldlinkers, and may be removed in the future. so, enjoy her while she's here ๐ฆ--warn-unresolved-symbolsโ report unresolved symbols as warnings instead of full-on errors ๐ซถ--whole-archiveโ force-load every single member of a static library. no skipping, everyone's invited ๐--why-extract=fileโ prints tofileabout **why archive members are extracted. the receipts, basically ๐งพ- *
--why-live=glob* โ for each symbol matching the glob, report a whole chain of references that's preventing garbage collection. detective mode ๐ - *
--wrap=symbol* โ redirect references tosymbolover to__wrap_symbol, and references to__real_symbolback tosymbol. identity theft, but make it linker ๐ญ
๐
the -z option ๐
Linker option extensions. the little extra-spicy menu ๐ถ๏ธ
dead-reloc-in-nonalloc=section_glob=valueโ resolves a relocation in a matched non-SHF_ALLOCsection that references a discarded symbol, setting it tovalue. accepts globs, and if a section matches more than one option, **the last option takes precedence. an order of least specific to most specific match is recommended, mwah ๐execstackโ makes the main stack executable. stack permissions get recorded in thePT_GNU_STACKsegment โ ๏ธ- **
bti-report=[none|warning|error] โ specifies how to report the missingGNU_PROPERTY_AARCH64_FEATURE_1_BTIproperty.noneis the default, so the linker won't report the missing property; otherwise it gets reported as a warning or an error ๐จ - **
cet-report=[none|warning|error] โ specifies how to report the missingGNU_PROPERTY_X86_FEATURE_1_IBTorGNU_PROPERTY_X86_FEATURE_1_SHSTKproperties.noneis the default, no report; otherwise warning or error ๐ธ - **
gcs-report=[none|warning|error] โ specifies how to report a missingGNU_PROPERTY_AARCH64_FEATURE_1_GCSproperty.GNU_PROPERTY_AARCH64_FEATURE_1_GCSindicates that an object file supports the Guarded Control Stack security feature.noneis the default, no report; otherwise warning or error ๐ก๏ธ dynamic-undefined-weakโ makes undefined weak symbols dynamic when the dynamic symbol table is present, if they're referenced from relocatable object files and are not forced local by symbol visibility or versioning. don't make them dynamic whennodynamic-undefined-weakis specified.dynamic-undefined-weakis the default when building a shared object, or when an input shared object is present โจ- **
pauth-report=[none|warning|error] โ specifies how to report the missingGNU_PROPERTY_AARCH64_FEATURE_PAUTHproperty.noneis the default, no report; otherwise warning or error ๐ force-btiโ force-enables AArch64 BTI instructions in the PLT, and warns if an input ELF file doesn't have theGNU_PROPERTY_AARCH64_FEATURE_1_BTIproperty ๐ชforce-ibtโ force-enables Intel Indirect Branch Tracking in the PLT, and warns if an input ELF file doesn't have theGNU_PROPERTY_X86_FEATURE_1_IBTproperty ๐ชglobalโ sets theDF_1_GLOBALflag in theDYNAMICsection. different loaders can decide how to handle this flag on their own ๐คทโโ๏ธifunc-nopltโ doesn't emit PLT entries for ifunc symbols. instead, emits text relocations referencing the resolver. this is an experimental optimization and only suitable for standalone environments where text relocations don't have the usual drawbacks. this option must be combined with the-z notextoption ๐งชinitfirstโ sets theDF_1_INITFIRSTflag to indicate the module should be initialized first. main character energy ๐ฅinterposeโ sets theDF_1_INTERPOSEflag to tell the runtime linker that the object is an interposer. during symbol resolution, interposers are searched after the application but before other dependencies ๐ฏlrodata-after-bssโ places.lrodataafter.bss. the way that ordering works ๐ซถmuldefsโ don't error out if a symbol is defined multiple times; the first definition wins. this is a synonym for--allow-multiple-definition๐ฏโโ๏ธnocombrelocโ disables combining and sorting multiple relocation sections ๐ซnocopyrelocโ disables the creation of copy relocations ๐ซnodefaultlibโ sets theDF_1_NODEFLIBflag to indicate that default library search paths should be ignored ๐ โโ๏ธnodeleteโ sets theDF_1_NODELETEflag to indicate that the object can't be unloaded from a process. she stays ๐nodlopenโ sets theDF_1_NOOPENflag to indicate that the object may not be opened bydlopen(3)๐nognustackโ doesn't emit thePT_GNU_STACKsegment ๐ซnorelroโ doesn't indicate that portions of the object should be mapped read-only after initial relocation processing. the object will omit thePT_GNU_RELROsegment ๐ซnosectionheaderโ doesn't generate the section header table ๐notextโ allows relocations against read-only segments. sets theDT_TEXTRELflag in theDYNAMICsection โ ๏ธnowโ sets theDF_BIND_NOWflag to indicate that the run-time loader should do all relocation processing as part of object initialization. by default, relocations may be performed on demand. she's impatient, periodt โฐoriginโ sets theDF_ORIGINflag to indicate that the object requires$ORIGINprocessing ๐pac-pltโ AArch64 only, use pointer authentication in the PLT ๐pack-relative-relocsโ similar to-pack-dyn-relocs=relr, but it synthesizes theGLIBC_ABI_DT_RELRversion dependency if there's aGLIBC_2.*version dependency.glibcld.sorejects loading a dynamically linked object without theGLIBC_ABI_DT_RELRversion dependency ๐คrelโ use theRELformat for dynamic relocations โจrelaโ use theRELAformat for dynamic relocations โจretpolinepltโ emits retpoline-format PLT entries as a mitigation for CVE-2017-5715 ๐ก๏ธrodynamicโ makes the.dynamicsection read-only. theDT_DEBUGtag will not be emitted ๐ โโ๏ธseparate-loadable-segments,separate-code,noseparate-codeโ specify whether two adjacentPT_LOADsegments are allowed to overlap in pages.noseparate-code(default) allows overlap.separate-codeallows overlap between two executable segments, or between two non-executable segments.separate-loadable-segmentsdisallows overlap ๐shstkโ x86 only, use shadow stack ๐งตgcs=[implicit|never|always] โ specifies how theGNU_PROPERTY_AARCH64_FEATURE_1_GCSbit gets set in the output ELF file. when set, it indicates support for the Guarded Control Stack (GCS) security feature.implicit(default): the GCS feature bit is set if **all input relocatable files have a.note.gnu.propertysection containing theGNU_PROPERTY_AARCH64_FEATURE_1_GCSbit.never: clears the GCS feature bit regardless of input relocatable files' markings.always: sets the GCS feature bit regardless of input object markings ๐ก๏ธ- *
stack-size=size* โ sets the main thread's stack size tosize. the stack size is recorded as the size of the size.PT_GNU_STACKprogram segment ๐ start-stop-gcโ don't let__start_/__stop_references retain the associated C identifier name sections (default) ๐งนnostart-stop-gcโ makes those__start_/__stop_references keep the C identifier name sections they point at, instead of GC-ing them away. bestie, this is the "pls don't delete my stuff" flag ๐textโ nope, no relocations against read-only segments, we don't do that here. this one is the default, so you're already living it โจnobtcfiโ creates aPT_OPENBSD_NOBTCFIsegment ๐ฆwxneededโ creates aPT_OPENBSD_WXNEEDEDsegment ๐ธ
๐ ENVIRONMENT VARIABLES ๐
okay so ld.lld also reads your vibes from the environment, and by vibes i mean these two:
LLD_REPRODUCEโ create a reproduce tarball with the filename you give it. but heads up ๐: if--reproduceis also specified,--reproducetakes precedence. the flag wins, the env var loses, that's the hierarchy, periodt.LLD_VERSIONโld.lldcreates a section named.commentcontaining the LLD version string, and this env var lets you override that version string. why would you want that? because it eliminates differences in the binary caused by LLD version number differences ๐ literally so useful if you're diffing builds, iykyk.
๐ง IMPLEMENTATION NOTES ๐ง
okay this is lowkey the juiciest part, stay with me ๐ซถ
ld.lld's handling of archive files (the ones with a .a file extension) is different from traditional linkers used on Unix-like systems. not better, not worse, just built different, bestie.
๐ how traditional linkers do it ๐
Traditional linkers maintain a set of undefined symbols during linking. the linker processes each file in the order in which it appears on the command line, until the set of undefined symbols becomes empty. an object file is linked into the output object when it's encountered, with its undefined symbols added to the set. upon encountering an archive file, a traditional linker searches the objects contained therein, and processes those that satisfy symbols in the unresolved set.
and like... handling mutually dependent archives may be awkward when you're using a traditional linker ๐ญ archive files may have to be specified multiple times, or the special command line options --start-group and --end-group may be used to have the linker loop over the files in the group until no new symbols are added to the set. yes, that's the lore. yes, it's annoying.
๐ how ld.lld does it ๐
ld.lld records all symbols found in objects and archives as it iterates over command line arguments. so when ld.lld encounters an undefined symbol that can be resolved by an object file contained in a previously processed archive file, it immediately extracts and links it into the output object. no looping, no re-specifying, no drama โจ
โ ๏ธ but fr fr: with certain archive inputs,ld.lldmay produce different results compared to traditional linkers. in practice, large bodies of third party software have been linked withld.lldwithout material issues, so like... it's giving "trust me bestie" and honestly it delivers ๐ซถ
and if you wanna catch the sketchy cases? the --warn-backrefs option may be used to identify a linker invocation that may be incompatible with traditional Unix-like linker behavior. it's the vibe check for your link line ๐
and that's the whole page, babe ๐ you just read the entire LD.LLD(1) โ this one's a Debian joint, dated Jul 25, 2023, and it's literally iconic for it ๐ go forth and link responsibly ๐ญ๐ซถ๐
๐ฆ where this page comes from
- centos-stream 9: lld 23.1.3-1.el9 ยท Apache-2.0 WITH LLVM-exception OR NCSA
- centos-stream 9: lld 23.1.3-1.el9 ยท Apache-2.0 WITH LLVM-exception OR NCSA
- ๐ the page's license: Apache-2.0 WITH LLVM-exception
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms