23.11.2013 Views

Obfuscation of Abstract Data-Types - Rowan

Obfuscation of Abstract Data-Types - Rowan

Obfuscation of Abstract Data-Types - Rowan

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

CHAPTER 2. OBFUSCATIONS FOR INTERMEDIATE LANGUAGE 33<br />

2.3.5 Applying transformations<br />

Although the logic language we have described makes it convenient to define<br />

side conditions for program transformation, it would be rather difficult to use<br />

this language to apply these transformations, since that would require the program<br />

flow graph to be represented as a logic term. The approach that is taken is<br />

that a successful logic query should also bind its parameter to a list <strong>of</strong> symbolic<br />

“actions” which define a correct transformation on the flow graph. A high-level<br />

strategy language, which is similar to Stratego [55], is responsible for directing<br />

in what order logic queries should be tried and for applying the resulting<br />

transformations.<br />

An action is a term, which can be either <strong>of</strong> the form replace vertex(V ,W)<br />

or new local(T,N). The former replaces the vertex V with the vertex W , while<br />

the latter introduces a new local variable named N <strong>of</strong> type T. We write a list<br />

<strong>of</strong> actions as the last parameter <strong>of</strong> predicate.<br />

Suppose that we have a predicate P specified. If we want to apply this<br />

predicate once then we write apply(P) in the strategy language. If we want to<br />

exhaustively apply this predicate (i.e. keep applying the predicate while it is<br />

true) then we write exhaustively(apply(P)). An example <strong>of</strong> a strategy is given<br />

at the end <strong>of</strong> the next section.<br />

2.3.6 Variable Transformation<br />

For our first example, let us consider how to define a variable transformation<br />

(Section 1.3.3). The first part <strong>of</strong> the transformation involves finding a suitable<br />

variable and for simplicity, we require that the variable is local and has integer<br />

type. We also require that it is assigned somewhere (otherwise there would be<br />

no point in performing the transformation). Once we find a suitable variable<br />

(which we call OldVar), we generate a new name using @fresh name which<br />

takes a type as a parameter. We can write the search for a suitable variable as<br />

follows:<br />

find local (OldVar,<br />

NewVar,<br />

new local(int(true,b32),NewVarName) : nil<br />

) :−<br />

exists ( { }∗ ;<br />

{ ′ set(OldVar,V ),<br />

OldVar = expr type(localvar( ),int(true,b32))}<br />

) (entry,OldVarVert),<br />

@fresh name (int(true,b32),NewVarName),<br />

NewVar = expr type(localvar (sname(NewVarName)),<br />

int(true,b32)).<br />

The next step <strong>of</strong> the transformation replaces uses and assignments <strong>of</strong> OldVar<br />

exhaustively. To do this, we need to define predicates which allow us to build<br />

expressions corresponding to f and g (the functions used for variable transformation).<br />

The predicate use fn(A,B) binds B to a representation <strong>of</strong> g(A) and<br />

similarly, assign fn(C,D) binds D to f (C). We can specify any variable transformation<br />

by changing these two predicates. As an example, let us suppose

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

Saved successfully!

Ooh no, something went wrong!