(PPC64le) 链接到 protobuf 的模块的节点 gyp 重建失败,"lacks nop, can't restore toc; recompile with -fPIC"

(PPC64le) node-gyp rebuild of a module that links to protobuf fails with "lacks nop, can't restore toc; recompile with -fPIC"

本文关键字:PPC64le can restore -fPIC with recompile toc nop lacks 节点 模块      更新时间:2023-10-16

第一次海报,老粉丝...

我正在尝试在 RHEL 64 上为 ppc7.1le(小字节序(重建一个节点模块,并获得以下令人困惑的输出。我已经在 x64 VM 上执行了相同的步骤,并且一切编译正常。

部分输出如下,即使它说使用 -fPIC 编译,该选项已经在发出的 g++ 命令中,如输出所示,所以我不知道如何处理此错误。

即使它正在 linux-x64 目录中查找静态 protobuf 库:../sdk/protobuf/2.5.0/linux-x64/libprotobuf.a

我用从 epel repo 的 protobuf-static-2.5.0-7.el7.ppc64le rpm 为 ppc64le 编译的库替换了该目录的内容。所以库应该没问题,它们与节点模块预期的版本相同

那么这个错误意味着什么?我怎样才能克服它呢?我正在使用的相同步骤在 linux-x64 中运行良好。我能想到的主要区别是,我不得不为ppc64le引入一些静态库(protobuf.a(,这是我从protobuf-static-2.5.0-7.el7.ppc64le包中获得的。这些被链接到我正在gyp'ng的节点模块中。下面是"node-gyp rebuild --verbose"的输出

提前感谢!

gyp info spawn args   '-Goutput_dir=.' ]
gyp verb command build []
gyp verb build type Release
gyp verb architecture ppc64
gyp verb node dev dir /root/.node-gyp/4.2.6
gyp verb `which` succeeded for `make` /usr/bin/make
gyp info spawn make
gyp info spawn args [ 'V=1', 'BUILDTYPE=Release', '-C', 'build' ]
make: Entering directory `/root/nodejs/napp1/node_modules/mynodemod/node_modules/mynodemod-protobuf/build'
  g++ '-DNODE_GYP_MODULE_NAME=protobuf_for_node' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/root/.node-gyp/4.2.6/include/node -I/root/.node-gyp/4.2.6/src -I/root/.node-gyp/4.2.6/deps/uv/include -I/root/.
node-gyp/4.2.6/deps/v8/include -I../../nan -I../sdk/protobuf/2.5.0/include  -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -mminimal-toc -O3 -ffunction-sections -fdata-sections -fno-omit-frame-pointer -fno-rtti -fno-exceptions -s
td=gnu++0x -MMD -MF ./Release/.deps/Release/obj.target/protobuf_for_node/protobuf_for_node.o.d.raw   -c -o Release/obj.target/protobuf_for_node/protobuf_for_node.o ../protobuf_for_node.cc
  g++ '-DNODE_GYP_MODULE_NAME=protobuf_for_node' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/root/.node-gyp/4.2.6/include/node -I/root/.node-gyp/4.2.6/src -I/root/.node-gyp/4.2.6/deps/uv/include -I/root/.
node-gyp/4.2.6/deps/v8/include -I../../nan -I../sdk/protobuf/2.5.0/include  -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -mminimal-toc -O3 -ffunction-sections -fdata-sections -fno-omit-frame-pointer -fno-rtti -fno-exceptions -s
td=gnu++0x -MMD -MF ./Release/.deps/Release/obj.target/protobuf_for_node/addon.o.d.raw   -c -o Release/obj.target/protobuf_for_node/addon.o ../addon.cc
  g++ -shared -pthread -rdynamic -m64  -Wl,-soname=protobuf_for_node.node -o Release/obj.target/protobuf_for_node.node -Wl,--start-group Release/obj.target/protobuf_for_node/protobuf_for_node.o Release/obj.target/protobuf_for_node/addon.o
 -Wl,--end-group ../sdk/protobuf/2.5.0/linux-x64/libprotobuf.a
/usr/bin/ld: ../sdk/protobuf/2.5.0/linux-x64/libprotobuf.a(descriptor.o): In function `void google::protobuf::STLDeleteContainerPointers<__gnu_cxx::__normal_iterator<google::protobuf::FileDescriptorTables**, std::vector<google::protobuf::
FileDescriptorTables*, std::allocator<google::protobuf::FileDescriptorTables*> > > >(__gnu_cxx::__normal_iterator<google::protobuf::FileDescriptorTables**, std::vector<google::protobuf::FileDescriptorTables*, std::allocator<google::protob
uf::FileDescriptorTables*> > >, __gnu_cxx::__normal_iterator<google::protobuf::FileDescriptorTables**, std::vector<google::protobuf::FileDescriptorTables*, std::allocator<google::protobuf::FileDescriptorTables*> > >)':
(.text._ZN6google8protobuf26STLDeleteContainerPointersIN9__gnu_cxx17__normal_iteratorIPPNS0_20FileDescriptorTablesESt6vectorIS5_SaIS5_EEEEEEvT_SB_[_ZN6google8protobuf26STLDeleteContainerPointersIN9__gnu_cxx17__normal_iteratorIPPNS0_20File
DescriptorTablesESt6vectorIS5_SaIS5_EEEEEEvT_SB_]+0x44): call to `google::protobuf::FileDescriptorTables::~FileDescriptorTables()' lacks nop, can't restore toc; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
make: *** [Release/obj.target/protobuf_for_node.node] Error 1
make: Leaving directory `/root/nodejs/napp1/node_modules/mynodemod/node_modules/mynodemod-protobuf/build'
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/root/nodejs/napp1/node_modules/node-gyp/lib/build.js:276:23)
gyp ERR! stack     at emitTwo (events.js:87:13)
gyp ERR! stack     at ChildProcess.emit (events.js:172:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
gyp ERR! System Linux 3.10.0-229.ael7b.ppc64le
gyp ERR! command "/root/ibm/node/bin/node" "/root/nodejs/napp1/node_modules/.bin/node-gyp" "rebuild" "--verbose"
gyp ERR! cwd /root/nodejs/napp1/node_modules/mynodemod/node_modules/mynodemod-protobuf
gyp ERR! node -v v4.2.6
gyp ERR! node-gyp -v v3.2.1

好吧,我似乎已经得到了它来编译...环顾了一些看似无关的帖子,开始怀疑我链接的 protobuf 静态库是否也必须使用 -fPIC 编译。由于我从 RPM 获得了库,所以我继续使用 fPIC 从源代码重建它们。现在我的节点 gyp 编译得很好...

希望这会对其他人有所帮助,因为我对此撞了一段时间......

您可能正在命中调用外部函数而不在其后添加 nop 的内联程序集(用于目录还原(。

POWER ABI v2,第 2.3.6 节。函数调用,说:

函数调用需要与通过 TOC 指针寄存器 r2 建立、维护和恢复可寻址性一起执行。调用函数时,可能会修改 TOC 指针寄存器。调用方必须在执行调用的 bl 指令后提供 nop,如果 r2不知道在被调用方中具有相同的值。对于外部调用,通常如此。如果调用方和被调用方使用不同的 r2 值,链接器将用 r2 恢复指令替换 nop,如果它们使用相同的 r2 值,链接器将保持不变。此方案避免编译器在每次外部调用周围生成过于保守的 r2 保存和恢复。