Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Linkers Lto

ASecurity

Use when choosing a linker, fixing link order or undefined symbol errors, enabling LTO or ThinLTO, or cutting dead code with --gc-sections. Not for inspecting the linked binary: use elf-inspection.

54 stars
0 votes
0 copies
0 views
Added 9/20/2026
ai-agentsgoc++bashapiperformance

Works with

api

Security Analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned 9/20/2026

$npx -y skills add OutlineDriven/outline-driven-development --skill linkers-lto --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Linkers Lto?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Linkers Lto
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/outlinedriven-linkers-lto-outline-driven-development/badge)](https://www.skillsdirectory.com/skills/outlinedriven-linkers-lto-outline-driven-development)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: linkers-lto
description: 'Use when choosing a linker, fixing link order or undefined symbol errors, enabling LTO or ThinLTO, or cutting dead code with --gc-sections. Not for inspecting the linked binary: use elf-inspection.'
---

# Linkers and LTO

The linker turns object files into one binary and decides what survives from each translation unit. Most link failures are order problems; most size wins are LTO plus dead-code removal.

## Contract

| Field | Bound contract |
|---|---|
| Trigger | The task fixes `undefined reference` or `multiple definition` errors, selects a linker, enables LTO or ThinLTO, removes dead code, controls symbol visibility, or reads a linker map. |
| Authority | Reversible local: writes only build flags, linker scripts, and build outputs; rollback is version control and a rebuild. No remote mutation. |
| Side effect | Local writes to the outputs the build produces and to build configuration the user names. |
| Done | The link succeeds with the intended flags, or the size and visibility changes are proven by the map, `--print-gc-sections`, or `nm -D` output. |

## Inputs

- The failing link command or build configuration: required.
- Toolchain in use: required. GCC and Clang differ in LTO setup and archive tools.
- Whether LTO must be incremental: required before choosing ThinLTO over full LTO.

## Procedure

1. Select the linker through the compiler driver. `ld` is the universal default, `gold` is the retired-in-name C++ linker kept for legacy builds, `lld` is the fast choice and the practical requirement for Clang LTO on large projects. Verify which linker actually ran from the driver's verbose output. Done when: the build uses the intended linker.

```bash
gcc  -fuse-ld=lld -o prog main.c
clang -fuse-ld=lld -o prog main.c
gcc -v main.c -o prog 2>&1 | grep 'collect2\|ld\.new\|lld'
```

2. Pass flags correctly. The driver forwards linker flags after `-Wl,` with commas instead of spaces. Done when: `readelf -d` or the map shows the flag took effect.

```bash
gcc main.o -o prog \
  -Wl,-rpath,/opt/mylibs/lib \
  -Wl,--as-needed \
  -Wl,--gc-sections \
  -Wl,-z,relro -Wl,-z,now \
  -L/opt/mylibs/lib -lfoo
```

3. Fix link order. GNU ld resolves archives left to right; a library must follow the objects that use it. Circular archive dependencies need a group. Done when: the link succeeds without suppression flags.

```bash
gcc main.o -lfoo -ldep -o prog                    # dependents first
gcc main.o -Wl,--start-group -lfoo -lbar -Wl,--end-group -o prog
```

4. Enable LTO with GCC. Every compile and the final link carry `-flto` with the same optimization level. LTO archives must be built with `gcc-ar` and `gcc-ranlib`, because plain `ar` cannot build the LTO symbol index. Done when: the link succeeds and size or performance improves against the non-LTO build.

```bash
gcc -O2 -flto -ffunction-sections -fdata-sections -c foo.c -o foo.o
gcc -O2 -flto -Wl,--gc-sections foo.o bar.o -o prog
gcc-ar rcs libfoo.a foo.o
gcc-ranlib libfoo.a
gcc -O2 -flto=auto foo.o bar.o -o prog   # parallel, uses the make jobserver
```

5. Enable ThinLTO with Clang. ThinLTO parallelizes across machines and caches results, so incremental links stay fast. Done when: the link succeeds and the ThinLTO cache directory fills.

```bash
clang -O2 -flto=thin -fuse-ld=lld foo.c bar.c -o prog
```

In CMake, `set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)` selects the right LTO mode per compiler.

6. Remove dead code. `--gc-sections` discards unreferenced sections, which only exist if compilation used `-ffunction-sections -fdata-sections`. Done when: `--print-gc-sections` reports the removals and the binary still runs.

```bash
gcc -O2 -ffunction-sections -fdata-sections -c foo.c -o foo.o
gcc -Wl,--gc-sections -Wl,--print-gc-sections foo.o -o prog
```

7. Control visibility for LTO quality and DSO size. Hide everything, export the API. Done when: `nm -D --defined-only libfoo.so` lists only the public API.

```bash
gcc -fvisibility=hidden -O2 -shared -fPIC foo.c -o libfoo.so
```

```text
# foo.ver
{
  global: my_public_function; my_other_public;
  local: *;
};
```

```bash
gcc -Wl,--version-script=foo.ver -shared -fPIC -o libfoo.so foo.o
```

8. Read the map file when size or placement puzzles. Every symbol's origin and address is in the map. Done when: the surprising symbol is traced to its object and input section.

```bash
gcc -Wl,-Map=prog.map -o prog foo.o bar.o
```

9. Diagnose by error class. Done when: each error maps to its row and the fix is applied.

| Error | Cause | Fix |
|-------|-------|-----|
| `undefined reference to 'foo'` | Missing or misordered library | Add `-lfoo` after the objects that need it |
| `multiple definition of 'foo'` | Symbol defined in two objects | Keep one definition, or declare the other `extern` |
| `cannot find -lfoo` | Library outside `-L` paths | Add `-L` or install the development package |
| `relocation truncated to fit` | Address outside the relocation's reach | Use `-mcmodel=large`, or restructure the image layout |
| `version 'GLIBC_2.xx' not found` | Built on a newer glibc | Build on the older host or link statically |
| LTO bytecode mismatch | Mixed LTO and non-LTO objects | Recompile every object with the same `-flto` |
| `file format not recognized` | Foreign architecture object | Use the matching cross toolchain for all objects |

## Failure and recovery

| Failure class | Behavior |
|---|---|
| LTO build fails on one object | That object was compiled without `-flto`. Recompile it with the same flags as the rest. |
| `--gc-sections` removed a needed section | Something referenced it only from assembly or a linker script. Add `KEEP(*(...))` in the script, or the reference. |
| ThinLTO cache grows without bound | Point `-Wl,--thinlto-cache-dir` at a managed path and clear it on a schedule. |
| A group link got slow | `--start-group` rescans archives until fixed point. Resolve the cycle explicitly instead of leaving the group in place. |
| LTO changed behavior | Inlining across units can expose latent UB. Reproduce without LTO, then fix the source. |

## Output

The linked binary plus the evidence for each decision: linker chosen, map excerpts, `--print-gc-sections` output, or `nm -D` export lists. The full flag tables, lld extras, MSVC `/GL /LTCG`, and a linker script skeleton are in `references/flags.md`.

Attribution

OutlineDrivenOutlineDriven
View sourceSee grades on GitHubMore from OutlineDriven →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Terse caveman voice: answer first, fluff gone, every technical fact kept. Use for /caveman, "caveman mode", "talk like caveman", "be brief", "less tokens". Stays on until "stop caveman" or "normal mode".

1100021 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

698621 votes

Writing Skills

Create and manage Claude Code skills in HASH repository following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns), UserPromptSubmit hook, and the 500-line rule. Includes validation and debugging with SKILL_DEBUG. Examples include rust-error-stack, cargo-dep...

3931 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3421 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Amp, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Grok Build, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

741 votes
View all in ai-agents →