Bug 1575110 - glibc: -lmcheck does not work for shared objects
Summary: glibc: -lmcheck does not work for shared objects
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Fedora
Classification: Fedora
Component: glibc
Version: 28
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Florian Weimer
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
: 1575117 (view as bug list)
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2018-05-04 19:14 UTC by Julian Z
Modified: 2018-05-09 09:33 UTC (History)
13 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2018-05-09 09:33:21 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Comment 4 Florian Weimer 2018-05-04 19:38:31 UTC
Reproducer:

$ touch empty.c
$ gcc -O2 -fpic -shared empty.c -lmcheck
/usr/bin/ld: a.out: version node not found for symbol __malloc_initialize_hook.5
/usr/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status

This looks like a linker limitation.

      /* If we are building an application, we need to create a
         version node for this version.  */
      if (t == NULL && bfd_link_executable (info))
        {
…
        }
      else if (t == NULL)
        {
          /* We could not find the version for a symbol when
             generating a shared archive.  Return an error.  */
          _bfd_error_handler
            /* xgettext:c-format */
            (_("%B: version node not found for symbol %s"),
             info->output_bfd, h->root.root.string);
          bfd_set_error (bfd_error_bad_value);
          sinfo->failed = TRUE;
          return FALSE;
        }
    }

I have no idea why it is okay to synthesize a symbol version for an executable, but not for a shared object.  This doesn't really make sense.

Comment 6 Florian Weimer 2018-05-04 19:39:55 UTC
*** Bug 1575117 has been marked as a duplicate of this bug. ***

Comment 7 Nick Clifton 2018-05-08 12:09:49 UTC
(In reply to Florian Weimer from comment #4)

Hi Florian,

> $ touch empty.c
> $ gcc -O2 -fpic -shared empty.c -lmcheck

This completes successfully for me, without producing any errors.

Do I need a specific version of glibc installed ?  (I was using
gcc-7.2.1-2.fc27.x86_64, binutils-2.29-13.fc27.x86_64 and glibc-2.26-27.fc27.x86_64).

Also - do you know if the bug happens if you use gold instead of ld.bfd ?

> This looks like a linker limitation.

> I have no idea why it is okay to synthesize a symbol version for an
> executable, but not for a shared object.  This doesn't really make sense.

My assumption - not verified with the binutils community - is that the
intention is to force shared libraries to always have complete version
information for all of their exported symbols and not leave any to be
invented by the linker.  Inventing symbol versions for applications should
not matter since the application is not going to be linked against anything
else.

Cheers
  Nick

Comment 8 Florian Weimer 2018-05-08 12:37:59 UTC
(In reply to Nick Clifton from comment #7)
> (In reply to Florian Weimer from comment #4)
> 
> Hi Florian,
> 
> > $ touch empty.c
> > $ gcc -O2 -fpic -shared empty.c -lmcheck
> 
> This completes successfully for me, without producing any errors.
> 
> Do I need a specific version of glibc installed ?  (I was using
> gcc-7.2.1-2.fc27.x86_64, binutils-2.29-13.fc27.x86_64 and
> glibc-2.26-27.fc27.x86_64).

You need glibc from Fedora 28 or rawhide.

> Also - do you know if the bug happens if you use gold instead of ld.bfd ?

$ gcc --use-ld=gold -O2 -fpic -shared empty.c -lmcheck
/usr/bin/ld.gold: error: symbol __malloc_initialize_hook has undefined version GLIBC_2.2.5
collect2: error: ld returned 1 exit status

> > This looks like a linker limitation.
> 
> > I have no idea why it is okay to synthesize a symbol version for an
> > executable, but not for a shared object.  This doesn't really make sense.
> 
> My assumption - not verified with the binutils community - is that the
> intention is to force shared libraries to always have complete version
> information for all of their exported symbols and not leave any to be
> invented by the linker.  Inventing symbol versions for applications should
> not matter since the application is not going to be linked against anything
> else.

Hmm.  -lmcheck is interposing a definition of __malloc_initialize_hook with an initializer, so this is really a fringe case, and it is technically an export (from both the main program and a DSO).

Comment 9 Nick Clifton 2018-05-09 09:17:50 UTC
Hang on a sec.  If __malloc_initialize_hook is deprecated, why is the libdrizzle library referencing it ?

It seems to me that the problem here is that the mcheck library is exporting a deprecated symbol, which it should not be doing.  The linker is getting confused because the symbol is defined, but there is no version information for it.  Rather than invent a version, the linker complains and stops.  To me this seems like correct behaviour.

Comment 10 Florian Weimer 2018-05-09 09:33:21 UTC
(In reply to Nick Clifton from comment #9)
> Hang on a sec.  If __malloc_initialize_hook is deprecated, why is the
> libdrizzle library referencing it ?

We deprecated the hook without realizing that -lmcheck would stop working due to the way the interposition works with a compatibility symbol (the .symver is new, it wasn't there in the first place).

> It seems to me that the problem here is that the mcheck library is exporting
> a deprecated symbol, which it should not be doing.  The linker is getting
> confused because the symbol is defined, but there is no version information
> for it.  Rather than invent a version, the linker complains and stops.  To
> me this seems like correct behaviour.

I'm not so sure, but I can see the rationale (there is no symbol version ordering, for example).

We will not fix this in glibc.  -lmcheck is going away anyway, in favor of a different mechanism.


Note You need to log in before you can comment on or make changes to this bug.