diff options
author | Vladimir Mezentsev <vladimir.mezentsev@oracle.com> | 2023-04-16 13:55:48 -0700 |
---|---|---|
committer | Vladimir Mezentsev <vladimir.mezentsev@oracle.com> | 2023-04-17 13:01:38 -0700 |
commit | 35fab451d9ec11a7e02df750fb24feb21e9732b8 (patch) | |
tree | 64f9f7b28c6ac6a1a300ad29e2c1455ec952333d /gprofng/libcollector/iotrace.c | |
parent | 7a515757db9681e86926b7068b3a4a6a2df70299 (diff) | |
download | binutils-35fab451d9ec11a7e02df750fb24feb21e9732b8.zip binutils-35fab451d9ec11a7e02df750fb24feb21e9732b8.tar.gz binutils-35fab451d9ec11a7e02df750fb24feb21e9732b8.tar.bz2 |
gprofng: 30360 Seg. Fault when application uses std::thread
We interpose a lot of libC functions (dlopen, fork, pthread_create, etc.).
Some of these functions have versions. For example,
% nm -D /lib64/gprofng/libgp-collector.so | grep thread_create@ | sort
000000000004b420 T pthread_create@GLIBC_2.34
000000000004b490 T pthread_create@GLIBC_2.17
000000000004b500 T pthread_create@GLIBC_2.2.5
000000000004b570 T pthread_create@GLIBC_2.1
000000000004b5e0 T pthread_create@GLIBC_2.0
Our library does not set the default version for symbols.
This is correct because we don't know which libC will be used.
gcc and g++ links differently the version symbols when the default version is
not set. c-linker is using our pthread_create@GLIBC_2.34 and c++-linker is using
our pthread_create@GLIBC_2.0 by default.
The current implementation of the interposed functions is:
If we are in our pthread_create@GLIBC_<NN>,
we use dlvsym (dlflag, "pthread_create", "GLIBC_<NN>") to find and call
the same function from libC.
In the test from PR 30360, pthread_create@GLIBC_2.0 is not in the current libC.
We need to call the default version symbol from libC.
gprofng/ChangeLog
2023-04-16 Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
PR gprofng/30360
* libcollector/iotrace.c: Find and call a default libC version symbol.
* libcollector/dispatcher.c: Likewise.
* libcollector/iotrace.c: Likewise.
* libcollector/linetrace.c: Likewise.
* libcollector/mmaptrace.c: Likewise.
* libcollector/synctrace.c: Likewise.
* libcollector/collector.h (REAL_DCL): Remove an unused argument.
Diffstat (limited to 'gprofng/libcollector/iotrace.c')
-rw-r--r-- | gprofng/libcollector/iotrace.c | 87 |
1 files changed, 51 insertions, 36 deletions
diff --git a/gprofng/libcollector/iotrace.c b/gprofng/libcollector/iotrace.c index d27f852..c0ea749 100644 --- a/gprofng/libcollector/iotrace.c +++ b/gprofng/libcollector/iotrace.c @@ -450,6 +450,21 @@ init_io_intf () else __real_fgetpos64 = dlsym (dlflag, "fgetpos64"); + __real_fsetpos64_2_17 = dlvsym (dlflag, "fsetpos64", "GLIBC_2.17"); + __real_fsetpos64_2_2_5 = dlvsym (dlflag, "fsetpos64", "GLIBC_2.2.5"); + __real_fsetpos64_2_2 = dlvsym (dlflag, "fsetpos64", "GLIBC_2.2"); + __real_fsetpos64_2_1 = dlvsym (dlflag, "fsetpos64", "GLIBC_2.1"); + if (__real_fsetpos64_2_17) + __real_fsetpos64 = __real_fsetpos64_2_17; + else if (__real_fsetpos64_2_2_5) + __real_fsetpos64 = __real_fsetpos64_2_2_5; + else if (__real_fsetpos64_2_2) + __real_fsetpos64 = __real_fsetpos64_2_2; + else if (__real_fsetpos64_2_1) + __real_fsetpos64 = __real_fsetpos64_2_1; + else + __real_fsetpos64 = dlsym (dlflag, "fsetpos64"); + __real_pread_2_2 = dlvsym (dlflag, "pread", "GLIBC_2.2"); if (__real_pread_2_2) __real_pread = __real_pread_2_2; @@ -1001,21 +1016,21 @@ gprofng_open64 (int(real_open64) (const char *, int, ...), return fd; } -#define DCL_OPEN64(dcl_f, real_f) \ +#define DCL_OPEN64(dcl_f) \ int dcl_f (const char *path, int oflag, ...) \ { \ - if ((real_f) == NULL) \ + if (__real_open64 == NULL) \ init_io_intf (); \ mode_t mode; \ va_list ap; \ va_start (ap, oflag); \ mode = va_arg (ap, mode_t); \ va_end (ap); \ - return gprofng_open64 (real_f, path, oflag, mode); \ + return gprofng_open64 (__real_open64, path, oflag, mode); \ } DCL_FUNC_VER (DCL_OPEN64, open64_2_2, open64@GLIBC_2.2) -DCL_OPEN64 (open64, CALL_REAL(open64)) +DCL_OPEN64 (open64) #define F_ERROR_ARG 0 @@ -1516,19 +1531,19 @@ gprofng_fopen (FILE*(real_fopen) (), const char *filename, const char *mode) return fp; } -#define DCL_FOPEN(dcl_f, real_f) \ +#define DCL_FOPEN(dcl_f) \ FILE *dcl_f (const char *filename, const char *mode) \ { \ - if ((real_f) == NULL) \ + if (__real_fopen == NULL) \ init_io_intf (); \ - return gprofng_fopen (real_f, filename, mode); \ + return gprofng_fopen (__real_fopen, filename, mode); \ } DCL_FUNC_VER (DCL_FOPEN, fopen_2_17, fopen@GLIBC_2.17) DCL_FUNC_VER (DCL_FOPEN, fopen_2_2_5, fopen@GLIBC_2.2.5) DCL_FUNC_VER (DCL_FOPEN, fopen_2_1, fopen@GLIBC_2.1) DCL_FUNC_VER (DCL_FOPEN, fopen_2_0, fopen@GLIBC_2.0) -DCL_FOPEN (fopen, CALL_REAL(fopen)) +DCL_FOPEN (fopen) /*------------------------------------------------------------- fclose */ static int @@ -1564,19 +1579,19 @@ gprofng_fclose (int(real_fclose) (), FILE *stream) return stat; } -#define DCL_FCLOSE(dcl_f, real_f) \ +#define DCL_FCLOSE(dcl_f) \ int dcl_f (FILE *stream) \ { \ - if ((real_f) == NULL) \ + if (__real_fclose == NULL) \ init_io_intf (); \ - return gprofng_fclose (real_f, stream); \ + return gprofng_fclose (__real_fclose, stream); \ } DCL_FUNC_VER (DCL_FCLOSE, fclose_2_17, fclose@GLIBC_2.17) DCL_FUNC_VER (DCL_FCLOSE, fclose_2_2_5, fclose@GLIBC_2.2.5) DCL_FUNC_VER (DCL_FCLOSE, fclose_2_1, fclose@GLIBC_2.1) DCL_FUNC_VER (DCL_FCLOSE, fclose_2_0, fclose@GLIBC_2.0) -DCL_FCLOSE (fclose, CALL_REAL(fclose)) +DCL_FCLOSE (fclose) /*------------------------------------------------------------- fflush */ int @@ -1653,19 +1668,19 @@ gprofng_fdopen (FILE*(real_fdopen) (), int fildes, const char *mode) return fp; } -#define DCL_FDOPEN(dcl_f, real_f) \ +#define DCL_FDOPEN(dcl_f) \ FILE *dcl_f (int fildes, const char *mode) \ { \ - if ((real_f) == NULL) \ + if (__real_fdopen == NULL) \ init_io_intf (); \ - return gprofng_fdopen (real_f, fildes, mode); \ + return gprofng_fdopen (__real_fdopen, fildes, mode); \ } DCL_FUNC_VER (DCL_FDOPEN, fdopen_2_17, fdopen@GLIBC_2.17) DCL_FUNC_VER (DCL_FDOPEN, fdopen_2_2_5, fdopen@GLIBC_2.2.5) DCL_FUNC_VER (DCL_FDOPEN, fdopen_2_1, fdopen@GLIBC_2.1) DCL_FUNC_VER (DCL_FDOPEN, fdopen_2_0, fdopen@GLIBC_2.0) -DCL_FDOPEN (fdopen, CALL_REAL(fdopen)) +DCL_FDOPEN (fdopen) /*------------------------------------------------------------- dup */ int @@ -2088,16 +2103,16 @@ gprofng_pread (ssize_t(real_pread) (int, void *, size_t, off_t), return ret; } -#define DCL_PREAD(dcl_f, real_f) \ +#define DCL_PREAD(dcl_f) \ ssize_t dcl_f (int fildes, void *buf, size_t nbyte, off_t offset) \ { \ - if ((real_f) == NULL) \ + if (__real_pread == NULL) \ init_io_intf (); \ - return gprofng_pread (real_f, fildes, buf, nbyte, offset); \ + return gprofng_pread (__real_pread, fildes, buf, nbyte, offset); \ } DCL_FUNC_VER (DCL_PREAD, pread_2_2, pread@GLIBC_2.2) -DCL_PREAD (pread, CALL_REAL(pread)) +DCL_PREAD (pread) /*------------------------------------------------------------- pwrite */ @@ -2914,19 +2929,19 @@ gprofng_fgetpos (int(real_fgetpos) (FILE *stream, fpos_t *pos), return ret; } -#define DCL_FGETPOS(dcl_f, real_f) \ +#define DCL_FGETPOS(dcl_f) \ int dcl_f (FILE *stream, fpos_t *pos) \ { \ - if ((real_f) == NULL) \ + if (__real_fgetpos == NULL) \ init_io_intf (); \ - return gprofng_fgetpos (real_f, stream, pos); \ + return gprofng_fgetpos (__real_fgetpos, stream, pos); \ } DCL_FUNC_VER (DCL_FGETPOS, fgetpos_2_17, fgetpos@GLIBC_2.17) DCL_FUNC_VER (DCL_FGETPOS, fgetpos_2_2_5, fgetpos@GLIBC_2.2.5) DCL_FUNC_VER (DCL_FGETPOS, fgetpos_2_2, fgetpos@GLIBC_2.2) DCL_FUNC_VER (DCL_FGETPOS, fgetpos_2_0, fgetpos@GLIBC_2.0) -DCL_FGETPOS (fgetpos, CALL_REAL(fgetpos)) +DCL_FGETPOS (fgetpos) /*------------------------------------------------------------- fgetpos64 */ static int @@ -2962,19 +2977,19 @@ gprofng_fgetpos64 (int(real_fgetpos64) (), FILE *stream, fpos64_t *pos) return ret; } -#define DCL_FGETPOS64(dcl_f, real_f) \ +#define DCL_FGETPOS64(dcl_f) \ int dcl_f (FILE *stream, fpos64_t *pos) \ { \ - if ((real_f) == NULL) \ + if (__real_fgetpos64 == NULL) \ init_io_intf (); \ - return gprofng_fgetpos64 (real_f, stream, pos); \ + return gprofng_fgetpos64 (__real_fgetpos64, stream, pos); \ } DCL_FUNC_VER (DCL_FGETPOS64, fgetpos64_2_17, fgetpos64@GLIBC_2.17) DCL_FUNC_VER (DCL_FGETPOS64, fgetpos64_2_2_5, fgetpos64@GLIBC_2.2.5) DCL_FUNC_VER (DCL_FGETPOS64, fgetpos64_2_2, fgetpos64@GLIBC_2.2) DCL_FUNC_VER (DCL_FGETPOS64, fgetpos64_2_1, fgetpos64@GLIBC_2.1) -DCL_FGETPOS64 (fgetpos64, CALL_REAL(fgetpos64)) +DCL_FGETPOS64 (fgetpos64) /*------------------------------------------------------------- fsetpos */ static int @@ -3011,19 +3026,19 @@ gprofng_fsetpos (int(real_fsetpos) (FILE *, const fpos_t *), return ret; } -#define DCL_FSETPOS(dcl_f, real_f) \ +#define DCL_FSETPOS(dcl_f) \ int dcl_f (FILE *stream, const fpos_t *pos) \ { \ - if ((real_f) == NULL) \ + if (__real_fsetpos == NULL) \ init_io_intf (); \ - return gprofng_fsetpos (real_f, stream, pos); \ + return gprofng_fsetpos (__real_fsetpos, stream, pos); \ } DCL_FUNC_VER (DCL_FSETPOS, fsetpos_2_17, fsetpos@GLIBC_2.17) DCL_FUNC_VER (DCL_FSETPOS, fsetpos_2_2_5, fsetpos@GLIBC_2.2.5) DCL_FUNC_VER (DCL_FSETPOS, fsetpos_2_2, fsetpos@GLIBC_2.2) DCL_FUNC_VER (DCL_FSETPOS, fsetpos_2_0, fsetpos@GLIBC_2.0) -DCL_FSETPOS (fsetpos, CALL_REAL(fsetpos)) +DCL_FSETPOS (fsetpos) /*------------------------------------------------------------- fsetpos64 */ static int @@ -3060,19 +3075,19 @@ gprofng_fsetpos64 (int(real_fsetpos64) (FILE *, const fpos64_t *), return ret; } -#define DCL_FSETPOS64(dcl_f, real_f) \ +#define DCL_FSETPOS64(dcl_f) \ int dcl_f (FILE *stream, const fpos64_t *pos) \ { \ - if ((real_f) == NULL) \ + if (__real_fsetpos64 == NULL) \ init_io_intf (); \ - return gprofng_fsetpos64 (real_f, stream, pos); \ + return gprofng_fsetpos64 (__real_fsetpos64, stream, pos); \ } DCL_FUNC_VER (DCL_FSETPOS64, fsetpos64_2_17, fsetpos64@GLIBC_2.17) DCL_FUNC_VER (DCL_FSETPOS64, fsetpos64_2_2_5, fsetpos64@GLIBC_2.2.5) DCL_FUNC_VER (DCL_FSETPOS64, fsetpos64_2_2, fsetpos64@GLIBC_2.2) DCL_FUNC_VER (DCL_FSETPOS64, fsetpos64_2_1, fsetpos64@GLIBC_2.1) -DCL_FSETPOS64 (fsetpos64, CALL_REAL(fsetpos64)) +DCL_FSETPOS64 (fsetpos64) /*------------------------------------------------------------- fsync */ int |