microsoft / vscode-cpptools

Official repository for the Microsoft C/C++ extension for VS Code.
Other
5.55k stars 1.57k forks source link

stdout of target program is streamed to debug console instead of terminal #4265

Open lgmcode opened 5 years ago

lgmcode commented 5 years ago

Type: Debugger

Describe the bug

I'm doing remote debugging on Ubuntu 16.04 for a target board running qnx7, everything works well, except that the stdout of my program is shown in the debug console instead of the terminal as local debugging which looks more comfortable.

A code sample:

#include <iostream>

int main(int argc, char *argv[])
{
    std::cout << "Hello, world!" << std::endl;
    std::cout << "argc = " << argc << std::endl;
    for (int i = 1; i < argc; i++)
    {
        std::cout << "argv[" << i << "] = " << argv[i] << std::endl;
    }

    return 0;
}

When debug locally, it's fine, debug console shows

=thread-group-added,id="i1"
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
=cmd-param-changed,param="pagination",value="off"
Stopped due to shared library event (no libraries added or removed)
Loaded '/lib64/ld-linux-x86-64.so.2'. Symbols loaded.

Breakpoint 1, main (argc=2, argv=0x7fffffffe258) at main.cpp:5
5       std::cout << "Hello, world!" << std::endl;
Loaded '/usr/lib/x86_64-linux-gnu/libstdc++.so.6'. Symbols loaded.
Loaded '/lib/x86_64-linux-gnu/libc.so.6'. Symbols loaded.
Loaded '/lib/x86_64-linux-gnu/libm.so.6'. Symbols loaded.
Loaded '/lib/x86_64-linux-gnu/libgcc_s.so.1'. Symbols loaded.
Execute debugger commands using "-exec <command>", for example "-exec info registers" will list registers in use (when GDB is the debugger)
[Inferior 1 (process 34697) exited normally]
The program '/build/xpt' has exited with code 0 (0x00000000).

and terminal shows

Hello, world!
argc = 2
argv[1] = arg_string
[1] + Done                       "/usr/bin/gdb" --interpreter=mi --tty=${DbgTerm} 0<"/tmp/Microsoft-MIEngine-In-slyrtsqi.vdn" 1>"/tmp/Microsoft-MIEngine-Out-lvf3edxt.mfe"

But if I use qnx-gdb to debug remotely, everything goes to debug console

=thread-group-added,id="i1"
GNU gdb (GDB) 7.12 [qnx700 r1234]
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=aarch64-unknown-nto-qnx7.0.0".
Type "show configuration" for configuration details.Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
=cmd-param-changed,param="pagination",value="off"
Remote: /tmp/xpt

Breakpoint 1, main (argc=2, argv=0x100c7a08) at main.cpp:5
5       std::cout << "Hello, world!" << std::endl;
Execute debugger commands using "-exec <command>", for example "-exec info registers" will list registers in use (when GDB is the debugger)
@"Hello, world!\r\n"
@"argc = 2\r\nargv[1] = arg_string\r\n"
[Inferior 1 (pid 17801281) exited normally]
The program '/build/xpt' has exited with code 0 (0x00000000).

and the terminal only has

[1] + Done                       "/usr/bin/ntoaarch64-gdb" --interpreter=mi --tty=${DbgTerm} 0<"/tmp/Microsoft-MIEngine-In-aszz1ibu.xa6" 1>"/tmp/Microsoft-MIEngine-Out-ga8klbwt.3fi"

I searched for the manual of gdb and found https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Stream-Records.html#GDB_002fMI-Stream-Records, according to which I know that the prefix character '@' means the following string is a target output, while it is not parsed by this extension, I thought.

Debugging the program in command line shows the different output of the two gdbs

With local gdb

lin@ubuntu:~$ gdb -i mi
=thread-group-added,id="i1"
~"GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1\n"
~"Copyright (C) 2016 Free Software Foundation, Inc.\n"
~"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\n"
~"This GDB was configured as \"x86_64-linux-gnu\".\nType \"show configuration\" for configuration details."
~"\nFor bug reporting instructions, please see:\n"
~"<http://www.gnu.org/software/gdb/bugs/>.\n"
~"Find the GDB manual and other documentation resources online at:\n<http://www.gnu.org/software/gdb/documentation/>.\n"
~"For help, type \"help\".\n"
~"Type \"apropos word\" to search for commands related to \"word\".\n"
(gdb)
file build/xpt
&"file build/xpt\n"
~"Reading symbols from build/xpt..."
~"done.\n"
^done
(gdb)
b main
&"b main\n"
~"Breakpoint 1 at 0x4008a6: file main.cpp, line 5.\n"
=breakpoint-created,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x00000000004008a6",func="main(int, char**)",file="main.cpp",fullname="main.cpp",line="5",thread-groups=["i1"],times="0",original-location="main"}
^done
(gdb)
run
&"run\n"
~"Starting program: build/xpt \n"
=thread-group-started,id="i1",pid="36208"
=thread-created,id="1",group-id="i1"
=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1"
^running
*running,thread-id="all"
(gdb)
=library-loaded,id="/usr/lib/x86_64-linux-gnu/libstdc++.so.6",target-name="/usr/lib/x86_64-linux-gnu/libstdc++.so.6",host-name="/usr/lib/x86_64-linux-gnu/libstdc++.so.6",symbols-loaded="0",thread-group="i1"
=library-loaded,id="/lib/x86_64-linux-gnu/libc.so.6",target-name="/lib/x86_64-linux-gnu/libc.so.6",host-name="/lib/x86_64-linux-gnu/libc.so.6",symbols-loaded="0",thread-group="i1"
=library-loaded,id="/lib/x86_64-linux-gnu/libm.so.6",target-name="/lib/x86_64-linux-gnu/libm.so.6",host-name="/lib/x86_64-linux-gnu/libm.so.6",symbols-loaded="0",thread-group="i1"
=library-loaded,id="/lib/x86_64-linux-gnu/libgcc_s.so.1",target-name="/lib/x86_64-linux-gnu/libgcc_s.so.1",host-name="/lib/x86_64-linux-gnu/libgcc_s.so.1",symbols-loaded="0",thread-group="i1"
=breakpoint-modified,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x00000000004008a6",func="main(int, char**)",file="main.cpp",fullname="main.cpp",line="5",thread-groups=["i1"],times="1",original-location="main"}
~"\n"
~"Breakpoint 1, main (argc=1, argv=0x7fffffffe448) at main.cpp:5\n"
~"5\t    std::cout << \"Hello, world!\" << std::endl;\n"
*stopped,reason="breakpoint-hit",disp="keep",bkptno="1",frame={addr="0x00000000004008a6",func="main",args=[{name="argc",value="1"},{name="argv",value="0x7fffffffe448"}],file="main.cpp",fullname="main.cpp",line="5"},thread-id="1",stopped-threads="all",core="10"
(gdb)
n 1
&"n 1\n"
^running
*running,thread-id="all"
(gdb)
Hello, world!
~"6\t    std::cout << \"argc = \" << argc << std::endl;\n"
*stopped,reason="end-stepping-range",frame={addr="0x00000000004008c2",func="main",args=[{name="argc",value="1"},{name="argv",value="0x7fffffffe448"}],file="main.cpp",fullname="main.cpp",line="6"},thread-id="1",stopped-threads="all",core="11"
(gdb)
n 1
&"n 1\n"
^running
*running,thread-id="all"
(gdb)
argc = 1
~"7\t    for (int i = 1; i < argc; i++)\n"
*stopped,reason="end-stepping-range",frame={addr="0x00000000004008ee",func="main",args=[{name="argc",value="1"},{name="argv",value="0x7fffffffe448"}],file="main.cpp",fullname="main.cpp",line="7"},thread-id="1",stopped-threads="all",core="11"
(gdb)
n 1
&"n 1\n"
^running
*running,thread-id="all"
(gdb)
~"12\t    return 0;\n"
*stopped,reason="end-stepping-range",frame={addr="0x000000000040095e",func="main",args=[{name="argc",value="1"},{name="argv",value="0x7fffffffe448"}],file="main.cpp",fullname="main.cpp",line="12"},thread-id="1",stopped-threads="all",core="11"
(gdb)
c
&"c\n"
~"Continuing.\n"
^running
*running,thread-id="all"
(gdb)
~"[Inferior 1 (process 36208) exited normally]\n"
=thread-exited,id="1",group-id="i1"
=thread-group-exited,id="i1",exit-code="0"
*stopped,reason="exited-normally"
(gdb)
q
&"q\n"
lin@ubuntu:~$

with qnx gdb

lin@ubuntu:~$ /usr/bin/ntoaarch64-gdb -i mi
=thread-group-added,id="i1"
~"GNU gdb (GDB) 7.12 [qnx700 r1234]\n"
~"Copyright (C) 2016 Free Software Foundation, Inc.\n"
~"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.  Type \"show copying\"\nand \"show warranty\" for details.\n"
~"This GDB was configured as \"--host=x86_64-pc-linux-gnu --target=aarch64-unknown-nto-qnx7.0.0\".\nType \"show configuration\" for configuration details."
~"Find the GDB manual and other documentation resources online at:\n<http://www.gnu.org/software/gdb/documentation/>.\n"
~"For help, type \"help\".\n"
~"Type \"apropos word\" to search for commands related to \"word\".\n"
(gdb)
target qnx ip:port
&"target qnx ip:port\n"
~"Remote debugging using ip:port\n"
~"MsgNak received - resending\n"
~"Remote target is little-endian\n"
^done
(gdb)
file build/xpt
&"file build/xpt\n"
~"Reading symbols from build/xpt..."
~"done.\n"
^done
(gdb)
upload build/xpt /tmp/xpt
&"upload build/xpt /tmp/xpt\n"
^done
(gdb)
b main
&"b main\n"
~"Breakpoint 1 at 0x1550: file main.cpp, line 5.\n"
=breakpoint-created,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x0000000000001550",func="main(int, char**)",file="main.cpp",fullname="main.cpp",line="5",thread-groups=["i1"],times="0",original-location="main"}
^done
(gdb)
run
&"run\n"
~"Starting program: build/xpt \n"
~"Remote: /tmp/xpt\n"
=thread-group-started,id="i1",pid="18014273"
=thread-created,id="1",group-id="i1"
=breakpoint-modified,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x00000000100c9550",func="main(int, char**)",file="main.cpp",fullname="main.cpp",line="5",thread-groups=["i1"],times="0",original-location="main"}
&"warning: Unable to find dynamic linker breakpoint function.\nGDB will be unable to debug shared library initializers\nand track explicitly loaded dynamic code."
&"\n"
^running
*running,thread-id="all"
(gdb)
=breakpoint-modified,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x00000000100c9550",func="main(int, char**)",file="main.cpp",fullname="main.cpp",line="5",thread-groups=["i1"],times="1",original-location="main"}
~"\n"
~"Breakpoint 1, main (argc=1, argv=0x100c7a18) at main.cpp:5\n"
~"5\t    std::cout << \"Hello, world!\" << std::endl;\n"
*stopped,reason="breakpoint-hit",disp="keep",bkptno="1",frame={addr="0x00000000100c9550",func="main",args=[{name="argc",value="1"},{name="argv",value="0x100c7a18"}],file="main.cpp",fullname="main.cpp",line="5"},thread-id="1",stopped-threads="all"
(gdb)
n 1
&"n 1\n"
^running
*running,thread-id="all"
(gdb)
@"Hello, world!\r\n"
~"6\t    std::cout << \"argc = \" << argc << std::endl;\n"
*stopped,reason="end-stepping-range",frame={addr="0x00000000100c9580",func="main",args=[{name="argc",value="1"},{name="argv",value="0x100c7a18"}],file="main.cpp",fullname="main.cpp",line="6"},thread-id="1",stopped-threads="all"
(gdb)
c
&"c\n"
~"Continuing.\n"
^running
*running,thread-id="all"
(gdb)
@"argc = 1\r\n"
~"[Inferior 1 (pid 18014273) exited normally]\n"
=thread-exited,id="1",group-id="i1"
=thread-group-exited,id="i1",exit-code="0"
&"No inferior.\n"
*stopped,reason="exited-normally"
(gdb)
q
&"q\n"
lin@ubuntu:~$

The main difference and which I think is also the reason of the problem is that the target output in qnx gdb is quoted and has a prefix character '@' while local gdb just output the raw string. Maybe this extension does not parse this output format and leave the stdout in the debug console. Is this a bug?

pieandcakes commented 5 years ago

You can change the filtering of stdout in the debug console by using the setting "filterStdout": false to see if you get output. I think by default its set to true

lgmcode commented 5 years ago

@pieandcakes Thanks for your advice. I just tried to add "filterStdout": false to the remote debugging configuration in my launch.json, but saddly nothing is changed, the stdout stays where it was. I also tried to add "filterStdout": false to the local debugging configuration, still nothing different happened. It seems this setting has no effect. Am I still missing something?