use of soot.jimple.FieldRef in project soot by Sable.
the class NullnessAssumptionAnalysis method flowThrough.
/**
* {@inheritDoc}
*/
protected void flowThrough(Object inValue, Object unit, Object outValue) // protected void flowThrough(Object flowin, Unit u, List fallOut, List branchOuts)
{
AnalysisInfo in = (AnalysisInfo) inValue;
AnalysisInfo out = new AnalysisInfo(in);
Stmt s = (Stmt) unit;
// in case of a monitor statement, we know that the programmer assumes we have a non-null value
if (s instanceof MonitorStmt) {
MonitorStmt monitorStmt = (MonitorStmt) s;
out.put(monitorStmt.getOp(), NON_NULL);
}
// cause we need to be conservative here
if (s.containsArrayRef()) {
ArrayRef arrayRef = s.getArrayRef();
handleArrayRef(arrayRef, out);
}
// same for field refs, but also set the receiver object to non-null, if there is one
if (s.containsFieldRef()) {
FieldRef fieldRef = s.getFieldRef();
handleFieldRef(fieldRef, out);
}
// same for invoke expr., also set the receiver object to non-null, if there is one
if (s.containsInvokeExpr()) {
InvokeExpr invokeExpr = s.getInvokeExpr();
handleInvokeExpr(invokeExpr, out);
}
// allow sublasses to define certain values as always-non-null
for (Iterator outIter = out.entrySet().iterator(); outIter.hasNext(); ) {
Entry entry = (Entry) outIter.next();
Value v = (Value) entry.getKey();
if (isAlwaysNonNull(v)) {
entry.setValue(NON_NULL);
}
}
// if we have a definition (assignment) statement to a ref-like type, handle it,
if (s instanceof DefinitionStmt) {
// need to copy the current out set because we need to assign under this assumption;
// so this copy becomes the in-set to handleRefTypeAssignment
AnalysisInfo temp = new AnalysisInfo(out);
DefinitionStmt defStmt = (DefinitionStmt) s;
if (defStmt.getLeftOp().getType() instanceof RefLikeType) {
handleRefTypeAssignment(defStmt, temp, out);
}
}
// save memory by only retaining information about locals
for (Iterator outIter = out.keySet().iterator(); outIter.hasNext(); ) {
Value v = (Value) outIter.next();
if (!(v instanceof Local)) {
outIter.remove();
}
}
// for (Iterator outBranchIter = outBranch.keySet().iterator(); outBranchIter.hasNext();) {
// Value v = (Value) outBranchIter.next();
// if(!(v instanceof Local)) {
// outBranchIter.remove();
// }
// }
// now copy the computed info to out
copy(out, outValue);
}
use of soot.jimple.FieldRef in project soot by Sable.
the class LockAllocationBodyTransformer method internalTransform.
protected void internalTransform(Body b, FlowSet fs, List<CriticalSectionGroup> groups, boolean[] insertedGlobalLock) {
//
JimpleBody j = (JimpleBody) b;
SootMethod thisMethod = b.getMethod();
PatchingChain<Unit> units = b.getUnits();
Iterator<Unit> unitIt = units.iterator();
Unit firstUnit = j.getFirstNonIdentityStmt();
Unit lastUnit = units.getLast();
// Objects of synchronization, plus book keeping
Local[] lockObj = new Local[groups.size()];
boolean[] addedLocalLockObj = new boolean[groups.size()];
SootField[] globalLockObj = new SootField[groups.size()];
for (int i = 1; i < groups.size(); i++) {
lockObj[i] = Jimple.v().newLocal("lockObj" + i, RefType.v("java.lang.Object"));
addedLocalLockObj[i] = false;
globalLockObj[i] = null;
}
// Get references to them if they do already exist.
for (int i = 1; i < groups.size(); i++) {
CriticalSectionGroup tnGroup = groups.get(i);
if (!tnGroup.useDynamicLock && !tnGroup.useLocksets) {
if (!insertedGlobalLock[i]) {
// use it!
try {
globalLockObj[i] = Scene.v().getMainClass().getFieldByName("globalLockObj" + i);
// field already exists
} catch (RuntimeException re) {
// field does not yet exist (or, as a pre-existing
// error, there is more than one field by this name)
globalLockObj[i] = Scene.v().makeSootField("globalLockObj" + i, RefType.v("java.lang.Object"), Modifier.STATIC | Modifier.PUBLIC);
Scene.v().getMainClass().addField(globalLockObj[i]);
}
insertedGlobalLock[i] = true;
} else {
globalLockObj[i] = Scene.v().getMainClass().getFieldByName("globalLockObj" + i);
}
}
}
// local lock object into the global lock object for use by other fns.
if (// thisMethod.getSubSignature().equals("void
!addedGlobalLockDefs) // <clinit>()") &&
// thisMethod.getDeclaringClass() ==
// Scene.v().getMainClass())
{
// Either get or add the <clinit> method to the main class
SootClass mainClass = Scene.v().getMainClass();
SootMethod clinitMethod = null;
JimpleBody clinitBody = null;
Stmt firstStmt = null;
boolean addingNewClinit = !mainClass.declaresMethod("void <clinit>()");
if (addingNewClinit) {
clinitMethod = Scene.v().makeSootMethod("<clinit>", new ArrayList(), VoidType.v(), Modifier.PUBLIC | Modifier.STATIC);
clinitBody = Jimple.v().newBody(clinitMethod);
clinitMethod.setActiveBody(clinitBody);
mainClass.addMethod(clinitMethod);
} else {
clinitMethod = mainClass.getMethod("void <clinit>()");
clinitBody = (JimpleBody) clinitMethod.getActiveBody();
firstStmt = clinitBody.getFirstNonIdentityStmt();
}
PatchingChain<Unit> clinitUnits = clinitBody.getUnits();
for (int i = 1; i < groups.size(); i++) {
CriticalSectionGroup tnGroup = groups.get(i);
// if( useGlobalLock[i - 1] )
if (!tnGroup.useDynamicLock && !tnGroup.useLocksets) {
// add local lock obj
// addedLocalLockObj[i] = true;
// TODO: add name
clinitBody.getLocals().add(lockObj[i]);
// conflict
// avoidance code
// assign new object to lock obj
Stmt newStmt = Jimple.v().newAssignStmt(lockObj[i], Jimple.v().newNewExpr(RefType.v("java.lang.Object")));
if (addingNewClinit)
clinitUnits.add(newStmt);
else
clinitUnits.insertBeforeNoRedirect(newStmt, firstStmt);
// initialize new object
SootClass objectClass = Scene.v().loadClassAndSupport("java.lang.Object");
RefType type = RefType.v(objectClass);
SootMethod initMethod = objectClass.getMethod("void <init>()");
Stmt initStmt = Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(lockObj[i], initMethod.makeRef(), Collections.EMPTY_LIST));
if (addingNewClinit)
clinitUnits.add(initStmt);
else
clinitUnits.insertBeforeNoRedirect(initStmt, firstStmt);
// copy new object to global static lock object (for use by
// other fns)
Stmt assignStmt = Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(globalLockObj[i].makeRef()), lockObj[i]);
if (addingNewClinit)
clinitUnits.add(assignStmt);
else
clinitUnits.insertBeforeNoRedirect(assignStmt, firstStmt);
}
}
if (addingNewClinit)
clinitUnits.add(Jimple.v().newReturnVoidStmt());
addedGlobalLockDefs = true;
}
int tempNum = 1;
// Iterate through all of the transactions in the current method
Iterator fsIt = fs.iterator();
Stmt newPrep = null;
while (fsIt.hasNext()) {
CriticalSection tn = ((SynchronizedRegionFlowPair) fsIt.next()).tn;
if (tn.setNumber == -1)
// this tn should be deleted... for now just skip it!
continue;
if (tn.wholeMethod) {
// remove
thisMethod.setModifiers(thisMethod.getModifiers() & ~(Modifier.SYNCHRONIZED));
// synchronized
// modifier
// for
// this
// method
}
// depends on type of locking
Local clo = null;
// current synchronized region
SynchronizedRegion csr = null;
int lockNum = 0;
boolean moreLocks = true;
while (moreLocks) {
// needed for this transaction, then create one.
if (tn.group.useDynamicLock) {
// adds
Value lock = getLockFor((EquivalentValue) tn.lockObject);
// needed
if (lock instanceof Ref) {
if (lock instanceof InstanceFieldRef) {
InstanceFieldRef ifr = (InstanceFieldRef) lock;
if (ifr.getBase() instanceof FakeJimpleLocal)
lock = reconstruct(b, units, ifr, (tn.entermonitor != null ? tn.entermonitor : tn.beginning), (tn.entermonitor != null));
}
if (!b.getLocals().contains(lockObj[tn.setNumber]))
b.getLocals().add(lockObj[tn.setNumber]);
newPrep = Jimple.v().newAssignStmt(lockObj[tn.setNumber], lock);
if (tn.wholeMethod)
units.insertBeforeNoRedirect(newPrep, firstUnit);
else
units.insertBefore(newPrep, tn.entermonitor);
clo = lockObj[tn.setNumber];
} else if (lock instanceof Local)
clo = (Local) lock;
else
throw new RuntimeException("Unknown type of lock (" + lock + "): expected Ref or Local");
csr = tn;
moreLocks = false;
} else if (tn.group.useLocksets) {
// adds
Value lock = getLockFor((EquivalentValue) tn.lockset.get(lockNum));
// needed
if (lock instanceof FieldRef) {
if (lock instanceof InstanceFieldRef) {
InstanceFieldRef ifr = (InstanceFieldRef) lock;
if (ifr.getBase() instanceof FakeJimpleLocal)
lock = reconstruct(b, units, ifr, (tn.entermonitor != null ? tn.entermonitor : tn.beginning), (tn.entermonitor != null));
}
// add a local variable for this lock
Local lockLocal = Jimple.v().newLocal("locksetObj" + tempNum, RefType.v("java.lang.Object"));
tempNum++;
b.getLocals().add(lockLocal);
// make it refer to the right lock object
newPrep = Jimple.v().newAssignStmt(lockLocal, lock);
if (tn.entermonitor != null)
units.insertBefore(newPrep, tn.entermonitor);
else
units.insertBeforeNoRedirect(newPrep, tn.beginning);
// use it as the lock
clo = lockLocal;
} else if (lock instanceof Local)
clo = (Local) lock;
else
throw new RuntimeException("Unknown type of lock (" + lock + "): expected FieldRef or Local");
if (lockNum + 1 >= tn.lockset.size())
moreLocks = false;
else
moreLocks = true;
if (lockNum > 0) {
SynchronizedRegion nsr = new SynchronizedRegion();
nsr.beginning = csr.beginning;
for (Pair earlyEnd : csr.earlyEnds) {
Stmt earlyExitmonitor = (Stmt) earlyEnd.getO2();
// <early
nsr.earlyEnds.add(new Pair(earlyExitmonitor, null));
// exitmonitor,
// null>
}
// last stmt before exception
nsr.last = csr.last;
// handling
if (csr.end != null) {
Stmt endExitmonitor = csr.end.getO2();
nsr.after = endExitmonitor;
}
csr = nsr;
} else
csr = tn;
} else // global lock
{
if (!addedLocalLockObj[tn.setNumber])
b.getLocals().add(lockObj[tn.setNumber]);
addedLocalLockObj[tn.setNumber] = true;
newPrep = Jimple.v().newAssignStmt(lockObj[tn.setNumber], Jimple.v().newStaticFieldRef(globalLockObj[tn.setNumber].makeRef()));
if (tn.wholeMethod)
units.insertBeforeNoRedirect(newPrep, firstUnit);
else
units.insertBefore(newPrep, tn.entermonitor);
clo = lockObj[tn.setNumber];
csr = tn;
moreLocks = false;
}
// monitorenter/monitorexit statements with new ones
if (true) {
// Remove old prep stmt
if (csr.prepStmt != null) {
// units.remove(clr.prepStmt); // seems to trigger bugs
// in code generation?
}
// Reuse old entermonitor or insert new one, and insert prep
Stmt newEntermonitor = Jimple.v().newEnterMonitorStmt(clo);
if (csr.entermonitor != null) {
units.insertBefore(newEntermonitor, csr.entermonitor);
// redirectTraps(b, clr.entermonitor, newEntermonitor);
// // EXPERIMENTAL
units.remove(csr.entermonitor);
csr.entermonitor = newEntermonitor;
// units.insertBefore(newEntermonitor, newPrep); //
// already inserted
// clr.prepStmt = newPrep;
} else {
units.insertBeforeNoRedirect(newEntermonitor, csr.beginning);
csr.entermonitor = newEntermonitor;
// units.insertBefore(newEntermonitor, newPrep); //
// already inserted
// clr.prepStmt = newPrep;
}
// For each early end, reuse or insert exitmonitor stmt
List<Pair<Stmt, Stmt>> newEarlyEnds = new ArrayList<Pair<Stmt, Stmt>>();
for (Pair<Stmt, Stmt> end : csr.earlyEnds) {
Stmt earlyEnd = end.getO1();
Stmt exitmonitor = end.getO2();
Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
if (exitmonitor != null) {
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
// seems
units.insertBefore(tmp, exitmonitor);
// to
// avoid
// code
// generation
// bugs?
}
units.insertBefore(newExitmonitor, exitmonitor);
// redirectTraps(b, exitmonitor, newExitmonitor); //
// EXPERIMENTAL
units.remove(exitmonitor);
newEarlyEnds.add(new Pair<Stmt, Stmt>(earlyEnd, newExitmonitor));
} else {
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
units.insertBefore(tmp, earlyEnd);
}
units.insertBefore(newExitmonitor, earlyEnd);
newEarlyEnds.add(new Pair<Stmt, Stmt>(earlyEnd, newExitmonitor));
}
}
csr.earlyEnds = newEarlyEnds;
// If fallthrough end, reuse or insert goto and exit
if (csr.after != null) {
Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
if (csr.end != null) {
Stmt exitmonitor = csr.end.getO2();
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
units.insertBefore(tmp, exitmonitor);
}
units.insertBefore(newExitmonitor, exitmonitor);
// redirectTraps(b, exitmonitor, newExitmonitor); //
// EXPERIMENTAL
units.remove(exitmonitor);
csr.end = new Pair<Stmt, Stmt>(csr.end.getO1(), newExitmonitor);
} else {
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
units.insertBefore(tmp, csr.after);
}
// steal
units.insertBefore(newExitmonitor, csr.after);
// jumps
// to
// end,
// send
// them
// to
// monitorexit
Stmt newGotoStmt = Jimple.v().newGotoStmt(csr.after);
units.insertBeforeNoRedirect(newGotoStmt, csr.after);
csr.end = new Pair<Stmt, Stmt>(newGotoStmt, newExitmonitor);
csr.last = newGotoStmt;
}
}
// If exceptional end, reuse it, else insert it and traps
Stmt newExitmonitor = Jimple.v().newExitMonitorStmt(clo);
if (csr.exceptionalEnd != null) {
Stmt exitmonitor = csr.exceptionalEnd.getO2();
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
units.insertBefore(tmp, exitmonitor);
}
units.insertBefore(newExitmonitor, exitmonitor);
units.remove(exitmonitor);
csr.exceptionalEnd = new Pair<Stmt, Stmt>(csr.exceptionalEnd.getO1(), newExitmonitor);
} else {
// insert after the last end
// last end stmt (not same as last
Stmt lastEnd = null;
// stmt)
if (csr.end != null) {
lastEnd = csr.end.getO1();
} else {
for (Pair earlyEnd : csr.earlyEnds) {
Stmt end = (Stmt) earlyEnd.getO1();
if (lastEnd == null || (units.contains(lastEnd) && units.contains(end) && units.follows(end, lastEnd)))
lastEnd = end;
}
}
if (// || !units.contains(clr.last))
csr.last == null)
// last stmt and last end are
csr.last = lastEnd;
// the same
if (lastEnd == null)
throw new RuntimeException("Lock Region has no ends! Where should we put the exception handling???");
// Add throwable
Local throwableLocal = Jimple.v().newLocal("throwableLocal" + (throwableNum++), RefType.v("java.lang.Throwable"));
b.getLocals().add(throwableLocal);
// Add stmts
Stmt newCatch = Jimple.v().newIdentityStmt(throwableLocal, Jimple.v().newCaughtExceptionRef());
if (csr.last == null)
throw new RuntimeException("WHY IS clr.last NULL???");
if (newCatch == null)
throw new RuntimeException("WHY IS newCatch NULL???");
units.insertAfter(newCatch, csr.last);
units.insertAfter(newExitmonitor, newCatch);
Stmt newThrow = Jimple.v().newThrowStmt(throwableLocal);
units.insertAfter(newThrow, newExitmonitor);
// Add traps
SootClass throwableClass = Scene.v().loadClassAndSupport("java.lang.Throwable");
b.getTraps().addFirst(Jimple.v().newTrap(throwableClass, newExitmonitor, newThrow, newCatch));
b.getTraps().addFirst(Jimple.v().newTrap(throwableClass, csr.beginning, lastEnd, newCatch));
csr.exceptionalEnd = new Pair<Stmt, Stmt>(newThrow, newExitmonitor);
}
}
lockNum++;
}
// deal with waits and notifys
{
for (Unit uNotify : tn.notifys) {
Stmt sNotify = (Stmt) uNotify;
Stmt newNotify = Jimple.v().newInvokeStmt(Jimple.v().newVirtualInvokeExpr(clo, sNotify.getInvokeExpr().getMethodRef().declaringClass().getMethod("void notifyAll()").makeRef(), Collections.EMPTY_LIST));
if (newPrep != null) {
Stmt tmp = (Stmt) newPrep.clone();
units.insertBefore(tmp, sNotify);
units.insertBefore(newNotify, tmp);
} else
units.insertBefore(newNotify, sNotify);
redirectTraps(b, sNotify, newNotify);
units.remove(sNotify);
}
// Replace base object of calls to wait with appropriate lockobj
for (Unit uWait : tn.waits) {
Stmt sWait = (Stmt) uWait;
// WHAT
((InstanceInvokeExpr) sWait.getInvokeExpr()).setBase(clo);
// LOCKS???
if (newPrep != null)
units.insertBefore((Stmt) newPrep.clone(), sWait);
}
}
}
}
use of soot.jimple.FieldRef in project soot by Sable.
the class LocalMustAliasAnalysis method flowThrough.
@Override
protected void flowThrough(HashMap<Value, Integer> in, Unit u, HashMap<Value, Integer> out) {
Stmt s = (Stmt) u;
out.clear();
out.putAll(in);
if (s instanceof DefinitionStmt) {
DefinitionStmt ds = (DefinitionStmt) s;
Value lhs = ds.getLeftOp();
Value rhs = ds.getRightOp();
if (rhs instanceof CastExpr) {
// un-box casted value
CastExpr castExpr = (CastExpr) rhs;
rhs = castExpr.getOp();
}
if ((lhs instanceof Local || (lhs instanceof FieldRef && this.localsAndFieldRefs.contains(new EquivalentValue(lhs)))) && lhs.getType() instanceof RefLikeType) {
if (rhs instanceof Local) {
// local-assignment - must be aliased...
Integer val = in.get(rhs);
if (val != null)
out.put(lhs, val);
} else if (rhs instanceof ThisRef) {
// ThisRef can never change; assign unique number
out.put(lhs, thisRefNumber());
} else if (rhs instanceof ParameterRef) {
// ParameterRef can never change; assign unique number
out.put(lhs, parameterRefNumber((ParameterRef) rhs));
} else {
// assign number for expression
out.put(lhs, numberOfRhs(rhs));
}
}
} else {
// which other kind of statement has def-boxes? hopefully none...
assert s.getDefBoxes().isEmpty();
}
}
use of soot.jimple.FieldRef in project soot by Sable.
the class UseChecker method caseAssignStmt.
public void caseAssignStmt(AssignStmt stmt) {
Value lhs = stmt.getLeftOp();
Value rhs = stmt.getRightOp();
Type tlhs = null;
if (lhs instanceof Local)
tlhs = this.tg.get((Local) lhs);
else if (lhs instanceof ArrayRef) {
ArrayRef aref = (ArrayRef) lhs;
Local base = (Local) aref.getBase();
// Try to force Type integrity. The left side must agree on the
// element type of the right side array reference.
ArrayType at = null;
Type tgType = this.tg.get(base);
if (tgType instanceof ArrayType)
at = (ArrayType) tgType;
else {
// is java.lang.Object
if (tgType == Scene.v().getObjectType() && rhs instanceof Local) {
Type rhsType = this.tg.get((Local) rhs);
if (rhsType instanceof PrimType) {
if (defs == null) {
defs = LocalDefs.Factory.newLocalDefs(jb);
uses = LocalUses.Factory.newLocalUses(jb, defs);
}
// Check the original type of the array from the alloc site
for (Unit defU : defs.getDefsOfAt(base, stmt)) {
if (defU instanceof AssignStmt) {
AssignStmt defUas = (AssignStmt) defU;
if (defUas.getRightOp() instanceof NewArrayExpr) {
at = (ArrayType) defUas.getRightOp().getType();
break;
}
}
}
}
}
if (at == null)
at = tgType.makeArrayType();
}
tlhs = ((ArrayType) at).getElementType();
this.handleArrayRef(aref, stmt);
aref.setBase((Local) this.uv.visit(aref.getBase(), at, stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
stmt.setLeftOp(this.uv.visit(lhs, tlhs, stmt));
} else if (lhs instanceof FieldRef) {
tlhs = ((FieldRef) lhs).getFieldRef().type();
if (lhs instanceof InstanceFieldRef)
this.handleInstanceFieldRef((InstanceFieldRef) lhs, stmt);
}
// They may have been changed above
lhs = stmt.getLeftOp();
rhs = stmt.getRightOp();
if (rhs instanceof Local)
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
else if (rhs instanceof ArrayRef) {
ArrayRef aref = (ArrayRef) rhs;
Local base = (Local) aref.getBase();
// try to force Type integrity
ArrayType at = null;
Type et = null;
if (this.tg.get(base) instanceof ArrayType)
at = (ArrayType) this.tg.get(base);
else {
Type bt = this.tg.get(base);
// For some fixed type T, we assume that we can fix the array to T[].
if (bt instanceof RefType || bt instanceof NullType) {
RefType rt = bt instanceof NullType ? null : (RefType) bt;
if (rt == null || rt.getSootClass().getName().equals("java.lang.Object") || rt.getSootClass().getName().equals("java.io.Serializable") || rt.getSootClass().getName().equals("java.lang.Cloneable")) {
if (defs == null) {
defs = LocalDefs.Factory.newLocalDefs(jb);
uses = LocalUses.Factory.newLocalUses(jb, defs);
}
outer: for (UnitValueBoxPair usePair : uses.getUsesOf(stmt)) {
Stmt useStmt = (Stmt) usePair.getUnit();
// from the callee's signature=
if (useStmt.containsInvokeExpr()) {
for (int i = 0; i < useStmt.getInvokeExpr().getArgCount(); i++) {
if (useStmt.getInvokeExpr().getArg(i) == usePair.getValueBox().getValue()) {
et = useStmt.getInvokeExpr().getMethod().getParameterType(i);
at = et.makeArrayType();
break outer;
}
}
} else // if the other value is a primitive.
if (useStmt instanceof IfStmt) {
IfStmt ifStmt = (IfStmt) useStmt;
if (ifStmt.getCondition() instanceof EqExpr) {
EqExpr expr = (EqExpr) ifStmt.getCondition();
final Value other;
if (expr.getOp1() == usePair.getValueBox().getValue())
other = expr.getOp2();
else
other = expr.getOp1();
Type newEt = getTargetType(other);
if (newEt != null)
et = newEt;
}
} else if (useStmt instanceof AssignStmt) {
// For binary expressions, we can look for type information in the
// other operands
AssignStmt useAssignStmt = (AssignStmt) useStmt;
if (useAssignStmt.getRightOp() instanceof BinopExpr) {
BinopExpr binOp = (BinopExpr) useAssignStmt.getRightOp();
final Value other;
if (binOp.getOp1() == usePair.getValueBox().getValue())
other = binOp.getOp2();
else
other = binOp.getOp1();
Type newEt = getTargetType(other);
if (newEt != null)
et = newEt;
}
} else if (useStmt instanceof ReturnStmt) {
et = jb.getMethod().getReturnType();
}
}
}
}
if (at == null)
at = et.makeArrayType();
}
Type trhs = ((ArrayType) at).getElementType();
this.handleArrayRef(aref, stmt);
aref.setBase((Local) this.uv.visit(aref.getBase(), at, stmt));
stmt.setRightOp(this.uv.visit(rhs, trhs, stmt));
} else if (rhs instanceof InstanceFieldRef) {
this.handleInstanceFieldRef((InstanceFieldRef) rhs, stmt);
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof BinopExpr)
this.handleBinopExpr((BinopExpr) rhs, stmt, tlhs);
else if (rhs instanceof InvokeExpr) {
this.handleInvokeExpr((InvokeExpr) rhs, stmt);
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof CastExpr)
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
else if (rhs instanceof InstanceOfExpr) {
InstanceOfExpr ioe = (InstanceOfExpr) rhs;
ioe.setOp(this.uv.visit(ioe.getOp(), RefType.v("java.lang.Object"), stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NewArrayExpr) {
NewArrayExpr nae = (NewArrayExpr) rhs;
nae.setSize(this.uv.visit(nae.getSize(), IntType.v(), stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NewMultiArrayExpr) {
NewMultiArrayExpr nmae = (NewMultiArrayExpr) rhs;
for (int i = 0; i < nmae.getSizeCount(); i++) nmae.setSize(i, this.uv.visit(nmae.getSize(i), IntType.v(), stmt));
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof LengthExpr) {
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
} else if (rhs instanceof NegExpr) {
((NegExpr) rhs).setOp(this.uv.visit(((NegExpr) rhs).getOp(), tlhs, stmt));
} else if (rhs instanceof Constant)
if (!(rhs instanceof NullConstant))
stmt.setRightOp(this.uv.visit(rhs, tlhs, stmt));
}
use of soot.jimple.FieldRef in project soot by Sable.
the class ConstantInitializerToTagTransformer method transformClass.
/**
* Transforms the given class, i.e. scans for a <clinit> method and
* generates new constant value tags for all constant assignments to static
* final fields.
*
* @param sc
* The class to transform
* @param removeAssignments
* True if the assignments inside the <clinit> method shall be
* removed, otherwise false
*/
public void transformClass(SootClass sc, boolean removeAssignments) {
// If this class has no <clinit> method, we're done
SootMethod smInit = sc.getMethodByNameUnsafe("<clinit>");
if (smInit == null || !smInit.isConcrete())
return;
Set<SootField> nonConstantFields = new HashSet<SootField>();
Map<SootField, ConstantValueTag> newTags = new HashMap<SootField, ConstantValueTag>();
// in case of
Set<SootField> removeTagList = new HashSet<SootField>();
for (Iterator<Unit> itU = smInit.getActiveBody().getUnits().snapshotIterator(); itU.hasNext(); ) {
Unit u = itU.next();
if (u instanceof AssignStmt) {
AssignStmt assign = (AssignStmt) u;
if (assign.getLeftOp() instanceof StaticFieldRef && assign.getRightOp() instanceof Constant) {
SootField field = null;
try {
field = ((StaticFieldRef) assign.getLeftOp()).getField();
if (field == null || nonConstantFields.contains(field))
continue;
} catch (ConflictingFieldRefException ex) {
// Ignore this statement
continue;
}
if (field.getDeclaringClass().equals(sc) && field.isStatic() && field.isFinal()) {
// Do we already have a constant value for this field?
boolean found = false;
for (Tag t : field.getTags()) {
if (t instanceof ConstantValueTag) {
if (checkConstantValue((ConstantValueTag) t, (Constant) assign.getRightOp())) {
// the assignment.
if (removeAssignments)
itU.remove();
} else {
logger.debug("" + "WARNING: Constant value for field '" + field + "' mismatch between code (" + assign.getRightOp() + ") and constant table (" + t + ")");
removeTagList.add(field);
}
found = true;
break;
}
}
if (!found) {
// tags.
if (!checkConstantValue(newTags.get(field), (Constant) assign.getRightOp())) {
nonConstantFields.add(field);
newTags.remove(field);
removeTagList.add(field);
continue;
}
ConstantValueTag newTag = createConstantTagFromValue((Constant) assign.getRightOp());
if (newTag != null)
newTags.put(field, newTag);
}
}
} else if (assign.getLeftOp() instanceof StaticFieldRef) {
// a non-constant is assigned to the field
try {
SootField sf = ((StaticFieldRef) assign.getLeftOp()).getField();
if (sf != null)
removeTagList.add(sf);
} catch (ConflictingFieldRefException ex) {
// let's assume that a broken field doesn't cause any
// harm
}
}
}
}
// Do the actual assignment
for (Entry<SootField, ConstantValueTag> entry : newTags.entrySet()) {
SootField field = entry.getKey();
if (removeTagList.contains(field))
continue;
field.addTag(entry.getValue());
}
if (removeAssignments && !newTags.isEmpty())
for (Iterator<Unit> itU = smInit.getActiveBody().getUnits().snapshotIterator(); itU.hasNext(); ) {
Unit u = itU.next();
if (u instanceof AssignStmt) {
AssignStmt assign = (AssignStmt) u;
if (assign.getLeftOp() instanceof FieldRef)
try {
SootField fld = ((FieldRef) assign.getLeftOp()).getField();
if (fld != null && newTags.containsKey(fld))
itU.remove();
} catch (ConflictingFieldRefException ex) {
// Ignore broken code
}
}
}
// remove constant tags
for (SootField sf : removeTagList) {
if (removeTagList.contains(sf)) {
List<Tag> toRemoveTagList = new ArrayList<Tag>();
for (Tag t : sf.getTags()) {
if (t instanceof ConstantValueTag) {
toRemoveTagList.add(t);
}
}
for (Tag t : toRemoveTagList) {
sf.getTags().remove(t);
}
}
}
}
Aggregations