certain architectures. The options class can be instantiated from command
line options, or it can be subclassed and the ivars programmatically set.
-ELF Section Groups
-~~~~~~~~~~~~~~~~~~
-Reference : `ELF Section Groups <http://mentorembedded.github.io/cxx-abi/abi/prop-72-comdat.html>`_
-
-C++ has many situations where the compiler may need to emit code or data,
-but may not be able to identify a unique compilation unit where it should be
-emitted. The approach chosen by the C++ ABI group to deal with this problem, is
-to allow the compiler to emit the required information in multiple compilation
-units, in a form which allows the linker to remove all but one copy. This is
-essentially the feature called COMDAT in several existing implementations.
-
-The COMDAT sections in ELF are modeled by using '.group' sections in the input
-files. Each '.group' section is associated with a signature. The '.group'
-section has a list of members that are part of the the '.group' which the linker
-selects to appear in the input file(Whichever .group section appeared first
-in the link). References to any of the '.group' members can also appear from
-outside the '.group'.
-
-In lld the the '.group' sections with COMDAT are identified by contentType(
-typeGroupComdat). The '.group' members are identified by using
-**kindGroupChild** references.
-
-The point to be noted here is the 'group child' members would need to be emitted
-in the output file **iff** the group was selected by the resolver.
-
-This is modeled in lld by removing the 'group child' members from the
-definedAtom List.
-
-Any reference to the group-child from **outside the group** is referenced using
-a 'undefined' atom.
-
Resolving
~~~~~~~~~
typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin]
typeTLVInitializerPtr, // pointer to thread local initializer [Darwin]
typeDSOHandle, // atom representing DSO handle [Darwin]
- typeThreadZeroFill, // Uninitialized thread local data(TBSS) [ELF]
- typeThreadData, // Initialized thread local data(TDATA) [ELF]
- typeRONote, // Identifies readonly note sections [ELF]
- typeRWNote, // Identifies readwrite note sections [ELF]
- typeNoAlloc, // Identifies non allocatable sections [ELF]
- typeGroupComdat, // Identifies a section group [ELF, COFF]
- typeGnuLinkOnce, // Identifies a gnu.linkonce section [ELF]
typeSectCreate, // Created via the -sectcreate option [Darwin]
};
ContentType atomContentType = contentType();
return !(atomContentType == DefinedAtom::typeZeroFill ||
atomContentType == DefinedAtom::typeZeroFillFast ||
- atomContentType == DefinedAtom::typeTLVInitialZeroFill ||
- atomContentType == DefinedAtom::typeThreadZeroFill);
- }
-
- /// Utility function to check if the atom belongs to a group section
- /// that represents section groups or .gnu.linkonce sections.
- bool isGroupParent() const {
- ContentType atomContentType = contentType();
- return (atomContentType == DefinedAtom::typeGroupComdat ||
- atomContentType == DefinedAtom::typeGnuLinkOnce);
+ atomContentType == DefinedAtom::typeTLVInitialZeroFill);
}
// Returns true if lhs should be placed before rhs in the final output.
// kindLayoutAfter is treated as a bidirected edge by the dead-stripping
// pass.
kindLayoutAfter = 1,
- // kindGroupChild is treated as a bidirected edge too.
- kindGroupChild,
kindAssociate,
};
bool undefinesAdded(int begin, int end);
File *getFile(int &index);
- /// \brief Add section group/.gnu.linkonce if it does not exist previously.
- void maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom);
-
/// \brief The main function that iterates over the files to resolve
void updatePreloadArchiveMap();
bool resolveUndefines();
/// @brief if atom has been coalesced away, return true
bool isCoalescedAway(const Atom *);
- /// @brief Find a group atom.
- const Atom *findGroup(StringRef name);
-
- /// @brief Add a group atom and returns true/false depending on whether the
- /// previously existed.
- bool addGroup(const DefinedAtom &da);
-
private:
typedef llvm::DenseMap<const Atom *, const Atom *> AtomToAtom;
LinkingContext &_ctx;
AtomToAtom _replacedAtoms;
NameToAtom _nameTable;
- NameToAtom _groupTable;
AtomContentSet _contentTable;
};
case typeDTraceDOF:
case typeCompactUnwindInfo:
case typeProcessedUnwindInfo:
- case typeRONote:
- case typeNoAlloc:
case typeObjCImageInfo:
case typeObjCMethodList:
return permR__;
case typeLazyDylibPointer:
case typeNonLazyPointer:
case typeThunkTLV:
- case typeRWNote:
return permRW_;
case typeGOT:
case typeTLVInitialData:
case typeTLVInitialZeroFill:
case typeTLVInitializerPtr:
- case typeThreadData:
- case typeThreadZeroFill:
return permRW_L;
- case typeGroupComdat:
- case typeGnuLinkOnce:
case typeUnknown:
case typeTempLTO:
case typeSectCreate:
static const Registry::KindStrings kindStrings[] = {
{Reference::kindLayoutAfter, "layout-after"},
- {Reference::kindGroupChild, "group-child"},
{Reference::kindAssociate, "associate"},
LLD_KIND_STRING_END};
return newUndefAdded;
}
-/// \brief Add the section group and the group-child reference members.
-void Resolver::maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom) {
- // First time adding a group?
- bool isFirstTime = _symbolTable.addGroup(atom);
-
- if (!isFirstTime) {
- // If duplicate symbols are allowed, select the first group.
- if (_ctx.getAllowDuplicates())
- return;
- auto *prevGroup = dyn_cast<DefinedAtom>(_symbolTable.findGroup(atom.name()));
- assert(prevGroup &&
- "Internal Error: The group atom could only be a defined atom");
- // The atoms should be of the same content type, reject invalid group
- // resolution behaviors.
- if (atom.contentType() == prevGroup->contentType())
- return;
- llvm::errs() << "SymbolTable: error while merging " << atom.name()
- << "\n";
- llvm::report_fatal_error("duplicate symbol error");
- }
-
- for (const Reference *r : atom) {
- if (r->kindNamespace() == lld::Reference::KindNamespace::all &&
- r->kindValue() == lld::Reference::kindGroupChild) {
- const DefinedAtom *target = dyn_cast<DefinedAtom>(r->target());
- assert(target && "Internal Error: kindGroupChild references need to "
- "be associated with Defined Atoms only");
- _atoms.push_back(target);
- _symbolTable.add(*target);
- }
- }
-}
-
// Called on each atom when a file is added. Returns true if a given
// atom is added to the symbol table.
void Resolver::doDefinedAtom(const DefinedAtom &atom) {
// add to list of known atoms
_atoms.push_back(&atom);
-
- if (atom.isGroupParent()) {
- maybeAddSectionGroupOrGnuLinkOnce(atom);
- } else {
- _symbolTable.add(atom);
- }
+ _symbolTable.add(atom);
// An atom that should never be dead-stripped is a dead-strip root.
if (_ctx.deadStrip() && atom.deadStrip() == DefinedAtom::deadStripNever) {
static bool isBackref(const Reference *ref) {
if (ref->kindNamespace() != lld::Reference::KindNamespace::all)
return false;
- return (ref->kindValue() == lld::Reference::kindLayoutAfter ||
- ref->kindValue() == lld::Reference::kindGroupChild);
+ return (ref->kindValue() == lld::Reference::kindLayoutAfter);
}
// remove all atoms not actually used
return false;
}
-const Atom *SymbolTable::findGroup(StringRef sym) {
- NameToAtom::iterator pos = _groupTable.find(sym);
- if (pos == _groupTable.end())
- return nullptr;
- return pos->second;
-}
-
-bool SymbolTable::addGroup(const DefinedAtom &da) {
- StringRef name = da.name();
- assert(!name.empty());
- const Atom *existing = findGroup(name);
- if (existing == nullptr) {
- _groupTable[name] = &da;
- return true;
- }
- _replacedAtoms[&da] = existing;
- return false;
-}
-
enum NameCollisionResolution {
NCR_First,
NCR_Second,
return nullptr;
}
- /// \brief Lookup a group parent when there is a reference of type
- /// kindGroupChild. If there was no group-parent produce an appropriate
- /// error.
- const lld::Atom *lookupGroupParent(StringRef name) const {
- NameToAtom::const_iterator pos = _groupMap.find(name);
- if (pos != _groupMap.end())
- return pos->second;
- _io.setError(Twine("no such group name: ") + name);
- return nullptr;
- }
-
private:
typedef llvm::StringMap<const lld::Atom *> NameToAtom;
void add(StringRef name, const lld::Atom *atom) {
- if (const lld::DefinedAtom *da = dyn_cast<DefinedAtom>(atom)) {
- if (da->isGroupParent()) {
- if (_groupMap.count(name)) {
- _io.setError(Twine("duplicate group name: ") + name);
- } else {
- _groupMap[name] = atom;
- }
- return;
- }
- }
if (_nameMap.count(name)) {
_io.setError(Twine("duplicate atom name: ") + name);
} else {
IO &_io;
NameToAtom _nameMap;
- NameToAtom _groupMap;
};
/// Mapping of Atoms.
DefinedAtom::typeTLVInitializerPtr);
io.enumCase(value, "mach_header", DefinedAtom::typeMachHeader);
io.enumCase(value, "dso_handle", DefinedAtom::typeDSOHandle);
- io.enumCase(value, "thread-data", DefinedAtom::typeThreadData);
- io.enumCase(value, "thread-zero-fill",DefinedAtom::typeThreadZeroFill);
- io.enumCase(value, "ro-note", DefinedAtom::typeRONote);
- io.enumCase(value, "rw-note", DefinedAtom::typeRWNote);
- io.enumCase(value, "no-alloc", DefinedAtom::typeNoAlloc);
- io.enumCase(value, "group-comdat", DefinedAtom::typeGroupComdat);
- io.enumCase(value, "gnu-linkonce", DefinedAtom::typeGnuLinkOnce);
io.enumCase(value, "sectcreate", DefinedAtom::typeSectCreate);
}
};
public:
NormalizedAtom(IO &io)
: _file(fileFromContext(io)), _name(), _refName(), _contentType(),
- _alignment(1), _content(), _references(), _isGroupChild(false) {
+ _alignment(1), _content(), _references() {
static uint32_t ordinalCounter = 1;
_ordinal = ordinalCounter++;
}
DynamicExport dynamicExport() const override { return _dynamicExport; }
CodeModel codeModel() const override { return _codeModel; }
ContentPermissions permissions() const override { return _permissions; }
- void setGroupChild(bool val) { _isGroupChild = val; }
- bool isGroupChild() const { return _isGroupChild; }
ArrayRef<uint8_t> rawContent() const override {
if (!occupiesDiskSpace())
return ArrayRef<uint8_t>();
StringRef _sectionName;
uint64_t _sectionSize;
std::vector<const lld::Reference *> _references;
- bool _isGroupChild;
};
static void mapping(IO &io, const lld::DefinedAtom *&atom) {
normAtom->bind(nameResolver);
}
- _definedAtoms._atoms.erase(
- std::remove_if(_definedAtoms._atoms.begin(), _definedAtoms._atoms.end(),
- [](const DefinedAtom *a) {
- return ((const NormalizedAtom *)a)->isGroupChild();
- }),
- _definedAtoms._atoms.end());
-
return this;
}
inline void MappingTraits<const lld::Reference *>::NormalizedReference::bind(
const RefNameResolver &resolver) {
- typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom NormalizedAtom;
-
_target = resolver.lookup(_targetName);
-
- if (_mappedKind.ns == lld::Reference::KindNamespace::all &&
- _mappedKind.value == lld::Reference::kindGroupChild) {
- ((NormalizedAtom *)const_cast<Atom *>(_target))->setGroupChild(true);
- }
}
inline StringRef
+++ /dev/null
----
-defined-atoms:
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
+++ /dev/null
----
-defined-atoms:
- - name: anotherfunction
- scope: global
- type: data
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: f3
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: f3
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
+++ /dev/null
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
+++ /dev/null
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
+++ /dev/null
-defined-atoms:
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
+++ /dev/null
----
-defined-atoms:
- - name: anotherfunction
- scope: global
- type: data
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: f3
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: f3
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
+++ /dev/null
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
+++ /dev/null
-# RUN: lld -core %s %p/Inputs/gnulinkonce-rearrange-resolve.objtxt | FileCheck %s
-
-#
-# Test that gnu linkonce sections are parsed and the first section selected for symbol
-# resolution
-#
-
----
-defined-atoms:
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
-...
-
-# CHECK: defined-atoms:
-# CHECK: - name: g1
-# CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-# CHECK: type: gnu-linkonce
-# CHECK: references:
-# CHECK: - kind: group-child
-# CHECK: target: f1
-# CHECK: - kind: group-child
-# CHECK: target: f2
-# CHECK: - kind: group-child
-# CHECK: target: [[CHILD:[a-zA-Z\.0-9_]+]]
-# CHECK: - kind: group-child
-# CHECK: target: d1
-# CHECK: - name: f1
-# CHECK: - name: f2
-# CHECK: - name: g1
-# CHECK: ref-name: [[CHILD]]
-# CHECK: - name: d1
+++ /dev/null
-# RUN: lld -core %s %p/Inputs/gnulinkonce-remaining-undef.objtxt \
-# RUN: %p/Inputs/gnulinkonce-remaining-undef2.objtxt | FileCheck %s
-
-#
-# Test that gnu linkonce sections are parsed and the first section selected for
-# symbol resolution. The second file which has the same gnu linkonce section has
-# a unresolved undefined symbol. lets make sure that the symbol is kept around
-# in the final link and remains undefined.
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
-...
-
-#CHECK: - name: anotherfunction
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: undefined-atoms:
-#CHECK: - name: f3
+++ /dev/null
-# RUN: lld -core %s %p/Inputs/gnulinkonce-resolve.objtxt | FileCheck %s
-
-#
-# Test that gnu linkonce sections are parsed and the first section selected for symbol
-# resolution
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
-...
-
-#CHECK: defined-atoms:
-#CHECK: - name: g1
-#CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-#CHECK: scope: global
-#CHECK: type: gnu-linkonce
-#CHECK: references:
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f2
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: [[GCHILD:[a-zA-Z\.0-9_]+]]
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: d1
-#CHECK: - name: f1
-#CHECK: scope: global
-#CHECK: - name: f2
-#CHECK: scope: global
-#CHECK: - name: g1
-#CHECK: ref-name: [[GCHILD]]
-#CHECK: scope: global
-#CHECK: - name: d1
-#CHECK: scope: global
-#CHECK: type: data
+++ /dev/null
-# RUN: lld -core %s %p/Inputs/gnulinkonce-simple.objtxt | FileCheck %s
-
-#
-# Test that gnu linkonce sections are parsed properly when there is a reference to a
-# atom from outside the gnu linkonce section.
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- references:
- - kind: layout-after
- target: anotherfunction
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: gnu-linkonce
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: d1
- - kind: group-child
- target: g1
- - name: anotherfunction
- scope: global
- type: data
-...
-
-#CHECK: defined-atoms:
-#CHECK: - name: g1
-#CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-#CHECK: scope: global
-#CHECK: type: gnu-linkonce
-#CHECK: references:
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f2
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: d1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: [[GCHILD:[a-zA-Z\.0-9_]+]]
-#CHECK: - name: f1
-#CHECK: scope: global
-#CHECK: references:
-#CHECK: - kind: layout-after
-#CHECK: offset: 0
-#CHECK: target: anotherfunction
-#CHECK: - name: f2
-#CHECK: scope: global
-#CHECK: - name: d1
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: - name: g1
-#CHECK: ref-name: [[GCHILD]]
-#CHECK: scope: global
-#CHECK: - name: anotherfunction
-#CHECK: scope: global
-#CHECK: type: data
+++ /dev/null
-# Test for section group members be preserved even if there is a
-# reference to only one functions in the group.
-# RUN: lld -core --dead-strip %s %p/Inputs/sectiongroup-deadstrip.objtxt | FileCheck %s
-
-#
-# Test that section groups are parsed properly when there is a reference to a
-# group atom from outside a group.
-#
-
----
-defined-atoms:
- - name: entry
- dead-strip: never
- references:
- - offset: 1
- kind: pcrel32
- target: d1
- - name: f1
- scope: global
- type: code
- references:
- - kind: layout-after
- target: anotherfunction
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: d1
- - kind: group-child
- target: g1
- - name: anotherfunction
- scope: global
- type: data
-...
-
-#CHECK: defined-atoms:
-#CHECK: - name: g1
-#CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-#CHECK: scope: global
-#CHECK: type: group-comdat
-#CHECK: references:
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f2
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: d1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: [[GCHILD:[a-zA-Z\.0-9_]+]]
-#CHECK: - name: f1
-#CHECK: scope: global
-#CHECK: references:
-#CHECK: - kind: layout-after
-#CHECK: offset: 0
-#CHECK: target: anotherfunction
-#CHECK: - name: f2
-#CHECK: scope: global
-#CHECK: - name: d1
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: - name: g1
-#CHECK: ref-name: [[GCHILD]]
-#CHECK: scope: global
-#CHECK: - name: anotherfunction
-#CHECK: scope: global
-#CHECK: type: data
+++ /dev/null
-# RUN: not lld -core %s %p/Inputs/sectiongroup-gnulinkonce-error.objtxt 2>&1 | FileCheck %s
-
-#
-# Test that section groups/gnu linkonce sections are parsed and a merge error
-# is displayed at the time of symbol resolution.
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
-...
-
-#CHECK: SymbolTable: error while merging g1
-#CHECK: LLVM ERROR: duplicate symbol error
-
+++ /dev/null
-# RUN: lld -core %s %p/Inputs/sectiongroup-rearrange-resolve.objtxt | FileCheck %s
-
-#
-# Test that section groups are parsed and the first group selected for symbol
-# resolution
-#
-
----
-defined-atoms:
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
-...
-
-# CHECK: defined-atoms:
-# CHECK: - name: g1
-# CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-# CHECK: type: group-comdat
-# CHECK: references:
-# CHECK: - kind: group-child
-# CHECK: target: f1
-# CHECK: - kind: group-child
-# CHECK: target: f2
-# CHECK: - kind: group-child
-# CHECK: target: [[CHILD:[a-zA-Z\.0-9_]+]]
-# CHECK: - kind: group-child
-# CHECK: target: d1
-# CHECK: - name: f1
-# CHECK: - name: f2
-# CHECK: - name: g1
-# CHECK: ref-name: [[CHILD]]
-# CHECK: - name: d1
+++ /dev/null
-# RUN: lld -core %s %p/Inputs/sectiongroup-remaining-undef.objtxt %p/Inputs/sectiongroup-remaining-undef2.objtxt | FileCheck %s
-
-#
-# Test that section groups are parsed and the first group selected for symbol
-# resolution. The second file which has the same group has a unresolved
-# undefined symbol. lets make sure that the symbol is kept around in the final
-# link and remains undefined.
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
-...
-
-#CHECK: - name: anotherfunction
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: undefined-atoms:
-#CHECK: - name: f3
+++ /dev/null
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test that section groups are parsed and the first group selected for symbol
-# resolution
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: g1
- - kind: group-child
- target: d1
-...
-
-#CHECK: defined-atoms:
-#CHECK: - name: g1
-#CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-#CHECK: scope: global
-#CHECK: type: group-comdat
-#CHECK: references:
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f2
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: [[GCHILD:[a-zA-Z\.0-9_]+]]
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: d1
-#CHECK: - name: f1
-#CHECK: scope: global
-#CHECK: - name: f2
-#CHECK: scope: global
-#CHECK: - name: g1
-#CHECK: ref-name: [[GCHILD]]
-#CHECK: scope: global
-#CHECK: - name: d1
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: ...
+++ /dev/null
-# RUN: lld -core %s | FileCheck %s
-
-#
-# Test that section groups are parsed properly when there is a reference to a
-# group atom from outside a group.
-#
-
----
-defined-atoms:
- - name: f1
- scope: global
- type: code
- references:
- - kind: layout-after
- target: anotherfunction
- - name: f2
- scope: global
- type: code
- - name: g1
- scope: global
- type: code
- - name: d1
- scope: global
- type: data
- - name: g1
- scope: global
- type: group-comdat
- references:
- - kind: group-child
- target: f1
- - kind: group-child
- target: f2
- - kind: group-child
- target: d1
- - kind: group-child
- target: g1
- - name: anotherfunction
- scope: global
- type: data
-...
-
-#CHECK: defined-atoms:
-#CHECK: - name: g1
-#CHECK: ref-name: [[PARENT:[a-zA-Z\.0-9_]+]]
-#CHECK: scope: global
-#CHECK: type: group-comdat
-#CHECK: references:
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: f2
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: d1
-#CHECK: - kind: group-child
-#CHECK: offset: 0
-#CHECK: target: [[GCHILD:[a-zA-Z\.0-9_]+]]
-#CHECK: - name: f1
-#CHECK: scope: global
-#CHECK: references:
-#CHECK: - kind: layout-after
-#CHECK: offset: 0
-#CHECK: target: anotherfunction
-#CHECK: - name: f2
-#CHECK: scope: global
-#CHECK: - name: d1
-#CHECK: scope: global
-#CHECK: type: data
-#CHECK: - name: g1
-#CHECK: ref-name: [[GCHILD]]
-#CHECK: scope: global
-#CHECK: - name: anotherfunction
-#CHECK: scope: global
-#CHECK: type: data