You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于Frama-C插件生成修改后C文件的技术咨询

How to Build a Frama-C Plugin for Clean AST Modification & Output

Absolutely! You can totally build a Frama-C plugin to tweak source code (clone functions, insert calls) and spit out a clean, modified C file—no messy extra output included. Let’s walk through how to make this happen:

Core Idea

Frama-C’s entire workflow revolves around the AST (Abstract Syntax Tree) of your C code, built using the Cil (C Intermediate Language) library. Instead of redirecting terminal output (which picks up extra logs from other plugins), you’ll directly modify the AST and then print it to a file using Cil’s dedicated printing functions—this gives you full control over what gets written.

Step-by-Step Implementation

1. Get Familiar with Cil’s AST Structures

First, you’ll need to learn the basics of Cil’s types since Frama-C uses them to represent code:

  • fundec: Represents a function definition (includes name, parameters, body, etc.)
  • stmt: A single statement (like a function call, assignment, or loop)
  • exp: An expression (like a function argument or variable reference)

Frama-C’s internal docs (accessible via frama-c -help api) will be your best friend here—look up functions related to copying functions, creating calls, and manipulating statements.

2. Write Your AST Modification Logic

Cloning a Function

To clone a function, copy its fundec structure, adjust the name, and add the new function to the global list of functions in the AST:

let clone_function (original : Cil.fundec) : Cil.fundec =
  let cloned = Cil.copyFunction original in
  cloned.svar.vname <- cloned.svar.vname ^ "_clone";
  (* Add the cloned function to the global scope *)
  Cil.currentFile.globals <- Cil.GFun(cloned, cloned.svar.vdecl) :: Cil.currentFile.globals;
  cloned

Inserting a Function Call

To insert a call to your cloned function (or any function) into another function’s body, create a call statement and insert it into the target function’s statement list:

let insert_function_call (target_func : Cil.fundec) (call_func : Cil.fundec) =
  (* Create the function call expression *)
  let call_exp = Cil.Lval(Cil.Var call_func.svar, Cil.NoOffset) in
  let call_stmt = Cil.mkStmt (Cil.Instr [Cil.Call(None, call_exp, [], call_func.svar.vdecl)]) in
  (* Insert the call at the start of the target function's body *)
  match target_func.body with
  | Cil.Block(block) ->
      block.bstmts <- call_stmt :: block.bstmts
  | _ -> ()

3. Print the Modified AST to a Clean File

The key to avoiding redundant output is to skip Frama-C’s default terminal printing and use Cil’s direct file-printing functions. Here’s how to do it:

let output_modified_file (output_path : string) =
  (* Ensure for loops are printed as for, not while *)
  Cil.printForAsFor := true;
  (* Open the output file and print the AST *)
  let oc = open_out output_path in
  Cil.printFile ~out:oc !Cil.currentFile;
  close_out oc;
  Printf.printf "Modified code written to %s\n" output_path

4. Wire It All Together in Your Plugin

Register your plugin so it runs the modification and output logic when Frama-C starts:

let () =
  Db.Main.extend (fun () ->
      (* Example: Find a function named "foo", clone it, and insert the clone call into "bar" *)
      let find_func name =
        List.find_opt (fun g ->
            match g with
            | Cil.GFun(f, _) when f.svar.vname = name -> true
            | _ -> false) Cil.currentFile.globals
      in
      match find_func "foo", find_func "bar" with
      | Some(Cil.GFun(foo, _)), Some(Cil.GFun(bar, _)) ->
          let cloned_foo = clone_function foo in
          insert_function_call bar cloned_foo;
          output_modified_file "modified_code.c"
      | _ -> Printf.printf "Could not find target functions\n"
    )

Avoiding Common Pitfalls

  • Disable Unnecessary Plugins: When running your plugin, don’t include other analysis plugins (like value or constant-folding) unless you need them—they can modify the AST or add extra terminal output. Run it like: frama-c -load-script your_plugin.cmxs your_source.c
  • Check Cil’s Print Options: Adjust flags like Cil.printForAsFor to preserve original loop syntax instead of converting for loops to while.
  • Test with Minimal Code: Start with a tiny C file (e.g., a single function) to test your plugin—this makes debugging way easier than jumping into complex codebases.

Final Tips

If you’re stuck, look at the source code of existing Frama-C plugins that modify the AST (like sparecode or loopext). While their output goes to the terminal, you can adapt their AST manipulation logic and replace the output step with your direct file print.

内容的提问来源于stack exchange,提问作者R. Fomba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:29:55