All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sootup.java.bytecode.interceptors.TrapTightener Maven / Gradle / Ivy

There is a newer version: 1.3.0
Show newest version
package sootup.java.bytecode.interceptors;

/*-
 * #%L
 * Soot - a J*va Optimization Framework
 * %%
 * Copyright (C) 1997-2020 John Jorgensen, Zun Wang
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.util.*;
import javax.annotation.Nonnull;
import sootup.core.graph.BasicBlock;
import sootup.core.graph.MutableStmtGraph;
import sootup.core.graph.StmtGraph;
import sootup.core.jimple.basic.Trap;
import sootup.core.jimple.common.stmt.Stmt;
import sootup.core.jimple.javabytecode.stmt.JEnterMonitorStmt;
import sootup.core.jimple.javabytecode.stmt.JExitMonitorStmt;
import sootup.core.model.Body;
import sootup.core.transform.BodyInterceptor;
import sootup.core.types.ClassType;
import sootup.core.views.View;

/**
 * @author Zun Wang
 *     

description from Soot: A BodyTransformer that shrinks the protected area covered by each * Trap in the Body so that it begins at the first of the Body's Units which might throw an * exception caught by the Trap and ends just after the last Unit which might throw an exception * caught by the Trap. In the case where none of the Units protected by a Trap can throw the * exception it catches, the Trap's protected area is left completely empty, which will likely * cause the UnreachableCodeEliminator to remove the Trap(handler?) completely (if the * traphandler does not cover another range). The TrapTightener is used to reduce the risk of * unverifiable code which can result from the use of ExceptionalUnitGraphs from which * unrealizable exceptional control flow edges have been removed. */ public class TrapTightener implements BodyInterceptor { @Override public void interceptBody(@Nonnull Body.BodyBuilder builder, @Nonnull View view) { // FIXME: [ms] ThrowAnalysis is missing and in result mightThrow (...) makes no sense. Issue // #486 if (true) { return; } MutableStmtGraph graph = builder.getStmtGraph(); List stmtsInPrintOrder = builder.getStmts(); // collect stmts Set monitoredStmts = monitoredStmts(graph); Map> toRemove = new HashMap<>(); for (BasicBlock block : graph.getBlocks()) { for (Stmt stmt : block.getStmts()) { Collection removeForStmt = new ArrayList<>(); for (Map.Entry exception : block.getExceptionalSuccessors().entrySet()) { // FIXME: check for java9 modules signature, too! boolean isCatchAll = exception.getKey().getFullyQualifiedName().equals("java.lang.Throwable"); if ( /* mightThrow(graph, stmt, trap) || */ (isCatchAll && monitoredStmts.contains(stmt))) { // if it might throw or if trap is a catch-all block and the current stmt has an active // monitor, we need to keep the block removeForStmt.add(exception.getKey()); break; } } if (!removeForStmt.isEmpty()) { toRemove.put(stmt, removeForStmt); } } } // remove exceptions for stmts for (Map.Entry> entry : toRemove.entrySet()) { for (ClassType classType : entry.getValue()) { graph.removeExceptionalEdge(entry.getKey(), classType); } } // FIXME: check if there are traphandlers that have no predecessor } /** * Find out all monitored stmts from a given exceptional graph, collect them into a list * * @param graph a given exceptionalStmtGraph * @return a list of monitored stmts */ private Set monitoredStmts(@Nonnull StmtGraph graph) { Set monitoredStmts = new HashSet<>(); Deque queue = new ArrayDeque<>(); queue.add(graph.getStartingStmt()); Set visitedStmts = new HashSet<>(); while (!queue.isEmpty()) { Stmt stmt = queue.removeFirst(); visitedStmts.add(stmt); // enter a monitored block if (stmt instanceof JEnterMonitorStmt) { Deque monitoredQueue = new ArrayDeque<>(); monitoredQueue.add(stmt); while (!monitoredQueue.isEmpty()) { Stmt monitoredStmt = monitoredQueue.removeFirst(); monitoredStmts.add(monitoredStmt); visitedStmts.add(monitoredStmt); if (monitoredStmt instanceof JExitMonitorStmt) { queue.addAll(graph.getAllSuccessors(monitoredStmt)); } else { for (Stmt succ : graph.getAllSuccessors(monitoredStmt)) { if (!visitedStmts.contains(succ)) { monitoredQueue.add(succ); } } } } } else { queue.addAll(graph.getAllSuccessors(stmt)); } } return monitoredStmts; } /** * Check whether trap-destinations of the given stmt contain the given trap. * * @param graph is a exceptional StmtGraph * @param stmt is a stmt in the given graph * @param trap is a given trap * @return If trap-destinations of the given stmt contain the given trap, return true, otherwise * return false */ // FIXME: [ms] makes no sense in that Implementation! StmtGraph is not the legacy // ExceptionalUnitGraph private boolean mightThrow(@Nonnull StmtGraph graph, @Nonnull Stmt stmt, @Nonnull Trap trap) { final BasicBlock block = graph.getBlockOf(stmt); for (Map.Entry> dest : block.getExceptionalSuccessors().entrySet()) { final ClassType exceptionType = dest.getKey(); final BasicBlock traphandlerBlock = dest.getValue(); if (exceptionType.equals(trap.getExceptionType()) && traphandlerBlock.getHead().equals(trap.getHandlerStmt())) { return true; } } return false; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy