New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.
Starred by 3 users

Issue metadata

Status: Fixed
Last visit > 30 days ago
Closed: Oct 5
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 1
Type: Bug

Blocked on:
issue 765852

issue 636111
issue 709690

Sign in to add a comment

(debug build) Function parameters not shown in MSVS

Project Member Reported by, Aug 16 2017 Back to list

Issue description

I put a breakpoint in a debug build in 
bool BrowserThread::PostTask(ID identifier,
                             const tracked_objects::Location& from_here,
                             base::OnceClosure task) {

and I can't see any of the parameter values.

This is the same gn args as in  bug 755213 .

Comment 1 by, Aug 16 2017

Blocking: 636111
Summary: (debug build) Function parameters not shown in MSVS (was: Function parameters not shown in MSVS)

Comment 2 by, Aug 16 2017

Labels: -Pri-3 Pri-1
More examples: putting a breakpoint in BeginNavigationParams::BeginNavigationParams, I can't see any of the constructor parameters. It says "Variable is optimized away and not available."

Comment 3 Deleted

Comment 4 by, Aug 16 2017

Do the variables show up if you step one line in?

CodeView has a way to provide an offset into the function where the debugger should put its initial breakpoint, but I don't think we use it today. What might be happening here is the debugger puts it's breakpoint at the start of the code, but the values are stored to memory sometime later in the function body. The PC range that we use starts there, so whenever the debugger stops between the entry point and the end of the real prologue, you won't be able to see the parameters. If this is the case, there's a bunch of stuff we can do:
1. Find a way to indicate where to put the initial breakpoint
2. Add debug info describing which registers the parameters are in between the entry point and the end of the prologue

Comment 5 by, Aug 16 2017

@rnk: the variables don't show up after stepping. also stepping is very weird in that it keeps going back and forth.

Please try this out in Visual Studio to see what I mean.
Status: Assigned
Assigning to amccarth.  Assuming you can get a repro in chrome, see if you can make a minimal repro independent of chrome so that we better understand what the problem is.

Comment 7 by, Aug 23 2017

Blocking: 709690

Comment 8 by, Aug 29 2017

Building Chromium exceeded 250 GB size of my SSD.  After a yak shave and a new 1 TB SSD, Chromium now builds locally with clang-cl using the gn args from the bug report.

The newly-built Chromium crashes on startup, apparently because something tries to call CoCreateInstance before COM has been initialized.  Fatal Error dialog is taller than the screen, making the button at the bottom reachable only by keyboard.

Attaching VS 2015 debugger to any of the Chromium processes causes VS to crash.

Debugging VS suggested it might be a problem initializing an installed extension.  Disabled third-party extensions.  VS still crashes when attaching.

Debugging VS suggested that it might be Intellisense.  Disabled Intellisense.  VS still crashes.

Debugging VS suggests the problem is in managed code during "cleanup" of the MSBuild engine.  (Not sure why the MSBuild engine is involved when attaching to a process.)

Synched and rebuilt Chromium to see if the crash-on-startup is fixed.  It is not.

Abandoning Chromium and trying to repro with a small test program.

Comment 9 by, Aug 29 2017

250 GB should be enough to build chrome. What's your build command? Do you build all binaries, or just 'chrome'?

Does MSVC also crash if you build with cl.exe?
> 250 GB should be enough to build chrome.

My Chromium tree is 203 GB.  Since I also have over 90 GB in my LLVM tree, the old SSD wasn't feasible.  Irrelevant since I now have 1 TB.

> What's your build command?

ninja -C out\Debug chrome

with these gn args (per jam's report):
is_debug = true
enable_nacl = false
target_cpu = "x86"
is_win_fastlink = true
symbol_level = 2
is_clang = true

> Does MSVC also crash if you build with cl.exe?

I'll try it and let you know.
> My Chromium tree is 203 GB.

Hm, I don't have access to my Windows box atm, but that seems really high to me. On my linux box, my chromium tree is currently 180 GB, and that contains 13 different full compile dirs or so.
VS does not crash when Chromium is built with cl.exe.  In fact, I was able to find and locally fix the missing COM initialization (in, GetElevationIcon) that gets me past the Chromium crash on startup.
VS crashing only when debugging clang-built chrome sounds like an important bug then too :-)

Are you sending a Cl for
I've finally managed to repro the problem with Chrome, so I'll start working on reducing it.  I think it might have to do with the fact that these functions are inlined in multiple places.

I'm told some recent fixes to clang may have already addressed this, so I'm rebuilding to see if I can confirm that.

As for the VS 2015 crash, it now seems to be intermittent, so it may not be related to clang-build binaries after all.

As for the Chrome bug, I started a conversation with some of the OWNERS who want to understand the problem better.  My proposed fix may be too close the symptom.

Comment 15 by, Aug 31 2017

> I think it might have to do with the fact that these functions are inlined in multiple places.

Both BeginNavigationParams::BeginNavigationParams and BrowserThread::PostTask are defined out-of-line in .cc files, so inlining in a debug build seems unlikely. These are the definitions I'm looking at:
When debugging with VS and attempting to set a breakpoint in BrowserThread::PostTask, VS asked me to disambiguate between three seemingly identical copies of that function in the DLL.  I assumed there were three because of inlining.
The intermittent VS crashes appear to be memory exhaustion.

With no solution or projects loaded, attaching to a clang-built Chrome process triggers symbol loading and the devenv's working set soars right up to the 3GB limit.  Doing anything else at that point (e.g., loading one source file and attempting to set a break point) pushes it over the 3 GB limit and devenv crashes.

Note that if you connect VS to an MSVC-built Chrome process, the working set climbs, but not as high (peaking just below 2.4 GB), which leaves a little headroom for debugging but still puts us within crash territory.

None of that explains the actual problem in this bug (unviewable parameter values), but it explains why it's been hard to repro.

By the way, the devenv crash often leaves one of its caches in a bad state, so you can get all sorts of strange errors the next time you try to run it.  To clear the bad cache (per StackOverflow):

    rmdir /q /s %LOCALAPPDATA%\Microsoft\VisualStudio\14.0\ComponentModelCache

The parameters are not visible when they're in constructors or static member functions.  Parameters in non-static member functions and non-member functions are readily viewable.  I can now repro with a simple test program.

Comment 19 by, Sep 13 2017

Status: Started
Fix in progress:

Comment 20 by, Sep 13 2017

Adrian committed r313192
My commit is a step in the right direction, but it's not a fix.  Still diagnosing.

Comment 22 by, Sep 14 2017

Static methods seem to work for me locally after Adrian's change.

I think the constructor parameter issue described in c#4/c#5 is that all parameters are completely unavailable in clang builds until you step past the prologue. However, the function body may be empty, so stepping once may return before you get a chance to look at the locals. This is especially common for constructors, which often have lots of member initializers and no statements. That's the case for BeginNavigationParams::BeginNavigationParams:

    std::string headers,
    int load_flags,
    bool has_user_gesture,
    bool skip_service_worker,
    RequestContextType request_context_type,
    blink::WebMixedContentContextType mixed_content_context_type,
    bool is_form_submission,
    const base::Optional<url::Origin>& initiator_origin)
    : headers(headers),
      initiator_origin(initiator_origin) {}

In this small example, breaking on 'Foo::Foo' will also show <value unavailable> in windbg:

// t.cpp
struct Foo {
  Foo(int a, int b, int c);
  int x;
Foo::Foo(int a, int b, int c) : x(a + b + c) {}
int main() { Foo f(1, 2, 3); }

clang transcript:
0:000> bp t!Foo::Foo
*** WARNING: Unable to verify checksum for t.exe
0:000> g
Breakpoint 0 hit
00007ff7`deb764b0 4883ec18        sub     rsp,18h
0:000> dv
           this = <value unavailable>
              a = <value unavailable>
              b = <value unavailable>
              c = <value unavailable>

MSVC on the other hand doesn't say value unavailable, but it gives you garbage for register parameters. This means 'this' is garbage for constructors for 32-bit, but the parameters are right. It looks like this:
0:000> dv
           this = 0x0096685d  # wrong, |this| is in ecx
              a = 0n1
              b = 0n2
              c = 0n3
0:000> r ecx

x64 MSVC will get the first four parameters wrong, since that's how many regparms there are:
0:000> dv
           this = 0x00007ff6`af06c680
              a = 0n-1358860887
              b = 0n7
              c = 0n0

It might be possible to create some kind of artificial line table entry so that you can step past the prologue in otherwise empty functions, but I'm not sure what else we can do here. <value unavailable> seems better than incorrect values.
> Static methods seem to work for me locally after Adrian's change.

Really?  Because they still don't work for me locally after my change.  Neither in Chrome nor in my little test app.

As for the prologue issue, someone just raised a related question on lldb-dev. 
 See the "Prologue instructions having line information" thread on lldb-dev.

Comment 24 by, Sep 14 2017

> > Static methods seem to work for me locally after Adrian's change.
> Really?  Because they still don't work for me locally after my change.  Neither in Chrome nor in my little test app.

My bad, I was using 'dv' in windbg, which gives correct values. I thought we observed the problem there when we started looking into this, but I misremembered.

What we're seeing now is that the VS locals window works just fine, but the autos window doesn't work in static methods. It works for instance methods for some reason. =/

Comment 25 by, Sep 15 2017

OK, r313329 fixes the autos window in VS for static methods. We were using 'void' as the type of 'this' instead of 'none' (type index zero).
Static methods are fixed.

With constructors, we're only a tiny bit worse than Microsoft, so I don't think this is a blocker.  (I'd be happy to open a separate bug for constructors.)


  struct Foo {
    Foo(int xx) : x(xx) {
    int x;

If you break at the beginning of the constructor, you'll see garbage values for this and xx with either compiler.  With Microsoft, you'll see a value for x.  If you then single step, you'll get to the close brace, at which point you'll see correct values for everything, regardless of whether it's compiled with cl or clang-cl.

The problem is that local code styles tend to use {} on a single line for empty function bodies, which means you can't step past the prologue without stepping out of the constructor (unless you drop into the Disassembly view).  So the code style aggravates the problem even with cl (it's hard to see this and the member variables).  With clang-cl, it's slightly worse because you cannot even see the parameter.

Comment 27 by, Sep 15 2017

Blockedon: 765852

Comment 28 Deleted

Comment 29 Deleted

Comment 30 by, Sep 21 2017

Trying to check what's the status here..

Using Chromium #503270 with patched in (though that one shouldn't affect this bug), and building with:

is_clang = true
is_debug = true
target_cpu = "x86"
use_goma = true
enable_nacl = false

Breaking in BrowserThread::PostTask at the line of the opening curly shows the variables as not available. If I step, they all show up correctly.

Breaking in BeginNavigationParams::BeginNavigationParams shows the same thing: no variables available on the line of the open curly, if I step they all show up.

I also tried breaking in BeginNavigationParams::BeginNavigationParams mentioned in #22. As on the others, the variables show as unavailable on entry, but it's not clear how to step to make them show up, which is unfortunate. The artificial linetable entry from #22 sounds like an interesting idea.

Comment 31 by, Sep 21 2017

> sing Chromium #503270 with patched in (though that one shouldn't affect this bug)

Sorry, it should: that one picks up Adrian's r313329.
Blocking: -709690
I believe the conclusion was that we're not blocking on this? Please re-add as a blocker of 709690 otherwise.
We're not blocking on the problem for constructors, but we were waiting to hear back if the fix worked for static methods.
From what I saw in #30, I think we're good.

And the problem with constructors is really the problem of not being able to easily break after thr prologue in one-line functions, nothing constructor specific right?
I originally misread #30.  You are correct.  I think we can just mark this as fixed.

We can open a separate bug for c'tors.  Yes, fundamentally, the problem is that you don't have enough information while stopped in the prologue.  I'm not sure we settled on which approach to take for that.
Status: Fixed
> We can open a separate bug for c'tors.

Filed Bug 773047 to track that.
Blocking: 709690
Thanks, I've verified this.

Sign in to add a comment