Unused unexported methods kept by DCE when using plugins

166 views
Skip to first unread message

Pierre Gimalac

unread,
Feb 7, 2025, 5:59:31 PMFeb 7
to golang-nuts
Hello,
I noticed that when importing the std "plugin" package then (some ?) unexported methods are kept in the binary.

Disclaimer it's something I only observed on a complex binary, I could not make a minimal reproducible example, so I'm probably misunderstanding something.

When using `-ldflags=-dumpdep` on my complex binary I was seeing something like `type:*text/template.Template -> text/template.(*Template).execute`, so just having the type `Template` makes the unexported method reachable. It disappeared when removing the "plugin" import.

We can see that if we have reflect and the binary is dynamically linked (with plugin or shared build modes), then unexported methods are also kept. Note that when `dynlink` is true then `reflectSeen` is also set to true, so I think you actually don't even need to use reflect for that to happen.

I'm curious why ? The documentation of `Plugin.Lookup` says the symbol must be exported https://pkg.go.dev/plugin#Plugin.Lookup .
I would have expected the first part of the condition to be `m.isExported() && (d.reflectSeen || d.dynlink)` instead.

This makes binaries importing "plugin" (and probably plugins and shared builds too) significantly bigger, in my case removing the "plugin" import reduced the size of various binaries by around 30%.

Thanks !
Pierre.

Ian Lance Taylor

unread,
Feb 7, 2025, 7:17:06 PMFeb 7
to Pierre Gimalac, golang-nuts
As the comment in the linker code says, the linker is ensuring that
all methods of any reachable interface are kept. An interface can have
unexported methods, and in the general case we must keep any method
that may satisfy that interface.

Ian

Pierre Gimalac

unread,
Feb 11, 2025, 4:58:27 AMFeb 11
to Ian Lance Taylor, golang-nuts
But in that case why would that only happen for dynamic builds ?
Shouldn't all unexported methods also be kept for the "normal" build ?

Pierre.

Ian Lance Taylor

unread,
Feb 11, 2025, 9:53:09 AMFeb 11
to Pierre Gimalac, golang-nuts
On Tue, Feb 11, 2025 at 1:57 AM Pierre Gimalac
<pierre....@datadoghq.com> wrote:
>
> But in that case why would that only happen for dynamic builds ?
> Shouldn't all unexported methods also be kept for the "normal" build ?

In a normal build the linker can see all the code in the program, so
it knows whether something is possible. In a dynamic build it doesn't
know.

Ian

Pierre Gimalac

unread,
Feb 12, 2025, 10:58:18 AMFeb 12
to Ian Lance Taylor, golang-nuts
I stumbled on https://go-review.googlesource.com/c/go/+/393365 which explains why plugins need to keep unexported methods.

Thanks for taking the time to answer my questions, have a good day !

Reply all
Reply to author
Forward
0 new messages