https://sourceware.org/bugzilla/show_bug.cgi?id=34985

            Bug ID: 34985
           Summary: [2.46 Regression] ld fails to build on hosts without
                    <dlfcn.h>: implicit declaration of dlopen in plugin.c
           Product: binutils
           Version: 2.48 (HEAD)
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: binutils
          Assignee: unassigned at sourceware dot org
          Reporter: yegorslists at googlemail dot com
  Target Milestone: ---

ld no longer builds on a host whose C library does not provide <dlfcn.h>,
even when configured with --disable-plugins. We hit this in Buildroot when
cross-compiling binutils to run on an ARM Cortex-M7 (no MMU) target with a
static-only uClibc-ng. uClibc-ng does not install <dlfcn.h> when it is built
without shared library support. The failure is:

  plugin.c: In function 'plugin_opt_plugin':
  plugin.c:252:23: error: implicit declaration of function 'dlopen'; did you
mean 'open'? [-Wimplicit-function-declaration]
    252 |   newplug->dlhandle = dlopen (plugin, RTLD_NOW);
        |                       ^~~~~~
  plugin.c:252:39: error: 'RTLD_NOW' undeclared (first use in this function)
  plugin.c: In function 'plugin_load_plugins':
  plugin.c:1134:37: error: implicit declaration of function 'dlsym'
[-Wimplicit-function-declaration]
  plugin.c: In function 'plugin_call_cleanup':
  plugin.c:1410:11: error: implicit declaration of function 'dlclose'; did you
mean 'gzclose'? [-Wimplicit-function-declaration]

binutils 2.45.1 builds fine in the same configuration.

Analysis:

Until 2.45, the body of ld/plugin.c was wrapped in "#if BFD_SUPPORTS_PLUGINS",
so it compiled to nothing when plugins were disabled. Commit 7e432e93f8aa
("Limit BFD_SUPPORTS_PLUGINS check to plugin.h and targets.c") removed that
guard, so plugin.c is now always compiled. Plugin availability is checked at
run time through bfd_plugin_enabled() instead.

plugin.c only gets dlopen, dlsym, dlclose and RTLD_NOW from <dlfcn.h>
(HAVE_DLFCN_H). On Windows (HAVE_WINDOWS_H) it uses local wrappers around
LoadLibrary, GetProcAddress and FreeLibrary. With neither header, those
symbols are undefined, and the file no longer compiles.

AC_PLUGINS in config/plugins.m4 already handles this host: with neither
dlfcn.h nor windows.h, plugins default to "no", and --enable-plugins is
rejected with "Building with plugin support requires a host that supports
dlopen". So configure works, and only the unconditional compilation of
ld/plugin.c breaks. At run time the dl* calls cannot be reached:
-plugin and -plugin-opt are ignored in lexsup.c when bfd_plugin_enabled()
returns false.

A possible fix would be for plugin.c to provide do-nothing fallbacks for
dlopen, dlsym, dlclose and RTLD_NOW when neither <dlfcn.h> nor <windows.h>
is available, next to the existing Windows wrappers. Another option is to
restore a guard around the dl*-dependent code.

How to reproduce:

Configure binutils 2.46 or later for a host whose sysroot has no
<dlfcn.h>, for example uClibc-ng built with HAVE_SHARED disabled, then run
"make all-ld":

  ./configure --host=arm-buildroot-uclinux-uclibcgnueabi \
              --target=arm-buildroot-uclinux-uclibcgnueabi \
              --disable-plugins --disable-shared --enable-static \
              --disable-gdb --disable-sim --disable-gprofng
  make all-ld

The generated ld/config.h contains "/* #undef HAVE_DLFCN_H */", and the
build stops on ld/plugin.c as shown above.

Buildroot autobuilder failure:
https://autobuild.buildroot.org/results/ee94fc7c8d5d76a8f359ee35fb03bc6dfc82986c

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to