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
Issue 1716: Improve CodeView debug info #1717
Conversation
case Twchar: | ||
case Tdchar: | ||
#if LDC_LLVM_VER >= 305 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LLVM 3.5 is the oldest supported version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I changed the condition from 309 to let the build servers tell me what version supports the changes.
This seems to make perfect sense to me, so I guess you're fixing debuginfos generally for all platforms. ;) |
Anything in particular you are worried about? Also, could you add IR tests for the things you've fixed here? |
@@ -131,18 +139,28 @@ ldc::DIType ldc::DIBuilder::CreateBasicType(Type *type) { | |||
Encoding = DW_ATE_boolean; | |||
break; | |||
case Tchar: | |||
Encoding = type->isunsigned() ? DW_ATE_unsigned_char : DW_ATE_signed_char; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, this would be a DW_ATE_UTF
too for UTF8-char
, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but this is not supported in the CodeViewDebug::lowerTypeBasic.
What's the forward declaration issue? I've seen that |
Breaking debugging in gdb, which might only support a different combination of debug data. See the breakage of the CI builders...
I could try that, but it wouldn't really test correctness, as this very much depends on the debug info emission and the used debugger. |
It would test correct IR emission, right? If there are different paths for tuning the output for different debuggers (something we don't do but clang does), you can easily extend testing with passing commandline flags that trigger those paths. The CI systems breaking is exactly why we need to have tests for this. Otherwise someone in the future is going to "fix" things for GDB again, but break the CodeView debuginfo, and your work is lost. (btw, combining all these little changes into one PR is not helping!) |
I'd argue that this is why we need similar CI tests for debugging on Windows as well. The problem with IR-level tests is that they are exceedingly brittle – how do you know whether a change was benign or not? What about future changes to the (textual) IR format, such as possibly with the next LLVM release? It is clear that we need rather comprehensive "integration tests" for debug info generation that actually use the target debugger, because there is just too much that can go wrong in the interplay of poorly specified components. The question then becomes whether IR-level tests on top of that add sufficient value. |
I was just about to post the |
#if LDC_LLVM_VER >= 309 | ||
return t->merge()->deco; | ||
#else | ||
return nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better return the llvm::StringRef
directly here, and then the bugfix nullptr => {}
needs to be applied here as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, done.
As an intermediate step, we could use object file dumpers to verify the debug info output. llvm-dwarfdump/llvm-readobj should do the job, there is also cvdump.exe released by Microsoft: https://github.com/Microsoft/microsoft-pdb/tree/master/cvdump. I'm not yet familiar with FileCheck, but it seems it could help with this verification, too. |
Sorry, I was hoping for easy passing of the builds. Seeing the breakage in all the previous LLVM versions I begin to regret that decision, too. |
I think "exceedingly brittle" is overstating things. When writing a test, you have to check for the things that matter, and not for the things that don't. FileCheck's regexp matching is pretty nice for that. When the IR text changes in a newer LLVM release, you can update the test for that using There are many things here that are easily tested in a robust manner. If you don't want to add tests for workarounds, that's fine. |
FileCheck is just a string matcher. So whenever a program outputs text data, you can feed it into FileCheck and it will check whether certain strings are there (or check that they are not there). Usually we write the strings-to-be-checked-for (e.g. |
Anyway, all I'm saying is: testing this would be very good, whichever method you choose. |
I'd say let's get these first steps merged.
|
Using
|
I've removed changing Type.next, maybe calling "t->merge()" is also not necessary without it. |
Removed that, too. BTW: the debug info for local variables emitted by LDC doesn't work at all with the "old" debug engine (the one that you get when you enable "native" edit and continue in VS2013 or earlier). The UTF16/UTF32 types also don't show in VS2013. |
@JohanEngelen: Definitely agreed on the alignment use case. My claim is just that for debug info, the IR layer is not the correct place for tests, as it doesn't really have much meaning by itself – as you pointed out from Clang, it is a rather leaky abstraction. What we really want to test is that debug info is lowered to the object/PDB files in a way we know works with the target debuggers. We can probably dump the debug info into a textual form, though, and use FileCheck on that, like Rainer suggested (this is way less complex than requiring debugger scripting, of course). |
@@ -131,18 +139,33 @@ ldc::DIType ldc::DIBuilder::CreateBasicType(Type *type) { | |||
Encoding = DW_ATE_boolean; | |||
break; | |||
case Tchar: | |||
if (global.params.targetTriple->isWindowsMSVCEnvironment()) { | |||
// VS debugger does not support DW_ATE_UTF for char | |||
Encoding = type->isunsigned() ? DW_ATE_unsigned_char : DW_ATE_signed_char; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A D char
is always unsigned, right? [I can't test it myself at work right now]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A D char is always unsigned, right? [I can't test it myself at work right now]
Yes. This is just the original code, but I guess it's clearer to just emit DW_ATE_unsigned_char.
@klickverbot Yeah I got that. I was thinking about LLVM modifying the IR debuginfo when optimizing (this is what causes some ICEs, I still have to file bugs about it, argh). So the IR has to be "correct" in a certain way too. Regardless, let's get things tested, whichever way :) |
I investigated a couple of options:
I'm not 100% which option to choose, but my current preference would be |
Cool, I didn't know there was a console version of windbg. I'd tend towards it too then. So it'd be cool if most stuff worked for both windbg and VS 2015+ (the LLVM guys are thinking about dropping pre-2015 support too). Afaik, windbg still offers functionality you don't get in the VS debugger, for hardcore debugging sessions; and it allows subsequent automated testing via |
Added a cdb based test. |
16601d6
to
59ec9ae
Compare
if (platform.system() == 'Windows') and (config.default_target_bits == 32): | ||
cdb = config.environment['WindowsSDKDir'] + 'Debuggers\\x86\\cdb.exe' | ||
if (platform.system() == 'Windows') and (config.default_target_bits == 64): | ||
cdb = config.environment['WindowsSDKDir'] + 'Debuggers\\x64\\cdb.exe' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently lit's TestingConfig.environment
is only a small subset of the actual environment variables. So accessing those directly via os.environ['WindowsSdkDir']
should do the job.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So accessing those directly via os.environ['WindowsSdkDir'] should do the job.
Thanks, fixed. There was also an import missing. [My last tries were from a different computer that cannot realistically compile LDC in finite time.]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[My last tries were from a different computer that cannot realistically compile LDC in finite time.]
Off topic, but out of curiosity: What sort of system was that? I've found LDC to be relatively quick to build even on a 32 bit ARM board with only 1 GB of RAM and slow storage – it's LLVM that's the annoying step.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Off topic, but out of curiosity: What sort of system was that?
A Core2 Duo @ 2 GHz, with 2 GB of RAM. You might be right, with a precompiled LLVM, it could be managable. I've seen failures compiling dmd due to other applications eating too much memory...
What happened to the AppVeyor build? It looks like we should get this merged as soon as possible (possibly after cleaning up the history a bit). |
The |
8a4e73a
to
c33f0b3
Compare
@@ -13,7 +13,8 @@ int main(string[] args) | |||
wstring ws = "b"; | |||
dstring ds = "c"; | |||
|
|||
// CDB: bp `codeview.d:18` | |||
// CDB: ld codeview | |||
// CDB: bp `codeview.d:19` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Congratz, finally working. 👍 Some stashing (- AppVeyor hack) and it's good to be merged.
There's an offset by +1 line, right? I seem to recall that from VS too...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem was not a line offset (I had to change it here due to the added line), but -s
above caused loading of other modules' symbols aswell, so it displayed combase!STRING
instead of codeview!string
.
- byte,ubyte should be encoded as DW_ATE_signed_char/DW_ATE_unsigned_char, not DW_ATE_signed/DW_ATE_unsigned - encode wchar,dchar as UTF - do not declare struct/class definitions as FlagFwdDecl - pass deco as unique identifier to UDTs - dynamic arrays: use type name, don't leave it empty - use proper type name for delegates - add support for type "void" and "typeof(null)"
Squashed commits and added test for x86 codeview output. |
Nice! |
Thanks, I updated #1716 accordingly. |
Changes:
Not sure how much of this can negatively affect other platforms. Should I put it under some Windows/codeView specific conditional?