英文:
Is there a way to get debugging symbols for CGO code linked into Go?
问题
我有一些Cgo代码,我将其链接到我的Go二进制文件中。我已经成功运行Cgo并构建了我的代码和包装器。最近进行了一些更改后,我开始在链接的C++代码中遇到双重释放的问题。我尝试在lldb下运行我的二进制文件,它确实捕获了malloc错误,但符号并不是特别有用。
在普通的C或C++中,我使用-g3
选项来获取包含变量名和源代码的丰富调试符号。这使得使用lldb更加高效。然而,我在我的Go二进制文件中无法获取这些符号。我注意到在回溯中,我的函数显示为main'foo
,其中foo是我的函数名。然而,没有其他的调试信息,我只能得到一串汇编代码和内存指针/寄存器的跟踪信息。
我尝试使用CGO_CFLAGS="-g3" CGO_CXXFLAGS="-g3"
来调用go build
,但二进制文件仍然没有这些符号。我还尝试在设置其他标志的.go文件中(在import "C"
之前)的CFLAGS/CXXFLAGS中添加-g3
,但似乎也不起作用。我想不到其他任何方法来将这些调试信息添加到我的二进制文件中,是否有一些特定于Go的标志或构建顺序可以启用这个功能?
英文:
I have some Cgo code that I'm linking into my Go binary. I've got Cgo running and building my code and wrapper. After some recent changes, I started getting a double-free in my C++ that I'm linking in. I've tried running my binary under lldb and it does trap the malloc panic, but the symbols are not especially useful.
In vanilla C or C++ I've used -g3
to get rich debugging symbols that includes variable names and source. This makes using lldb much more productive. However, I'm having some issues getting these symbols to show up in my go binary. I've noticed that in the backtrace my function appears as main'foo
, where foo is the name of my function. There is no other debug info present though, all I get is a trace of assembly and memory pointers/registers.
I've tried invoking go build
with CGO_CFLAGS="-g3" CGO_CXXFLAGS="-g3"
but the binary still doesn't have the symbols. I've also tried adding -g3
to the CFLAGS/CXXFLAGS in my .go file where I set other flags (before import "C"
) but this doesn't seem to work either. I can't think of any other way to get this debugging info added into my binary - is there some Go-specific flag or build sequence that enables this?
答案1
得分: 0
我不知道Go和C++链接过程是如何工作的。但是,关于在OS X上如何处理调试信息的简要描述可能会帮助你找出调试信息丢失的位置。
在OS X上,与大多数系统一样,单个源文件编译的调试信息存储在生成的.o文件中。你可以通过多种方式验证你的.o文件是否包含调试信息,下面是其中一种方法:
lldb -o "image dump sections" Target.o --batch | grep DWARF
0x00000300 container [0x0000000000061538-0x0000000000782c77) rwx 0x00061cb8 0x0072173f 0x00000000 Target.o.__DWARF
0x00000009 dwarf-str [0x0000000000061538-0x00000000004eeabc) rwx 0x00061cb8 0x0048d584 0x02000000 Target.o.__DWARF.__debug_str
0x0000000a dwarf-loc [0x00000000004eeabc-0x00000000004ef493) rwx 0x004ef23c 0x000009d7 0x02000000 Target.o.__DWARF.__debug_loc
0x0000000b dwarf-abbrev [0x00000000004ef493-0x00000000004f09a7) rwx 0x004efc13 0x00001514 0x02000000 Target.o.__DWARF.__debug_abbrev
0x0000000c dwarf-info [0x00000000004f09a7-0x00000000006ea7f1) rwx 0x004f1127 0x001f9e4a 0x02000000 Target.o.__DWARF.__debug_info
0x0000000d dwarf-ranges [0x00000000006ea7f1-0x00000000006ec481) rwx 0x006eaf71 0x00001c90 0x02000000 Target.o.__DWARF.__debug_ranges
0x0000000e dwarf-macinfo [0x00000000006ec481-0x00000000006ec482) rwx 0x006ecc01 0x00000001 0x02000000 Target.o.__DWARF.__debug_macinfo
0x0000000f apple-names [0x00000000006ec482-0x000000000071134e) rwx 0x006ecc02 0x00024ecc 0x02000000 Target.o.__DWARF.__apple_names
0x00000010 apple-objc [0x000000000071134e-0x0000000000711372) rwx 0x00711ace 0x00000024 0x02000000 Target.o.__DWARF.__apple_objc
0x00000011 apple-namespaces [0x0000000000711372-0x00000000007116d6) rwx 0x00711af2 0x00000364 0x02000000 Target.o.__DWARF.__apple_namespac
0x00000012 apple-types [0x00000000007116d6-0x0000000000748797) rwx 0x00711e56 0x000370c1 0x02000000 Target.o.__DWARF.__apple_types
0x00000015 dwarf-line [0x000000000075d348-0x0000000000782c77) rwx 0x0075dac8 0x0002592f 0x02000000 Target.o.__DWARF.__debug_line
如果你在这里看不到任何内容,那么编译器没有生成调试信息...
下一步是特定于Darwin的,不是将调试信息放入链接阶段的输出中,而是将调试信息保留在.o文件中,并在输出映像中插入一个“调试映射”。这就是调试器如何找回到.o文件的方式。你可以通过执行以下命令来查看:
$ nm -ap <YourBinary> | grep OSO
你应该在这里看到所有的.o文件列表。如果你没有看到,那么在构建过程中的某个时刻,你的二进制文件被剥离了(至少使用strip -S
)。你必须找出何时发生这种情况,并避免这样做。还要检查.o文件是否仍然在上述命令中看到的位置。可能是构建过程的某个部分将它们移动了,调试器无法再找到它们了。
英文:
I don't know how the process of go & C++ linking works. But a brief description of how debug information is handled on OS X might help you figure out where the debug information is being lost.
On OS X as on most systems, the debug information for an individual source file compile goes into the .o file made from it. You can verify that your .o file got debug information in a variety of ways, here's one:
lldb -o "image dump sections" Target.o --batch | grep DWARF
0x00000300 container [0x0000000000061538-0x0000000000782c77) rwx 0x00061cb8 0x0072173f 0x00000000 Target.o.__DWARF
0x00000009 dwarf-str [0x0000000000061538-0x00000000004eeabc) rwx 0x00061cb8 0x0048d584 0x02000000 Target.o.__DWARF.__debug_str
0x0000000a dwarf-loc [0x00000000004eeabc-0x00000000004ef493) rwx 0x004ef23c 0x000009d7 0x02000000 Target.o.__DWARF.__debug_loc
0x0000000b dwarf-abbrev [0x00000000004ef493-0x00000000004f09a7) rwx 0x004efc13 0x00001514 0x02000000 Target.o.__DWARF.__debug_abbrev
0x0000000c dwarf-info [0x00000000004f09a7-0x00000000006ea7f1) rwx 0x004f1127 0x001f9e4a 0x02000000 Target.o.__DWARF.__debug_info
0x0000000d dwarf-ranges [0x00000000006ea7f1-0x00000000006ec481) rwx 0x006eaf71 0x00001c90 0x02000000 Target.o.__DWARF.__debug_ranges
0x0000000e dwarf-macinfo [0x00000000006ec481-0x00000000006ec482) rwx 0x006ecc01 0x00000001 0x02000000 Target.o.__DWARF.__debug_macinfo
0x0000000f apple-names [0x00000000006ec482-0x000000000071134e) rwx 0x006ecc02 0x00024ecc 0x02000000 Target.o.__DWARF.__apple_names
0x00000010 apple-objc [0x000000000071134e-0x0000000000711372) rwx 0x00711ace 0x00000024 0x02000000 Target.o.__DWARF.__apple_objc
0x00000011 apple-namespaces [0x0000000000711372-0x00000000007116d6) rwx 0x00711af2 0x00000364 0x02000000 Target.o.__DWARF.__apple_namespac
0x00000012 apple-types [0x00000000007116d6-0x0000000000748797) rwx 0x00711e56 0x000370c1 0x02000000 Target.o.__DWARF.__apple_types
0x00000015 dwarf-line [0x000000000075d348-0x0000000000782c77) rwx 0x0075dac8 0x0002592f 0x02000000 Target.o.__DWARF.__debug_line
If you don't see anything here, then the compiler isn't emitting debug information...
The next step is specific to Darwin, instead of putting the debug information into the output of the link stage, the debug info is left in the .o files, and a "debug map" is inserted into the output image. That's how the debugger finds its way back to the .o files. You can see that by doing:
$ nm -ap <YourBinary> | grep OSO
you should see a list of all your .o files here. If you don't then at some point in the build process your binary is getting stripped (using at least strip -S
) You have to find out when that is happening and not do that. Also check that the .o files are still where the entries you see from the command above say they are. It may be some part of the build process is moving them around, and the debugger can't find them anymore.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论