When targetting x64, before this patch LLD would generate duplicate RUNTIME_FUNCTION entries. They are not exactly duplicates stricto sensu, because the unwind RVA is different. However the two target UNWIND_INFOs would have the same content. An example out of the final EXE before this patch (I used dumpbin /unwindinfo ...):
0049D0DC 0554E9D0 0554E9F7 06ACBCE8 <- RUNTIME_FUNCTION entry (in .pdata) Unwind version: 1 <- pointed UNWIND_INFO entry (in .xdata) Unwind flags: EHANDLER UHANDLER Size of prologue: 0x0A Count of codes: 2 Unwind codes: 0A: ALLOC_SMALL, size=0x30 06: PUSH_NONVOL, register=rbp Handler: 05503340 0049D0E8 0554E9D0 0554E9F7 06ACB0E8 <- note the last value (the unwind RVA) is different Unwind version: 1 <- different UNWIND_INFO entry, but same content as above Unwind flags: EHANDLER UHANDLER Size of prologue: 0x0A Count of codes: 2 Unwind codes: 0A: ALLOC_SMALL, size=0x30 06: PUSH_NONVOL, register=rbp Handler: 05503340
Unfourtunately this prevents us from using some external (commercial) post-processing tools, which assert if the EXE contains duplicate .pdata entries. This behavior is probably wrong anyway, how would the NT loader handle duplicate entries for the same function?
After this patch, we thusly remove any .pdata entries that have the same starting address. We make those changes directly into the final output stream, because the input .pdata streams need to merged, reallocated & sorted first. This has two side-effects: 1. the output PE section that receives the .pdata ends-up a bit larger than needed. 2. the .xdata entries are not stripped currently since they are part of .text sections (same chunks). But all in all we're talking about a few kbytes wasted. In our case, out of 300,000 RUNTIME_FUNCTION entries, this patch removes about 700, so that's about 14 kb wasted out of a 96 MB EXE.
If reviewers would think of a better way to implement this, I would gladly oblige.
Fixes PR45950.
Would it be possible to adjust the virtual size of the .pdata section as well, to exclude the pruned bits? I could imagine that some runtime introspection tools locate the section directly instead of using the data directory.