2016-04-06 34 views
1

私は次の基準を満たしているLinux上で実行可能ファイルを構築しようとしています:libstdC++とmemcpyを静的にリンクすることはできますか?

  1. が静的​​のlibstdC++にリンクして
  2. GCC(バージョン> = 4.8.2)の最新バージョンで構築された
  3. とglibc(のlibgccバージョン> 2.14)
  4. のglibcの旧バージョンとの下位互換性(バージョン< 2.5)

私の現在のdevの環境が構築されたバイナリはglibcを持つシステムでは動作しませんCentOSの7の2.17 glibcを、gcc4.8.5です< 2.14 memcpyへの依存のため。

objdump -T main | fgrep GLIBC_2.14 
0000000000000000  DF *UND* 0000000000000000 GLIBC_2.14 memcpy 

はglibc 2.14で導入されたmemcpyのための互換性に影響する変更は、私は古いバージョンの使用を強制する必要がありました。私はこのstackoverflowポストLinking against older symbol version in a .so fileに出くわしましたが、libstdC++に関連したリンカーの問題のために私のために働かなかった。以下は私の試みです。

main.cppに

#include <iostream> 
#include <string.h> 

int main(int argc, char** argv) 
{ 
    char source[] = "once upon a midnight dreary...", dest[4]; 
    memcpy(dest, source, sizeof dest); 
    std::cout << dest << std::endl; 
} 

wrap_memcpy.cpp

#include <string.h> 

__asm__(".symver memcpy, [email protected]_2.2.5"); 

void *__wrap_memcpy(void *dest, const void *src, size_t n) 
{ 
    return memcpy(dest, src, n); 
} 

コンパイラオプションとエラー:

g++ -static-libgcc -static-libstdc++ wrap_memcpy.cpp main.cpp -o main -Wl,--wrap=memcpy 

/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o): In function `std::ctype<char>::widen(char const*, char const*, char*) const': 
(.text._ZNKSt5ctypeIcE5widenEPKcS2_Pc[_ZNKSt5ctypeIcE5widenEPKcS2_Pc]+0x5f): undefined reference to `__wrap_memcpy' 
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o): In function `std::__timepunct<char>::__timepunct(__locale_struct*, char const*, unsigned long)': 
(.text._ZNSt11__timepunctIcEC2EP15__locale_structPKcm[_ZNSt11__timepunctIcEC5EP15__locale_structPKcm]+0x96): undefined reference to `__wrap_memcpy' 
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o): In function `std::messages<char>::messages(__locale_struct*, char const*, unsigned long)': 
(.text._ZNSt8messagesIcEC2EP15__locale_structPKcm[_ZNSt8messagesIcEC5EP15__locale_structPKcm]+0x8e): undefined reference to `__wrap_memcpy' 
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o): In function `std::messages_byname<char>::messages_byname(char const*, unsigned long)': 
(.text._ZNSt15messages_bynameIcEC2EPKcm[_ZNSt15messages_bynameIcEC5EPKcm]+0xd6): undefined reference to `__wrap_memcpy' 
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o): In function `std::__numpunct_cache<char>::_M_cache(std::locale const&)': 
(.text._ZNSt16__numpunct_cacheIcE8_M_cacheERKSt6locale[_ZNSt16__numpunct_cacheIcE8_M_cacheERKSt6locale]+0x2ad): undefined reference to `__wrap_memcpy' 
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/libstdc++.a(locale-inst.o):(.text._ZNSt16__numpunct_cacheIcE8_M_cacheERKSt6locale[_ZNSt16__numpunct_cacheIcE8_M_cacheERKSt6locale]+0x2cd): more undefined references to `__wrap_memcpy' follow 
collect2: error: ld returned 1 exit status 

私はここで間違って何をしているのですか?スタックオーバーフローポストで他のソリューションも試してみましたが、同じエラーが発生します。私はまた、Ubuntu 15.0.4でglibc 5.2.1をビルドしようとしましたが、同じ結果が得られました。 memcpy(GPLライセンスの下にある)をバイナリに静的にリンクすることは、ライセンス問題のためにオプションではないことに注意してください。

+0

以上のパス:この問題は(条件が完全に完璧ではないので、それらを調整する必要があるかもしれません)以降のコンパイラのバージョンでのみx64のために発生するので、私は強く、いくつかの追加の#ifdefを提案する。また おそらく、あなたのコード内の 'memcpy'のすべての使用を' memmove'でグローバルに検索して置き換えることになります。そして、あなたは古い 'memcpy'を必要としません。代わりに、保証されていない 'memcpy'動作に依存するコードを修正してください。それが簡単だった場合は、すでに完了しています。 – zwol

+0

返事をありがとう。残念ながら、私たちは新しいmemcpy(例えばboost)に依存している第三者のライブラリに依存しています。また#include はmemcpyにも依存関係を追加します。 – yoshimonster

+0

私はあなたの問題を理解していないかもしれません。あなたのコードが古い 'memcpy'の保証されていない動作を必要としない場合は、なぜそれを使用しようとしていますか? (別の言い方をすれば、なぜそれがあなたのバイナリが新しい 'memcpy'を参照するための問題です?) – zwol

答えて

3

あなたはこの関数はCの関数としてエクスポートされるように、にextern「C」{}で__wrap_memcpyラップする必要があります。それ以外の場合、その名前はC++関数として修飾されます。

#if defined(__GNUC__) && defined(__LP64__) && __LP64__ >= 1 && \ 
(_GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && \ 
(defined(__x86_64__) || defined(__i386__) ||\ 
defined(__i486__) || defined(__i586__) || defined(__i686__)) 

#include <string.h> 

__asm__(".symver memcpy, [email protected]_2.2.5"); 

extern "C" 
{ 
void *__wrap_memcpy(void *dest, const void *src, size_t n) 
{ 
    return memcpy(dest, src, n); 
} 
} 

#endif 
+0

それはトリックでした!どうもありがとうございます! – yoshimonster

+0

この質問と回答は、私の仕事の日数を節約しました。ありがとう –

関連する問題