A CIL Tutorial - Department of Computer Science - ETH Zürich

A CIL Tutorial - Department of Computer Science - ETH Zürich A CIL Tutorial - Department of Computer Science - ETH Zürich

29.01.2014 Views

CHAPTER 1. THE AST 12 1.1 tut1.ml The function tut1FixInstr returns false if the instruction i is an assignment to a global variable called deleted. Otherwise it returns true. We'll be using this function as an argument to List.filter. let tut1FixInstr (i : instr) : bool = match i with | Set((Var vi, NoOffset), , loc) when vi.vname = "deleted" ∧ vi.vglob → E.log "%a: Deleted assignment: %a\n" d loc loc d instr i; false | → true The tut1FixStmt function inspects a statement. If the statement is a list of instructions, it overwrites the mutable skind eld of the statement with a list of instructions ltered by tut1FixInstr. Otherwise, it recursively descends into sub-statements. let rec tut1FixStmt (s : stmt) : unit = match s.skind with | Instr il → s.skind ← Instr(List.filter tut1FixInstr il) | If( , tb, fb, ) → tut1FixBlock tb; tut1FixBlock fb (∗ and so forth.∗) | → () and tut1FixBlock (b : block) : unit = List.iter tut1FixStmt b.bstmts let tut1FixFunction (fd : fundec) : unit = tut1FixBlock fd.sbody Now that we have dened a set of functions for traversing the AST of a function denition, we can write a function for the entry point into this module that iterates over all of the globals of a le. When we nd the function called target we invoke tut1FixFunction. let tut1 (f : file) : unit = List.iter (fun g → match g with | GFun (fd, loc) when fd.svar.vname = "target" → tut1FixFunction fd | → ()) f.globals

CHAPTER 1. THE AST 13 1.2 Printing the AST The function tut1FixInstr also uses CIL's logging and pretty-printing features. The call to E.log causes messages to be printed to stdout. It is similar to Printf.printf from the OCaml standard library with a few dierences that are documented in cil/ocamlutil/errormsg.mli. Most importantly, you can print elements of the CIL AST by using the %a format specier. Then, corresponding to that format you must supply two arguments: a function (unit → α → doc), and such an α that you want to print. Functions like this for the AST elements are dened in cil.ml (e.g. Cil.d exp for Cil.exp's). Functions for building objects of type doc are available in the Pretty module documented in cil/ocamlutil/pretty.mli. 1.3 test/tut1.c The module tut1.ml deletes writes inside functions named target to global variables named deleted. Thus, the function target below will return 37. # include int deleted = 37; ../test/tut1.c int target() { int l; deleted = 0; l = deleted; return l; } int main() { int r; r = target(); printf("r = %d\n", r); return 0; } We can build this le with the following command: $ ciltutcc --enable-tut1 -o tut1 test/tut1.c test/tut1.c:14: Deleted assignment: #line 14 "test/tut1.c" deleted = 0; Using the log message emitted by tut1FixInstr, ciltutcc informs us that it has removed an assignment to deleted. Now, we can run the resulting program:

CHAPTER 1. THE AST 12<br />

1.1 tut1.ml<br />

The function tut1FixInstr returns false if the instruction i is an assignment to a global variable<br />

called deleted. Otherwise it returns true. We'll be using this function as an argument to<br />

List.filter.<br />

let tut1FixInstr (i : instr) : bool =<br />

match i with<br />

| Set((Var vi, NoOffset), , loc)<br />

when vi.vname = "deleted" ∧ vi.vglob →<br />

E.log "%a: Deleted assignment: %a\n" d loc loc d instr i;<br />

false<br />

| → true<br />

The tut1FixStmt function inspects a statement. If the statement is a list <strong>of</strong> instructions, it overwrites<br />

the mutable skind eld <strong>of</strong> the statement with a list <strong>of</strong> instructions ltered by tut1FixInstr.<br />

Otherwise, it recursively descends into sub-statements.<br />

let rec tut1FixStmt (s : stmt) : unit =<br />

match s.skind with<br />

| Instr il →<br />

s.skind ← Instr(List.filter tut1FixInstr il)<br />

| If( , tb, fb, ) →<br />

tut1FixBlock tb;<br />

tut1FixBlock fb<br />

(∗ and so forth.∗)<br />

| → ()<br />

and tut1FixBlock (b : block) : unit = List.iter tut1FixStmt b.bstmts<br />

let tut1FixFunction (fd : fundec) : unit = tut1FixBlock fd.sbody<br />

Now that we have dened a set <strong>of</strong> functions for traversing the AST <strong>of</strong> a function denition, we can<br />

write a function for the entry point into this module that iterates over all <strong>of</strong> the globals <strong>of</strong> a le.<br />

When we nd the function called target we invoke tut1FixFunction.<br />

let tut1 (f : file) : unit =<br />

List.iter (fun g →<br />

match g with<br />

| GFun (fd, loc) when fd.svar.vname = "target" →<br />

tut1FixFunction fd<br />

| → ())<br />

f.globals

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!