digoal
2024-01-24
PostgreSQL , PolarDB , DuckDB , chatgpt , linux , lib , so , undefined symbol , nm , objdump , ldd
使用gpt4_turbo_128K 排查PG create extension duckdb_fdw
异常: could not load library...undefined symbol...
.
create extension duckdb_fdw
报错
ERROR: could not load library "/usr/lib/postgresql/14/lib/duckdb_fdw.so": /usr/lib/postgresql/14/lib/duckdb_fdw.so: undefined symbol: _ZN6duckdb9Exception25ConstructMessageRecursiveERKSsRSt6vectorINS_20ExceptionFormatValueESaIS4_EE
使用的是如下2个pg/duckdb学习docker image环境
duckdb_fdw安装过程:
cd $TEMP_DIR
git clone --depth 1 https://github.com/alitrack/duckdb_fdw
cd $TEMP_DIR/duckdb_fdw
# 使用了已编译好的libduckdb.so
wget -T 36000 -t 0 --waitretry=5 https://github.com/duckdb/duckdb/releases/download/v0.9.2/libduckdb-linux-aarch64.zip
unzip -n -d . libduckdb-linux-aarch64.zip
cp libduckdb.so $(pg_config --libdir)
USE_PGXS=1 make
USE_PGXS=1 make install
gpt4_turbo_128K回复使用ldd, nm, objdump
查一下duckdb_fdw.so. 可以看到依赖libduckdb.so
, 怀疑和编译好的libduckdb.so有关.
nm
and objdump
are powerful tools used for inspecting binary files such as shared libraries and object files. They can help diagnose issues with symbols and dependencies within binaries.
Here's how you can use these tools to diagnose the undefined symbol issue with duckdb_fdw.so
:
nm
lists symbols from object files. If you want to check whether a specific symbol is present in a binary, you can use nm
and then grep
for the symbol.
-
List symbols in
duckdb_fdw.so
:nm -C /usr/lib/postgresql/14/lib/duckdb_fdw.so | grep 'ConstructMessageRecursive'
The
-C
flag demangles (decodes) the symbol names, which makes them more readable. Look for symbols related toConstructMessageRecursive
. If the symbol is undefined, it will have aU
next to it. -
Check for the symbol in DuckDB's library:
nm -C /path/to/libduckdb.so | grep 'ConstructMessageRecursive'
Replace
/path/to/libduckdb.so
with the actual path to the DuckDB library file. You're looking to see if this symbol is defined in the DuckDB library, which should not have theU
next to it if it's properly defined.
objdump
displays information about object files. You can use it to examine the dynamic symbol table, which contains the symbols needed for dynamic linking.
-
Inspect dynamic symbols of
duckdb_fdw.so
:objdump -T /usr/lib/postgresql/14/lib/duckdb_fdw.so | grep 'ConstructMessageRecursive'
The
-T
option displays the dynamic symbol table of the shared object. If the symbol is undefined, it will be marked with*UND*
. -
Inspect dynamic symbols of DuckDB's library:
objdump -T /path/to/libduckdb.so | grep 'ConstructMessageRecursive'
Again, replace
/path/to/libduckdb.so
with the actual path to the DuckDB library file. The symbol should be defined here and should not show*UND*
.
If you see that the symbol is listed as undefined (U
with nm
or *UND*
with objdump
) in duckdb_fdw.so
but is defined in libduckdb.so
, this means that the linker is unable to resolve this symbol when attempting to load duckdb_fdw.so
. This could be due to issues such as library path misconfiguration, version incompatibility, or improper building or installation procedures.
If the symbol is not found in libduckdb.so
, this indicates that the duckdb_fdw
extension might be compiled against a different version of the DuckDB library than the one you have installed, or there might be some corruption or issue with the library itself.
Based on the information you gather from nm
and objdump
, you can take appropriate action, such as recompiling duckdb_fdw
against the correct version of DuckDB, fixing library paths, or reinstalling DuckDB if necessary.
下载libduckdb-src.zip
重新编译, 而不是使用编译好的libduckdb.so
https://github.com/duckdb/duckdb/releases
https://github.com/duckdb/duckdb/releases/download/v0.9.2/libduckdb-src.zip
但是怎么把h,cpp,hpp变易成so? gpt4_turbo_128K回复:
如果你只有 .h
, .cpp
, .hpp
文件,并且想要将它们编译成 .so
文件(共享库),你将需要创建一个适当的编译命令或者使用 CMake
等构建系统来管理编译过程。这里,我将演示如何手动使用 g++
(GCC 的 C++ 编译器)来编译这些文件为 .so
文件。
-
安装编译工具:
确保你的系统上安装了g++
和其他构建工具。在 Ubuntu 上,你可以使用下面的命令来安装:sudo apt-get update sudo apt-get install build-essential
-
编译源代码为对象文件:
对于每个.cpp
文件,你需要使用g++
来编译它们为对象文件(.o
)。使用-fPIC
选项(Position Independent Code)是创建共享库的要求,因为它允许代码在内存中任意位置运行。g++ -c -fPIC source1.cpp -o source1.o g++ -c -fPIC source2.cpp -o source2.o ...
可以用通配符来简化这个过程,假设当前目录下所有
.cpp
文件都是你想要编译的:g++ -c -fPIC *.cpp
-
创建共享库:
将所有的对象文件链接成一个.so
文件。使用-shared
选项告诉编译器创建一个共享库。g++ -shared -o libmylibrary.so source1.o source2.o ...
如果你有很多对象文件,可以使用通配符:
g++ -shared -o libmylibrary.so *.o
-
(可选) 设置库版本和soname:
如果你想要设置版本或者 soname(共享对象名称),你可以使用-Wl
选项。g++ -shared -Wl,-soname,libmylibrary.so.1 -o libmylibrary.so.1.0 source1.o source2.o ...
这里,
libmylibrary.so.1
是 soname,而libmylibrary.so.1.0
是库文件的实际名称。 -
测试共享库:
为了测试你的共享库,你可以创建一个简单的测试程序,然后使用g++
并链接你的库来编译它。g++ -L. -lmylibrary -o testprogram testprogram.cpp
这里,
-L.
表示告诉编译器在当前目录寻找库,而-lmylibrary
链接到libmylibrary.so
。 -
运行时库路径:
如果你在非标准库路径中创建了.so
文件,运行时你可能需要设置LD_LIBRARY_PATH
环境变量来指定共享库的位置。export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
现在你可以运行你的测试程序,它应该会使用你的共享库。
请记住,这个过程是通用的,并且假定你所有的源文件都是独立的,不需要额外的依赖或者复杂的构建步骤。如果库有复杂的依赖关系,创建一个 CMakeLists.txt
文件来使用 CMake
构建系统可能更合适。
clang++ -c -fPIC duckdb.cpp -o duckdb.o
clang++ -shared -o libduckdb.so *.o
编译完, 把libduckdb.so替换后重新安装duckdb_fdw, 报了另一个错, 看起来只是符号_ZN6duckdb9ExceptionC1ENS_13ExceptionTypeERKSs
变了.
cd duckdb_fdw
grep -r _ZN6duckdb9ExceptionC1ENS_13ExceptionTypeERKSs *
duckdb_fdw.so
sqlite3_api_wrapper.o
The grep
command you've run indicates that the symbol _ZN6duckdb9ExceptionC1ENS_13ExceptionTypeERKSs
is found in both duckdb_fdw.so
and sqlite3_api_wrapper.o
. This means that this specific symbol, which is a mangled C++ name, is indeed present in those binary files.
Given that the symbol is there, but PostgreSQL is reporting an "undefined symbol" error, the issue might be related to the following:
-
Linkage Issues: The symbol may not be correctly linked. This could be due to the
duckdb_fdw.so
extension being compiled against a different version of the DuckDB library than the one currently installed on your system. -
Mismatched ABIs: The Application Binary Interface (ABI) expected by
duckdb_fdw.so
might differ from the ABI provided by the installed DuckDB library. This could occur if they were compiled with different compiler versions or settings. -
Incorrect Load Order: It's possible that the dependencies are not being loaded in the correct order, causing the symbol to appear undefined when
duckdb_fdw.so
is loaded.
To resolve the issue, you can try the following:
-
Ensure Consistent Versions: Double-check that you have consistent versions of DuckDB and
duckdb_fdw
installed. They should be compatible with each other. -
Recompile
duckdb_fdw
: Recompile theduckdb_fdw
extension with the correct and currently installed version of DuckDB to ensure they are compatible. Make sure you clean any previous build artifacts before recompiling. -
Install DuckDB Correctly: Verify that DuckDB is installed correctly and the headers and libraries are consistent with what
duckdb_fdw
expects. -
Set Proper Library Paths: Make sure that the library path (
LD_LIBRARY_PATH
) is set correctly, and PostgreSQL can find all necessary libraries at runtime. -
Use
ldd
to Check Dependencies: You can use theldd
command to check the shared library dependencies ofduckdb_fdw.so
:ldd /usr/lib/postgresql/14/lib/duckdb_fdw.so
This will list the shared libraries that
duckdb_fdw.so
depends on and whether they are found. -
Look for Help: If you're still stuck, look for help in the DuckDB community or reach out to the maintainers.
-
File an Issue: If you suspect this is a bug or regression, you may file an issue on the GitHub repository of DuckDB or
duckdb_fdw
with detailed information about your situation.
Remember, after making any changes to the system's libraries or PostgreSQL's configuration, it's important to restart the PostgreSQL server to ensure that changes take effect.
说明是编译so的参数和duckdb_fdw src Makefile 不一致, 修改后重新编译正常.
# 编译 libduckdb.so 可能比较费内存, 建设调大docker 内存限制到8GB以上
cd /tmp
wget -T 36000 -t 0 --waitretry=5 https://github.com/duckdb/duckdb/releases/download/v0.9.2/libduckdb-src.zip
git clone --depth 1 https://github.com/alitrack/duckdb_fdw
mkdir /tmp/duckdb_fdw/libduckdb
mv /tmp/libduckdb-src.zip /tmp/duckdb_fdw/libduckdb
cd /tmp/duckdb_fdw/libduckdb
unzip libduckdb-src.zip
unalias cp
cp -f duckdb.h ../
cp -f duckdb.hpp ../
# 编译参数需要 -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 与 duckdb_fdw src Makefile 一致
clang++ -c -fPIC -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 duckdb.cpp -o duckdb.o
clang++ -shared -o libduckdb.so *.o
cp -f libduckdb.so $(pg_config --libdir)
cp -f libduckdb.so /tmp/duckdb_fdw/
cd /tmp/duckdb_fdw
USE_PGXS=1 make uninstall
USE_PGXS=1 make clean
USE_PGXS=1 make distclean
USE_PGXS=1 make
USE_PGXS=1 make install
postgres=# create extension duckdb_fdw ;
正常.
- man nm
- man objdump
- ldd
- clang