mcpField
L
llvm-tooling

llvm-tooling

github.com/gmh5225开发89054 次安装4 周前更新
代码仓库

关于 llvm-tooling

llvm-tooling 是面向 LLVM 和 Clang 工具开发者的参考 Skill,涵盖源码分析、调试、重构和语言服务器集成,并提供示例与工具参考。

主要功能

  1. 01开发 Clang 插件
  2. 02使用 LibTooling 和 AST Matchers
  3. 03扩展 LLDB
  4. 04扩展 Clangd 与 LSP
  5. 05进行源码到源码转换

适用场景

  1. 01构建基于 Clang 的源码分析器
  2. 02添加自定义 LLDB 命令
  3. 03为 clangd 实现代码操作
  4. 04自动化 C++ 重构

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gmh5225/awesome-llvm-security --skill llvm-tooling

安装后在 Claude Code 中输入/llvm-tooling确认已加载。

详细介绍

LLVM 工具开发技能

此技能涵盖使用 LLVM/Clang 基础设施开发用于源代码分析、调试和 IDE 集成的工具。

Clang 插件开发

插件架构

Clang 插件是动态加载的库,可在编译期间扩展 Clang 的功能。

#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"

class MyVisitor : public clang::RecursiveASTVisitor<MyVisitor> {
public:
    bool VisitFunctionDecl(clang::FunctionDecl *FD) {
        llvm::outs() << "Found function: " << FD->getName() << "\n";
        return true;
    }
};

class MyConsumer : public clang::ASTConsumer {
    MyVisitor Visitor;
public:
    void HandleTranslationUnit(clang::ASTContext &Context) override {
        Visitor.TraverseDecl(Context.getTranslationUnitDecl());
    }
};

class MyPlugin : public clang::PluginASTAction {
protected:
    std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(
        clang::CompilerInstance &CI, llvm::StringRef) override {
        return std::make_unique<MyConsumer>();
    }
    
    bool ParseArgs(const clang::CompilerInstance &CI,
                   const std::vector<std::string> &args) override {
        return true;
    }
};

static clang::FrontendPluginRegistry::Add<MyPlugin>
    X("my-plugin", "My custom plugin description");
运行 Clang 插件
# Build plugin
clang++ -shared -fPIC -o MyPlugin.so MyPlugin.cpp \
    $(llvm-config --cxxflags --ldflags)

# Run plugin
clang -Xclang -load -Xclang ./MyPlugin.so \
      -Xclang -plugin -Xclang my-plugin \
      source.cpp

LibTooling

独立工具
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

using namespace clang::tooling;
using namespace clang::ast_matchers;

// Define matcher
auto functionMatcher = functionDecl(hasName("targetFunction")).bind("func");

// Callback handler
class FunctionCallback : public MatchFinder::MatchCallback {
public:
    void run(const MatchFinder::MatchResult &Result) override {
        if (auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("func")) {
            llvm::outs() << "Found: " << FD->getQualifiedNameAsString() << "\n";
        }
    }
};

int main(int argc, const char **argv) {
    auto ExpectedParser = CommonOptionsParser::create(argc, argv, MyCategory);
    ClangTool Tool(ExpectedParser->getCompilations(),
                   ExpectedParser->getSourcePathList());
    
    FunctionCallback Callback;
    MatchFinder Finder;
    Finder.addMatcher(functionMatcher, &Callback);
    
    return Tool.run(newFrontendActionFactory(&Finder).get());
}
AST Matchers 参考
// Declaration matchers
functionDecl()           // Match function declarations
varDecl()               // Match variable declarations
recordDecl()            // Match struct/class/union
fieldDecl()             // Match class fields
cxxMethodDecl()         // Match C++ methods
cxxConstructorDecl()    // Match constructors

// Expression matchers
callExpr()              // Match function calls
binaryOperator()        // Match binary operators
unaryOperator()         // Match unary operators
memberExpr()            // Match member access

// Narrowing matchers
hasName("name")         // Filter by name
hasType(asString("int")) // Filter by type
isPublic()              // Filter by access specifier
hasAnyParameter(...)    // Match parameters

// Traversal matchers
hasDescendant(...)      // Match anywhere in subtree
hasAncestor(...)        // Match in parent chain
has(...)                // Match direct children
forEach(...)            // Match all children

LLDB 扩展开发

Python 命令
import lldb

def my_command(debugger, command, result, internal_dict):
    """Custom LLDB command implementation"""
    target = debugger.GetSelectedTarget()
    process = target.GetProcess()
    thread = process.GetSelectedThread()
    frame = thread.GetSelectedFrame()
    
    # Get variable value
    var = frame.FindVariable("my_var")
    result.AppendMessage(f"my_var = {var.GetValue()}")

def __lldb_init_module(debugger, internal_dict):
    debugger.HandleCommand(
        'command script add -f my_module.my_command my_cmd')
脚本化进程
class MyScriptedProcess(lldb.SBScriptedProcess):
    def __init__(self, target, args):
        super().__init__(target, args)
        
    def get_thread_with_id(self, tid):
        # Return thread info
        pass
    
    def get_registers_for_thread(self, tid):
        # Return register context
        pass
    
    def read_memory_at_address(self, addr, size):
        # Read memory
        pass
LLDB GUI 扩展
  • visual-lldb:LLDB 的 GUI 前端
  • vegvisir:基于浏览器的 LLDB GUI
  • lldbg:轻量级原生 GUI
  • CodeLLDB:VSCode 调试器扩展

Clangd / 语言服务器协议

自定义 LSP 扩展
// Implementing custom code actions
class MyCodeActionProvider {
public:
    std::vector<CodeAction> getCodeActions(
        const TextDocumentIdentifier &File,
        const Range &Range,
        const CodeActionContext &Context) {
        
        std::vector<CodeAction> Actions;
        
        // Add custom refactoring action
        CodeAction Action;
        Action.title = "Extract to function";
        Action.kind = "refactor.extract";
        
        // Define workspace edits
        WorkspaceEdit Edit;
        // ... populate edits
        Action.edit = Edit;
        
        Actions.push_back(Action);
        return Actions;
    }
};
Clangd 配置
# .clangd configuration file
CompileFlags:
  Add: [-xc++, -std=c++17]
  Remove: [-W*]

Diagnostics:
  ClangTidy:
    Add: [modernize-*, performance-*]
    Remove: [modernize-use-trailing-return-type]

Index:
  Background: Build

源代码到源代码转换

Clang Rewriter
#include "clang/Rewrite/Core/Rewriter.h"

class MyRewriter : public RecursiveASTVisitor<MyRewriter> {
    Rewriter &R;
    
public:
    MyRewriter(Rewriter &R) : R(R) {}
    
    bool VisitFunctionDecl(FunctionDecl *FD) {
        // Add comment before function
        R.InsertTextBefore(FD->getBeginLoc(), "// Auto-generated\n");
        
        // Replace function name
        R.ReplaceText(FD->getLocation(), 
                      FD->getName().size(), "new_name");
        
        return true;
    }
};
RefactoringTool
#include "clang/Tooling/Refactoring.h"

class MyRefactoring : public RefactoringCallback {
public:
    void run(const MatchFinder::MatchResult &Result) override {
        // Generate replacements
        Replacement Rep(
            *Result.SourceManager,
            CharSourceRange::getTokenRange(Range),
            "new_text");
        
        Replacements.insert(Rep);
    }
};

使用 LLVM 工具开发的知名工具

分析工具
  • cppinsights:C++ 模板实例化可视化
  • ClangBuildAnalyzer:构建时间分析
  • clazy:针对 Qt 的静态分析
重构工具
  • clang-rename:符号重命名
  • clang-tidy:代码检查和自动修复
  • include-what-you-use:优化头文件包含
代码生成
  • classgen:提取类型信息以用于 IDA
  • constexpr-everything:自动应用 constexpr
  • clang-expand:内联函数展开

最佳实践

  1. 使用 AST Matchers:比手动遍历更易读
  2. 保留格式:谨慎使用 Rewriter,以保持代码风格
  3. 处理宏:注意宏展开位置
  4. 充分测试:C++ 中的边缘情况很多
  5. 提供良好的诊断信息:清晰的错误消息能提升易用性

资源

如需全面的工具列表,请参阅 README.md 中的 Clang Plugins、Clangd/Language Server 和 LLDB 章节。

获取详细信息

如需详细且最新的资源链接、工具列表或项目参考,请从以下位置获取最新数据:

https://raw.githubusercontent.com/gmh5225/awesome-llvm-security/refs/heads/main/README.md

此 README 包含经过全面整理的以下内容:

  • Clang 插件和扩展(Clang Plugins 章节)
  • 语言服务器实现(Clangd/Language Server 章节)
  • LLDB 调试器工具和 GUI(LLDB 章节)
  • 静态分析和重构工具

评论

支持 Markdown