Saya menemukan solusi kerja berikut. Pertama buat file memcpy.c:
#include <string.h>
/* some systems do not have newest [email protected]@GLIBC_2.14 - stay with old good one */
asm (".symver memcpy, [email protected]_2.2.5");
void *__wrap_memcpy(void *dest, const void *src, size_t n)
{
return memcpy(dest, src, n);
}
Tidak diperlukan CFLAGS tambahan untuk mengkompilasi file ini. Kemudian tautkan program Anda dengan -Wl,--wrap=memcpy .
Saya memiliki masalah yang sama. Mencoba menginstal beberapa komponen oracle di RHEL 7.1, saya mendapatkan ini:
$ gcc -o /some/oracle/bin/foo .... -L/some/oracle/lib ...
/some/oracle/lib/libfoo.so: undefined reference to `[email protected]_2.14'
Tampaknya glibc RHEL (saya) hanya mendefinisikan [email protected]_2.2.5:
$ readelf -Ws /usr/lib/x86_64-redhat-linux6E/lib64/libc_real.so | fgrep [email protected]
367: 000000000001bfe0 16 FUNC GLOBAL DEFAULT 8 [email protected]@GLIBC_2.2.5
1166: 0000000000019250 16 FUNC WEAK DEFAULT 8 [email protected]@GLIBC_2.2.5
Jadi, saya berhasil menyiasatinya, dengan terlebih dahulu membuat file memcpy.c tanpa pembungkus, sebagai berikut:
#include <string.h>
asm (".symver old_memcpy, [email protected]_2.2.5"); // hook old_memcpy as [email protected]
void *old_memcpy(void *, const void *, size_t );
void *memcpy(void *dest, const void *src, size_t n) // then export memcpy
{
return old_memcpy(dest, src, n);
}
dan file memcpy.map yang mengekspor memcpy kami sebagai [email protected]_2.14:
GLIBC_2.14 {
memcpy;
};
Saya kemudian mengkompilasi memcpy.c saya sendiri ke dalam lib bersama seperti ini:
$ gcc -shared -fPIC -c memcpy.c
$ gcc -shared -fPIC -Wl,--version-script memcpy.map -o libmemcpy-2.14.so memcpy.o -lc
, memindahkan libmemcpy-2.14.so ke /some/Oracle/lib (ditunjukkan oleh argumen -L dalam penautan saya), dan ditautkan lagi oleh
$ gcc -o /some/oracle/bin/foo .... -L/some/oracle/lib ... /some/oracle/lib/libmemcpy-2.14.so -lfoo ...
(yang dikompilasi tanpa kesalahan) dan memverifikasinya dengan:
$ ldd /some/oracle/bin/foo
linux-vdso.so.1 => (0x00007fff9f3fe000)
/some/oracle/lib/libmemcpy-2.14.so (0x00007f963a63e000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f963a428000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f963a20c000)
librt.so.1 => /lib64/librt.so.1 (0x00007f963a003000)
libc.so.6 => /lib64/libc.so.6 (0x00007f9639c42000)
/lib64/ld-linux-x86-64.so.2 (0x00007f963aa5b000)
Ini bekerja untuk saya. Saya harap ini juga berlaku untuk Anda.
Saya memiliki masalah serupa. Pustaka pihak ketiga yang kami gunakan membutuhkan [email protected]_2.2.5
lama . Solusi saya adalah pendekatan yang diperluas @anight diposting.
Saya juga membengkokkan memcpy
perintah, tetapi saya harus menggunakan pendekatan yang sedikit berbeda, karena solusi @anight diposting tidak bekerja untuk saya.
memcpy_wrap.c:
#include <stddef.h>
#include <string.h>
asm (".symver wrap_memcpy, [email protected]_2.2.5");
void *wrap_memcpy(void *dest, const void *src, size_t n) {
return memcpy(dest, src, n);
}
memcpy_wrap.map:
GLIBC_2.2.5 {
memcpy;
};
Bangun pembungkusnya:
gcc -c memcpy_wrap.c -o memcpy_wrap.o
Sekarang akhirnya saat menautkan program, tambahkan
-Wl,--version-script memcpy_wrap.map
memcpy_wrap.o
sehingga Anda akan berakhir dengan sesuatu seperti:
g++ <some flags> -Wl,--version-script memcpy_wrap.map <some .o files> memcpy_wrap.o <some libs>
Cukup tautkan memcpy secara statis - tarik memcpy.o dari libc.a ar x /path/to/libc.a memcpy.o
(versi apa pun - memcpy adalah fungsi yang berdiri sendiri) dan sertakan di tautan terakhir Anda. Perhatikan bahwa penautan statis dapat memperumit masalah lisensi jika proyek Anda didistribusikan ke publik dan bukan sumber terbuka.
Sebagai alternatif, Anda dapat mengimplementasikan memcpy sendiri, meskipun versi rakitan yang disesuaikan dengan tangan di glibc cenderung lebih efisien
Perhatikan bahwa [email protected]_2.2.5 dipetakan ke memmove (versi lama memcpy secara konsisten disalin ke arah yang dapat diprediksi, yang terkadang menyebabkannya disalahgunakan ketika memmove seharusnya digunakan), dan ini adalah satu-satunya alasan untuk peningkatan versi - Anda cukup mengganti memcpy dengan memmove dalam kode Anda untuk kasus khusus ini.
Atau Anda dapat menggunakan penautan statis, atau Anda dapat memastikan bahwa semua sistem di jaringan Anda memiliki versi yang sama atau lebih baik daripada mesin build Anda.