已开启
Percona Server 5.7.44 进行 CFGO 优化时, CSPGO 构建阶段丢失 `Gis_wkb_vector<Gis_point>::set_ptr` 符号导致 mysqld 链接失败 #93
liangwenjiao创建于  8月12日
liangwenjiao
liangwenjiao
8月12日 创建

问题概述

使用 openEuler GCC 12.3.1 2025.06 的 AutoCFGO 流程构建 Percona Server 5.7.44 时,05-build-cfgo-cspgo 阶段在最终链接 mysqld 时失败:

undefined reference to `Gis_wkb_vector<Gis_point>::set_ptr(void*, unsigned long)'`
collect2: error: ld returned 1 exit status

该错误来自 GIS 几何相关模板代码。调用方位于 sql/item_geofunc_setops.cc,而应提供该符号的实现位于 sql/spatial.cc。在失败阶段生成的 libsql.a 中,item_geofunc_setops.cc.o 保留了对该符号的未定义引用,但 spatial.cc.o 没有导出对应定义,最终导致 mysqld 链接失败。

问题只在 CFGO-CSPGO 的 profile-use 构建阶段暴露,前面的原生构建、CFGO-PGO 插桩构建和 PGO 运行均成功。

环境

操作系统和架构

AArch64
openEuler

编译器

gcc-12.3.1-2025.06-aarch64-linux

CFGO 相关源码提交:

84635dc65ebe285457d0c16bbb5caf995f803436
[CFGO] Add cfgo-pgo optimization

9f8d7de855feb149e2ea58b72167b22908afacdc
[CFGO] Add more opts to cfgo

65b4c05ba79d7dc10ac9ed963ad17fd32c9f2fce
[CFGO] Update opts for CFGO-PGO

数据库版本

Percona Server 5.7.44

构建配置

opt_mode=AutoCFGO
build_mode=Wrapper
compiler=gcc

复现流程

执行完整 AutoCFGO 流程。

阶段结果:

阶段 状态 说明
01-build-raw PASS 原生构建成功
02-run-raw PASS 原生二进制运行成功
03-build-cfgo-pgo PASS PGO generate 插桩二进制构建成功
04-run-cfgo-pgo PASS PGO workload 运行成功
05-build-cfgo-cspgo FAIL 最终链接 mysqld 时失败
06-run-cfgo-cspgo 及之后 未执行 因第五阶段失败而停止

第五阶段 Wrapper 注入的关键参数为:

-fprofile-prefix-path=/home/workspace/
-fcfgo-profile-use=/home/workspace/20260727-162953/profiles/cfgo-pgo
-fcfgo-csprofile-generate=/home/workspace/20260727-162953/profiles/cfgo-cspgo
-Wno-error=missing-profile
-Wno-error=coverage-mismatch
-fprofile-correction

失败日志

链接 mysqld 时的主要错误如下:

/home/workspace/percona-server-Percona-Server-5.7.44-53/sql/item_geofunc_setops.cc:1458:
undefined reference to `Gis_wkb_vector<Gis_point>::set_ptr(void*, unsigned long)'

/home/workspace/percona-server-Percona-Server-5.7.44-53/sql/item_geofunc_setops.cc:1387:
undefined reference to `Gis_wkb_vector<Gis_point>::set_ptr(void*, unsigned long)'

/home/workspace/percona-server-Percona-Server-5.7.44-53/sql/item_geofunc_setops.cc:1633:
undefined reference to `Gis_wkb_vector<Gis_point>::set_ptr(void*, unsigned long)'

/home/workspace/percona-server-Percona-Server-5.7.44-53/sql/item_geofunc_setops.cc:1562:
undefined reference to `Gis_wkb_vector<Gis_point>::set_ptr(void*, unsigned long)'

/home/workspace/percona-server-Percona-Server-5.7.44-53/sql/item_geofunc_setops.cc:2743:
undefined reference to `Gis_wkb_vector<Gis_point>::set_ptr(void*, unsigned long)'

collect2: error: ld returned 1 exit status
make[2]: *** [sql/CMakeFiles/mysqld.dir/build.make:144: sql/mysqld] Error 1
make[1]: *** [CMakeFiles/Makefile2:6461: sql/CMakeFiles/mysqld.dir/all] Error 2
make: *** [Makefile:166: all] Error 2

相关调用函数包括:

BG_setop_wrapper<...>::linestring_difference_linestring
BG_setop_wrapper<...>::linestring_difference_multilinestring
BG_setop_wrapper<...>::multilinestring_difference_linestring
BG_setop_wrapper<...>::multilinestring_difference_multilinestring
Item_func_spatial_operation::simplify_multilinestring

符号级定位

对失败阶段生成的静态库进行符号检查:

nm -C gcc_build/archive_output_directory/libsql.a

观察结果:

item_geofunc_setops.cc.o:
                 U Gis_wkb_vector<Gis_point>::set_ptr(void*, unsigned long)

spatial.cc.o:
                 未发现 Gis_wkb_vector<Gis_point>::set_ptr(void*, unsigned long) 的定义

因此当前可以确认:

  1. item_geofunc_setops.cc.o 生成了对 Gis_wkb_vector<Gis_point>::set_ptr 的引用;
  2. spatial.cc.o 没有生成或保留对应的可链接定义;
  3. 错误发生在最终链接阶段,不是头文件找不到、库搜索路径错误或运行时加载失败;
  4. 失败产物之间出现了引用与定义不一致。

触发范围和当前判断

03-build-cfgo-pgo 阶段只启用:

-fcfgo-profile-generate=<profile-dir>

该阶段构建和运行均成功。

05-build-cfgo-cspgo 阶段同时启用:

-fcfgo-profile-use=<pgo-profile-dir>
-fcfgo-csprofile-generate=<cspgo-profile-dir>
-fprofile-correction

该阶段在链接 mysqld 时失败。因此目前最可疑的是 PGO use 与 CSPGO generate 组合触发的 IPA/内联/模板符号生成问题,而不是 profile 文件损坏或 workload 运行失败。

当前还不能断言根因一定是某个单独 GCC pass,也不能排除该模板代码在激进跨过程优化下缺少显式实例化或出现 COMDAT/弱符号处理问题。需要进一步确认。

临时规避

已验证的工程侧规避方向是:只对 sql/spatial.cc 关闭可能导致符号消失的 IPA 和内联 pass,保留其余翻译单元的 CFGO 优化:

-fno-ipa-cp-clone
-fno-ipa-cp
-fno-inline-functions

可以通过现有 CMake 按文件追加参数:

ADD_CXX_COMPILE_FLAGS_TO_FILES(
  -fno-ipa-cp-clone
  -fno-ipa-cp
  -fno-inline-functions
  FILES spatial.cc)

如果同时构建 libmysqld 目标,还需要对对应路径的 ../sql/spatial.cc 使用相同设置。

期望结果

在启用:

-fcfgo-profile-use=<pgo-profile-dir>
-fcfgo-csprofile-generate=<cspgo-profile-dir>

时,Percona Server 的 mysqld 应能够正常完成编译和链接。由 sql/spatial.cc 提供的:

Gis_wkb_vector<Gis_point>::set_ptr(void*, unsigned long)

应与 sql/item_geofunc_setops.cc 的调用保持一致,不应出现 undefined reference。

希望协助确认

  1. 请确认 CFGO/CSPGO profile-use 组合是否会在 sql/spatial.cc 中错误删除、隐藏或未实例化 Gis_wkb_vector<Gis_point>::set_ptr 的可链接定义。
  2. 请检查 IPA constant propagation、IPA cloning、inline、COMDAT/weak symbol 和模板实例化相关 pass 是否存在跨翻译单元不一致。
  3. 请对比同一文件在普通 GCC、标准 PGO、CFGO PGO generate 和 CFGO CSPGO profile-use 下的 nm -C、GIMPLE/RTL dump 以及最终符号可见性。
  4. 请确认 -fcfgo-profile-use + -fcfgo-csprofile-generate + -fprofile-correction 是否是必要触发条件,并建议最小化的独立复现参数。
  5. 请提供不需要修改 Percona Server 源码的编译器侧规避,或确认按翻译单元关闭 -fipa-cp-clone、-fipa-cp 和内联优化是否是可靠方案。
  6. 建议基于 Gis_wkb_vector<T>::set_ptr 的跨翻译单元模板实例化构造独立 AArch64 GCC testcase,以便后续定位和修复。
likedislike
openeuler-ci-botopeneuler-ci-bot成员
8月12日 添加了label:sig/Compiler
openeuler-ci-bot
openeuler-ci-bot成员
8月12日 评论:

Welcome To openEuler Community

Hey @always_flipped_1 , thanks for your contribution to the community.

Bot Usage Manual

I'm the Bot here serving you. You can find the instructions on how to interact with me at Here . That means you can comment below every pull request or issue to trigger Bot Commands.

Contact Guide

If you have any questions, please contact the SIG: Compiler ,
and any of the maintainers: @SegFault, @alexanderbill, @cf-zhao, @chenzheng1030, @eastb233, @kuenking111_admin, @li-yancheng, @wangqiang95, @wd-gitcode ,
and any of the committers: @huang-xiaoquan, @huzife, @lin-4682, @xiongzhou4 .

likedislike
liangwenjiaoliangwenjiao
8月12日 修改标题为 “Percona Server 5.7.44 进行 CFGO 优化时, CSPGO 构建阶段丢失 `Gis_wkb_vector<Gis_point>::set_ptr` 符号导致 mysqld 链接失败”,原标题为“Percona Server 5.7.44 进行CFGO优化时, CSPGO 构建阶段丢失 `Gis_wkb_vector<Gis_point>::set_ptr` 符号导致 mysqld 链接失败”
rfwang07
rfwang07
8月19日 评论:

问题根因:Gis_wkb_vector::set_ptr 的声明在头文件、定义在 .cc 文件、且没有显式实例化

位置 内容
spatial.h:2359 void set_ptr(void *ptr, size_t len); —— 类模板内声明
spatial.cc:4738 template void Gis_wkb_vector::set_ptr(...)
spatial.cc:5148 实例化覆盖了 clear / push_back / reassemble / resize / shallow_push / 构造函数 / operator=,唯独没有 set_ptr

后果是:

  1. item_geofunc_setops.cc 只看得到 spatial.h:2359 的声明,看不到定义,因此无法自行实例化,只能发一个未定义外部引用出去;
  2. spatial.cc 里之所以有这个符号,纯属隐式实例化的副产品——parse_wkb_data(spatial.cc:3907,声明在 spatial.h:2120)在 spatial.cc:4112 对 Gis_polygon_ring *outer 调了 outer->set_ptr(q, nbytes),而 Gis_polygon_ring : public Gis_wkb_vector<Gis_point>(spatial.h:2424)且自己没有重声明 set_ptr,这一句就把 Gis_wkb_vector<Gis_point>::set_ptr 隐式实例化了出来;
  3. 隐式实例化出来的模板函数是 COMDAT/weak 符号。编译器对 COMDAT 的假设是「谁需要谁自己再生成一份」,所以一旦本 TU 内没有直接调用者了,把离线副本丢掉是完全合法的。

这个假设在这里不成立——因为定义不在头里,别的 TU 生成不出来。按标准这属于 IFNDR,编译器不必诊断。所以严格说这是 MySQL/Percona 的源码缺陷,只是一直被"优化不够激进、恰好没把最后一个调用点消除掉"掩盖着。CFGO调整了内联和ipa优化参数,正好触发这个场景,换个优化级别或者编译器也可能出现;

推荐修复:在spatial.cc中补上实例化流程

likedislike