Vscode-cpptools: An IntelliSense Bug When Coding Linux Kernel Module

Created on 31 May 2020  ·  15Comments  ·  Source: microsoft/vscode-cpptools

Type: LanguageService

Describe the bug

  • OS and Version:Linux4.15.0
  • VS Code Version:1.45.1
    5763d909d5f12fe19f215cbfdd29a91c0fa9208a
    x64
  • C/C++ Extension Version:0.28.1
  • Other extensions you installed (and if the issue persists after disabling them):None
  • Does this issue involve using SSH remote to run the extension on a remote machine?:No
  • A clear and concise description of what the bug is, including information about the workspace (i.e. is the workspace a single project or multiple projects, size of the project, etc).
    I think this is a IntelliSense error. I am trying to write a simple linux kernel module project, and vscode prompt me: 1. the semicolon is missing. 2. could not find macro __exit(but the macro __init is successfully found, which is in the same file with __exit)

Steps to reproduce

  1. This is my code hallo.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Fasion Chan");
MODULE_DESCRIPTION("An hello worlk module for demonstration");
MODULE_VERSION("1.0");

static int __init hello_init(void)
{
    printk(KERN_INFO "HELLO: Hello, this is hello module speaking\n");
    return 0;
}

static void __exit hello_exit(void)
{
    printk(KERN_INFO "HELLO: Goodbye");
}

module_init(hello_init);
module_exit(hello_exit);
  1. This is my c_cpp_properties.json
{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/src/linux-4.15/include/",
                "/usr/src/linux-4.15/arch/x86/include/"
            ],
            "defines": [
                "_GNU_SOURCE"
            ],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "gcc-x64"
        }
    ],
    "version": 4
}
  1. See error

Expected behavior

Obviously the program is no problem, because it can be compiled and loaded correctly. So i think it is IntelliSense‘ bug.


Logs

-------- Diagnostics - 2020/5/31 下午4:18:22
Version: 0.28.1
Current Configuration:
{
    "name": "Linux",
    "includePath": [
        "${workspaceFolder}/**",
        "/usr/src/linux-4.15/include/",
        "/usr/src/linux-4.15/arch/x86/include/"
    ],
    "defines": [
        "_GNU_SOURCE"
    ],
    "compilerPath": "/usr/bin/gcc",
    "cStandard": "c11",
    "cppStandard": "c++17",
    "intelliSenseMode": "gcc-x64",
    "compilerArgs": [],
    "browse": {
        "path": [
            "${workspaceFolder}/**",
            "/usr/src/linux-4.15/include/",
            "/usr/src/linux-4.15/arch/x86/include/"
        ],
        "limitSymbolsToIncludedHeaders": true
    }
}
Translation Unit Mappings:
[ /home/nano/Code/softwarebei/test_module/hello.c ]:
    /home/nano/Code/softwarebei/test_module/hello.c
Translation Unit Configurations:
[ /home/nano/Code/softwarebei/test_module/hello.c ]:
    Process ID: 14224
    Memory Usage: 39 MB
    Compiler Path: /usr/bin/gcc
    Includes:
        /usr/src/linux-4.15/include
        /usr/src/linux-4.15/arch/x86/include
        /usr/lib/gcc/x86_64-linux-gnu/6/include
        /usr/local/include
        /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
        /usr/include/x86_64-linux-gnu
        /usr/include
    Defines:
        _GNU_SOURCE
    Standard Version: c11
    IntelliSense Mode: gcc-x64
    Other Flags:
        --gcc
        --gnu_version=60300
Total Memory Usage: 39 MB

Screenshots

深度截图_选择区域_20200531160358
深度截图_选择区域_20200531160423
深度截图_选择区域_20200531160504

Additional context

Language Service bug investigate

Most helpful comment

Had similar problems, which I seem to be past with a couple of defines, and an explicit list of include directories.

My current .vscode/c_cpp_properties.json file note the defines, compilerArgs and includePath values. (You will need to adjust the include path for your kernel version.)

{
    "configurations": [
        {
            "name": "driver",
            "defines": [
                "__KERNEL__",
                "MODULE"
            ],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "gcc-x64",
            "includePath": [
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include",
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include/generated",
                "/usr/src/linux-headers-5.4.0-39-generic/include",
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include/generated/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/include/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/include/generated/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/ubuntu/include",
                "/usr/lib/gcc/x86_64-linux-gnu/9/include"
            ],
            "compilerArgs": [
                "-nostdinc",
                "-include", "/usr/src/linux-headers-5.4.0-39-generic/include/linux/kconfig.h",
                "-include", "/usr/src/linux-headers-5.4.0-39-generic/include/linux/compiler_types.h"
            ]
        }
    ],
    "version": 4
}

Note the include path may vary somewhat for your kernel and distribution. To get a dump of all the compiler options (including actual include path) actually used for your kernel module build, add to your Makefile (temporarily):

# Use these options only to determine compiler include directories.
ccflags-y := $(ccflags-y) -xc -E -v

Comment out that line when you have teased out the relevant compiler options. My understanding is the Qt developers deserve credit for coming up with the above set of compiler flags.

All 15 comments

Also seeing this. I think the parser has problems with the __section(...) blocks.

Also seeing this. I think the parser has problems with the __section(...) blocks.

Thanks for reply. So do you have any idea to solve this problem?

I'm having the same problem and am available for testing (or providing any debug information that may help). Feel free to tag me.

Had similar problems, which I seem to be past with a couple of defines, and an explicit list of include directories.

My current .vscode/c_cpp_properties.json file note the defines, compilerArgs and includePath values. (You will need to adjust the include path for your kernel version.)

{
    "configurations": [
        {
            "name": "driver",
            "defines": [
                "__KERNEL__",
                "MODULE"
            ],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "gcc-x64",
            "includePath": [
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include",
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include/generated",
                "/usr/src/linux-headers-5.4.0-39-generic/include",
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include/generated/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/include/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/include/generated/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/ubuntu/include",
                "/usr/lib/gcc/x86_64-linux-gnu/9/include"
            ],
            "compilerArgs": [
                "-nostdinc",
                "-include", "/usr/src/linux-headers-5.4.0-39-generic/include/linux/kconfig.h",
                "-include", "/usr/src/linux-headers-5.4.0-39-generic/include/linux/compiler_types.h"
            ]
        }
    ],
    "version": 4
}

Note the include path may vary somewhat for your kernel and distribution. To get a dump of all the compiler options (including actual include path) actually used for your kernel module build, add to your Makefile (temporarily):

# Use these options only to determine compiler include directories.
ccflags-y := $(ccflags-y) -xc -E -v

Comment out that line when you have teased out the relevant compiler options. My understanding is the Qt developers deserve credit for coming up with the above set of compiler flags.

I was having a very similar issue and the solution proposed by @pbannister solved it for me. I am on VS Code version 1.47.2 and C/C++ extension version 0.29.0.

Note my c_cpp_properties.json looks vastly different than his, but temporarily adding ccflags-y := $(ccflags-y) -xc -E -v to the Makefile as suggested spit out the information I needed to know.

Adding "__section(x)=" to the defines array (plus the ones from @pbannister's comment) seems to resolve the squiggles around __exit for me. I'm not 100% confident though because I still have a squiggle under a #include telling me it can't find a generated header (generated/asm-offsets.h). Having never worked on the linux kernel I'm not sure how to get those files generated.

@bobbrow I do not seem to have any squiggles, anymore. Note the list of include directories I gave are specific to Ubuntu 20.04 LTS. Your Linux distribution might require something a bit different. The check is to add the extra flags to ccflags-y and then read the actual include options.

You might find this command gives easier to read output. (Need to adjust if /usr/lib/gcc is not your compiler.)

make clean ; make |& grep '^ /usr/lib/gcc' | sed -e 's, -[a-zA-Z],\n\0,g' | grep '^ -' | awk '{ if(t[$0]) next; t[$0] = 1; print }' | less -SC

Maybe a warning. Intellisense has stopped working for regular C++ projects. (As in, WTF??)

Intellisense still works just fine in my driver project, but a simple hello-world example created from scratch cannot find <stdio.h>. (In disbelief, trying creating several from-scratch new projects, all with same result.)

Right. Deleted ~/.vscode/. Rebooted. Installed C/C++ extension from Microsoft (version 0.29.0). Created new project. Same. This is Visual Studio Code 1.47.2 on Linux.

No clues at the moment.

Can you run the C++ Log Diagnostics command and paste the result here? I suspect something is going on in your settings.

Had similar problems, which I seem to be past with a couple of defines, and an explicit list of include directories.

My current .vscode/c_cpp_properties.json file note the defines, compilerArgs and includePath values. (You will need to adjust the include path for your kernel version.)

{
    "configurations": [
        {
            "name": "driver",
            "defines": [
                "__KERNEL__",
                "MODULE"
            ],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "gcc-x64",
            "includePath": [
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include",
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include/generated",
                "/usr/src/linux-headers-5.4.0-39-generic/include",
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/arch/x86/include/generated/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/include/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/include/generated/uapi",
                "/usr/src/linux-headers-5.4.0-39-generic/ubuntu/include",
                "/usr/lib/gcc/x86_64-linux-gnu/9/include"
            ],
            "compilerArgs": [
                "-nostdinc",
                "-include", "/usr/src/linux-headers-5.4.0-39-generic/include/linux/kconfig.h",
                "-include", "/usr/src/linux-headers-5.4.0-39-generic/include/linux/compiler_types.h"
            ]
        }
    ],
    "version": 4
}

Note the include path may vary somewhat for your kernel and distribution. To get a dump of all the compiler options (including actual include path) actually used for your kernel module build, add to your Makefile (temporarily):

# Use these options only to determine compiler include directories.
ccflags-y := $(ccflags-y) -xc -E -v

Comment out that line when you have teased out the relevant compiler options. My understanding is the Qt developers deserve credit for coming up with the above set of compiler flags.

@pbannister ,
Thank you so much for this answer. After VSCode new C++ Extension (30), everything stopped working for me. It was a nightmare for me searching on google how to locate kernel header files in intellisense database. Your solution worked like a charm.

Two thousand lines of code later ... should update this, since things have worked well, and have settings for both Ubuntu 20 and Centos 8.

{
    "configurations": [
        {
            "name": "driver-ubuntu-20",
            "defines": [
                "__KERNEL__",
                "MODULE"
            ],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "gcc-x64",
            "includePath": [
                "/usr/src/linux-headers-5.4.0-42-generic/arch/x86/include",
                "/usr/src/linux-headers-5.4.0-42-generic/arch/x86/include/generated",
                "/usr/src/linux-headers-5.4.0-42-generic/include",
                "/usr/src/linux-headers-5.4.0-42-generic/arch/x86/include/uapi",
                "/usr/src/linux-headers-5.4.0-42-generic/arch/x86/include/generated/uapi",
                "/usr/src/linux-headers-5.4.0-42-generic/include/uapi",
                "/usr/src/linux-headers-5.4.0-42-generic/include/generated/uapi",
                "/usr/src/linux-headers-5.4.0-42-generic/ubuntu/include",
                "/usr/lib/gcc/x86_64-linux-gnu/9/include"
            ],
            "compilerArgs": [
                "-nostdinc",
                "-include", "/usr/src/linux-headers-5.4.0-42-generic/include/linux/kconfig.h",
                "-include", "/usr/src/linux-headers-5.4.0-42-generic/include/linux/compiler_types.h"
            ]
        },
        {
            "name": "driver-centos-8",
            "defines": [
                "__KERNEL__",
                "MODULE"
            ],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "gcc-x64",
            "includePath": [
                "/usr/src/kernels/4.18.0-80.el8.x86_64/arch/x86/include",
                "/usr/src/kernels/4.18.0-80.el8.x86_64/arch/x86/include/generated",
                "/usr/src/kernels/4.18.0-80.el8.x86_64/include",
                "/usr/src/kernels/4.18.0-80.el8.x86_64/arch/x86/include/uapi",
                "/usr/src/kernels/4.18.0-80.el8.x86_64/arch/x86/include/generated/uapi",
                "/usr/src/kernels/4.18.0-80.el8.x86_64/include/uapi",
                "/usr/src/kernels/4.18.0-80.el8.x86_64/include/generated/uapi",
                "/usr/lib/gcc/x86_64-redhat-linux/8/include"
            ],
            "compilerArgs": [
                "-nostdinc",
                "-include", "/usr/src/kernels/4.18.0-80.el8.x86_64/include/linux/kconfig.h",
                "-include", "/usr/src/kernels/4.18.0-80.el8.x86_64/include/linux/compiler_types.h"
            ]
        }
    ],
    "version": 4
}

Again, as mentioned before, the include path may vary somewhat for your kernel and distribution. To get a dump of all the compiler options (including actual include path) actually used for your kernel module build, add to your Makefile (temporarily):

# Use these options only to determine compiler include directories.
ccflags-y := $(ccflags-y) -xc -E -v

Comment out that line when you have teased out the relevant compiler options. My understanding is the Qt developers deserve credit for coming up with the above set of compiler flags.

Examining the compiler output from the above options is sufficient. If you want to get fancy, you might find this command gives easier to read output. (Need to adjust if /usr/lib/gcc is not your compiler.) Entirely optional. This bit of script will break if things change significantly (over time).

make clean ; make |& grep '^ /usr/lib/gcc' | sed -e 's, -[a-zA-Z],\n\0,g' | grep '^ -' | awk '{ if(t[$0]) next; t[$0] = 1; print }' | less -SC

Got a bit further. Realized I could use the ".*.cmd" files from the module build to extract the compiler options.

grep ' gcc ' .*cmd | sed -e 's, -,\n-,g' | awk '{if (v[$0]) next; v[$0]=1; print}'

Gets you the unique compiler options, in order of use. Wrapped the above in about.sh and to further subset:

sh about.sh | grep '^-D'

This gets you the list of defines. Format for the JSON file:

sh about.sh | grep '^-D' | sed -e 's/^-D/"/g' -e 's/$/",/g'

For includes, in order:

sh about.sh | grep '^-[Ii]'

Bit of cut and paste gets an updated .vscode/c_cpp_properties.json with configurations for current Ubuntu 20 and Centos 8:

{
    "configurations": [
        {
            "name": "driver-ubuntu-20",
            "defines": [
                "__KERNEL__",
                "CONFIG_X86_X32_ABI",
                "CONFIG_AS_CFI=1",
                "CONFIG_AS_CFI_SIGNAL_FRAME=1",
                "CONFIG_AS_CFI_SECTIONS=1",
                "CONFIG_AS_SSSE3=1",
                "CONFIG_AS_AVX=1",
                "CONFIG_AS_AVX2=1",
                "CONFIG_AS_AVX512=1",
                "CONFIG_AS_SHA1_NI=1",
                "CONFIG_AS_SHA256_NI=1",
                "CC_USING_FENTRY",
                "MODULE"
            ],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "gcc-x64",
            "includePath": [
                "/usr/src/linux-headers-5.4.0-42-generic/arch/x86/include",
                "/usr/src/linux-headers-5.4.0-42-generic/arch/x86/include/generated",
                "/usr/src/linux-headers-5.4.0-42-generic/include",
                "/usr/src/linux-headers-5.4.0-42-generic/arch/x86/include/uapi",
                "/usr/src/linux-headers-5.4.0-42-generic/arch/x86/include/generated/uapi",
                "/usr/src/linux-headers-5.4.0-42-generic/include/uapi",
                "/usr/src/linux-headers-5.4.0-42-generic/include/generated/uapi",
                "/usr/src/linux-headers-5.4.0-42-generic/ubuntu/include"
            ],
            "compilerArgs": [
                "-nostdinc",
                "-isystem",
                "/usr/lib/gcc/x86_64-linux-gnu/9/include",
                "-include",
                "/usr/src/linux-headers-5.4.0-42-generic/include/linux/kconfig.h",
                "-include",
                "/usr/src/linux-headers-5.4.0-42-generic/include/linux/compiler_types.h"
            ]
        },
        {
            "name": "driver-centos-8",
            "defines": [
                "CC_HAVE_ASM_GOTO",
                "CC_USING_FENTRY",
                "CONFIG_AS_AVX=1",
                "CONFIG_AS_AVX2=1",
                "CONFIG_AS_AVX512=1",
                "CONFIG_AS_CFI=1",
                "CONFIG_AS_CFI_SECTIONS=1",
                "CONFIG_AS_CFI_SIGNAL_FRAME=1",
                "CONFIG_AS_CRC32=1",
                "CONFIG_AS_FXSAVEQ=1",
                "CONFIG_AS_SHA1_NI=1",
                "CONFIG_AS_SHA256_NI=1",
                "CONFIG_AS_SSSE3=1",
                "__KERNEL__",
                "MODULE"
            ],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "gcc-x64",
            "includePath": [
                "/usr/src/kernels/4.18.0-193.14.2.el8_2.x86_64/arch/x86/include",
                "/usr/src/kernels/4.18.0-193.14.2.el8_2.x86_64/arch/x86/include/generated",
                "/usr/src/kernels/4.18.0-193.14.2.el8_2.x86_64/include/drm-backport",
                "/usr/src/kernels/4.18.0-193.14.2.el8_2.x86_64/include",
                "/usr/src/kernels/4.18.0-193.14.2.el8_2.x86_64/arch/x86/include/uapi",
                "/usr/src/kernels/4.18.0-193.14.2.el8_2.x86_64/arch/x86/include/generated/uapi",
                "/usr/src/kernels/4.18.0-193.14.2.el8_2.x86_64/include/uapi",
                "/usr/src/kernels/4.18.0-193.14.2.el8_2.x86_64/include/generated/uapi"
            ],
            "compilerArgs": [
                "-nostdinc",
                "-isystem",
                "/usr/lib/gcc/x86_64-redhat-linux/8/include",
                "-include",
                "/usr/src/kernels/4.18.0-193.14.2.el8_2.x86_64/include/linux/kconfig.h",
                "-include",
                "/usr/src/kernels/4.18.0-193.14.2.el8_2.x86_64/include/linux/compiler_types.h"
            ]
        }
    ],
    "version": 4
}

Note that as time passes, the above defines and includes are likely to change. With enough free time, could code this as Javascript to update the configuration. This is not likely. :)

@pbannister (and anyone else on this thread who may be interested). We are working on an extension that understands makefile projects such as the linux kernel and are nearing a point where we plan to have a public preview.

We have done some testing of the extension on the linux kernel repository but we could benefit from your expertise working in that codebase if you are interested in helping us shape the experience. One of the goals of this extension is to remove the need for you to craft extensive configurations in c_cpp_properties.json by using the information in your makefile and build logs to determine the correct configuration.

If you are interested in participating, please comment on issue #1587 so we can provide you access to the preview.

exactly the same problem for me, just adding "MODULE" in the defines section of c_cpp_properties.json solved it for me. I had already configured the includePaths though.

Posting my version of the c_cpp_properties.json file, hoping it helps someone.

{
    "configurations": [
        {
            "name": "Linux Kernel Module",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/lib/clang/10.0.1/include/",
                "/usr/src/linux/include",
                "/usr/src/linux/include/uapi",
                "/usr/src/linux/include/generated",
                "/usr/src/linux/arch/x86/include",
                "/usr/src/linux/arch/x86/include/uapi",
                "/usr/src/linux/arch/x86/include/generated"
            ],
            "defines": [
                "KBUILD_MODNAME=\"dummyname\"",
                "__GNUC__",
                "__KERNEL__",
                "MODULE"
            ],
            "compilerPath": "/usr/bin/clang",
            "cStandard": "c89",
            "cppStandard": "c++14",
            "intelliSenseMode": "clang-x64",
            "browse": {
                "path": [
                    "${workspaceFolder}",
                    "/usr/src/linux/include",
                    "/usr/src/linux/mm",
                    "/usr/src/linux/fs",
                    "/usr/src/linux/kernel"
                ],
                "limitSymbolsToIncludedHeaders": true,
                "databaseFilename": ""
            }
        }
    ],
    "version": 4
}

Linux has a file "autoconf.h" to conf the Defines:
such as
linux-2.6.22.6/include/linux/autoconf.h

I think VSCode-Cpptools can read it.

Was this page helpful?
0 / 5 - 0 ratings