This is an archive of the discontinued LLVM Phabricator instance.

[ELF] Refine section group --gc-sections rules to not discard .debug_types
ClosedPublic

Authored by MaskRay on Dec 6 2019, 4:49 PM.

Details

Summary

clang/gcc -fdebug-type-sections places .debug_types and
.rela.debug_types in a section group, with a signature symbol which
represents the type signature. The section group is for deduplication
purposes.

After D70146, we will discard such section groups. Refine the rule so
that we will retain the group if no member has the SHF_ALLOC flag.

GNU ld has a similar rule to retain the group if all members have the
SEC_DEBUGGING flag. We try to be more general for future-proof purposes:
if other non-SHF_ALLOC sections have deduplication needs, they may be
placed in a section group.

Diff Detail

Event Timeline

MaskRay created this revision.Dec 6 2019, 4:49 PM
grimar added a comment.Dec 7 2019, 1:20 AM

The logic looks OK to me. A suggestion about the code is inline.

lld/ELF/InputFiles.cpp
653–654

(while you are here)
secion -> section

663

I'd suggest adding a helper, because initializeSections becoming too large probably.
Something like:

template <typename ELFT>
static std::vector<InputSectionBase *>
getGroupSections(ArrayRef<typename ELFT::Word> entries,
                 ArrayRef<InputSectionBase *> sections) {
  std::vector<InputSectionBase *> ret;
  for (uint32_t i : entries)
    if (i < sections.size())
      if (InputSectionBase *s = sections[i])
        if (s != &InputSection::discarded)
          ret.push_back(s);
  return ret;
}

Then you can simplify a bit:

for (ArrayRef<Elf_Word> entries : selectedGroups) {
  bool hasAlloc = false;
  std::vector<InputSectionBase *> sections =
      getGroupSections<ELFT>(entries.slice(1), this->sections);
  for (InputSectionBase *s : sections) {
    if ((s->flags & SHF_ALLOC) == 0)
      continue;
    hasAlloc = true;
    break;
  }

  // If no member has the SHF_ALLOC flag, retain the whole group. This rule
  // retains .debug_types and .rela.debug_types.
  if (!hasAlloc)
    continue;

  InputSectionBase *head;
  InputSectionBase *prev = nullptr;
  for (InputSectionBase *s : sections) {
    if (prev)
      prev->nextInSectionGroup = s;
    else
      head = s;
    prev = s;
  }
  if (prev)
    prev->nextInSectionGroup = head;
}

I'd probably consider moving out the whole code related to groups into it's own method/helper though.
(not in this patch)

MaskRay updated this revision to Diff 232705.Dec 7 2019, 9:05 AM
MaskRay marked 3 inline comments as done.

Split off section group code

lld/ELF/InputFiles.cpp
663

I will move out the whole section group code. The split-off function is not too long, so we don't need the helper function (getGroupSections).

MaskRay updated this revision to Diff 232707.Dec 7 2019, 9:06 AM

Delete a redundant comment

Assuming George is happy with them, changes look good to me,

MaskRay edited the summary of this revision. (Show Details)Dec 9 2019, 4:08 PM

@grimar Does this look good to you? Rui is OOO. (This is somewhat important for our internal use cases but I want an official approval before committing it, to make sure there is no open questions.)

grimar accepted this revision.Dec 10 2019, 12:17 AM

LGTM.

lld/ELF/InputFiles.cpp
511

I'd probably simplify:

if (InputSectionBase *s = sections[index])
  if (s != &InputSection::discarded && s->flags & SHF_ALLOC)
    hasAlloc = true;

Up to you.

This revision is now accepted and ready to land.Dec 10 2019, 12:17 AM
MaskRay marked 2 inline comments as done.Dec 10 2019, 8:59 AM
MaskRay added inline comments.
lld/ELF/InputFiles.cpp
511

Good idea. Applying.

MaskRay updated this revision to Diff 233125.Dec 10 2019, 8:59 AM
MaskRay marked an inline comment as done.

Simplify code

This revision was automatically updated to reflect the committed changes.
ruiu added inline comments.Dec 10 2019, 9:29 PM
lld/ELF/InputFiles.cpp
500

Could you add a function comment to explain what the section group is and what this function is supposed to do?

MaskRay marked an inline comment as done.Dec 10 2019, 11:47 PM
MaskRay added inline comments.
lld/ELF/InputFiles.cpp
500

How about

--- i/lld/ELF/InputFiles.cpp
+++ w/lld/ELF/InputFiles.cpp
@@ -498,4 +498,5 @@ static void addDependentLibrary(StringRef specifier, const InputFile *f) {
 }
 
+// Check if members of the section group can be discarded.
 template <class ELFT>
 static void handleSectionGroup(ArrayRef<InputSectionBase *> sections,

? The most useful comment is below

// If any member has the SHF_ALLOC flag, the whole group is subject to garbage
// collection. See the comment in markLive(). This rule retains .debug_types
// and .rela.debug_types.

So the function comment probably should not repeat that.

ruiu added inline comments.Dec 11 2019, 8:22 PM
lld/ELF/InputFiles.cpp
500

It's more like

Record the membership of a section group so that in the garbage collection pass,
section group members are kept or discarded as a unit.

?