Skip to content

Instantly share code, notes, and snippets.

@mszoek
CreatedApril 3, 2022 21:10
    LLVM patches for ELF Framework bundles on FreeBSD
    diff --git a/contrib/llvm-project/clang/include/clang/Driver/Options.td b/contrib/llvm-project/clang/include/clang/Driver/Options.td
    index a0cbcae0bdc3..a5ef948450c3 100644
    --- a/contrib/llvm-project/clang/include/clang/Driver/Options.td
    +++ b/contrib/llvm-project/clang/include/clang/Driver/Options.td
    @@ -634,7 +634,7 @@ def D : JoinedOrSeparate<["-"], "D">, Group<Preprocessor_Group>,
    HelpText<"Define <macro> to <value> (or 1 if <value> omitted)">;
    def E : Flag<["-"], "E">, Flags<[NoXarchOption,CC1Option, FlangOption, FC1Option]>, Group<Action_Group>,
    HelpText<"Only run the preprocessor">;
    -def F : JoinedOrSeparate<["-"], "F">, Flags<[RenderJoined,CC1Option]>,
    +def F : JoinedOrSeparate<["-"], "F">, Flags<[RenderJoined,CC1Option,LinkerInput]>,
    HelpText<"Add directory to framework include search path">;
    def G : JoinedOrSeparate<["-"], "G">, Flags<[NoXarchOption]>, Group<m_Group>,
    MetaVarName<"<size>">, HelpText<"Put objects of at most <size> bytes "
    diff --git a/contrib/llvm-project/clang/lib/Basic/ObjCRuntime.cpp b/contrib/llvm-project/clang/lib/Basic/ObjCRuntime.cpp
    index cfc437409b5d..1f803e090339 100644
    --- a/contrib/llvm-project/clang/lib/Basic/ObjCRuntime.cpp
    +++ b/contrib/llvm-project/clang/lib/Basic/ObjCRuntime.cpp
    @@ -72,7 +72,7 @@ bool ObjCRuntime::tryParse(StringRef input) {
    } else if (runtimeName == "gnustep") {
    // If no version is specified then default to the most recent one that we
    // know about.
    - Version = VersionTuple(1, 6);
    + Version = VersionTuple(2, 0);
    kind = ObjCRuntime::GNUstep;
    } else if (runtimeName == "gcc") {
    kind = ObjCRuntime::GCC;
    diff --git a/contrib/llvm-project/clang/lib/Basic/Targets/OSTargets.h b/contrib/llvm-project/clang/lib/Basic/Targets/OSTargets.h
    index 3fe39ed64d9c..97ef94bdc90b 100644
    --- a/contrib/llvm-project/clang/lib/Basic/Targets/OSTargets.h
    +++ b/contrib/llvm-project/clang/lib/Basic/Targets/OSTargets.h
    @@ -218,6 +218,8 @@
    @@ -6984,7 +6984,7 @@ ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
    objcABIVersion = 1 + nonFragileABIVersion;
    } else {
    - objcABIVersion = 1;
    + objcABIVersion = 3;
    }
    }
    diff --git a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
    index 5dcf74dabf4f..94a11cb60f2b 100644
    --- a/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
    +++ b/contrib/llvm-project/clang/lib/Driver/ToolChains/FreeBSD.cpp
    @@ -12,6 +12,7 @@
    #include "Arch/Sparc.h"
    #include "CommonArgs.h"
    #include "clang/Driver/Compilation.h"
    +#include "clang/Driver/Driver.h"
    #include "clang/Driver/DriverDiagnostic.h"
    #include "clang/Driver/Options.h"
    #include "clang/Driver/SanitizerArgs.h"
    @@ -247,6 +248,27 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
    assert(Output.isNothing() && "Invalid output.");
    }
    + CmdArgs.push_back("-F");
    + CmdArgs.push_back("/System/Library/Frameworks");
    + CmdArgs.push_back("-F");
    + CmdArgs.push_back("/Library/Frameworks");
    +
    + Driver::InputList PPInputs;
    + D.BuildInputs(C.getDefaultToolChain(), C.getArgs(), PPInputs);
    +
    + // Auto
    if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
    const char *crt1 = nullptr;
    if (!Args.hasArg(options::OPT_shared)) {
    @@ -281,7 +303,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
    Args.AddAllArgs(CmdArgs, options::OPT_t);
    Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
    Args.AddAllArgs(CmdArgs, options::OPT_r);
    -
    +
    if (D.isUsingLTO()) {
    assert(!Inputs.empty() && "Must have at least one input.");
    addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
    diff --git a/contrib/llvm-project/clang/lib/Frontend/InitHeaderSearch.cpp b/contrib/llvm-project/clang/lib/Frontend/InitHeaderSearch.cpp
    index ba9f96384f81..5aa10c20e716 100644
    --- a/contrib/llvm-project/clang/lib/Frontend/InitHeaderSearch.cpp
    +++ b/contrib/llvm-project/clang/lib/Frontend/InitHeaderSearch.cpp
    @@ -447,14 +447,14 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
    }
    // All header search logic is handled in the Driver for Darwin.
    - if (triple.isOSDarwin()) {
    + //if (triple.isOSDarwin()) {
    if (HSOpts.UseStandardSystemIncludes) {
    // Add the default framework include paths on Darwin.
    AddPath("/System/Library/Frameworks", System, true);
    AddPath("/Library/Frameworks", System, true);
    }
    - return;
    - }
    + //return;
    + //}
    if (Lang.CPlusPlus && !Lang.AsmPreprocessor &&
    HSOpts.UseStandardCXXIncludes && HSOpts.UseS
    }
    uptr internal_rename(const char *oldpath, const char *newpath) {
    -#if defined(__riscv)
    +#if defined(__riscv) && defined(__linux__)
    return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
    (uptr)newpath, 0);
    #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
    @@ -1218,7 +1218,8 @@ void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
    }
    #endif
    -#if defined(__x86_64__) && SANITIZER_LINUX
    +#if SANITIZER_LINUX
    +#if defined(__x86_64__)
    // We cannot use glibc's clone wrapper, because it messes with the child
    // task's TLS. It writes the PID and TID of the child task to its thread
    // descriptor, but in our case the child task shares the thread descriptor with
    diff --git a/contrib/llvm-project/lld/ELF/Config.h b/contrib/llvm-project/lld/ELF/Config.h
    index e1abb4dfab36..64ac9d0a766b 100644
    --- a/contrib/llvm-project/lld/ELF/Config.h
    +++ b/contrib/llvm-project/lld/ELF/Config.h
    @@ -135,6 +135,8 @@ struct Configuration {
    std::vector<llvm::StringRef> auxiliaryList;
    std::vector<llvm::StringRef> filterList;
    std::vector<llvm::StringRef> searchPaths;
    + std::vector<llvm::StringRef> frameworkSearchPaths;
    + std::vector<std::string> frameworkRunPaths;
    std::vector<llvm::StringRef> symbolOrderingFile;
    std::vector<llvm::StringRef> thinLTOModulesToCompile;
    std::vector<llvm::StringRef> undefined;
    @@ -199,6 +201,7 @@ struct Configuration {
    bool optRemarksWithHotness;
    bool picThunk;
    bool pie;
    + bool preservePath;
    bool printGcSections;
    bool printIcfSections;
    bool relocatable;
    diff --git a/contrib/llvm-project/lld/ELF/Driver.cpp b/contrib/llvm-project/lld/ELF/Driver.cpp
    index 594c20016827..33d346a346ea 100644
    --- a/contrib/llvm-project/lld/ELF/Driver.cpp
    +++ b/contrib/llvm-project/lld/ELF/Driver.cpp
    @@ -62,6 +62,7 @@
    #include "llvm/Support/raw_ostream.h"
    #include <cstdlib>
    #include <utility>
    +#include <unistd.h> // readlink
    using namespace llvm;
    using namespace llvm::ELF;
    @@ -272,8 +273,12 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) {
    // If a file was speci
    }
    +// Add all libraries within a framework found on the framework search path
    +void LinkerDriver::addFramework(StringRef name) {
    + if (Optional<std::string> path = searchFramework(name)) {
    + path->append("/Versions/");
    +
    + std::string rpath(path.getValue());
    +
    + path->append("Current");
    + config->searchPaths.push_back(path.getValue());
    +
    + char buffer[_POSIX_PATH_MAX];
    + int count = ::readlink(path.getValue().c_str(), buffer, sizeof(buffer));
    + if(count > 0)
    + rpath.append(buffer, buffer + count);
    + else
    + rpath.append("Current");
    +
    + // handle frameworks relative to executable (in the app bundle)
    + if(llvm::sys::path::is_relative(Twine(rpath))) {
    + std::string opath("$ORIGIN");
    + opath.append("/");
    + opath.append(rpath);
    + rpath = opath;
    + }
    + config->frameworkRunPaths.push_back(rpath);
    +
    + // Now that we've added the current version folder of the framework, find
    + // all the shared libs inside it and add them to the link
    + std::error_code EC;
    + llvm::sys::fs::directory_iterator Dir = llvm::sys::fs::directory_iterator(Twine(path.getValue()), EC, true);
    + llvm::sys::fs::directory_iterator DirEnd;
    + for(Dir; Dir != DirEnd && !EC; Dir.increment(EC)) {
    + i
    config->filterList = args::getStrings(args, OPT_filter);
    config->fini = args.getLastArgValue(OPT_fini, "_fini");
    + config->frameworkSearchPaths = args::getStrings(args, OPT_F);
    config->fixCortexA53Errata843419 = args.hasArg(OPT_fix_cortex_a53_843419) &&
    !args.hasArg(OPT_relocatable);
    config->fixCortexA8 =
    @@ -1484,6 +1531,9 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
    case OPT_library:
    addLibrary(arg->getValue());
    break;
    + case OPT_framework:
    + addFramework(arg->getValue());
    + break;
    case OPT_INPUT:
    addFile(arg->getValue(), /*withLOption=*/false);
    break;
    @@ -1571,6 +1621,9 @@ void LinkerDriver::createFiles(opt::InputArgList &args) {
    std::tie(config->asNeeded, config->isStatic, inWholeArchive) = stack.back();
    stack.pop_back();
    break;
    + case OPT_preserve_path:
    + config->preservePath = true;
    + break;
    }
    }
    diff --git a/contrib/llvm-project/lld/ELF/Driver.h b/contrib/llvm-project/lld/ELF/Driver.h
    index 96d040041c5a..edc985b3d76c 100644
    --- a/contrib/llvm-project/lld/ELF/Driver.h
    +++ b/contrib/llvm-project/lld/ELF/Driver.h
    @@ -29,6 +29,7 @@ class LinkerDriver {
    void linkerMain(ArrayRef<const char *> args);
    void addFile(StringRef path, bool withLOption);
    void addLibrary(StringRef name);
    + void addFramework(StringRef name);
    } // namespace lld
    diff --git a/contrib/llvm-project/lld/ELF/DriverUtils.cpp b/contrib/llvm-project/lld/ELF/DriverUtils.cpp
    index f49deb9012b2..b2444c82cafe 100644
    --- a/contrib/llvm-project/lld/ELF/DriverUtils.cpp
    +++ b/contrib/llvm-project/lld/ELF/DriverUtils.cpp
    @@ -251,6 +251,14 @@ Optional<std::string> elf::searchLibrary(StringRef name) {
    return searchLibraryBaseName(name);
    }
    +Optional<std::string> elf::searchFramework(StringRef name) {
    + for (StringRef dir : config->frameworkSearchPaths) {
    + if (Optional<std::string> s = findFile(dir, name + ".framework"))
    + return s;
    + }
    + return None;
    +}
    +
    // If a linker/version script doesn't exist in the current directory, we also
    // look for the script in the '-L' search paths. This matches the behaviour of
    // '-T', --version-script=, and linker script INPUT() command in ld.bfd.
    diff --git a/contrib/llvm-project/lld/ELF/InputFiles.cpp b/contrib/llvm-project/lld/ELF/InputFiles.cpp
    index d5b9efbe18fc..0a031fd6cebc 100644
    --- a/contrib/llvm-project/lld/ELF/InputFiles.cpp
    +++ b/contrib/llvm-project/lld/ELF/InputFiles.cpp
    @@ -1491,7 +1491,8 @@ template <class ELFT> void SharedFile::parse() {
    uint64_t val = dyn.getVal();
    if (val >= this->stringTable.size())
    fatal(toString(this) + ": invalid DT_SONAME entry");
    - soName = this->stringTable.data() + val;
    + if(!config->preservePath)
    + soName = this->stringTable.data() + val;
    }
    }
    diff --git a/contrib/llvm-project/lld/ELF/Options.td b/contri
    index f0e4c11b79eb..24ba51d39228 100644
    --- a/contrib/llvm-project/lld/ELF/Options.td
    +++ b/contrib/llvm-project/lld/ELF/Options.td
    @@ -52,6 +52,16 @@ def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">;
    def build_id: F<"build-id">, HelpText<"Alias for --build-id=fast">;
    +def F : JoinedOrSeparate<["-"], "F">,
    + MetaVarName<"<dir>">,
    + HelpText<"Add directory to framework search path">;
    +
    +def framework : Separate<["-"], "framework">,
    + MetaVarName<"<name>">,
    + HelpText<"Base name of framework searched for in -F directories">;
    +
    +def preserve_path : FF<"preserve-path">, HelpText<"Preserve full path of DSOs">;
    +
    def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">,
    MetaVarName<"[fast,md5,sha1,uuid,0x<hexstring>]">;
    @@ -516,7 +526,7 @@ def: Flag<["-"], "q">, Alias<emit_relocs>, HelpText<"Alias for --emit-relocs">;
    def: Flag<["-"], ")">, Alias<end_group>, HelpText<"Alias for --end-group">;
    def: JoinedOrSeparate<["-"], "e">, Alias<entry>, HelpText<"Alias for --entry">;
    def: Flag<["-"], "E">, Alias<export_dynamic>, HelpText<"Alias for --export-dynamic">;
    -def: Separate<["-"], "F">, Alias<filter>, HelpText<"Alias for --filter">;
    +//def: Separate<["-"], "F">, Alias<filter>, HelpText<"Alias for --filter">;
    def: Separate<["-"], "b">, Alias<format>, HelpText<"Alias for --format">;
    def: JoinedOrSeparate<["-"], "l">, Alias<library>, HelpText<"Alias for --library">;
    def: JoinedOrSeparate<["-"], "L">, Alias<library_path>, HelpText<"Alias for --library-path">;
    diff --git a/contrib/llvm-project/lld/ELF/SyntheticSections.cpp b/contrib/llvm-project/lld/ELF/SyntheticSections.cpp
    index 187b2ac90c21..b43e4463b228 100644
    --- a/contrib/llvm-project/lld/ELF/SyntheticSections.cpp
    +++ b/contrib/llvm-project/lld/ELF/SyntheticSections.cpp
    @@ -1336,6 +1336,14 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
    for (StringRef s : config->auxiliaryList)
    addInt(DT_AUXILIARY, part.dynStrTab->addString(s));
    + if (!config->frameworkRunPaths.empty()) {
    + std::string s(llvm::join(config->frameworkRunPaths.begin(),config->frameworkRunPaths.end(),":"));
    + if(config->rpath.empty())
    + config->rpath = s;
    + else
    + config->rpath.append(":" + s);
    + }
    +
    if (!config->rpath.empty())
    addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH,
    part.dynStrTab->addString(config->rpath));
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment