use of soot.ConflictingFieldRefException 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