Skip to content

Symbols loading from the target (via gdb/gdbserver) does not work #11949

Open

Description

@UR3IQO

Environment

  • OS and version:
    ОС: Windows_NT x64 10.0.19044
  • VS Code:
    1.86.0
  • C/C++ extension:
    1.19.1
  • OS and version of remote machine (if applicable):
    Linux raspberrypi 4.19.304-v7+ #3 SMP Wed Jan 10 14:46:02 MSK 2024 armv7l GNU/Linux
  • GDB / LLDB version:
    14.1

Bug Summary and Steps to Reproduce

When using remote debugging with extended remote target it is possible to load symbols from the remote target directly using the target:/path-to-executable path for the -file-exec-and-symbols GDB command.

Unfortunately there is a problem in the current cpptools.
Steps to reproduce:

  1. Use any project with the remote debugging (target and host machines should differ)
  2. Set program in the launch.json to target:/path-to-executable-on-the-remote-target
  3. Enable extended remote "useExtendedRemote": true
  4. Start remote gdbserver and debugging

cpptools issue GDB -file-exec-and-symbols command before connecting to the remote target, so it looks for the file on the host, fails and debugging can not be started (see the filtered log)

Debugger Configurations

{
   //NOTE: remote username, address, project directory and executable name are defined in the config file (.vscode/settings.json)
   "version": "0.2.0",
   "configurations": [
      {
         "name": "Remote debug",
         "type": "cppdbg",
         "request": "launch",
         "targetArchitecture": "arm",
         "useExtendedRemote": true,
         "program": "target:${config:remote.dir}/${config:remote.exec}",
         "miDebuggerServerAddress": "${config:remote.addr}:1234",
         "args": [],
         "stopAtEntry": true,
         "cwd": "${workspaceRoot}",
         "environment": [],
         "externalConsole": true,
         "sourceFileMap":{
            "/share/OGL" : "$WorkspaceRoot}"
         },
         "windows": {
           "MIMode": "gdb",
           "miDebuggerPath": "C:\\gdb-arm-linux\\bin\\arm-linux-gnueabihf-gdb.exe",
           "preLaunchTask": "debug"
         },
         "logging": {
            "engineLogging": true,
            "trace": true
         }
       }      
   ]
}

Debugger Logs

1: (202) <-1001-gdb-set mi-async on
1: (233) <-1002-interpreter-exec console "show configuration"
1: (261) <-1003-interpreter-exec console "set pagination off"
1: (276) <-1004-gdb-set auto-solib-add on
1: (291) <-1005-gdb-set solib-search-path target:/share/OGL/build;
1: (308) <-1006-environment-cd D:/Oleg/_Projects/Neon3/Software/Client/CtrlPi
1: (324) <-1007-gdb-set new-console on
1: (347) <-1008-file-exec-and-symbols target:/share/OGL/build/main.elf
1: (355) ->1008^error,msg="/share/OGL/build/main.elf: No such file or directory."
1: (360) <--gdb-exit
1: (363) <-logout

Other Extensions

No response

Additional Information

Possible solutions

  1. Probably the most correct is to connect to remote target early (before issuing -file-exec-and-symbols command) if program starts with target:
  2. The most simple is to skip checking program existence on the host if path specified in program starts with target:
    How it works:
    It is possible to issue target extended-remote command explicitly by using the setupCommands. the miDebuggerServer should not be used, cause we connect to target in setupCommands. Unfortunately when miDebuggerServer is not specified cpptools check the existence of the program specified by the program and of cause it does not exists on the host (moreover the path is also invalid). If it will not do that check the following configuration will work and load symbols from the target directly:
{
   //NOTE: remote username, address, project directory and executable name are defined in the config file (.vscode/settings.json)
   "version": "0.2.0",
   "configurations": [
      {
         "name": "Remote debug",
         "type": "cppdbg",
         "request": "launch",
         "targetArchitecture": "arm",
         "useExtendedRemote": true,
         "program": "target:${config:remote.dir}/${config:remote.exec}",
         "args": [],
         "stopAtEntry": true,
         "cwd": "${workspaceRoot}",
         "environment": [],
         "externalConsole": true,
         "sourceFileMap":{
            "/share/OGL" : "$WorkspaceRoot}"
         },
         "setupCommands": [ 
            { "text":"target extended-remote ${config:remote.addr}:1234", "ignoreFailure":false }
         ],
         "windows": {
           "MIMode": "gdb",
           "miDebuggerPath": "C:\\gdb-arm-linux\\bin\\arm-linux-gnueabihf-gdb.exe",
           "preLaunchTask": "debug"
         },
         "logging": {
            "engineLogging": true,
            "trace": true
         }
       }      
   ]
}
  1. The ability to specify fully custom setup commands (so the -file-exec-and-symbols and -target-select extended-remote are specified explicitly) will also solve this problem

Ugly current workaround

Issue target extended-remote command in the setupCommands and do not remove miDebuggerServer from the launch.json. This will result in issuing target extended-remote command twice, but somehow it works :). Not sure it will with the other GDB version:

1: (217) <-1001-gdb-set mi-async on
1: (228) <-1002-interpreter-exec console "show configuration"
1: (256) <-1003-interpreter-exec console "target extended-remote 192.168.122.233:1234"
1: (327) <-1004-interpreter-exec console "set pagination off"
1: (328) <-1005-gdb-set auto-solib-add on
1: (349) <-1006-gdb-set solib-search-path target:/share/OGL/build;
1: (369) <-1007-environment-cd D:/Oleg/_Projects/Neon3/Software/Client/CtrlPi
1: (380) <-1008-gdb-set new-console on
1: (401) <-1009-file-exec-and-symbols target:/share/OGL/build/main.elf
1: (4575) <-1010-interpreter-exec console "show architecture"
1: (4593) <-1011-break-insert -f main
1: (5106) <-1012-target-select extended-remote 192.168.122.233:1234
1: (5180) <-1013-interpreter-exec console "set remote exec-file /share/OGL/build/main.elf"
1: (5199) <-1014-interpreter-exec console "set scheduler-locking step"
<--   C (setBreakpoints-3): {"command":"setBreakpoints","arguments":{"source":{"name":"test.c","path":"d:\\Oleg\\_Projects\\Neon3\\Software\\Client\\CtrlPi\\test.c"},"lines":[243],"breakpoints":[{"line":243}],"sourceModified":false},"type":"request","seq":3}
1: (5273) <-1015-break-insert -f test.c:243
1: (5306) <-1016-symbol-list-lines D:/Oleg/_Projects/Neon3/Software/Client/CtrlPi/test.c
<--   C (setFunctionBreakpoints-4): {"command":"setFunctionBreakpoints","arguments":{"breakpoints":[]},"type":"request","seq":4}
<--   C (setDataBreakpoints-5): {"command":"setDataBreakpoints","arguments":{"breakpoints":[]},"type":"request","seq":5}
<--   C (setInstructionBreakpoints-6): {"command":"setInstructionBreakpoints","arguments":{"breakpoints":[]},"type":"request","seq":6}
<--   C (setExceptionBreakpoints-7): {"command":"setExceptionBreakpoints","arguments":{"filters":[],"filterOptions":[]},"type":"request","seq":7}
<--   C (configurationDone-8): {"command":"configurationDone","type":"request","seq":8}
<--   C (threads-9): {"command":"threads","type":"request","seq":9}
1: (5399) <-1017-exec-run

Activity

  1. UR3IQO commented on Feb 14, 2024

    @UR3IQO
    Author

    I looked at the GetInitializeCommands in DebuggedProcess.cs (MIEngine repo) and realized that Option 3 in the possible solutions was already implemented. So, I tried to use fully custom setup and launch gdb commands and it did the trick:

    {
       //NOTE: remote username, address, project directory and executable name are defined in the config file (.vscode/settings.json)
       "version": "0.2.0",
       "configurations": [
          {
             "name": "GDBserver debug",
             "type": "cppdbg",
             "request": "launch",
             "targetArchitecture": "arm",
             "useExtendedRemote": true,
             "program": "target:${config:remote.dir}/${config:remote.exec}",
             "miDebuggerServerAddress": "${config:remote.addr}:1234",
             "args": [],
             "cwd": "${workspaceRoot}",
             "environment": [],
             //"externalConsole": true,
             "sourceFileMap":{
                "/share/OGL" : "{$workspaceRoot}",
                "/share" : "D:\\src\\lib"
             },
             "customLaunchSetupCommands" : [
                { "text":"target extended-remote ${config:remote.addr}:1234", "ignoreFailure":false },
                { "text": "-file-exec-and-symbols target:${config:remote.dir}/${config:remote.exec}", "ignoreFailure":false },
                { "text": "set remote exec-file ${config:remote.dir}/${config:remote.exec}", "ignoreFailure":false },
                { "text":"set scheduler-locking step" }
             ],
             "windows": {
               "MIMode": "gdb",
               "miDebuggerPath": "C:\\gdb-arm-linux\\bin\\arm-linux-gnueabihf-gdb.exe",
               "preLaunchTask": "debug"
             },
             "logging": {
                "engineLogging": true,
                "trace": true
             }
        }
    }
    

    And the filtered log:

    1: (242) <-1001-gdb-set mi-async on
    1: (269) <-1002-interpreter-exec console "set pagination off"
    1: (274) <-1003-gdb-set auto-solib-add on
    1: (289) <-1004-gdb-set solib-search-path target:/share/OGL/build;
    1: (306) <-1005-interpreter-exec console "target extended-remote 192.168.122.233:1234"
    1: (382) <-1007-file-exec-and-symbols target:/share/OGL/build/main.elf
    1: (4407) <-1008-interpreter-exec console "set remote exec-file /share/OGL/build/main.elf"
    1: (4437) <-1010-interpreter-exec console "set scheduler-locking step"
    <--   C (setFunctionBreakpoints-3): {"command":"setFunctionBreakpoints","arguments":{"breakpoints":[]},"type":"request","seq":3}
    <--   C (setDataBreakpoints-4): {"command":"setDataBreakpoints","arguments":{"breakpoints":[]},"type":"request","seq":4}
    <--   C (setInstructionBreakpoints-5): {"command":"setInstructionBreakpoints","arguments":{"breakpoints":[]},"type":"request","seq":5}
    <--   C (setExceptionBreakpoints-6): {"command":"setExceptionBreakpoints","arguments":{"filters":[],"filterOptions":[]},"type":"request","seq":6}
    <--   C (configurationDone-7): {"command":"configurationDone","type":"request","seq":7}
    1: (4526) <-1011-exec-run
    
  2. jfuentesa commented on Sep 30, 2024

    @jfuentesa

    Is it possible to avoid sending the -file-exec-and-symbols command?
    I'm using the following syntax to start a gdbserver instance via stdin with a custom .gdbinit:
    "target remote | ssh HOST gdbserver - --attach PID"

    I don't want to debug the executable itself; instead, I want to debug a shared library. However, the trace shows the following error:

    --> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (185489) <-1050-file-exec-and-symbols ......................../executable\n"},"seq":774}
    1: (185489) <-1050-file-exec-and-symbols ......................../executable
    --> E (output): {"type":"event","event":"output","body":{"category":"console","output":"1: (185519) ->1050^error,msg=\"\\\"......................../executable\\\": not in executable format: file format not recognized\"\n"},"seq":776}
    1: (185519) ->1050^error,msg="\"......................../executable\": not in executable format: file format not recognized"
    

    I have tested the options "launch" and "attach" but they don't work for one reason or another.
    "attach": It asks for a local PID.
    "launch": Try to run the program, which is already launched. It fails if the file does not exist (it only exists in the remote host).

    I need a way to override this behaviour.
    Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions