[llvm-dev] Range lists, zero-length functions, linker gc

David Blaikie via llvm-dev
Wed, 27 May 2020 20:44:26 -0000

So there have been several recent discussions about the issues around
DWARF-agnostic linking and gc-sections, linkonce function definitions being
dropped, etc - and just how much DWARF-awareness would be suitable in a
linker to help with this situation.

I'd like to discuss a narrower instance of this issue: Zero length
gc'd/deduplicated functions.

LLVM seems to at least produce zero length functions in a few cases:
* non-void function without a return statement
* function definition containing only llvm_unreachable
(both of these trap at -O0, but at higher optimization levels even the trap
instruction is removed & you get the full power UB of control flowing off
the end of the function into whatever other bytes are after that function)

So, for context, debug_ranges (this whole issue doesn't exist in DWARFv5,
FWIW) is a list of address pairs, terminated by a pair of zeros.
With function sections, or even just with normal C++ inline functions, the
CU will have a range entry for that function that consists of two
relocations - to the start and end of the function. Generally the start of
the function is the start of the section, and the end is "start of
function + length of function (aka addend)".

Usually any relocation to the section would keep that section "alive"
during linking - but that would cause debug info to defeat linker GC and
deduplication. So there's special rules for how linkers handle these
relocations in debug info to allow the sections to be dropped - what do you
write in the bytes that requested the relocation?

Binutils ld: Special cases only debug_ranges, resolving all relocations to
dead code to 1. In other debug sections, these values are all resolved to
zero.
Gold and lld: Special cases all debug info sections - resolving all
relocations to "addend" (so begin usually goes to zero, end goes to
"size
of function")

These special rules are designed to ensure omitted/gc'd/deduplicated
functions don't cause the range list to terminate prematurely (which would
happen if begin/end were both resolved to zero).


But with an empty function, gold and lld's strategy here fails to avoid
terminating a range list by accident.

What should we do about it?

1) Ensure no zero-length functions exist? (doesn't address backwards
compatibility/existing functions/other compilers)
2) adopt the binutils approach to this (at least in debug_ranges - maybe in
all debug sections? (doing it in other sections could break )
3) Revisit the discussion about using an even more 'blessed' value, like
int max-1? ( https://reviews.llvm.org/D59553 )

(I don't have links to all the recent threads about this discussion - I
think D59553 might've spawned a separate broader discussion/non-review -
oh, Alexey wrote a good summary with links to other discussions here:
http://lists.llvm.org/pipermail/llvm-dev/2019-September/135068.html )

Thoughts?
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20200527/1293fa00/attachment.html>