代码跳转到未引用的共享对象
Code jumps into unreferenced shared object
我的静态链接 CryptoPP 代码(在 Linux 上通过 Matlab mex 调用时)跳转到 libmwflcryptocryptopp.so 二进制文件(然后冻结)。
我的代码怎么跳转到国外的.so而不是静态链接库?
从我的 vcpkg_installed/.../cryptopp/filters.h:1443
中的函数 CryptoPP::SourceTemplate<CryptoPP::FileStore>::PumpAll2
跳转到 CryptoPP::BufferedTransformation::TransferAllTo2
来自 Matlabs 自己的 libmwflcryptocryptopp.so
文件。
gdb 堆栈跟踪
#0 0x00007ffff02e6cab in CryptoPP::BufferedTransformation::Peek(unsigned char&) const () from /usr/local/MATLAB/R2020b/bin/glnxa64/libmwflcryptocryptopp.so
#1 0x00007ffff02e6c19 in CryptoPP::BufferedTransformation::AnyRetrievable() const () from /usr/local/MATLAB/R2020b/bin/glnxa64/libmwflcryptocryptopp.so
#2 0x00007ffff02e6ffe in CryptoPP::BufferedTransformation::TransferMessagesTo2(CryptoPP::BufferedTransformation&, unsigned int&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) () from /usr/local/MATLAB/R2020b/bin/glnxa64/libmwflcryptocryptopp.so
#3 0x00007ffff02e7129 in CryptoPP::BufferedTransformation::TransferAllTo2(CryptoPP::BufferedTransformation&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) () from /usr/local/MATLAB/R2020b/bin/glnxa64/libmwflcryptocryptopp.so
#4 0x00007fff9758aa4d in CryptoPP::SourceTemplate<CryptoPP::FileStore>::PumpAll2 (this=0x7fffdd87fbc0, blocking=<optimized out>)
at /home/keinkoenig/build-o1/vcpkg_installed/x64-linux/include/cryptopp/filters.h:1443
#5 0x00007fff9758a130 in CryptoPP::Source::PumpAll (this=0x7fffdd87fbc0) at /home/keinkoenig/build-o1/vcpkg_installed/x64-linux/include/cryptopp/filters.h:1420
#6 CryptoPP::Source::SourceInitialize (parameters=warning: RTTI symbol not found for class 'CryptoPP::AlgorithmParameters'
..., pumpAll=true, this=0x7fffdd87fbc0) at /home/keinkoenig/build-o1/vcpkg_installed/x64-linux/include/cryptopp/filters.h:1420
#7 CryptoPP::FileSource::FileSource (attachment=0x7fffd6063160, pumpAll=true, in=..., this=0x7fffdd87fbc0) at /home/keinkoenig/build-o1/vcpkg_installed/x64-linux/include/cryptopp/files.h:102
#8 mexFunction (nlhs=<optimized out>, plhs=<optimized out>, nrhs=<optimized out>, prhs=<optimized out>) at /home/keinkoenig/src/CryptoppMinimal/CryptoppMinimal.cpp:18
最小示例代码
#include <mex.h>
#include <cryptopp/files.h>
#include <cryptopp/aes.h>
#include <cryptopp/modes.h>
#include <fstream>
unsigned char Key[CryptoPP::AES::DEFAULT_KEYLENGTH] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF };
unsigned char IV[CryptoPP::AES::BLOCKSIZE] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF };
extern "C"
{
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
std::ifstream instream(mxArrayToString(prhs[0]));
std::string decryptedString;
CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption cfbDecryption(Key, sizeof(Key), IV);
CryptoPP::FileSource(instream, true, new CryptoPP::StreamTransformationFilter( cfbDecryption, new CryptoPP::StringSink( decryptedString)));
}
}
和 CMakeLists 链接
set(PROJECT_NAME CryptoppMinimal)
...
target_link_libraries(${PROJECT_NAME} PRIVATE cryptopp-static)
用 gdb 启动控制台 matlab
/usr/local/MATLAB/R2020b/bin/matlab -nojvm -Dgdb
和运行在Matlab中测试mex函数
addpath ~/build-o1/bin
CryptoppMinimal('/home/keinkoenig/src/encrypted.dat')
TL;DR;你的 cryptocpp 正在被 Matlab LD_PRELOAD
编辑,即使它是静态链接的。
关于正在发生的事情的一个重要提示是正在加载的 .so 的路径:
#3 0x00007ffff02e7129 [...] /usr/local/MATLAB/R2020b/bin/glnxa64/libmwflcryptocryptopp.so
与编译期间使用的 headers 相比:
#5 [...] /home/keinkoenig/build-o1/vcpkg_installed/x64-linux/include/cryptopp/filters.h:1420
这表明 cryptocpp 运行 不仅来自动态库,而且 运行 来自与您编译的库不同的 .so
!
怎么会这样?如果使用与位置无关的代码编译静态库,对库中函数的调用仍将以与动态库相同的方式分派:跳转 table.
与动态库非常相似,如果在加载代码时跳转 table 已经填充,现有的函数指针将被重用。
所以,如果:
- crypto-cpp 是用
-fPIC
编译的
- Matlab 恰好在您的代码加载之前加载了 crypto-cpp
.so
。
然后项目中嵌入的 crypto-cpp 版本将被忽略,而将使用 Matlab 版本。
快速查看 crypto-cpp 项目,我们发现,在 Makefile 中:
# Add -fPIC for targets *except* X86, X32, Cygwin or MinGW
ifeq ($(IS_X86)$(IS_CYGWIN)$(IS_MINGW),000)
ifeq ($(findstring -fpic,$(CXXFLAGS))$(findstring -fPIC,$(CXXFLAGS)),)
CRYPTOPP_CXXFLAGS += -fPIC
endif
endif
这似乎证实了这就是正在发生的事情。
您可以通过从 Matlab 外部加载和 运行 您的库来确认,它应该按预期调用静态库的代码。
我的静态链接 CryptoPP 代码(在 Linux 上通过 Matlab mex 调用时)跳转到 libmwflcryptocryptopp.so 二进制文件(然后冻结)。
我的代码怎么跳转到国外的.so而不是静态链接库?
从我的 vcpkg_installed/.../cryptopp/filters.h:1443
中的函数 CryptoPP::SourceTemplate<CryptoPP::FileStore>::PumpAll2
跳转到 CryptoPP::BufferedTransformation::TransferAllTo2
来自 Matlabs 自己的 libmwflcryptocryptopp.so
文件。
gdb 堆栈跟踪
#0 0x00007ffff02e6cab in CryptoPP::BufferedTransformation::Peek(unsigned char&) const () from /usr/local/MATLAB/R2020b/bin/glnxa64/libmwflcryptocryptopp.so
#1 0x00007ffff02e6c19 in CryptoPP::BufferedTransformation::AnyRetrievable() const () from /usr/local/MATLAB/R2020b/bin/glnxa64/libmwflcryptocryptopp.so
#2 0x00007ffff02e6ffe in CryptoPP::BufferedTransformation::TransferMessagesTo2(CryptoPP::BufferedTransformation&, unsigned int&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) () from /usr/local/MATLAB/R2020b/bin/glnxa64/libmwflcryptocryptopp.so
#3 0x00007ffff02e7129 in CryptoPP::BufferedTransformation::TransferAllTo2(CryptoPP::BufferedTransformation&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) () from /usr/local/MATLAB/R2020b/bin/glnxa64/libmwflcryptocryptopp.so
#4 0x00007fff9758aa4d in CryptoPP::SourceTemplate<CryptoPP::FileStore>::PumpAll2 (this=0x7fffdd87fbc0, blocking=<optimized out>)
at /home/keinkoenig/build-o1/vcpkg_installed/x64-linux/include/cryptopp/filters.h:1443
#5 0x00007fff9758a130 in CryptoPP::Source::PumpAll (this=0x7fffdd87fbc0) at /home/keinkoenig/build-o1/vcpkg_installed/x64-linux/include/cryptopp/filters.h:1420
#6 CryptoPP::Source::SourceInitialize (parameters=warning: RTTI symbol not found for class 'CryptoPP::AlgorithmParameters'
..., pumpAll=true, this=0x7fffdd87fbc0) at /home/keinkoenig/build-o1/vcpkg_installed/x64-linux/include/cryptopp/filters.h:1420
#7 CryptoPP::FileSource::FileSource (attachment=0x7fffd6063160, pumpAll=true, in=..., this=0x7fffdd87fbc0) at /home/keinkoenig/build-o1/vcpkg_installed/x64-linux/include/cryptopp/files.h:102
#8 mexFunction (nlhs=<optimized out>, plhs=<optimized out>, nrhs=<optimized out>, prhs=<optimized out>) at /home/keinkoenig/src/CryptoppMinimal/CryptoppMinimal.cpp:18
最小示例代码
#include <mex.h>
#include <cryptopp/files.h>
#include <cryptopp/aes.h>
#include <cryptopp/modes.h>
#include <fstream>
unsigned char Key[CryptoPP::AES::DEFAULT_KEYLENGTH] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF };
unsigned char IV[CryptoPP::AES::BLOCKSIZE] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF };
extern "C"
{
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
std::ifstream instream(mxArrayToString(prhs[0]));
std::string decryptedString;
CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption cfbDecryption(Key, sizeof(Key), IV);
CryptoPP::FileSource(instream, true, new CryptoPP::StreamTransformationFilter( cfbDecryption, new CryptoPP::StringSink( decryptedString)));
}
}
和 CMakeLists 链接
set(PROJECT_NAME CryptoppMinimal)
...
target_link_libraries(${PROJECT_NAME} PRIVATE cryptopp-static)
用 gdb 启动控制台 matlab
/usr/local/MATLAB/R2020b/bin/matlab -nojvm -Dgdb
和运行在Matlab中测试mex函数
addpath ~/build-o1/bin
CryptoppMinimal('/home/keinkoenig/src/encrypted.dat')
TL;DR;你的 cryptocpp 正在被 Matlab LD_PRELOAD
编辑,即使它是静态链接的。
关于正在发生的事情的一个重要提示是正在加载的 .so 的路径:
#3 0x00007ffff02e7129 [...] /usr/local/MATLAB/R2020b/bin/glnxa64/libmwflcryptocryptopp.so
与编译期间使用的 headers 相比:
#5 [...] /home/keinkoenig/build-o1/vcpkg_installed/x64-linux/include/cryptopp/filters.h:1420
这表明 cryptocpp 运行 不仅来自动态库,而且 运行 来自与您编译的库不同的 .so
!
怎么会这样?如果使用与位置无关的代码编译静态库,对库中函数的调用仍将以与动态库相同的方式分派:跳转 table.
与动态库非常相似,如果在加载代码时跳转 table 已经填充,现有的函数指针将被重用。
所以,如果:
- crypto-cpp 是用
-fPIC
编译的
- Matlab 恰好在您的代码加载之前加载了 crypto-cpp
.so
。
然后项目中嵌入的 crypto-cpp 版本将被忽略,而将使用 Matlab 版本。
快速查看 crypto-cpp 项目,我们发现,在 Makefile 中:
# Add -fPIC for targets *except* X86, X32, Cygwin or MinGW
ifeq ($(IS_X86)$(IS_CYGWIN)$(IS_MINGW),000)
ifeq ($(findstring -fpic,$(CXXFLAGS))$(findstring -fPIC,$(CXXFLAGS)),)
CRYPTOPP_CXXFLAGS += -fPIC
endif
endif
这似乎证实了这就是正在发生的事情。
您可以通过从 Matlab 外部加载和 运行 您的库来确认,它应该按预期调用静态库的代码。