How does this test-suite failure manifest?

It manifests as a failure in the following test-case:

 elf/check-localplt.out

What is this test for?

GLIBC needs to maintain internal consistency and stability, especially in the libc and libm libaries. If libc accesses it's own symbols via a PLT call then if a user overrides a symbol GLIBC will invoke that overridden symbol and potentially destabilize the library. Therefore, applications are prevented from impacting GLIBC internally by making GLIBC directly call internal, hidden versions of all of its symbols. Only expressly allowed symbols may be overridden, and called from within libc, e.g. malloc.

These expressly allowed symbols are denoted in the following files:

 scripts/data/localplt-i386-linux-gnu.data
 scripts/data/localplt-generic.data
 scripts/data/localplt-powerpc-linux-gnu.data
 scripts/data/localplt-powerpc64-linux-gnu.data

Additionally, PLT calls are expensive (more-so on some architectures than other) compared to direct branches/calls to functions so they should be avoided if possible.

The check-localplt test case ensures that no PLT calls from within libc to other libc functions are introduced.

What's a failure look like?

 --- ../scripts/data/localplt-i386-linux-gnu.data        2006-01-11 
 21:06:19.000000000 +0000
 +++ -   2008-11-30 20:52:09.962033876 +0000
 @@ -1,4 +1,5 @@
  libc.so: _Unwind_Find_FDE
 +libc.so: __bzero
  libc.so: calloc
  libc.so: free
  libc.so: malloc

This indicates that one or more invocations of the symbol __bzero via the PLT have been introduced into GLIBC erroneously.

Potential Causes

There are a few potential causes for this particular error:

  1. The symbol may be new and not have the proper hidden symbol macros defined for it.
  2. libc should invoke a hidden version of the symbol rather than the PLT version.

  3. The symbol may not be intended for invocation internally.

Problem Determination

Still can't figure out where the invocation originates?

Macros, and symbol aliasing magic can obscure the invocation of a symbol and sometimes we need to use more arcane methods to find the problematic invocation.

In order to determine where an obscure invocation is originating follow these steps:

 > objdump -DR libc.so > libc.dis

Search libc.dis for:

 __bzero@plt

You should see a plt call stub, e.g.

00016198 <__bzero@plt>:
   16198:       ff a3 0c 00 00 00       jmp    *0xc(%ebx)
   1619e:       68 00 00 00 00          push   $0x0
   161a3:       e9 e0 ff ff ff          jmp    16188 <h_errno+0x16168>

Now search for all instances of: call   16198

call   16198 <__bzero@plt>

This should bring you to the disassembly of the function which invoked __bzero via the PLT. You can then go into the C source file and replace this with a memset(). Do this for all calls to the PLT stub address for __bzero@plt.