Skip to content

[LLD] Adding a modern target-selection flag to the drivers #97124

@Ericson2314

Description

@Ericson2314

LLD's frontends are currently very faithful to the linkers they are based on. But that means the target-selection mechanisms they have are rather underpowered. I think would be good to have modern flags that would allow us to set the EM_* choice, ELFOSABI_* choice, and ELFKind independently (for valid combinations)

A good use for this would be better handling of the "OSABI" field. For example:

Problems

FreeBSD existing hacks

if (s.ends_with("_fbsd")) {
s = s.drop_back(5);
osabi = ELFOSABI_FREEBSD;
}

is an ad-hoc hack for FreeBSD. The corresponding code in Clang to use it is even uglier:

// Explicitly set the linker emulation for platforms that might not
// be the default emulation for the linker.
switch (Arch) {
case llvm::Triple::x86:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf_i386_fbsd");
break;
case llvm::Triple::ppc:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32ppc_fbsd");
break;
case llvm::Triple::ppcle:
CmdArgs.push_back("-m");
// Use generic -- only usage is for freestanding.
CmdArgs.push_back("elf32lppc");
break;
case llvm::Triple::mips:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32btsmip_fbsd");
break;
case llvm::Triple::mipsel:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32ltsmip_fbsd");
break;
case llvm::Triple::mips64:
CmdArgs.push_back("-m");
if (tools::mips::hasMipsAbiArg(Args, "n32"))
CmdArgs.push_back("elf32btsmipn32_fbsd");
else
CmdArgs.push_back("elf64btsmip_fbsd");
break;
case llvm::Triple::mips64el:
CmdArgs.push_back("-m");
if (tools::mips::hasMipsAbiArg(Args, "n32"))
CmdArgs.push_back("elf32ltsmipn32_fbsd");
else
CmdArgs.push_back("elf64ltsmip_fbsd");
break;
case llvm::Triple::riscv64:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf64lriscv");
break;
default:
break;
}

If Clang could use "regular" code to transform the CPU into a -m flag, and then separately tell LLD that the ELFOSABI_* is ELFOSABI_FREEBSD, that would be much cleaner.

OpenBSD has similar needs

As discussed in #92675, we ought to have CI for OpenBSD, but OpenBSD has some outstanding downstream changes that need to be upstreamed before upstream-tool-produced binaries will work, and many of those changes today assume OpenBSD->OpenBSD native compilation and so are unfit to upstream as is

#97122 is the first such patch I've rebased. This is a somewhat borderline case, as there is already blanket handling to .openbsd.random regardless of the ELFOSABI_* in use. Still, "stealing names" from all ELF usages of LLD doesn't seem very elegant, even if the .openbsd.random case is grandfathered in --- I much rather start requiring ELFOSABI_OPENBSD with the .openbsd.random case deprecated with a warning. That said, if doing this would require a _obsd hack like FreeBSD's _fbsd, I can't help but think the medicine is as almost as bad is the disease.

Solutions

Proposal A: --target flag

Add a flag for "regular" LLVM triples --- like Clang's --target or LLVM's -mtriple --- so we have more expressive power. Those triples should be mostly possible to map to the choices above, and -m flags could still be used to fill in the gaps.

Advantages:

  • "no new syntax"
  • tools like Clang can just forward their --target argument as-is and hope for the best

Disadvantages:

LLVM triples can both say to much and too little

Proposal B: New greenfield flags

Add multiple new flags for specifying the these parts independently. Certainly ELFOSABI_ needs one. -m does the EM_ and ELFKind residual alright, perhaps, or perhaps they get fresh new flags too.

Advantages: No syntax vs semantics mismatch / friction / corner cases.

Disadvantage: Greenfield new flags for other tooling to have to learn about.


CC @brad0 because OpenBSD

C @mstorsjo because I am curious if Windows stuff has similar needs / not sure what to do about lld-link (clang-cl takes --target and many other GNU-style flags, but lld-link only takes /flag MS-style-flags)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementImproving things as opposed to bug fixing, e.g. new or missing featurelld:ELF

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions