I often have a need to set a breakpoint on method, print the arguments, and break on a specific argument or continue when not matched. In native code, I would use bp <symbol> "commands"
. But this is a managed application, so the method is not always JITted. As such, !sos.bpmd is available; however, it does not support a commands arguments. !sosex.mbm is another option and the documentation indicates that it can accept a commands arguments. From !sosex.help mbm
:
"command" - Exactly one quoted string parameter may be specified. The contents of this string will be passed on to corresponding native breakpoints as the command parameter.
For further details about these options, see the debugger documentation for the 'bp' command.
The implication is that it this command argument is passed to the native breakpoint commands, such as bp
. However, it fails to parse command arguments that the same bp
command is able to accept.
Below are my attempts.
0:022> $ Set a breakpoint on Foo.Bar.CBase!Foo.Bar.CBase.set_Item.
0:022> !sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item
The breakpoint could not be resolved immediately.
Further attempts will be made as modules are loaded.
Breakpoint set at Foo.Bar.CBase.set_Item(System.String, System.Object) in AppDomain 0000000001f32cc0.
0:022> $ Breakpoint set. Check the native address.
0:022> !sosex.mbl
AppDomain 0000000001eceee0
--------------------------
0 eu: disable Foo.Bar.CBase!Foo.Bar.CBase.SET_ITEM ILOffset=0: pass=1 oneshot=false thread=ANY
AppDomain 0000000001f32cc0
--------------------------
0 e : disable Foo.Bar.CBase!Foo.Bar.CBase.SET_ITEM ILOffset=0: pass=1 oneshot=false thread=ANY
Foo.Bar.CBase!Foo.Bar.CBase.set_Item(string, object)
0 e 000007ff005cc799
0:022> $ Clear the breakpoint.
0:022> $ !sosex.mbc 0
0:022> $ Set breakpoint on same address with command argument.
0:022> bp 000007ff005cc799 "as /mu ${/v:col} (@rdx+0x10); .block { .printf \"Column: %mu, Value: %mu\\n\", @rdx+10, @r8+10; .if (0 != $scmp( \"${col}\", \"opt_id\")) { gc } }"
0:022> $ Check the set breakpoint.
0:022> bl
0 e 000007ff`005cc799 0001 (0001) 0:**** "as /mu ${/v:col} (@rdx+0x10); .block { .printf \"Column: %mu, Value: %mu\\n\", @rdx+10, @r8+10; .if (0 != $scmp( \"${col}\", \"opt_id\")) { gc } }"
0:022> $ Continue execution.
0:022> g
Column: abc_id, Value: 80
Column: hoge_id, Value: N
Column: priority, Value:
Column: opt_id, Value: ZEI
000007ff`005cc799 488b542430 mov rdx,qword ptr [rsp+30h] ss:00000000`056cae00=000000013f7ed498
0:022> $ Outputs arguments and continues on non-match. Breaks on match. Expected results.
The commands argument seems to be valid and does as I desire. Such breakpoints are a frequent task, so I would much prefer to set the whole thing with a single command rather than go through the above multiple steps. As far as I can determine from the sosex.mbm
documentation, I should be able to do the following:
0:022> $ Cleanup. Clear the breakpoint.
0:022> bc 0
0:022> $ Ensure that the alias is not defined.
0:022> ad /q ${/v:col}
0:022> $ Try to set the same breakpoint with sosex.mbm.
0:022> !sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "as /mu ${/v:col} (@rdx+0x10); .block { .printf \"Column: %mu, Value: %mu\\n\", @rdx+10, @r8+10; .if (0 != $scmp( \"${col}\", \"opt_id\")) { gc } }"
syntax error
^ Quotes required in ' .printf \"Column: %mu, Value: %mu\\n\", @rdx+10, @r8+10; .if (0 != $scmp( \"${col}\", \"opt_id\")) { gc } '
It fails, indicating that quotes are required, but I cannot determine where. The syntax is a bit complicated, so lets try something a little simpler:
0:022> $ Output RDX and R8 when the breakpoint is hit.
0:022> !sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "r @rdx; r @r8"
syntax error
^ Syntax error in '!sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "r @rdx; r @r8"'
This time it is a syntax error, but again I cannot determine where. Lets try another one.
0:022> $ Output RDX when the breakpoint is hit, and then continue.
0:022> !sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "r @rdx; gc"
syntax error
^ Extra character error in '!sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "r @rdx; gc"'
Another error, but this time about an extra character, but it looks OK to me. Lets try something even easier.
0:022> $ Output RDX when the breakpoint is hit.
0:022> !sosex.mbm Foo.Bar.CBase!Foo.Bar.CBase.set_Item "r @rdx"
The breakpoint could not be resolved immediately.
Further attempts will be made as modules are loaded.
Breakpoint set at Foo.Bar.CBase.set_Item(System.String, System.Object) in AppDomain 0000000001f32cc0.
Success at last. The conclusion that I draw from this is that sosex.mbm
can only accept a single command argument as long as it does not contain multiple statements. As the documentation indicates, if the single command argument is merely being passed to the native breakpoint (such as bp), then there should be no such restriction.
Is this behavior expected or am I doing something wrong? Is there another way to accomplish this? I can use the above workaround, but I often need to set such breakpoints are so would much rather find a more direct way to do this.
Please note that I am using version 4.5.0.783 of sosex. This is the latest version available for download.
You're not doing anything wrong. I can see why your command with embedded quotes would fail. SOSEX isn't terribly sophisticated about parsing the quoted string. However, your simple commands should succeed. I'll work on this and get back to you.