Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -153,6 +153,7 @@ bool Target1Rel; bool Trace; bool UndefinedVersion; + bool WarnBackrefs; bool WarnCommon; bool WarnMissingEntry; bool WarnSymbolOrdering; Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -704,6 +704,8 @@ Config->UndefinedVersion = Args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, true); Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args); + Config->WarnBackrefs = + Args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false); Config->WarnCommon = Args.hasFlag(OPT_warn_common, OPT_no_warn_common, false); Config->WarnSymbolOrdering = Args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true); @@ -937,6 +939,16 @@ Files.back()->JustSymbols = true; } break; + case OPT_start_group: + if (InputFile::IsInGroup) + error("nested --start-group"); + InputFile::IsInGroup = true; + break; + case OPT_end_group: + if (!InputFile::IsInGroup) + error("stray --end-group"); + InputFile::IsInGroup = false; + break; case OPT_start_lib: InLib = true; break; Index: lld/trunk/ELF/InputFiles.h =================================================================== --- lld/trunk/ELF/InputFiles.h +++ lld/trunk/ELF/InputFiles.h @@ -112,6 +112,13 @@ // True if this is an argument for --just-symbols. Usually false. bool JustSymbols = false; + // GroupId is used for --warn-backrefs which is an optional error + // checking feature. All files within the same --{start,end}-group + // get the same group ID. Otherwise, each file gets a new group + // ID. For more info, see checkDependency() in SymbolTable.cpp. + uint32_t GroupId; + static bool IsInGroup; + protected: InputFile(Kind K, MemoryBufferRef M); std::vector Sections; @@ -119,6 +126,8 @@ private: const Kind FileKind; + + static uint32_t NextGroupId; }; template class ELFFileBase : public InputFile { Index: lld/trunk/ELF/InputFiles.cpp =================================================================== --- lld/trunk/ELF/InputFiles.cpp +++ lld/trunk/ELF/InputFiles.cpp @@ -38,6 +38,8 @@ using namespace lld; using namespace lld::elf; +bool InputFile::IsInGroup; +uint32_t InputFile::NextGroupId; std::vector elf::BinaryFiles; std::vector elf::BitcodeFiles; std::vector elf::ObjectFiles; @@ -45,7 +47,13 @@ TarWriter *elf::Tar; -InputFile::InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} +InputFile::InputFile(Kind K, MemoryBufferRef M) + : MB(M), GroupId(NextGroupId), FileKind(K) { + // All files within the same --{start,end}-group get the same group ID. + // Otherwise, a new file will get a new group ID. + if (!IsInGroup) + ++NextGroupId; +} Optional elf::readFile(StringRef Path) { // The --chroot option changes our virtual root directory. @@ -760,8 +768,10 @@ if (Tar && C.getParent()->isThin()) Tar->append(relativeToRoot(CHECK(C.getFullName(), this)), MB.getBuffer()); - return createObjectFile(MB, getName(), - C.getParent()->isThin() ? 0 : C.getChildOffset()); + InputFile *File = createObjectFile( + MB, getName(), C.getParent()->isThin() ? 0 : C.getChildOffset()); + File->GroupId = GroupId; + return File; } template @@ -1168,7 +1178,10 @@ MemoryBufferRef MBRef = getBuffer(); if (MBRef.getBuffer().empty()) return nullptr; - return createObjectFile(MBRef, ArchiveName, OffsetInArchive); + + InputFile *File = createObjectFile(MBRef, ArchiveName, OffsetInArchive); + File->GroupId = GroupId; + return File; } template void LazyObjFile::parse() { Index: lld/trunk/ELF/Options.td =================================================================== --- lld/trunk/ELF/Options.td +++ lld/trunk/ELF/Options.td @@ -113,6 +113,9 @@ def enable_new_dtags: F<"enable-new-dtags">, HelpText<"Enable new dynamic tags">; +def end_group: F<"end-group">, + HelpText<"Ignored for compatibility with GNU unless you pass --warn-backrefs">; + def end_lib: F<"end-lib">, HelpText<"End a grouping of objects that should be treated as if they were together in an archive">; @@ -274,6 +277,9 @@ defm sort_section: Eq<"sort-section">, HelpText<"Specifies sections sorting rule when linkerscript is used">; +def start_group: F<"start-group">, + HelpText<"Ignored for compatibility with GNU unless you pass --warn-backrefs">; + def start_lib: F<"start-lib">, HelpText<"Start a grouping of objects that should be treated as if they were together in an archive">; @@ -323,6 +329,10 @@ defm version_script: Eq<"version-script">, HelpText<"Read a version script">; +defm warn_backrefs: B<"warn-backrefs", + "Warn about backward symbol references to fetch archive members", + "Do not warn about backward symbol references to fetch archive members">; + defm warn_common: B<"warn-common", "Warn about duplicate common symbols", "Do not warn about duplicate common symbols">; @@ -357,6 +367,7 @@ def alias_discard_all_x: Flag<["-"], "x">, Alias; def alias_discard_locals_X: Flag<["-"], "X">, Alias; def alias_emit_relocs: Flag<["-"], "q">, Alias; +def alias_end_group_paren: Flag<["-"], ")">, Alias; def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias; def alias_export_dynamic_E: Flag<["-"], "E">, Alias; def alias_filter: Separate<["-"], "F">, Alias; @@ -374,6 +385,7 @@ def alias_script_T: JoinedOrSeparate<["-"], "T">, Alias