use of soot.Body in project soot by Sable.
the class GroupIntPair method emitMethodBody.
@Override
protected void emitMethodBody(SootMethod method) {
if (Options.v().time())
Timers.v().buildJasminTimer.end();
Body activeBody = method.getActiveBody();
if (!(activeBody instanceof BafBody)) {
if (activeBody instanceof JimpleBody) {
if (Options.v().verbose()) {
logger.debug("Was expecting Baf body for " + method + " but found a Jimple body. Will convert body to Baf on the fly.");
}
activeBody = PackManager.v().convertJimpleBodyToBaf(method);
} else
throw new RuntimeException("method: " + method.getName() + " has an invalid active body!");
}
BafBody body = (BafBody) activeBody;
if (body == null)
throw new RuntimeException("method: " + method.getName() + " has no active body!");
if (Options.v().time())
Timers.v().buildJasminTimer.start();
Chain<Unit> instList = body.getUnits();
int stackLimitIndex = -1;
subroutineToReturnAddressSlot = new HashMap<Unit, Integer>(10, 0.7f);
// Determine the unitToLabel map
{
unitToLabel = new HashMap<Unit, String>(instList.size() * 2 + 1, 0.7f);
labelCount = 0;
for (UnitBox uBox : body.getUnitBoxes(true)) {
// Assign a label for each statement reference
{
InstBox box = (InstBox) uBox;
if (!unitToLabel.containsKey(box.getUnit()))
unitToLabel.put(box.getUnit(), "label" + labelCount++);
}
}
}
// Emit the exceptions, recording the Units at the beginning
// of handlers so that later on we can recognize blocks that
// begin with an exception on the stack.
Set<Unit> handlerUnits = new ArraySet<Unit>(body.getTraps().size());
{
for (Trap trap : body.getTraps()) {
handlerUnits.add(trap.getHandlerUnit());
if (trap.getBeginUnit() != trap.getEndUnit()) {
emit(".catch " + slashify(trap.getException().getName()) + " from " + unitToLabel.get(trap.getBeginUnit()) + " to " + unitToLabel.get(trap.getEndUnit()) + " using " + unitToLabel.get(trap.getHandlerUnit()));
}
}
}
// Determine where the locals go
{
int localCount = 0;
int[] paramSlots = new int[method.getParameterCount()];
int thisSlot = 0;
Set<Local> assignedLocals = new HashSet<Local>();
localToSlot = new HashMap<Local, Integer>(body.getLocalCount() * 2 + 1, 0.7f);
// assignColorsToLocals(body);
// Determine slots for 'this' and parameters
{
if (!method.isStatic()) {
thisSlot = 0;
localCount++;
}
for (int i = 0; i < method.getParameterCount(); i++) {
paramSlots[i] = localCount;
localCount += sizeOfType(method.getParameterType(i));
}
}
// Handle identity statements
{
for (Unit u : instList) {
Inst s = (Inst) u;
if (s instanceof IdentityInst && ((IdentityInst) s).getLeftOp() instanceof Local) {
Local l = (Local) ((IdentityInst) s).getLeftOp();
IdentityRef identity = (IdentityRef) ((IdentityInst) s).getRightOp();
int slot = 0;
if (identity instanceof ThisRef) {
if (method.isStatic())
throw new RuntimeException("Attempting to use 'this' in static method");
slot = thisSlot;
} else if (identity instanceof ParameterRef)
slot = paramSlots[((ParameterRef) identity).getIndex()];
else {
// Exception ref. Skip over this
continue;
}
localToSlot.put(l, new Integer(slot));
assignedLocals.add(l);
}
}
}
// Assign the rest of the locals
{
for (Local local : body.getLocals()) {
if (assignedLocals.add(local)) {
localToSlot.put(local, new Integer(localCount));
localCount += sizeOfType(local.getType());
}
}
if (!Modifier.isNative(method.getModifiers()) && !Modifier.isAbstract(method.getModifiers())) {
emit(" .limit stack ?");
stackLimitIndex = code.size() - 1;
emit(" .limit locals " + localCount);
}
}
}
// Emit code in one pass
{
isEmittingMethodCode = true;
maxStackHeight = 0;
isNextGotoAJsr = false;
for (Unit u : instList) {
Inst s = (Inst) u;
if (unitToLabel.containsKey(s))
emit(unitToLabel.get(s) + ":");
// emit this statement
{
emitInst(s);
}
}
isEmittingMethodCode = false;
// calculate max stack height
{
maxStackHeight = 0;
if (activeBody.getUnits().size() != 0) {
BlockGraph blockGraph = new BriefBlockGraph(activeBody);
List<Block> blocks = blockGraph.getBlocks();
if (blocks.size() != 0) {
// set the stack height of the entry points
List<Block> entryPoints = ((DirectedGraph<Block>) blockGraph).getHeads();
for (Block entryBlock : entryPoints) {
Integer initialHeight;
if (handlerUnits.contains(entryBlock.getHead())) {
initialHeight = new Integer(1);
} else {
initialHeight = new Integer(0);
}
if (blockToStackHeight == null) {
blockToStackHeight = new HashMap<Block, Integer>();
}
blockToStackHeight.put(entryBlock, initialHeight);
if (blockToLogicalStackHeight == null) {
blockToLogicalStackHeight = new HashMap<Block, Integer>();
}
blockToLogicalStackHeight.put(entryBlock, initialHeight);
}
// entryPoints list as roots
for (Block nextBlock : entryPoints) {
calculateStackHeight(nextBlock);
calculateLogicalStackHeightCheck(nextBlock);
}
}
}
}
if (!Modifier.isNative(method.getModifiers()) && !Modifier.isAbstract(method.getModifiers()))
code.set(stackLimitIndex, " .limit stack " + maxStackHeight);
}
// emit code attributes
{
for (Tag t : body.getTags()) {
if (t instanceof JasminAttribute) {
emit(".code_attribute " + t.getName() + " \"" + ((JasminAttribute) t).getJasminValue(unitToLabel) + "\"");
}
}
}
}
use of soot.Body in project soot by Sable.
the class DavaBody method clone.
public Object clone() {
Body b = Dava.v().newBody(getMethod());
b.importBodyContentsFrom(this);
return b;
}
use of soot.Body in project soot by Sable.
the class DavaStaticBlockCleaner method staticBlockInlining.
// invoked by the PackManager
public void staticBlockInlining(SootClass sootClass) {
this.sootClass = sootClass;
// the clinit method gets converted into the static block which could initialize the final variable
if (!sootClass.declaresMethod("void <clinit>()")) {
// System.out.println("no clinit");
return;
}
SootMethod clinit = sootClass.getMethod("void <clinit>()");
// retireve the active body
if (!clinit.hasActiveBody())
throw new RuntimeException("method " + clinit.getName() + " has no active body!");
Body clinitBody = clinit.getActiveBody();
Chain units = ((DavaBody) clinitBody).getUnits();
if (units.size() != 1) {
throw new RuntimeException("DavaBody AST doesn't have single root.");
}
ASTNode AST = (ASTNode) units.getFirst();
if (!(AST instanceof ASTMethodNode))
throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");
// running methodCallFinder on the Clinit method
AST.apply(new MethodCallFinder(this));
}
use of soot.Body in project soot by Sable.
the class BuildIntermediateAppClasses method internalTransform.
protected void internalTransform(String phaseName, Map<String, String> options) {
if (output) {
out.println("Building Intermediate Classes...");
}
BodyBuilder.retrieveAllBodies();
// iterate through application classes, build intermediate classes
Iterator<SootClass> it = Scene.v().getApplicationClasses().snapshotIterator();
while (it.hasNext()) {
List<SootMethod> initMethodsToRewrite = new ArrayList<>();
Map<String, SootMethod> methodsToAdd = new HashMap<>();
SootClass sc = it.next();
SootClass originalSuperclass = sc.getSuperclass();
if (output) {
out.println("Processing " + sc.getName() + " with super " + originalSuperclass.getName());
}
Iterator<SootMethod> methodIterator = sc.methodIterator();
while (methodIterator.hasNext()) {
SootMethod method = methodIterator.next();
if (!method.isConcrete()) {
continue;
}
try {
method.getActiveBody();
} catch (Exception e) {
if (method.retrieveActiveBody() == null)
throw new RuntimeException(method.getSignature() + " has no body. This was not expected dude.");
}
String subSig = method.getSubSignature();
if (subSig.equals("void main(java.lang.String[])") && method.isPublic() && method.isStatic()) {
// skip the main method - it needs to be named 'main'
continue;
} else if (subSig.indexOf("init>(") > 0) {
if (subSig.startsWith("void <init>(")) {
initMethodsToRewrite.add(method);
}
// skip constructors, just add for rewriting at the end
continue;
} else {
Scene.v().releaseActiveHierarchy();
findAccessibleInSuperClassesBySubSig(sc, subSig).ifPresent(m -> methodsToAdd.put(subSig, m));
}
}
if (methodsToAdd.size() > 0) {
final String fullName = ClassRenamer.v().getNewName(ClassRenamer.getPackageName(sc.getName()), null);
if (output) {
out.println("\tBuilding " + fullName);
}
// make non-final soot class
SootClass mediatingClass = new SootClass(fullName, sc.getModifiers() & (~Modifier.FINAL));
Main.IntermediateAppClasses.add(mediatingClass);
mediatingClass.setSuperclass(originalSuperclass);
Scene.v().addClass(mediatingClass);
mediatingClass.setApplicationClass();
mediatingClass.setInScene(true);
ThisRef thisRef = new ThisRef(mediatingClass.getType());
for (String subSig : methodsToAdd.keySet()) {
SootMethod originalSuperclassMethod = methodsToAdd.get(subSig);
List<Type> paramTypes = originalSuperclassMethod.getParameterTypes();
Type returnType = originalSuperclassMethod.getReturnType();
List<SootClass> exceptions = originalSuperclassMethod.getExceptions();
int modifiers = originalSuperclassMethod.getModifiers() & ~Modifier.ABSTRACT & ~Modifier.NATIVE;
SootMethod newMethod;
{
// build new junk method to call original method
String newMethodName = MethodRenamer.v().getNewName();
newMethod = Scene.v().makeSootMethod(newMethodName, paramTypes, returnType, modifiers, exceptions);
mediatingClass.addMethod(newMethod);
Body body = Jimple.v().newBody(newMethod);
newMethod.setActiveBody(body);
Chain<Local> locals = body.getLocals();
PatchingChain<Unit> units = body.getUnits();
BodyBuilder.buildThisLocal(units, thisRef, locals);
BodyBuilder.buildParameterLocals(units, locals, paramTypes);
if (returnType instanceof VoidType) {
units.add(Jimple.v().newReturnVoidStmt());
} else if (returnType instanceof PrimType) {
units.add(Jimple.v().newReturnStmt(IntConstant.v(0)));
} else {
units.add(Jimple.v().newReturnStmt(NullConstant.v()));
}
newmethods++;
}
// end build new junk method to call original method
{
// build copy of old method
newMethod = Scene.v().makeSootMethod(originalSuperclassMethod.getName(), paramTypes, returnType, modifiers, exceptions);
mediatingClass.addMethod(newMethod);
Body body = Jimple.v().newBody(newMethod);
newMethod.setActiveBody(body);
Chain<Local> locals = body.getLocals();
PatchingChain<Unit> units = body.getUnits();
Local ths = BodyBuilder.buildThisLocal(units, thisRef, locals);
List<Local> args = BodyBuilder.buildParameterLocals(units, locals, paramTypes);
SootMethodRef superclassMethodRef = originalSuperclassMethod.makeRef();
if (returnType instanceof VoidType) {
units.add(Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(ths, superclassMethodRef, args)));
units.add(Jimple.v().newReturnVoidStmt());
} else {
Local loc = Jimple.v().newLocal("retValue", returnType);
body.getLocals().add(loc);
units.add(Jimple.v().newAssignStmt(loc, Jimple.v().newSpecialInvokeExpr(ths, superclassMethodRef, args)));
units.add(Jimple.v().newReturnStmt(loc));
}
newmethods++;
}
// end build copy of old method
}
sc.setSuperclass(mediatingClass);
// rewrite class init methods to call the proper superclass inits
int i = initMethodsToRewrite.size();
while (i-- > 0) {
SootMethod im = initMethodsToRewrite.remove(i);
Body b = im.getActiveBody();
Local thisLocal = b.getThisLocal();
Iterator<Unit> uIt = b.getUnits().snapshotIterator();
while (uIt.hasNext()) {
for (ValueBox valueBox : uIt.next().getUseBoxes()) {
Value v = valueBox.getValue();
if (v instanceof SpecialInvokeExpr) {
SpecialInvokeExpr sie = (SpecialInvokeExpr) v;
SootMethodRef smr = sie.getMethodRef();
if (sie.getBase().equivTo(thisLocal) && smr.declaringClass().getName().equals(originalSuperclass.getName()) && smr.getSubSignature().getString().startsWith("void " + constructorName)) {
SootMethod newSuperInit;
if (!mediatingClass.declaresMethod(constructorName, smr.parameterTypes())) {
List<Type> paramTypes = smr.parameterTypes();
newSuperInit = Scene.v().makeSootMethod(constructorName, paramTypes, smr.returnType());
mediatingClass.addMethod(newSuperInit);
JimpleBody body = Jimple.v().newBody(newSuperInit);
newSuperInit.setActiveBody(body);
PatchingChain<Unit> initUnits = body.getUnits();
Collection<Local> locals = body.getLocals();
Local ths = BodyBuilder.buildThisLocal(initUnits, thisRef, locals);
List<Local> args = BodyBuilder.buildParameterLocals(initUnits, locals, paramTypes);
initUnits.add(Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(ths, smr, args)));
initUnits.add(Jimple.v().newReturnVoidStmt());
} else {
newSuperInit = mediatingClass.getMethod(constructorName, smr.parameterTypes());
}
sie.setMethodRef(newSuperInit.makeRef());
}
}
}
}
}
// end of rewrite class init methods to call the proper superclass inits
}
}
newclasses = Main.IntermediateAppClasses.size();
Scene.v().releaseActiveHierarchy();
Scene.v().getActiveHierarchy();
Scene.v().setFastHierarchy(new FastHierarchy());
}
use of soot.Body in project soot by Sable.
the class CollectConstants method addInitializingValue.
private void addInitializingValue(SootClass sc, SootField f, Constant constant) {
if (constant instanceof NullConstant) {
return;
} else if (constant instanceof IntConstant) {
if (((IntConstant) constant).value == 0)
return;
} else if (constant instanceof LongConstant) {
if (((LongConstant) constant).value == 0)
return;
} else if (constant instanceof StringConstant) {
if (((StringConstant) constant).value == null)
return;
} else if (constant instanceof DoubleConstant) {
if (((DoubleConstant) constant).value == 0)
return;
} else if (constant instanceof FloatConstant) {
if (((FloatConstant) constant).value == 0)
return;
}
Body b;
boolean newInit = false;
if (!sc.declaresMethodByName(SootMethod.staticInitializerName)) {
SootMethod m = Scene.v().makeSootMethod(SootMethod.staticInitializerName, emptyList(), VoidType.v(), Modifier.STATIC);
sc.addMethod(m);
b = Jimple.v().newBody(m);
m.setActiveBody(b);
newInit = true;
} else {
SootMethod m = sc.getMethodByName(SootMethod.staticInitializerName);
if (!m.hasActiveBody()) {
b = Jimple.v().newBody(m);
m.setActiveBody(b);
newInit = true;
} else {
b = m.getActiveBody();
}
}
PatchingChain<Unit> units = b.getUnits();
units.addFirst(Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(f.makeRef()), constant));
if (newInit)
units.addLast(Jimple.v().newReturnVoidStmt());
}
Aggregations