Has gc-sections changed behaviour?

I’m sorry for the rather vague title! I use lld for my embedded IDE. I’m building small simple programs for AVR microcontrollers. I use -ffunction-sections -fdata-sections when compiling and --gc-sections in the link. This has been working with my older build of lld (built from a year or two old code…might even be three years old).

When I recently tried updating llvm and lld, most things worked but suddenly gc-sections doesn’t seem to be working properly, or I’m not using it right (maybe I never was!) Many sections I don’t think are needed or used in the final binary are not being removed from the link.

In a test example this morning, building using the old lld makes a binary of size approx 3.9k, but linking exactly the same objects/libraries with the same command and a newly built lld from current trunk builds a binary of 890k in size! Clearly far too big for my microcontrollers.

This is the linking command I’m using…

"/Users/carlpeto/compilers/llvm-project/llvm/build/bin/ld.lld" -L"/Applications/Swift For Arduino.app/Contents/XPCServices/S4ABuildEngine.xpc/Contents/Resources/gpl-tools-avr/lib/avr-libc/lib/avr5" -L"/Applications/Swift For Arduino.app/Contents/XPCServices/S4ABuildEngine.xpc/Contents/Resources/gpl-tools-avr/lib/avr-libgcc/avr5" -LAVR -L. -L"/Applications/Swift For Arduino.app/Contents/XPCServices/S4ABuildEngine.xpc/Contents/Resources/gpl-tools-avr/lib/avr-binutils/avr/lib/ldscripts" -Tavr5.xn --static -Tdata 0x800100 "/Applications/Swift For Arduino.app/Contents/XPCServices/S4ABuildEngine.xpc/Contents/Resources/gpl-tools-avr/lib/avr-libc/lib/avr5/crtatmega328p.o"  --gc-sections -z dead-reloc-in-nonalloc='.debug_*=0xffffffff' -z dead-reloc-in-nonalloc=.debug_loc=0xfffffffe -z dead-reloc-in-nonalloc=.debug_ranges=0xfffffffe -Map main.map -o main.elf main.o unitTests.o uSwift/bin/AVR/missing_runtime_stub.o -lAVR -lAVR    -L"uSwift/bin/AVR" -l"Swift" -l"SwiftExperimentalRuntime" --start-group -lgcc -lm -lc -latmega328p --end-group

Also, if I use a new avr-ld from avr binutils, the same issue occurs. So in a way it looks like the behaviour of modern lld is more “correct” (it matches GNU ld) … so it might mean that I need to change my linker scripts (which are fairly standard linker scripts from GNU binutils) or my command or something.

p.s. The biggest library being linked in, libSwift.a is compiled from my modified version of the Swift standard library and runtime… it contains a lot of things that would very rarely be linked into an embedded binary, things the Swift guys call “metadata” which support a mix of dynamic language features… maybe somewhat equivalent to rtti in C++. It’s possible that some of the sections emitted have flags on them that cause them to be retained and act as GC roots and if so, it’s probably intended behaviour. But it’s harmful for me because my programs don’t use those dynamic features… they only use standard, static behaviour.

Cc: @MaskRay