gcc编译的C ++中未包含的调试符号

时间:2019-06-20 14:37:09

标签: c++ macos debugging clang cython

我正在用C ++构建模块以在Python中使用。我的流程分为三个步骤:将各个C ++源代码编译为对象,创建一个库,然后运行setup.py脚本来编译.pyx->。cpp->。so,同时引用我刚刚创建的库。

我知道我可以使用Cython setup.py一步完成所有事情,而这就是我过去所做的。将其拆分为多个步骤的原因是我希望C ++代码能够独立发展,在这种情况下,我将只使用Cython / python中的编译库。

因此,在没有错误的情况下,此流程工作正常。问题是我试图找到一个segfault的来源,所以我想获取调试符号,以便可以与gdb一起运行(我将其安装在OSX 10.14上,虽然很痛苦,但确实可行)。

我有一个生成文件,该文件执行以下操作。

步骤1:编译单个C ++源文件

所有文件都使用最低限度的标志进行编译,但是存在-g:

gcc -mmacosx-version-min=10.7 -stdlib=libc++ -std=c++14 -c -g -O0 -I ./csrc -o /Users/colinww/system-model/build/data_buffer.o csrc/data_buffer.cpp

我认为即使在这里也有问题:当我执行nm -pa data_buffer.o时,没有看到调试符号。此外,我得到:

(base) cmac-2:system-model colinww$ dsymutil build/data_buffer.o
warning: no debug symbols in executable (-arch x86_64)

第2步:编译cython来源

makefile有一行

cd $(CSRC_DIR) && CC=$(CC) CXX=$(CXX) python3 setup_csrc.py build_ext --build-lib $(BUILD)

setup.py的相关部分是

....
....
....
compile_args = ['-stdlib=libc++', '-std=c++14', '-O0', '-g']
link_args = ['-stdlib=libc++', '-g']
....
....
....
      Extension("circbuf",
                ["circbuf.pyx"],
                language="c++",
                libraries=["cpysim"],
                include_dirs = ['../build'],
                library_dirs=['../build'],
                extra_compile_args=compile_args,
                extra_link_args=link_args),
....
....
....
ext = cythonize(extensions,
                gdb_debug=True,
                compiler_directives={'language_level': '3'})

setup(ext_modules=ext,
      cmdclass={'build_ext': build_ext},
      include_dirs=[np.get_include()])

运行此命令时,它会生成一堆编译/链接命令,例如

gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/colinww/anaconda3/include -arch x86_64 -I/Users/colinww/anaconda3/include -arch x86_64 -I. -I../build -I/Users/colinww/anaconda3/lib/python3.7/site-packages/numpy/core/include -I/Users/colinww/anaconda3/include/python3.7m -c circbuf.cpp -o build/temp.macosx-10.7-x86_64-3.7/circbuf.o -stdlib=libc++ -std=c++14 -O0 -g

g++ -bundle -undefined dynamic_lookup -L/Users/colinww/anaconda3/lib -arch x86_64 -L/Users/colinww/anaconda3/lib -arch x86_64 -arch x86_64 build/temp.macosx-10.7-x86_64-3.7/circbuf.o -L../build -lcpysim -o /Users/colinww/system-model/build/circbuf.cpython-37m-darwin.so -stdlib=libc++ -g

在两个命令中,都存在-g标志。

第3步:运行调试器

最后,我用gdb运行程序

(base) cmac-2:sim colinww$ gdb python3
(gdb) run system_sim.py

它倾倒了大量与系统文件相关的内容(似乎不相关),并最终在程序出现段错误时运行我的程序:

Thread 2 received signal SIGSEGV, Segmentation fault.
0x0000000a4585469e in cpysim::DataBuffer<double>::Write(long, long, double) () from /Users/colinww/system-model/build/circbuf.cpython-37m-darwin.so
(gdb) info local
No symbol table info available.
(gdb) where
#0  0x0000000a4585469e in cpysim::DataBuffer<double>::Write(long, long, double) () from /Users/colinww/system-model/build/circbuf.cpython-37m-darwin.so
#1  0x0000000a458d6276 in cpysim::ChannelFilter::Filter(long, long, long) () from /Users/colinww/system-model/build/chfilt.cpython-37m-darwin.so
#2  0x0000000a458b0d29 in __pyx_pf_6chfilt_6ChFilt_4filter(__pyx_obj_6chfilt_ChFilt*, long, long, long) () from /Users/colinww/system-model/build/chfilt.cpython-37m-darwin.so
#3  0x0000000a458b0144 in __pyx_pw_6chfilt_6ChFilt_5filter(_object*, _object*, _object*) () from /Users/colinww/system-model/build/chfilt.cpython-37m-darwin.so
#4  0x000000010002f1b8 in _PyMethodDef_RawFastCallKeywords ()
#5  0x000000010003be64 in _PyMethodDescr_FastCallKeywords ()

如上所述,我认为问题始于初始编译步骤。这与cython无关,我只是从命令行通过-g标志调用gcc。

(base) cmac-2:system-model colinww$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

感谢您的帮助,谢谢!

更新

我删除了gcc标签并将其更改为clang。因此,我想我现在很困惑,如果Apple将gcc别名为clang,并不表示在“那种模式”下它的行为应类似于gcc(并且暗示有人确定是这样)。

更新2

因此,我永远无法使调试符号出现在调试器中,而不得不诉诸许多有趣的if-printf语句,但是问题是由于索引变量变得不确定。因此,感谢所有建议,但问题或多或少得到了解决(直到下一次)。谢谢!

1 个答案:

答案 0 :(得分:3)

macOS链接器不会像链接器通常在其他Unixen上所做的那样将调试信息链接到最终的二进制文件中。而是将调试信息保留在.o文件中,并在二进制文件中写入一个“调试图”,以告诉调试器如何查找和链接从.o文件读取的调试信息。当您剥离二进制文件时,调试映射也会被剥离。

因此,必须确保在最终链接之后不要移动或删除.o文件,并且在调试之前不要剥离正在调试的二进制文件。

您可以通过以下操作检查调试映射的存在:

$ nm -ap <PATH_TO_BINARY> | grep OSO

您应该看到如下输出:

000000005d152f51-03 0001 OSO /Path/To/Build/Folder/SomeFile.o

如果看不到可执行文件可能已被剥离。如果.o文件不存在,那么有人会比他们早应该清理了构建文件夹。

我也不知道gdb是否知道如何在macOS上读取调试映射。如果存在调试映射条目和.o文件,则可以尝试使用lldb,看看是否可以找到调试信息。如果可以,则可能是gdb-on-macOS问题。如果OSO和.o文件都存在,那么我无法猜测出了问题,可能值得向http://bugreporter.apple.com提交错误。