LisCa is a C++ command-line tool built with LLVM/Clang LibTooling. It searches a compilation database for a function by name and reports:
- File location.
- Starting line.
- Ending line.
- The signature line.
The project is designed to work well on Linux kernel source trees once you have a compile_commands.json database, but it also includes a toy example so you can validate the workflow on a small codebase first.
LisCa needs a C++17 compiler and the LLVM/Clang development packages that provide LibTooling and the CMake package files.
This is the primary workflow if you want to run LisCa on Linux kernel source code.
On Ubuntu or Debian, install the build requirements first:
sudo apt update
sudo apt install build-essential cmake ninja-build clang llvm-dev libclang-dev libzstd-dev bearIf your distro splits LLVM by version, you may also have packages such as llvm-18-dev and libclang-18-dev. Install the matching version for both LLVM and Clang.
If CMake still complains about zstd::libzstd_shared, install libzstd-dev on Linux and re-run the configure step.
Find the LLVM and Clang CMake package directories:
llvm-config --cmakedir
llvm-config --prefixOn Debian and Ubuntu, they are often under one of these paths:
/usr/lib/llvm-*/lib/cmake/llvm
/usr/lib/llvm-*/lib/cmake/clangIf you want to search directly:
find /usr/lib /usr/local -name LLVMConfig.cmake -o -name ClangConfig.cmake 2>/dev/nullOnce you know the paths, configure and build LisCa:
bash ./scripts/configure-build.sh
# or
cmake -S . -B build -DLLVM_DIR=/usr/lib/llvm-18/lib/cmake/llvm -DClang_DIR=/usr/lib/llvm-18/lib/cmake/clang
cmake --build buildOn macOS with Homebrew:
brew install cmake llvmIf you also want the compilation database generator on macOS, install bear:
brew install bearYou need the CMake package directories for LLVM and Clang when configuring the build, especially on Linux.
Common commands to find them are:
llvm-config --cmakedir
clang --print-resource-dirOn Homebrew systems, the paths are often:
brew --prefix llvmThen use the package directories under that prefix, typically:
$(brew --prefix llvm)/lib/cmake/llvm
$(brew --prefix llvm)/lib/cmake/clangIf clang is installed elsewhere, you can also search for the package files directly:
find /usr /opt -name LLVMConfig.cmake -o -name ClangConfig.cmake 2>/dev/nullYou need a local LLVM/Clang development installation with CMake package files available.
You can configure and build automatically with the helper script:
bash ./scripts/configure-build.shIt tries llvm-config, then Homebrew, then common install locations to find LLVM_DIR and Clang_DIR.
cmake -S . -B build -DLLVM_DIR=/path/to/llvm/lib/cmake/llvm -DClang_DIR=/path/to/clang/lib/cmake/clang
cmake --build buildTypical packages on Ubuntu or Debian are cmake, ninja-build, clang, llvm-dev, and libclang-dev.
Use the toy source in examples/toy_sample.cpp as the first validation target. Generate compile_commands.json with the build above, then run:
./build/lisca --compile-commands-dir build --input examples/toy_sample.cpp --function addExpected output includes the file path, the start and end lines of the function, and the signature line.
You can also try the class method in the same file:
./build/lisca --compile-commands-dir build --input examples/toy_sample.cpp --function subtractThe easiest workflow is to build the kernel with a compilation database and then run LisCa against that database.
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linuxStart from a clean config that matches your machine or use a default one:
make defconfigIf you only want to analyze a subtree like fs/ext4, you do not need to build the whole kernel. A focused module build is faster and usually enough for function lookup.
Use bear to capture the kernel build commands:
bear -- make -j"$(nproc)" fs/ext4/For a module-focused workflow, this is usually enough:
bear -- make -j"$(nproc)" M=fs/ext4 modulesIf you want the whole project, capture a full build instead:
bear -- make -j"$(nproc)"The important part is that compile_commands.json ends up in the directory you pass to --compile-commands-dir.
If --input is a relative path such as fs/ext4, LisCa resolves it against --compile-commands-dir.
Return to the LisCa project and build it once the LLVM and Clang CMake paths are known:
cmake -S . -B build -DLLVM_DIR=/path/to/llvm/lib/cmake/llvm -DClang_DIR=/path/to/clang/lib/cmake/clang
cmake --build buildFor a function in fs/ext4, point LisCa at the kernel source tree or the specific subtree:
./build/lisca \
--compile-commands-dir /path/to/linux \
--input /path/to/linux/fs/ext4 \
--function ext4_file_read_iterIf your build database was generated from the whole tree, you can also search the full kernel source:
./build/lisca \
--compile-commands-dir /path/to/linux \
--input /path/to/linux \
--function scheduleE.g,
$ ./build/lisca --compile-commands-dir linux-master/ --input fs/ext4/ --function ext4_has_free_clusters
# Found 1 match(es) for 'ext4_has_free_clusters':
# fs/ext4/balloc.c:620-666
# File: fs/ext4/balloc.c
# LOC: 47 lines
# Function: ext4_has_free_clusters
# Signature: static int ext4_has_free_clusters(struct ext4_sb_info *sbi,Or, if you do know the exact file of a function,
$ ./build/lisca --compile-commands-dir linux-master/ --input fs/ext4/balloc.c --function ext4_has_free_clusters
# Processing /home/ubuntu/lisca/linux-master/fs/ext4/balloc.c
# Found 1 match(es) for 'ext4_has_free_clusters':
# fs/ext4/balloc.c:620-666
# File: fs/ext4/balloc.c
# LOC: 47 lines
# Function: ext4_has_free_clusters
# Signature: static int ext4_has_free_clusters(struct ext4_sb_info *sbi,Good first targets are small, well-known functions such as ext4_file_read_iter, ext4_file_write_iter, vfs_read, or schedule. If you get no matches, check that the function is actually compiled in the build database you captured.
If you use intercept-build or another compilation-capture tool instead of bear, make sure the generated compile_commands.json matches the same kernel tree you pass to --input.