George Rimar via llvm-dev
2018-Jan-29 07:58 UTC
[llvm-dev] [lld] Garbage collection of linked sections with the SHF_LINK_ORDER flag
>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, >RobertHi 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.