Hex/Binary display of debug variables in C++
OS - Linux and Mac
Hex (Octal, Binary etc.) display of variables in watch or variable window in debug is not available. This is absolutely imperative for the C++ developers.
Please provide support.
@nilanjan I'll add it to the backlog but in the meantime you can use the gdb-mi command: -var-set-format in the debugConsole by typing -exec -var-set-format <name of variable> <format>. The difficulty we have is offering context menu options to allow the change of the format, which would require VSCode changes. You can also add the variable specifiers in the watch window to change the format.
This is the same request as #319
Does it work for lldb too?
@nilanjan I don't have my MacBook with me but I can try it tomorrow and let you know.
Tried this on MacBook, but this does not work. Got following message.
Driver. Received command '45-exec -var-set-format hex'. It was not handled. Command 'exec' not in Command Factory (from exec -var-set-format hex)_
Any update on this? This is significantly affecting productivity. Can you point where to add this feature?
How do I specify the variable name with the below command in the debug console?
-exec -var-set-format
If I use the above command while on a breakpoint (using gbg) I always get the error "msg: Variable object not found" but adding the variable name to the watch window works.
@Numinel Are you doing this on Mac or Linux?
So the format of -var-set-format seems to be -var-set-format <NAME> <FORMAT> where name is the automatic variable name assigned by gdb/lldb.
I enabled "logging": { "engineLogging": true } and I looked for the lines where -var-create was called for Variables and the response will have the <NAME> that you need to specify.
1: (918) <-1023-var-create - * "a" 1: (928) ->1023^done,name="var1",numchild="0",value="0",type="int",thread-id="1",has_more="0"
So for instance, my variable here is a and it is expecting <NAME> to be "var1".
I use Linux. The log show that my variable is mapped to the internal name "var29" and when using the command '-exec -var-set-format "var29" hex' the output will be shown as hexadecimal. It was unclear to me that I had to use a different name that the variable name.
Adding a variable to the watch window with "
Is there any timeline for this feature implementation?
@nilanjan Not at this time. If you feel like it is something you would like to contribute we welcome community support. You can find source code at: https://github.com/Microsoft/MIEngine.
This feature has been on the backlog for a while now, any plans to resurrect this feature request from the dead?
When I enabled the logging to decipher the transposed variable name the out on the Debug Console shows me the value in hex, but the Variable in the Debug tab still remains as decimal
-exec -var-set-format var158.param1 hexadecimal 1: (1205572) <-1599-var-set-format var158.param1 hexadecimal 1: (1205573) ->1599^done,format="hexadecimal",value="0xffffff01" 1: (1205573) ->(gdb) 1: (1205573) 1599: elapsed time 1 result-class: done format: hexadecimal value: 0xffffff01
From this particular experiment this is not a viable long term work around
@EmbeddedBacon That is the expected behavior. If you change the var-set-format, it will change it for all future calls but existing data is not updated as the UI hasn't requested to refresh yet.
We don't have a gesture in the UI to change the value and I haven't had time to investigate if VS Code's extensibility contains the ability to add this feature.
@pieandcakes Thanks for the info, but I still couldn't get it to work. This will not work with Locals under Variables since I don't control those. I did try this in the Watch panel, but this doesn't seem to work correctly. I also noticed the translated variable is always changing. In one case the varible "pFsaCmd" was initially var39, then var40, then var42, then var43, then etc. If I didn't have pFasCmd in the Watch panel, then after trying to set its format. I tried setting the format to pFasCmd and pFasCmd.param1, but unfortunately neither worked for me. I am not sure what I am doing wrong.
Here is the output from the Debug Console. If I were to look into this, what area of the code base would I look at?
MI Log
1: (1213357) ->(gdb)
1: (1213357) 1296: elapsed time 1
1: (1213357) <-1297-var-create - * "pFsaCmd"
1: (1213363) ->1297^done,name="var39",numchild="5",value="0xaa57d4c <ddrMemory+18033228>",type="VsFsaOperateReq_t *",thread-id="137",has_more="0"
1: (1213363) ->(gdb)
1: (1213363) 1297: elapsed time 5
1: (1213637) <-1298-stack-list-variables 0
1: (1213637) ->1298^done,variables=[{name="pFsaCmd"},{name="status"}]
1: (1213638) ->(gdb)
1: (1213638) 1298: elapsed time 0
1: (1213638) <-1299-var-create - * "pFsaCmd"
1: (1213643) ->1299^done,name="var40",numchild="5",value="0xaa57d4c <ddrMemory+18033228>",type="VsFsaOperateReq_t *",thread-id="137",has_more="0"
1: (1213643) ->(gdb)
1: (1213643) 1299: elapsed time 4
1: (1213643) <-1300-var-create - * "status"
1: (1213644) ->1300^done,name="var41",numchild="0",value="VS_STAT_COMMAND_SUCCESS",type="VsProtocolStatusCode_t",thread-id="137",has_more="0"
1: (1213644) ->(gdb)
1: (1213644) 1300: elapsed time 1
1: (1213728) <-1301-var-list-children --simple-values "var40" 0 1000
1: (1213734) ->1301^done,numchild="5",children=[child={name="var40.task",exp="task",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var40.param1",exp="param1",numchild="0",value="4294967041",type="uint32_t",thread-id="137"},child={name="var40.param2",exp="param2",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var40.param3",exp="param3",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var40.data",exp="data",numchild="0",type="uint8_t []",thread-id="137"}],has_more="0"
1: (1213734) ->(gdb)
1: (1213735) 1301: elapsed time 6
-exec -var-set-format var40.param1 hexadecimal
1: (1242036) <-1302-var-set-format var40.param1 hexadecimal
1: (1242037) ->1302^done,format="hexadecimal",value="0xffffff01"
1: (1242037) ->(gdb)
1: (1242037) 1302: elapsed time 0
1: (1242043) <-1303-var-create - * "pFsaCmd"
1: (1242045) ->1303^done,name="var42",numchild="5",value="0xaa57d4c <ddrMemory+18033228>",type="VsFsaOperateReq_t *",thread-id="137",has_more="0"
1: (1242045) ->(gdb)
1: (1242045) 1303: elapsed time 1
1: (1248577) <-1304-var-list-children --simple-values "var42" 0 1000
1: (1248584) ->1304^done,numchild="5",children=[child={name="var42.task",exp="task",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var42.param1",exp="param1",numchild="0",value="4294967041",type="uint32_t",thread-id="137"},child={name="var42.param2",exp="param2",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var42.param3",exp="param3",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var42.data",exp="data",numchild="0",type="uint8_t []",thread-id="137"}],has_more="0"
1: (1248584) ->(gdb)
1: (1248584) 1304: elapsed time 7
1: (1258554) <-1305-var-create - * "pFsaCmd"
1: (1258558) ->1305^done,name="var43",numchild="5",value="0xaa57d4c <ddrMemory+18033228>",type="VsFsaOperateReq_t *",thread-id="137",has_more="0"
1: (1258558) ->(gdb)
1: (1258558) 1305: elapsed time 4
1: (1258567) <-1306-var-create - * "pFsaCmd"
1: (1258571) ->1306^done,name="var44",numchild="5",value="0xaa57d4c <ddrMemory+18033228>",type="VsFsaOperateReq_t *",thread-id="137",has_more="0"
1: (1258572) ->(gdb)
1: (1258572) 1306: elapsed time 4
1: (1261053) <-1307-var-list-children --simple-values "var44" 0 1000
1: (1261060) ->1307^done,numchild="5",children=[child={name="var44.task",exp="task",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var44.param1",exp="param1",numchild="0",value="4294967041",type="uint32_t",thread-id="137"},child={name="var44.param2",exp="param2",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var44.param3",exp="param3",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var44.data",exp="data",numchild="0",type="uint8_t []",thread-id="137"}],has_more="0"
1: (1261060) ->(gdb)
1: (1261060) 1307: elapsed time 7
1: (1268111) <-1308-var-create - * "part"
1: (1268126) ->1308^error,msg="-var-create: unable to create variable object"
1: (1268126) ->(gdb)
1: (1268126) 1308: elapsed time 14
-exec -var-set-format var40 hexadecimal
1: (1390499) <-1309-var-set-format var40 hexadecimal
1: (1390500) ->1309^done,format="hexadecimal",value="0xaa57d4c"
1: (1390500) ->(gdb)
1: (1390500) 1309: elapsed time 0
1: (1402256) <-1310-var-create - * "pFsaCmd"
1: (1402260) ->1310^done,name="var46",numchild="5",value="0xaa57d4c <ddrMemory+18033228>",type="VsFsaOperateReq_t *",thread-id="137",has_more="0"
1: (1402260) ->(gdb)
1: (1402260) 1310: elapsed time 4
1: (1402270) <-1311-var-create - * "pFsaCmd"
1: (1402271) ->1311^done,name="var47",numchild="5",value="0xaa57d4c <ddrMemory+18033228>",type="VsFsaOperateReq_t *",thread-id="137",has_more="0"
1: (1402271) ->(gdb)
1: (1402271) 1311: elapsed time 1
1: (1404271) <-1312-var-list-children --simple-values "var47" 0 1000
1: (1404278) ->1312^done,numchild="5",children=[child={name="var47.task",exp="task",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var47.param1",exp="param1",numchild="0",value="4294967041",type="uint32_t",thread-id="137"},child={name="var47.param2",exp="param2",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var47.param3",exp="param3",numchild="0",value="0",type="uint32_t",thread-id="137"},child={name="var47.data",exp="data",numchild="0",type="uint8_t []",thread-id="137"}],has_more="0"
1: (1404278) ->(gdb)
1: (1404278) 1312: elapsed time 7
@EmbeddedBacon if you are trying to view just a few items as hex for gdb, you can add to the watch window as <variable>,x where x is the hex format and it should give you the value correctly.
Every time a -var-create is issued, the name assigned to it is new. When you step and a stackwalk is performed, this causes all the variables to be refreshed and in that instance the variable names are also refreshed.
As a reference, here is the documentation for variables through mi commands`. The problem is unless we have a way for the user to ask for it in the UI, we don't have a way to know to change the value. VS Code has an open issue https://github.com/Microsoft/vscode/issues/28025 which should be upvoted so they can add the gesture in the UI.
Depending if they make it a global or per variable flag, we would need to do work to let the Eval call know that we want something other than the gdb default.
For watch variables and natvis you can use format specifiers. See microsoft/MIEngine#1031.
https://github.com/microsoft/vscode/issues/70377 https://code.visualstudio.com/api/references/contribution-points#contributes.menus seem that vscode has add something to invest debugging view. it's time to pick it up
https://code.visualstudio.com/updates/v1_49#_contributable-context-menu-for-variables-view
looks like delicious on 1.49.0

FYI
You should link to it instead of posting a screenshot: https://github.com/microsoft/vscode/issues/28025#issuecomment-722687806
Today I had this problem too. 'b'(binary) and 'o'(octal) both work, but, 'x' or 'h' dosen't work, I work on C++ on Linux. Any updates?
I'm also seeing that ,x and ,h don't work but the rest of them do work.
Which version of gdb are you using? Also you can check what's going on with the debug launch options:
"logging": {
"engineLogging": true
},
@Trass3r My gdb version: 7.3.1. I'll try that "engineLogging" option tomorrow. Thanks. Maybe it's because my gdb's version is too low ? I'll try a higher version on Fedora33 later
Indeed, it may not support the format specifier.
I can also try the logging when j get a chance. Note that doing ,b does work and I see the variable in binary. I'm also able to just use the debug console to print my variable in hex with -exec p/x <var_name>.
Well binary wasn't implemented before so it looks like my https://github.com/microsoft/MIEngine/pull/1031/files got silently integrated by now. I can only imagine your gdb version not supporting zero-hexadecimal. Please try -exec p/z.
Yeah -exec p/z doesn't work on my GDB.
Does this mean your changes actually always use p/z (var,z) even if we only specify ,x which is supported as p/x?
There is no ,z in https://docs.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp.
Yes ,x maps to /z which seems to have been introduced in 7.11, available even in Ubuntu 16.04.
Yeah I'm using GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-110.el7. Is there any chance of this changing? p/x gives the functionality that I'd want, and the error message when i try ,x is slightly misleading.
I have correctly specified ,x for hexadecimal. But because my GDB is outdated and doesn't support /z, I get this error message.
At least, I think we should catch this scenario and say something like: "To display hexadecimal values in watch. Please use a GDB version >= 7.11" Then link to some documentation that explains the workaround to use the debug console directly with /x.