PHP7.4依赖双版本libssl,咨询ld.so同名符号处理行为
在AlmaLinux 9编译带PostgreSQL支持的PHP 7.4:OpenSSL版本符号冲突疑问
背景
我需要在AlmaLinux 9上编译带有PostgreSQL模块支持的PHP 7.4。由于mysql-devel依赖系统的openssl-devel(3.0版本)RPM包,但PHP 7.4无法与OpenSSL 3.x编译兼容,因此我从源码编译了OpenSSL 1.1.x并安装到默认前缀路径/usr/local。
编译步骤
通过以下命令完成了PHP 7.4的编译:
$ cd php-7.4.33 $ ./configure PKG_CONFIG_PATH='/usr/local/lib64/pkgconfig:/usr/lib64/pkgconfig' OPENSSL_LIBS="-L/usr/local/lib64/ -lssl -lcrypto" --with-apxs2 --with-pgsql --with-external-pcre --enable-mbstring --sysconfdir=/etc --with-config-file-path=/etc --enable-pdo --with-pdo-pgsql --with-zlib --with-zip --with-jpeg --with-pear --with-curl --enable-opcache --with-openssl --with-freetype --with-xpm --with-libdir=lib64 --with-ldap --with-mysqli --with-pdo-mysql --enable-soap --enable-gd --without-sqlite3 --without-pdo-sqlite --with-curl $ make -j $(nproc)
编译警告
编译过程中出现如下警告:
/usr/bin/ld: ext/openssl/.libs/openssl.o: in function `php_openssl_load_cipher_mode': php-7.4.33/ext/openssl/openssl.c:6499: undefined reference to `EVP_CIPHER_flags'
依赖冲突现状
问题核心在于系统的libpq.so依赖libssl.so.3,而编译后的PHP依赖libssl.so.1.1,导致ld.so需要同时加载两个版本的OpenSSL库:
$ ldd sapi/cli/php | egrep "ssl|crypto|pq" libpq.so.5 => /lib64/libpq.so.5 libssl.so.1.1 => /usr/local/lib64/libssl.so.1.1 libcrypto.so.1.1 => /usr/local/lib64/libcrypto.so.1.1 libssl.so.3 => /lib64/libssl.so.3 libcrypto.so.3 => /lib64/libcrypto.so.3 $ ldd /usr/lib64/libpq.so libssl.so.3 => /lib64/libssl.so.3 libcrypto.so.3 => /lib64/libcrypto.so.3
疑问
当libssl.so.1.1和libssl.so.3中存在同名符号时,ld.so会如何处理?目前php-cli看似运行正常,但我尚未测试PostgreSQL连接功能。
解答
- 符号解析优先级规则
ld.so(动态链接器)会按照库的加载顺序解析符号:
- 先加载直接链接到PHP二进制的库(即
libssl.so.1.1、libcrypto.so.1.1),这些库的符号会被优先注册到全局符号表。 - 后续加载
libpq.so及其依赖的libssl.so.3时,若遇到同名符号,动态链接器会直接使用已注册的全局符号(来自OpenSSL 1.1.x),不会加载OpenSSL 3.x中的同名符号。
- 潜在风险
这种场景存在严重稳定性隐患:
libpq.so是基于OpenSSL 3.x编译的,它调用的符号行为与OpenSSL 1.1.x的同名符号可能存在差异(比如参数结构、返回值、内部逻辑变化)。强行用1.1.x的符号替代3.x的符号,极易导致libpq在运行时崩溃、出现内存错误或逻辑异常,尤其是在PostgreSQL SSL连接这类加密操作中。- 你遇到的编译警告
undefined reference to EVP_CIPHER_flags已经是信号:PHP 7.4的OpenSSL扩展依赖的符号在OpenSSL 3.x中已被移除/重命名,两者符号集不兼容。
- 解决方案建议
- 编译独立libpq库:从PostgreSQL源码编译,指定链接到你安装的OpenSSL 1.1.x,替换系统默认的
libpq.so,确保PHP和libpq依赖同一版本OpenSSL。 - 调整PHP编译参数:编译PHP时,用
--with-pgsql指定自己编译的PostgreSQL库路径,避免链接系统的libpq.so。 - 容器隔离环境:使用Docker等容器工具,基于兼容PHP 7.4的基础镜像(如CentOS 8、旧版AlmaLinux)构建环境,从根源规避OpenSSL版本冲突。
内容的提问来源于stack exchange,提问作者lp64
相关产品推荐
相关产品推荐

