-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lldb cannot print std::string #60994
Comments
@llvm/issue-subscribers-lldb |
Could you please try 16 or |
Yes. $ clang -v
Ubuntu clang version 17.0.0 (++20230224031317+a52332df5d1f-1~exp1~20230224151434.767)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/11
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/11
Candidate multilib: .;@m64
Selected multilib: .;@m64
$ lldb --version
lldb version 17.0.0 Problem is still here. Only a little different: cmd lldb show |
Could you put |
This is the log when lldb debugging gcc_out. ( |
You're probably missing debug info for If you're using libstdc++ for instance, on ubuntu you'd need to install Note that Clang does an optimization for debug info that GCC doesn't do, which is why the GCC/Clang divergence here - but GCC does similar/equivalent optimizations - for instance, if you try to debug/print a Without the Compiled with clang (
Built with gcc:
And then with the package installed:
GCC:
LLDB does have some more fussy issues about needing definitions to be compiled into the same library - but I /think/ at least this case should be ironed out by now/should work... but maybe not? (at least my internal release lldb crashed, and my just-built debug lldb crashed in a different way) |
Here's a lightning talk I gave that discusses these issues pretty closely: https://www.youtube.com/watch?v=XvkLHIASlp8 |
The expression parser imports its types from wherever it finds them into the expression scratch AST context. So except for bugs it shouldn't matter for the expression parser where the types come from.
But we use per-module ClangAST's to realize the debug information from each dylib, and those types are the ones that we use to present Variables (e.g. SBFrame.FindVariables).
We don't import types across modules because we don't really have the machinery to track these definitions and, for instance, if the library where we found the debug information was unloaded, remove the type or make it complete itself on demand. I'm haven't been following that part of lldb super-closely of late, but I'm pretty sure nobody's gotten that part working yet.
That will matter if you use the `v` command or use UI's that have "local variable" views since they all rely on SBValues that get their types from modules. On Darwin standalone-debug is the default because many many developers on that platform use Xcode or VSCode, and having the locals view not work for cross-module type usage would be a big problem.
Jim
… On Feb 27, 2023, at 4:00 PM, David Blaikie ***@***.***> wrote:
You're probably missing debug info for std::string as it's part of your standard library's package, not the code you built that uses std::string.
If you're using libstdc++ for instance, on ubuntu you'd need to install libstdc++6-dbgsym or similar.
Note that Clang does an optimization for debug info that GCC doesn't do, which is why the GCC/Clang divergence here - but GCC does similar/equivalent optimizations - for instance, if you try to debug/print a std::ifstream with GCC built debug info or clang built debug info (without -fstandalone-debug) you'll see it's "declared but not defined" too.
Without the -dbgsym package installed:
Compiled with clang (in is a std::ifstream and x is a std::string):
(gdb) p in
$1 = <incomplete type>
(gdb) p x
Python Exception <class 'gdb.error'> There is no member named _M_dataplus.:
$2 =
Built with gcc:
(gdb) p in
$1 = <incomplete type>
(gdb) p x
$2 = ""
And then with the package installed:
Clang:
(gdb) p in
$1 = (std::basic_ifstream<char, std::char_traits<char> >) {
<std::basic_istream<char, std::char_traits<char> >> = {
<std::basic_ios<char, std::char_traits<char> >> = {
<std::ios_base> = {
_vptr.ios_base = 0x7ffff7e0fe68 <vtable for std::basic_ifstream<char, std::char_traits<char> >+64>,
_M_precision = 6,
...
(gdb) p x
$2 = ""
GCC:
(gdb) p in
$1 = (std::basic_ifstream<char, std::char_traits<char> >) {
<std::basic_istream<char, std::char_traits<char> >> = {
<std::basic_ios<char, std::char_traits<char> >> = {
<std::ios_base> = {
_vptr.ios_base = 0x7ffff7e0fe68 <vtable for std::basic_ifstream<char, std::char_traits<char> >+64>,
_M_precision = 6,
...
(gdb) p x
$2 = ""
LLDB does have some more fussy issues about needing definitions to be compiled into the same library - but I /think/ at least this case should be ironed out by now/should work... but maybe not? (at least my internal release lldb crashed, and my just-built debug lldb crashed in a different way)
—
Reply to this email directly, view it on GitHub <#60994 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/ADUPVWYD4DG76WRCVJN2H33WZU52JANCNFSM6AAAAAAVH4SLTA>.
You are receiving this because you are on a team that was mentioned.
|
Now I have installed the
But it still cannot print I'm confused. Here is lldb log: |
I'm guessing this might be related to lldb not having a pretty printer for this version of libstdc++`s std::string, maybe? If you run |
On Feb 28, 2023, at 9:55 AM, David Blaikie ***@***.***> wrote:
(std::string) $0 = error: summary string parsing error
I'm guessing this might be related to lldb not having a pretty printer for this version of libstdc++`s std::string, maybe?
If there were no summary then we would have just printed the raw fields. This error means that is a summary that matched `std::string`, but either there was a real error getting the summary or iit doesn't grok the layout of this version of std::string. If you have a variable of a type you suspect has a formatter, you can find out whether that's true and what the formatter is with:
(lldb) type summary info a_string
summary applied to (std::string) a_string is: (hide value) std::string summary provider
Jim
… If you run image lookup --type "basic_string<char, std::char_traits<char>, std::allocator<char> >" what does that print?
—
Reply to this email directly, view it on GitHub <#60994 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/ADUPVWY7DJKJNUGLI7GB6GDWZY3YLANCNFSM6AAAAAAVH4SLTA>.
You are receiving this because you are on a team that was mentioned.
|
I find this is different from
Result of
|
Yep, so it looks like you got the debug info working and the debugger is finding the definition in the library from the declaration in the main program. Oh, hmm, but the I can reproduce the failure on my machine, and the same image lookup result. It looks like the
But the failure to associate that definition with the declaration inside basic_string is a problem/probably a bug in lldb, I'd think. Let's see about a smaller repro... |
(oh, and I should say - it works for gdb, for me, once I've got the -debug/dev/whatever package installed - which does point to an lldb bug, regardless of the specifics, probably) But still, good to figure out the specifics... |
Oh, poked around in more detail - I guess libstdc++ doesn't have an explicit instantiation decl/def for basic_string, so we do get the definition of basic_string in the clang-built usage code, but the _Alloc_hider is maybe homed into the .so/debug file maybe because of ctor homing. So... I guess that's the lldb issue - a nested type defined in a shared library where the outer type is defined in the immediate program. Let's test that... |
Yep. Looks like that's it - lldb doesn't do a good job resolving nested types when defined across dynamic library/executable boundaries:
Reproduced with this:
inner.cpp:
main.cpp:
I was going to suggest this would be tru efor non-nested types too, but that doesn't seem to be the case - they get resolved correctly. But also the failure mode is different from the non-nested type case, where the type is still declared-but-not-defined in the current CU/executable, but the definition is missing elsewhere. In that case you usually get a "error: <user expression 1>:1:1: incomplete type 't1' where a complete type is required" Whereas in this nested type isn't linked to its definition case, you get this:
If the shared library doesn't have debug info - /then/ you get the "complete type is required" thing... oooh, I think I know what's going on: It also looks like it's somehow relevant that I think I know why that member variable is load bearing - it's causing lldb to synthesize a definition for the inner type. We can reproduce this without nested types, maybe.. Yeah:
So this causes my guess is that imagined empty definition then inhibits resolving the definition correctly to one contained in another dynamic library. |
I get exactly same bug. Here are steps to reproduce the bug in the form of Dockerfile: # 20230227 = 20230227T000000Z = 20230226T090712Z
FROM debian:sid-20230227
ENV LC_ALL C.UTF-8
# https://github.com/fepitre/debian-snapshot , https://debconf21.debconf.org/talks/22-making-use-of-snapshotdebianorg-for-fun-and-profit/
RUN sed -i 's~^URIs:.*$~URIs: http://snapshot.notset.fr/archive/debian/20230226T090712Z~' /etc/apt/sources.list.d/debian.sources
RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf.d/02acquire-check-valid-until
RUN apt-get update && apt-get install -y apt-utils whiptail
RUN apt-get update && apt-get install -y less mc aptitude man-db wget ca-certificates gnupg
RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
RUN echo deb http://apt.llvm.org/unstable/ llvm-toolchain-16 main >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y clang-16 lldb-16 libstdc++6-12-dbg libc++-16-dev libc++abi-16-dev g++ gdb
# https://michael.stapelberg.ch/posts/2019-02-15-debian-debugging-devex/
RUN echo deb http://snapshot.debian.org/archive/debian-debug/20230226T090712Z sid-debug main >> /etc/apt/sources.list
RUN apt-get update && apt-get install -y libc6-dbg libgcc-s1-dbgsym libstdc++6-dbgsym
RUN echo '#include <string>' >> o.cpp
RUN echo 'int' >> o.cpp
RUN echo 'main (void)' >> o.cpp
RUN echo '{' >> o.cpp
RUN echo ' std::string a = "a";' >> o.cpp
RUN echo ' a = "b";' >> o.cpp
RUN echo '}' >> o.cpp
RUN clang++-16 -g -o o o.cpp
RUN lldb-16 ./o -o 'br set -l 6' -o 'r' -o 'p a' < /dev/null # "summary string parsing error"
RUN clang++-16 -std=gnu++17 -g -o o o.cpp
RUN lldb-16 ./o -o 'br set -l 6' -o 'r' -o 'p a' < /dev/null # "summary string parsing error"
RUN clang++-16 -std=gnu++20 -g -o o o.cpp
RUN lldb-16 ./o -o 'br set -l 6' -o 'r' -o 'p a' < /dev/null # Works
RUN clang++-16 -std=gnu++14 -g -o o o.cpp
RUN lldb-16 ./o -o 'br set -l 6' -o 'r' -o 'p a' < /dev/null || : # Backtrace
RUN clang++-16 -fstandalone-debug -g -o o o.cpp
RUN lldb-16 ./o -o 'br set -l 6' -o 'r' -o 'p a' < /dev/null # Works
RUN clang++-16 -stdlib=libc++ -g -o o o.cpp
RUN lldb-16 ./o -o 'br set -l 6' -o 'r' -o 'p a' < /dev/null # Works
RUN g++ -g -o o o.cpp
RUN lldb-16 ./o -o 'br set -l 6' -o 'r' -o 'p a' < /dev/null # Works
RUN clang++-16 -g -o o o.cpp
RUN printf 'br 6\nr\np a\n' | gdb ./o # Works
As you can see, there are zillions of various workarounds, i. e. zillions of way to make this bug disappear. Here we go:
|
Ah, in that case the _Alloc_hider type doesn't get omitted from the usage - not sure about the exact usage that leads to this difference between the 17 and 20 versions of the code. Ah, the ctor becomes constexpr - so it isn't subject to Clang's DWARF ctor homing strategy. That doesn't quite explain it - the 17 version does have the ctor for the type - possible there's a clang bug here about type homing. Yeah, looks like this is being omitted due to ctor homing -
Includes extra info that avoids the "type defined in this binary/shared library depends on a type defined in another binary/shared library".
Different implementation details about what ends up where for sure.
Yep, g++ won't omit types related to ctor definitions (it does do this with vtables, which is similar but doesn't happen to tickle this particular instance) decls/defs, so the extra type info is enough for lldb to work.
Yep, gdb doesn't have a problem going looking for a type definition in another shared library at any point - lldb won't do it (& will instead synthesize a fictional/incorrect/trivial type definition) when it's needed to complete the AST of one binary (it'll do it in other cases - like during expression evaluation - printing a dereferenced pointer, etc). |
Currently, it is not possible to sensibly debug LLVM using shared library builds with LLDB since types are not resolved across shared library boundaries. As a workaround we can enable -glldb to emit standalone debug info which ensures we get a working debugging experience at the expense of increased disk usage. See llvm#60994 (comment)
OS: Ubuntu 22.04
main.cpp
Compile:
LLDB can print
std::string
when usinggcc_out
, but shows error when usingclang_out
.When using CodeLLDB to debug in VScode, it shows
error: summary string parsing error
I know a workaround is to add
-fstandalone-debug
flag, but that's a bit annoying.It is said that another solution is to install a debug version of libstdc++. I think I have already installed it but it not works. I wonder how to make it work, or if there is another way to solve it.
The text was updated successfully, but these errors were encountered: