Set up the Debugging Environment for SVF in VSCode - SVF-tools/SVF GitHub Wiki

Contents

  1. Pre-requisites
  2. Create Files in .vscode Directory
  3. Run the configurations

Step 1: Pre-requisites

  • Note: If running on Windows, you need to install WSL (Ubuntu subsystem) following (6) of this link

  • Install libs on your Ubuntu System.

   sudo apt install cmake gcc g++ libtinfo-dev libz-dev zip wget
  • Clone and build the SVF repository
    git clone https://github.com/SVF-tools/SVF.git
    cd SVF
    source ./build.sh debug
  • Install the C/C++ extension for VSCode by navigating to the Extensions Marketplace on the left and searching C++.

Extension

Step 2: Create Files in .vscode Directory

We can utilise VSCode's inbuilt features to properly setup the debugging environment for SVF.

We will need to create a directory called .vscode in the project's main directory, inside there will be 3 files:

  • c_cpp_properties.json: Configures Intellisense
  • tasks.json: Binds commands to VSCode UI options/keyboard shortcuts
  • launch.json: Launches Debug binaries and attaches gdb debugger, allowing you to step-through the code

Your directory structure should look like this:

Directory Structure

Step 2.1: Write in c_cpp_properties.json

The main purpose of this file is to be able to use features such as Intellisense, "Go to definition", "Find all references" features by providing the path to the relevant source files in the includePath property.

For more information about what each property in c_cpp_properties.json means, head to this page.

Copy the following into the c_cpp_properties.json file:

{
    "configurations": 
    [
      {
        "name": "Linux",
        "intelliSenseMode": "clang-x64",
        "includePath": [
            "${workspaceFolder}/llvm-16.0.0.obj/include/**",
            "${workspaceFolder}/svf/include/**",
            "${workspaceFolder}/svf-llvm/include/**"
        ],
        "compilerPath": "${workspaceFolder}/llvm-16.0.0.obj/bin/clang",
        "cStandard": "c11",
        "cppStandard": "c++17",
        "browse": {
          "path": ["${workspaceFolder}"],
          "limitSymbolsToIncludedHeaders": true,
          "databaseFilename": ""
        }
      }
    ],
    "version": 4
}

Step 2.2: Write in tasks.json

NOTE Before using this file: This task assumes that the project is initially built by running

    cd SVF
    source ./build.sh debug

And as a result, the Debug-build directory is created. This command does not rebuild the project each time it is executed, rather only calls make to build the modified, un-cached changes, making the build process much quicker when testing and making slight modifications to the code whilst debugging.

See this page for the documentation about the tasks.json format

Copy the following json into the tasks.json file:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Make (Debug)",
            "type": "shell",
            "command": "cd Debug-build && make -j4",
            "problemMatcher": [],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        },
        {
            "label": "Build (Debug)",
            "type": "shell",
            "command": "./build debug",
            "problemMatcher": [],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

Step 2.3: Write in launch.json

This is where all of the binaries that you wish to debug will be defined. In this example, some binaries defined in the tools directory are used.

Important things to note when defining your own configuration:

  • program the path of the built executable
  • args additional cli arguments
  • cwd the current working directory used when running the binary
  • environment any environment variables you wish to define

For more information, visit this page.

Copy the following json into the launch.json file:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch SVF-EX",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/Debug-build/bin/svf-ex",
            "args": ["example.ll"],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}/Debug-build/bin",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",                 // change to lldb on mac
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "Make (Debug)"
        },
        {
            "name": "(gdb) Launch WPA",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/Debug-build/bin/wpa",
            "args": ["-ander","example.ll"],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}/Debug-build/bin",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",                    // change to lldb on mac
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "Make (Debug)"
        }
    ]
}

Step 3: Run these configurations

  • Ctrl+Shift+B will execute the build task, if more than one is defined, VSCode will display a list of tasks, select one to execute.

Build Tasks

  • F5 will debug the current active binary. To select which executable to debug, navigate to the debug menu and select it in the drop down menu. From there, you can also add more configurations for other binaries.

Debug List