@@ -15,6 +15,7 @@ typedef struct malloc_state *mstate;
#define __malloc_initialized __libc_malloc_initialized
/* Nonzero if the malloc is already initialized. */
extern int __malloc_initialized attribute_hidden;
+extern FILE *__mtrace_mallstream attribute_hidden;
enum mcheck_status __mcheck_checkptr (const void *) attribute_hidden;
extern int __mcheck_initialize (void (*) (enum mcheck_status), bool)
@@ -271,7 +271,8 @@ $(objpfx)memusage: memusage.sh
# Extra dependencies
$(foreach o,$(all-object-suffixes),$(objpfx)malloc$(o)): arena.c hooks.c \
malloc-check.c \
- mcheck-hooks.c
+ mcheck-hooks.c \
+ mtrace-hooks.c
# Compile the tests with a flag which suppresses the mallopt call in
# the test skeleton.
@@ -37,6 +37,7 @@ enum malloc_debug_hooks
MALLOC_NONE_HOOK = 0,
MALLOC_CHECK_HOOK = 1 << 0, /* MALLOC_CHECK_ or glibc.malloc.check. */
MALLOC_MCHECK_HOOK = 1 << 1, /* mcheck() */
+ MALLOC_MTRACE_HOOK = 1 << 2, /* mtrace() */
};
static unsigned __malloc_debugging_hooks;
@@ -79,6 +80,7 @@ __malloc_debug_disable (enum malloc_debug_hooks flag)
#include "malloc-check.c"
#include "mcheck-hooks.c"
+#include "mtrace-hooks.c"
static __always_inline bool
_malloc_debug_before (size_t *bytesp, void **victimp, const void *address)
@@ -111,8 +113,13 @@ _malloc_debug_before (size_t *bytesp, void **victimp, const void *address)
static __always_inline void *
_malloc_debug_after (void *mem, size_t bytes, const void *address)
{
- if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && mem != NULL)
- mem = malloc_mcheck_after (mem, bytes);
+ if (__glibc_unlikely (__malloc_debugging_hooks))
+ {
+ if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && mem != NULL)
+ mem = malloc_mcheck_after (mem, bytes);
+ if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
+ mem = malloc_mtrace_after (mem, bytes, address);
+ }
return mem;
}
@@ -129,6 +136,8 @@ _free_debug_before (void **mem, const void *address)
if (__glibc_unlikely (__malloc_debugging_hooks))
{
+ if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
+ free_mtrace (mem, address);
if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
*mem = free_mcheck (*mem);
if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
@@ -171,8 +180,13 @@ static __always_inline void *
_realloc_debug_after (void *mem, void *oldmem, size_t bytes, size_t oldsize,
const void *address)
{
- if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && mem != NULL)
- mem = realloc_mcheck_after (mem, oldmem, bytes, oldsize);
+ if (__glibc_unlikely (__malloc_debugging_hooks))
+ {
+ if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && mem != NULL)
+ mem = realloc_mcheck_after (mem, oldmem, bytes, oldsize);
+ if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
+ mem = realloc_mtrace_after (mem, oldmem, bytes, address);
+ }
return mem;
}
@@ -206,8 +220,13 @@ static __always_inline void *
_memalign_debug_after (void *mem, size_t alignment, size_t bytes,
const void *address)
{
- if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && mem != NULL)
- mem = memalign_mcheck_after (mem, alignment, bytes);
+ if (__glibc_unlikely (__malloc_debugging_hooks))
+ {
+ if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK) && mem != NULL)
+ mem = memalign_mcheck_after (mem, alignment, bytes);
+ if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
+ mem = memalign_mtrace_after (mem, bytes, address);
+ }
return mem;
}
@@ -244,11 +263,16 @@ _calloc_debug_before (size_t *bytesp, void **victimp, const void *address)
static __always_inline void *
_calloc_debug_after (void *mem, size_t bytes, const void *address)
{
- if (__glibc_unlikely (__malloc_debugging_hooks) && mem != NULL)
+ if (__glibc_unlikely (__malloc_debugging_hooks))
{
if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
mem = malloc_mcheck_after (mem, bytes);
- memset (mem, 0, bytes);
+ if (__is_malloc_debug_enabled (MALLOC_MTRACE_HOOK))
+ mem = malloc_mtrace_after (mem, bytes, address);
+ /* mtrace uses __libc_calloc to do the zeroing. */
+ if (mem != NULL && __is_malloc_debug_enabled (MALLOC_CHECK_HOOK
+ | MALLOC_MCHECK_HOOK))
+ memset (mem, 0, bytes);
}
return mem;
}
new file mode 100644
@@ -0,0 +1,137 @@
+
+# include <libc-lock.h>
+
+#include <kernel-features.h>
+
+FILE *__mtrace_mallstream;
+
+__libc_lock_define_initialized (static, lock);
+
+static void
+tr_where (const void *caller, Dl_info *info)
+{
+ if (caller != NULL)
+ {
+ if (info != NULL)
+ {
+ char *buf = (char *) "";
+ if (info->dli_sname != NULL)
+ {
+ size_t len = strlen (info->dli_sname);
+ buf = alloca (len + 6 + 2 * sizeof (void *));
+
+ buf[0] = '(';
+ __stpcpy (_fitoa (caller >= (const void *) info->dli_saddr
+ ? caller - (const void *) info->dli_saddr
+ : (const void *) info->dli_saddr - caller,
+ __stpcpy (__mempcpy (buf + 1, info->dli_sname,
+ len),
+ caller >= (void *) info->dli_saddr
+ ? "+0x" : "-0x"),
+ 16, 0),
+ ")");
+ }
+
+ fprintf (__mtrace_mallstream, "@ %s%s%s[%p] ",
+ info->dli_fname ? : "", info->dli_fname ? ":" : "",
+ buf, caller);
+ }
+ else
+ fprintf (__mtrace_mallstream, "@ [%p] ", caller);
+ }
+}
+
+static Dl_info *
+lock_and_info (const void *caller, Dl_info *mem)
+{
+ if (caller == NULL)
+ return NULL;
+
+ Dl_info *res = _dl_addr (caller, mem, NULL, NULL) ? mem : NULL;
+
+ __libc_lock_lock (lock);
+
+ return res;
+}
+
+static bool
+free_mtrace (void *ptr, const void *caller)
+{
+ if (ptr == NULL)
+ return true;
+
+ Dl_info mem;
+ Dl_info *info = lock_and_info (caller, &mem);
+ tr_where (caller, info);
+ /* Be sure to print it first. */
+ fprintf (__mtrace_mallstream, "- %p\n", ptr);
+ __libc_lock_unlock (lock);
+
+ /* Continue on to free. */
+ return false;
+}
+
+static void *
+malloc_mtrace_after (void *block, size_t size, const void *caller)
+{
+ Dl_info mem;
+ Dl_info *info = lock_and_info (caller, &mem);
+
+ tr_where (caller, info);
+ /* We could be printing a NULL here; that's OK. */
+ fprintf (__mtrace_mallstream, "+ %p %#lx\n", block,
+ (unsigned long int) size);
+
+ __libc_lock_unlock (lock);
+
+ return block;
+}
+
+static void *
+realloc_mtrace_after (void *block, const void *oldptr, size_t size,
+ const void *caller)
+{
+ Dl_info mem;
+ Dl_info *info = lock_and_info (caller, &mem);
+
+ tr_where (caller, info);
+ if (block == NULL)
+ {
+ if (size != 0)
+ /* Failed realloc. */
+ fprintf (__mtrace_mallstream, "! %p %#lx\n", oldptr,
+ (unsigned long int) size);
+ else
+ fprintf (__mtrace_mallstream, "- %p\n", oldptr);
+ }
+ else if (oldptr == NULL)
+ fprintf (__mtrace_mallstream, "+ %p %#lx\n", block,
+ (unsigned long int) size);
+ else
+ {
+ fprintf (__mtrace_mallstream, "< %p\n", oldptr);
+ tr_where (caller, info);
+ fprintf (__mtrace_mallstream, "> %p %#lx\n", block,
+ (unsigned long int) size);
+ }
+
+ __libc_lock_unlock (lock);
+
+ return block;
+}
+
+static void *
+memalign_mtrace_after (void *block, size_t size, const void *caller)
+{
+ Dl_info mem;
+ Dl_info *info = lock_and_info (caller, &mem);
+
+ tr_where (caller, info);
+ /* We could be printing a NULL here; that's OK. */
+ fprintf (__mtrace_mallstream, "+ %p %#lx\n", block,
+ (unsigned long int) size);
+
+ __libc_lock_unlock (lock);
+
+ return block;
+}
@@ -22,7 +22,6 @@
# define _MALLOC_INTERNAL
# include <malloc.h>
# include <mcheck.h>
-# include <libc-lock.h>
#endif
#include <dlfcn.h>
@@ -35,20 +34,14 @@
#include <libc-internal.h>
#include <dso_handle.h>
-
#include <libio/iolibio.h>
#define setvbuf(s, b, f, l) _IO_setvbuf (s, b, f, l)
#define fwrite(buf, size, count, fp) _IO_fwrite (buf, size, count, fp)
-#include <kernel-features.h>
-
#define TRACE_BUFFER_SIZE 512
-static FILE *mallstream;
-static const char mallenv[] = "MALLOC_TRACE";
static char *malloc_trace_buffer;
-
-__libc_lock_define_initialized (static, lock);
+static const char mallenv[] = "MALLOC_TRACE";
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_34)
/* Compatibility symbols that were introduced to help break at allocation sites
@@ -69,204 +62,6 @@ tr_break (void)
compat_symbol (libc, tr_break, tr_break, GLIBC_2_0);
#endif
-
-/* Old hook values. */
-static void (*tr_old_free_hook) (void *ptr, const void *);
-static void *(*tr_old_malloc_hook) (size_t size, const void *);
-static void *(*tr_old_realloc_hook) (void *ptr, size_t size,
- const void *);
-static void *(*tr_old_memalign_hook) (size_t __alignment, size_t __size,
- const void *);
-
-static void
-tr_where (const void *caller, Dl_info *info)
-{
- if (caller != NULL)
- {
- if (info != NULL)
- {
- char *buf = (char *) "";
- if (info->dli_sname != NULL)
- {
- size_t len = strlen (info->dli_sname);
- buf = alloca (len + 6 + 2 * sizeof (void *));
-
- buf[0] = '(';
- __stpcpy (_fitoa (caller >= (const void *) info->dli_saddr
- ? caller - (const void *) info->dli_saddr
- : (const void *) info->dli_saddr - caller,
- __stpcpy (__mempcpy (buf + 1, info->dli_sname,
- len),
- caller >= (void *) info->dli_saddr
- ? "+0x" : "-0x"),
- 16, 0),
- ")");
- }
-
- fprintf (mallstream, "@ %s%s%s[%p] ",
- info->dli_fname ? : "", info->dli_fname ? ":" : "",
- buf, caller);
- }
- else
- fprintf (mallstream, "@ [%p] ", caller);
- }
-}
-
-static Dl_info *
-lock_and_info (const void *caller, Dl_info *mem)
-{
- if (caller == NULL)
- return NULL;
-
- Dl_info *res = _dl_addr (caller, mem, NULL, NULL) ? mem : NULL;
-
- __libc_lock_lock (lock);
-
- return res;
-}
-
-static void tr_freehook (void *, const void *);
-static void * tr_mallochook (size_t, const void *);
-static void * tr_reallochook (void *, size_t, const void *);
-static void * tr_memalignhook (size_t, size_t, const void *);
-
-/* Set all the default non-trace hooks. */
-static __always_inline void
-set_default_hooks (void)
-{
- __free_hook = tr_old_free_hook;
- __malloc_hook = tr_old_malloc_hook;
- __realloc_hook = tr_old_realloc_hook;
- __memalign_hook = tr_old_memalign_hook;
-}
-
-/* Set all of the tracing hooks used for mtrace. */
-static __always_inline void
-set_trace_hooks (void)
-{
- __free_hook = tr_freehook;
- __malloc_hook = tr_mallochook;
- __realloc_hook = tr_reallochook;
- __memalign_hook = tr_memalignhook;
-}
-
-/* Save the current set of hooks as the default hooks. */
-static __always_inline void
-save_default_hooks (void)
-{
- tr_old_free_hook = __free_hook;
- tr_old_malloc_hook = __malloc_hook;
- tr_old_realloc_hook = __realloc_hook;
- tr_old_memalign_hook = __memalign_hook;
-}
-
-static void
-tr_freehook (void *ptr, const void *caller)
-{
- if (ptr == NULL)
- return;
-
- Dl_info mem;
- Dl_info *info = lock_and_info (caller, &mem);
- tr_where (caller, info);
- /* Be sure to print it first. */
- fprintf (mallstream, "- %p\n", ptr);
- set_default_hooks ();
- if (tr_old_free_hook != NULL)
- (*tr_old_free_hook)(ptr, caller);
- else
- free (ptr);
- set_trace_hooks ();
- __libc_lock_unlock (lock);
-}
-
-static void *
-tr_mallochook (size_t size, const void *caller)
-{
- void *hdr;
-
- Dl_info mem;
- Dl_info *info = lock_and_info (caller, &mem);
-
- set_default_hooks ();
- if (tr_old_malloc_hook != NULL)
- hdr = (void *) (*tr_old_malloc_hook)(size, caller);
- else
- hdr = (void *) malloc (size);
- set_trace_hooks ();
-
- tr_where (caller, info);
- /* We could be printing a NULL here; that's OK. */
- fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
-
- __libc_lock_unlock (lock);
-
- return hdr;
-}
-
-static void *
-tr_reallochook (void *ptr, size_t size, const void *caller)
-{
- void *hdr;
-
- Dl_info mem;
- Dl_info *info = lock_and_info (caller, &mem);
-
- set_default_hooks ();
- if (tr_old_realloc_hook != NULL)
- hdr = (void *) (*tr_old_realloc_hook)(ptr, size, caller);
- else
- hdr = (void *) realloc (ptr, size);
- set_trace_hooks ();
-
- tr_where (caller, info);
- if (hdr == NULL)
- {
- if (size != 0)
- /* Failed realloc. */
- fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size);
- else
- fprintf (mallstream, "- %p\n", ptr);
- }
- else if (ptr == NULL)
- fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
- else
- {
- fprintf (mallstream, "< %p\n", ptr);
- tr_where (caller, info);
- fprintf (mallstream, "> %p %#lx\n", hdr, (unsigned long int) size);
- }
-
- __libc_lock_unlock (lock);
-
- return hdr;
-}
-
-static void *
-tr_memalignhook (size_t alignment, size_t size, const void *caller)
-{
- void *hdr;
-
- Dl_info mem;
- Dl_info *info = lock_and_info (caller, &mem);
-
- set_default_hooks ();
- if (tr_old_memalign_hook != NULL)
- hdr = (void *) (*tr_old_memalign_hook)(alignment, size, caller);
- else
- hdr = (void *) memalign (alignment, size);
- set_trace_hooks ();
-
- tr_where (caller, info);
- /* We could be printing a NULL here; that's OK. */
- fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
-
- __libc_lock_unlock (lock);
-
- return hdr;
-}
-
-
#ifdef _LIBC
/* This function gets called to make sure all memory the library
@@ -276,7 +71,7 @@ static void __libc_freeres_fn_section
release_libc_mem (void)
{
/* Only call the free function if we still are running in mtrace mode. */
- if (mallstream != NULL)
+ if (__mtrace_mallstream != NULL)
__libc_freeres ();
}
#endif
@@ -293,7 +88,7 @@ mtrace (void)
char *mallfile;
/* Don't panic if we're called more than once. */
- if (mallstream != NULL)
+ if (__mtrace_mallstream != NULL)
return;
#ifdef _LIBC
@@ -310,15 +105,15 @@ mtrace (void)
if (mtb == NULL)
return;
- mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wce");
- if (mallstream != NULL)
+ __mtrace_mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null",
+ "wce");
+ if (__mtrace_mallstream != NULL)
{
/* Be sure it doesn't malloc its buffer! */
malloc_trace_buffer = mtb;
- setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
- fprintf (mallstream, "= Start\n");
- save_default_hooks ();
- set_trace_hooks ();
+ setvbuf (__mtrace_mallstream, malloc_trace_buffer, _IOFBF,
+ TRACE_BUFFER_SIZE);
+ fprintf (__mtrace_mallstream, "= Start\n");
#ifdef _LIBC
if (!added_atexit_handler)
{
@@ -336,15 +131,11 @@ mtrace (void)
void
muntrace (void)
{
- if (mallstream == NULL)
+ if (__mtrace_mallstream == NULL)
return;
- /* Do the reverse of what done in mtrace: first reset the hooks and
- MALLSTREAM, and only after that write the trailer and close the
- file. */
- FILE *f = mallstream;
- mallstream = NULL;
- set_default_hooks ();
+ FILE *f = __mtrace_mallstream;
+ __mtrace_mallstream = NULL;
fprintf (f, "= End\n");
fclose (f);
@@ -4,7 +4,6 @@
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libm.so: matherr
# The TLS-enabled version of these functions is interposed from libc.so.
@@ -6,7 +6,6 @@
libc.so: calloc + REL R_386_GLOB_DAT
libc.so: free + REL R_386_GLOB_DAT
libc.so: malloc + REL R_386_GLOB_DAT
-libc.so: memalign + REL R_386_GLOB_DAT
libc.so: realloc + REL R_386_GLOB_DAT
libm.so: matherr + REL R_386_GLOB_DAT
# The TLS-enabled version of these functions is interposed from libc.so.
@@ -4,7 +4,6 @@
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libm.so: matherr
# If outline atomics are used, libgcc (built outside of glibc) may
@@ -18,7 +18,6 @@ libc.so: _Unwind_Find_FDE
libc.so: calloc + RELA R_ALPHA_GLOB_DAT
libc.so: free + RELA R_ALPHA_GLOB_DAT
libc.so: malloc + RELA R_ALPHA_GLOB_DAT
-libc.so: memalign + RELA R_ALPHA_GLOB_DAT
libc.so: realloc + RELA R_ALPHA_GLOB_DAT
libm.so: matherr + RELA R_ALPHA_GLOB_DAT
# We used to offer inline functions that used this, so it must be exported.
@@ -1,6 +1,5 @@
libc.so: realloc
libc.so: malloc
-libc.so: memalign
libc.so: calloc
libc.so: free
# At -Os, a struct assignment in libgcc-static pulls this in
@@ -1,7 +1,6 @@
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: raise
libc.so: realloc
libm.so: matherr
@@ -4,7 +4,6 @@
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
# The TLS-enabled version of these functions is interposed from libc.so.
ld.so: _dl_signal_error
@@ -4,7 +4,6 @@
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libc.so: __sigsetjmp
libc.so: _IO_funlockfile
@@ -4,7 +4,6 @@ libc.so: _Unwind_Find_FDE + REL R_386_GLOB_DAT
libc.so: calloc + REL R_386_GLOB_DAT
libc.so: free + REL R_386_GLOB_DAT
libc.so: malloc + REL R_386_GLOB_DAT
-libc.so: memalign + REL R_386_GLOB_DAT
libc.so: realloc + REL R_386_GLOB_DAT
libm.so: matherr + REL R_386_GLOB_DAT
# The TLS-enabled version of these functions is interposed from libc.so.
@@ -1,7 +1,6 @@
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libm.so: matherr
libm.so: matherrf
@@ -2,7 +2,6 @@ libc.so: __m68k_read_tp
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libm.so: matherr
# The TLS-enabled version of these functions is interposed from libc.so.
@@ -3,7 +3,6 @@ libc.so: __m68k_read_tp
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libm.so: matherr
# The TLS-enabled version of these functions is interposed from libc.so.
@@ -2,7 +2,6 @@ libc.so: __errno_location
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libm.so: matherr
# The dynamic loader needs __tls_get_addr for TLS.
@@ -6,7 +6,6 @@ libc.so: __gedf2
libc.so: malloc
libc.so: __gtsf2 ?
libc.so: __nesf2
-libc.so: memalign
libc.so: __mulsf3
libc.so: __floatunsisf
libc.so: __addsf3
@@ -2,7 +2,6 @@ libc.so: _Unwind_Find_FDE
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libm.so: matherr
# The TLS-enabled version of these functions is interposed from libc.so.
@@ -30,7 +30,6 @@ libc.so: abort ?
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: memset ?
libc.so: realloc
libm.so: copysignl ?
@@ -1,7 +1,6 @@
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libm.so: matherr
# The TLS-enabled version of these functions is interposed from libc.so.
@@ -4,7 +4,6 @@
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: memset ?
libc.so: realloc
# The TLS-enabled version of these functions is interposed from libc.so.
@@ -2,7 +2,6 @@ libc.so: _Unwind_Find_FDE
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libm.so: matherr
# The TLS-enabled version of these functions is interposed from libc.so.
@@ -4,7 +4,6 @@
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libc.so: _Unwind_Find_FDE
libc.so: _exit
@@ -16,7 +16,6 @@ libc.so: _Unwind_Find_FDE
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libm.so: matherr
# The TLS-enabled version of these functions is interposed from libc.so.
@@ -15,7 +15,6 @@ libc.so: _Unwind_Find_FDE
libc.so: calloc
libc.so: free
libc.so: malloc
-libc.so: memalign
libc.so: realloc
libm.so: matherr
# The TLS-enabled version of these functions is interposed from libc.so.
@@ -6,7 +6,6 @@
libc.so: calloc + RELA R_X86_64_GLOB_DAT
libc.so: free + RELA R_X86_64_GLOB_DAT
libc.so: malloc + RELA R_X86_64_GLOB_DAT
-libc.so: memalign + RELA R_X86_64_GLOB_DAT
libc.so: realloc + RELA R_X86_64_GLOB_DAT
libm.so: matherr + RELA R_X86_64_GLOB_DAT
# The TLS-enabled version of these functions is interposed from libc.so.