[llvm-dev] [lld] Garbage collection of linked sections with the SHF_LINK_ORDER flag

George Rimar via llvm-dev llvm-dev at lists.llvm.org
Sun Jan 28 23:58:36 PST 2018


>Hi folks,
>
>Our LLVM compiler creates a special debug section, which depends on a
>certain
>text section. This debug section is created with the SHF_LINK_ORDER
>flag, and
>sh_link field in the section header points to the correct section.
>
>When linking the program with the linker flag '-gc-sections', lld can
>garbage-
>collect unused sections. In my case, the text section is correctly garbage-
>collected. However,  the linked debug section remains in the program and
>relocations in these debug sections are invalid.
>
>I found the following Google groups thread on the Generic System V ABI
>mailing
>list (https://groups.google.com/d/msg/generic-abi/_CbBM6T6WeM/eGF9A0AnAAAJ),
>which also discusses this topic. In particular, it is discussing the
>following
>change to the description of SHF_LINK_ORDER flag:
>
>"When performing unused section elimination, the link editor should
>ensure that both the section and the referenced section are retained
>or discarded together."
>
>This sentence makes sense to me, and I assumed lld works like this.
>
>When looking through the code of lld, I found that in
>MarkLive::markLive(), the
>liveness of parent sections is not propagated to the child sections.
>Instead,
>it is marked as live resulting that the section is kept even though the
>parent
>section is removed.
>
>To fix this issue, I propose changing the code marking sections live to
>the following loop:
>
>for (InputSectionBase *Sec : InputSections) {
>     if (Sec->Flags & SHF_LINK_ORDER)
>         Sec->Live = Sec->getLinkOrderDep()->Live;
>     else {
>         bool IsAlloc = (Sec->Flags & SHF_ALLOC);
>         bool IsRel = (Sec->Type == SHT_REL || Sec->Type == SHT_RELA);
>         if (!IsAlloc && !IsRel)
>         Sec->Live = true;
>     }
>}
>
>If an input section has the SHF_LINK_ORDER flag set, it propagates the
>liveness
>of this section to the parent. This allows the garbage collector to also
>remove
>children sections if dependent parent sections are marked to be removed.
>
>I found a similar code already inside lld. There is a special case for ARM.
>When ICF being enabled, this live propagation of linked sections is already
>performed for ARM targets in ICF::run(). However, I think this makes sense
>also for other targets.
>
>I am new to lld and may not know all implications of the SHF_LINK_ORDER flag
>or what implications my proposed change may has. Can someone help me in
>understanding what's the expected behavior and if my change makes sense?
>
>If so, I am happy to make an upstream patch.
>
>Thanks!
>
>Cheers,
>Robert

Hi Robert,

current support of SHF_LINK_ORDER in LLD is poor for ICF case.
ICF is not aware of link order dependencies when do its job. 
And I think ARM target is assumed to be the only user of SHF_LINK_ORDER atm.

You might want to take a look at D38180 which tried
to improve the situation (and I believe would address the issue) but was not landed.
It also probably shows the expected behavior. If we have section A and B, where
B is linked with A, and also sections C and D where D is linked to C, and A == C, ICF should only
merge A and C when linked sections B and D are equal too.

Current implementation as you mentioned simply propogates the flag in a hacky way instead when
target is ARM. And easy change for your case would be to remove "if (Config->EMachine == EM_ARM)"
check at line
https://github.com/llvm-mirror/lld/blob/master/ELF/ICF.cpp#L442 I believe.

I do not know what way we would want to go here.
+Rui and Rafael.

George.


More information about the llvm-dev mailing list