View Javadoc

1   /* Soot - a J*va Optimization Framework
2    * Copyright (C) 1999 Patrick Lam
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, write to the
16   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17   * Boston, MA 02111-1307, USA.
18   */
19  
20  /*
21   * Modified by the Sable Research Group and others 1997-1999.  
22   * See the 'credits' file distributed with Soot for the complete list of
23   * contributors.  (Soot is distributed at http://www.sable.mcgill.ca/soot)
24   */
25  
26  
27  package org.kit.furia.fragment.soot.representation;
28  import soot.options.*;
29  
30  import soot.*;
31  import soot.jimple.*;
32  import soot.jimple.internal.*;
33  import soot.shimple.ShimpleBody;
34  import soot.tagkit.CodeAttribute;
35  import soot.tagkit.Tag;
36  import java.util.*;
37  
38  /** Implementation of the Body class for the Grimp IR. */
39  public class FrimpBody extends StmtBody
40  {
41      /**
42  	 * 
43  	 */
44  	private static final long serialVersionUID = -559420704371577505L;
45  
46  
47  	/**
48          Construct an empty GrimpBody 
49       **/
50       
51      FrimpBody(SootMethod m)
52      {
53          super(m);
54      }
55  
56      public Object clone()
57      {
58          Body b = Frimp.v().newBody(getMethod());
59          b.importBodyContentsFrom(this);
60          return b;
61      }
62  
63      /**
64          Constructs a GrimpBody from the given Body.
65       */
66  
67      public FrimpBody(Body body)
68      {
69          super(body.getMethod());
70  
71          if(Options.v().verbose())
72              G.v().out.println("[" + getMethod().getName() + "] Constructing FrimpBody...");
73  
74          if(! (body instanceof ShimpleBody || body instanceof JimpleBody))
75              throw new RuntimeException("Can only construct FrimpBody's from ShimpleBody (for now)"); // NOPMD by amuller on 11/16/06 4:07 PM
76  
77          Body jBody = body;
78  
79        
80         
81          Iterator it = jBody.getLocals().iterator();
82          while (it.hasNext())
83              getLocals().add(((Local)(it.next())));
84              //            getLocals().add(((Local)(it.next())).clone());
85  
86          it = jBody.getUnits().iterator();
87  
88          final HashMap oldToNew = new HashMap(getUnits().size() * 2 + 1, 0.7f);
89          LinkedList updates = new LinkedList();
90  
91          /* we should Frimpify (* x *) the Stmt's here... */
92          while (it.hasNext())
93          {
94              Stmt oldStmt = (Stmt)(it.next());
95              final StmtBox newStmtBox = (StmtBox) Frimp.v().newStmtBox(null);
96              final StmtBox updateStmtBox = (StmtBox) Frimp.v().newStmtBox(null);
97  
98              /* we can't have a general StmtSwapper on Grimp.v() */
99              /* because we need to collect a list of updates */
100             oldStmt.apply(new AbstractStmtSwitch()
101             {
102                 public void caseAssignStmt(AssignStmt s)
103                 {
104                     newStmtBox.setUnit(Frimp.v().newAssignStmt(s));
105                 }
106                 public void caseIdentityStmt(IdentityStmt s)
107                   {
108                     newStmtBox.setUnit(Frimp.v().newIdentityStmt(s));
109                 }
110                 public void caseBreakpointStmt(BreakpointStmt s)
111                 {
112                     newStmtBox.setUnit(Frimp.v().newBreakpointStmt(s));
113                 }
114                 public void caseInvokeStmt(InvokeStmt s)
115                 {
116                     newStmtBox.setUnit(Frimp.v().newInvokeStmt(s));
117                 }
118                 public void caseEnterMonitorStmt(EnterMonitorStmt s)
119                 {
120                     newStmtBox.setUnit(Frimp.v().newEnterMonitorStmt(s));
121                 }
122                 public void caseExitMonitorStmt(ExitMonitorStmt s)
123                 {
124                     newStmtBox.setUnit(Frimp.v().newExitMonitorStmt(s));
125                 }
126                 public void caseGotoStmt(GotoStmt s)
127                 {
128                     newStmtBox.setUnit(Frimp.v().newGotoStmt(s));
129                     updateStmtBox.setUnit(s);
130                 }
131                 public void caseIfStmt(IfStmt s)
132                 {
133                     newStmtBox.setUnit(Frimp.v().newIfStmt(s));
134                     updateStmtBox.setUnit(s);
135                 }
136                 public void caseLookupSwitchStmt(LookupSwitchStmt s)
137                 {
138                     newStmtBox.setUnit(Frimp.v().newLookupSwitchStmt(s));
139                     updateStmtBox.setUnit(s);
140                 }
141                 public void caseNopStmt(NopStmt s)
142                 {
143                     newStmtBox.setUnit(Frimp.v().newNopStmt(s));
144                 }
145 
146                 public void caseReturnStmt(ReturnStmt s)
147                 {
148                     newStmtBox.setUnit(Frimp.v().newReturnStmt(s));
149                 }
150                 public void caseReturnVoidStmt(ReturnVoidStmt s)
151                 {
152                     newStmtBox.setUnit(Frimp.v().newReturnVoidStmt(s));
153                 }
154                 public void caseTableSwitchStmt(TableSwitchStmt s)
155                 {
156                     newStmtBox.setUnit(Frimp.v().newTableSwitchStmt(s));
157                     updateStmtBox.setUnit(s);
158                 }
159                 public void caseThrowStmt(ThrowStmt s)
160                 {
161                     newStmtBox.setUnit(Frimp.v().newThrowStmt(s));
162                 }
163             });
164 
165             /* map old Expr's to new Expr's. */
166             Stmt newStmt = (Stmt)(newStmtBox.getUnit());
167             Iterator useBoxesIt;
168             useBoxesIt = newStmt.getUseBoxes().iterator();
169             while(useBoxesIt.hasNext())
170                 {
171                     ValueBox b = (ValueBox) (useBoxesIt.next());
172                     b.setValue(Frimp.v().newExpr(b.getValue()));
173                 }
174             useBoxesIt = newStmt.getDefBoxes().iterator();
175             while(useBoxesIt.hasNext())
176                 {
177                     ValueBox b = (ValueBox) (useBoxesIt.next());
178                     b.setValue(Frimp.v().newExpr(b.getValue()));
179                 }
180 
181             getUnits().add(newStmt);
182             oldToNew.put(oldStmt, newStmt);
183             if (updateStmtBox.getUnit() != null)
184                 updates.add(updateStmtBox.getUnit());
185         }
186 
187         /* fixup stmt's which have had moved targets */
188         it = updates.iterator();
189         while (it.hasNext())
190         {
191             Stmt stmt = (Stmt)(it.next());
192 
193             stmt.apply(new AbstractStmtSwitch()
194             {
195                 public void caseGotoStmt(GotoStmt s)
196                 {
197                     GotoStmt newStmt = (GotoStmt)(oldToNew.get(s));
198                     newStmt.setTarget((Stmt)oldToNew.get(newStmt.getTarget()));
199                 }
200                 public void caseIfStmt(IfStmt s)
201                 {
202                     IfStmt newStmt = (IfStmt)(oldToNew.get(s));
203                     newStmt.setTarget((Stmt)oldToNew.get(newStmt.getTarget()));
204                 }
205                 public void caseLookupSwitchStmt(LookupSwitchStmt s)
206                 {
207                     LookupSwitchStmt newStmt = 
208                         (LookupSwitchStmt)(oldToNew.get(s));
209                     newStmt.setDefaultTarget
210                         ((Unit)(oldToNew.get(newStmt.getDefaultTarget())));
211                     Unit[] newTargList = new Unit[newStmt.getTargetCount()];
212                     for (int i = 0; i < newStmt.getTargetCount(); i++)
213                         newTargList[i] = (Unit)(oldToNew.get
214                                                 (newStmt.getTarget(i)));
215                     newStmt.setTargets(newTargList);
216                 }
217                 public void caseTableSwitchStmt(TableSwitchStmt s)
218                 {
219                     TableSwitchStmt newStmt = 
220                         (TableSwitchStmt)(oldToNew.get(s));
221                     newStmt.setDefaultTarget
222                         ((Unit)(oldToNew.get(newStmt.getDefaultTarget())));
223                     int tc = newStmt.getHighIndex() - newStmt.getLowIndex()+1;
224                     LinkedList newTargList = new LinkedList();
225                     for (int i = 0; i < tc; i++)
226                         newTargList.add(oldToNew.get
227                                         (newStmt.getTarget(i)));
228                     newStmt.setTargets(newTargList);
229                 }
230             });
231         }
232 
233         it = jBody.getTraps().iterator();
234         while (it.hasNext())
235         {
236             Trap oldTrap = (Trap)(it.next());
237             getTraps().add(Frimp.v().newTrap
238                            (oldTrap.getException(),
239                             (Unit)(oldToNew.get(oldTrap.getBeginUnit())),
240                             (Unit)(oldToNew.get(oldTrap.getEndUnit())),
241                             (Unit)(oldToNew.get(oldTrap.getHandlerUnit()))));
242         }
243         
244 
245     }
246     
247     
248     /**
249      * Returns the result of iterating through all Units in this body
250      * and querying them for their UnitBoxes.  All UnitBoxes thus
251      * found are returned.  Branching Units and statements which use
252      * PhiExpr will have UnitBoxes; a UnitBox contains a Unit that is
253      * either a target of a branch or is being used as a pointer to
254      * the end of a CFG block.
255      *
256      * <p> This method is typically used for pointer patching, eg when
257      * the unit chain is cloned.
258      *
259      * @return A list of all the UnitBoxes held by this body's units.
260      * @see UnitBox
261      * @see #getUnitBoxes(boolean)
262      * @see Unit#getUnitBoxes()
263      * @see soot.shimple.PhiExpr#getUnitBoxes()
264      **/
265     public List getAllUnitBoxes()
266     {
267         ArrayList unitBoxList = new ArrayList();
268         {
269             Iterator it = unitChain.iterator();
270             while(it.hasNext()) {
271                 Unit item = (Unit) it.next();
272                 assert  item.getUnitBoxes() !=null: "This item returns null unitboxes: " + item + "\n class: " + item.getClass().getName();
273                 unitBoxList.addAll(item.getUnitBoxes());
274             }
275         }
276 
277         {
278             Iterator it = trapChain.iterator();
279             while(it.hasNext()) {
280                 Trap item = (Trap) it.next();
281                 unitBoxList.addAll(item.getUnitBoxes());
282             }
283         }
284 
285         {
286             Iterator it = getTags().iterator();
287             while(it.hasNext()) {
288                 Tag t = (Tag) it.next();
289                 if( t instanceof CodeAttribute)
290                     unitBoxList.addAll(((CodeAttribute) t).getUnitBoxes());
291             }
292         }
293 
294         return unitBoxList;
295     }
296     
297 }