00001 package edu.ksu.cis.bandera.jjjc.decompiler;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import java.util.*;
00036 import ca.mcgill.sable.soot.*;
00037 import ca.mcgill.sable.soot.jimple.*;
00038 import edu.ksu.cis.bandera.annotation.*;
00039 import edu.ksu.cis.bandera.abstraction.*;
00040 import edu.ksu.cis.bandera.abstraction.util.*;
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 public class DecompilerUtil {
00052 private static Hashtable assignedVar = new Hashtable();
00053 public static final String gotoStr = "$.goto";
00054 private static Hashtable tempTable = new Hashtable();
00055 private static boolean debugInfo = false;
00056 private static boolean allowField = false;
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 public static String analyzeCondition(Stmt[] stmts, int code)
00068 {
00069 Vector result = new Vector();
00070 if (stmts==null) return "";
00071 String thenID, elseID;
00072
00073 Hashtable condTable = new Hashtable();
00074 int max = stmts.length;
00075 Hashtable asgInIf = new Hashtable();
00076
00077
00078
00079 for (int i = 0; i < max; i++)
00080 {
00081 switch (code)
00082 {
00083
00084 case 1: DecompilerValueSwitch.isAnIfStmt(true); break;
00085 }
00086
00087 Vector res = DecompilerStmtSwitch.evaluate(stmts[i]);
00088 DecompilerStmtSwitch.reset();
00089
00090
00091 if (((String) res.get(0)).equals("if"))
00092 {
00093 String ref = ((String) res.get(res.size() - 1)).trim();
00094 Stmt s = DecompilerGotoMapper.getStmt(ref);
00095
00096
00097 replaceOccurence(res, tempTable);
00098
00099
00100
00101 if (!asgInIf.isEmpty())
00102 {
00103 int j = res.size();
00104 for (int it = 0; it < j; it++)
00105 {
00106 String id = (String) res.get(it);
00107 if (asgInIf.containsKey(id))
00108 {
00109
00110 String tempStr = (String) asgInIf.get(id);
00111 res.set(it,"("+id+" = "+tempStr+")");
00112 }
00113 }
00114 }
00115
00116 String cond = fixScrewedUpThis(extractCondition(res));
00117 result.add(cond);
00118 } else
00119 {
00120
00121 if (isAssignment(res))
00122 {
00123 Vector lhs = extractLHS(res);
00124 Vector rhs = extractRHS(res);
00125 replaceOccurence(rhs, tempTable);
00126 String right = fixScrewedUpThis(flattenToString(rhs));
00127 String left = flattenToString(lhs);
00128 right = stripImports(right);
00129
00130 if (!isAllJimpleTemp(lhs))
00131 {
00132 replaceOccurence(lhs, tempTable);
00133 left = fixScrewedUpThis(flattenToString(lhs));
00134 asgInIf.put(left, right);
00135 assignedVar.put(left, right);
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 } else
00162 {
00163 tempTable.put(left, right);
00164 }
00165 } else
00166 {
00167 if (!(stmts[i] instanceof GotoStmt))
00168 System.out.println("Error in processing condition in method "+DecompilerInfo.getMethodName());
00169 }
00170 }
00171 }
00172 if (result.size()==0)
00173 {
00174
00175
00176
00177
00178
00179
00180 return "(true)";
00181 }
00182 if (result.size()>1)
00183 {
00184 StringBuffer buf = new StringBuffer();
00185 buf.append("(");
00186 max = result.size();
00187
00188 for (int i=0; i<max; i++)
00189 {
00190 buf.append((String) result.get(i));
00191 if (i<(max-1)) buf.append(" && ");
00192 }
00193 buf.append(")");
00194 return (buf.toString());
00195 }
00196 return flattenToString(result);
00197 }
00198 public static Vector dumpStmt(Stmt[] s)
00199 {
00200 if ((s == null) || !isDebugInfo()) return new Vector();
00201 int max = s.length;
00202 Vector result = new Vector();
00203
00204 result.add("");
00205 result.add("/*");
00206 result.add(" Jimple trace:");
00207
00208 for (int i=0; i<max; i++)
00209 {
00210 if (s[i] instanceof JIfStmt)
00211 {
00212 String x = DecompilerGotoMapper.mapStmt(((JIfStmt) s[i]).getTarget());
00213 result.add(" "+s[i].toString()+x);
00214 } else
00215 result.add(" "+s[i].toString());
00216 }
00217 result.add("*/");
00218 return result;
00219 }
00220 private static String extractCondition(Vector x)
00221 { Vector temp = (Vector) x.clone();
00222
00223 temp.removeElementAt(0);
00224 temp.removeElementAt(temp.size() - 1);
00225 temp.removeElementAt(temp.size() - 1);
00226 temp.removeElementAt(temp.size() - 1);
00227
00228 return flattenToString(temp).trim();
00229 }
00230 private static Vector extractLHS(Vector x)
00231 {
00232 int eqpos = getEqPos(x);
00233 Vector res = new Vector();
00234
00235 for (int i=0; i<eqpos; i++)
00236 {
00237 res.add(x.get(i));
00238 }
00239 return res;
00240 }
00241 private static Vector extractRHS(Vector x)
00242 {
00243 int eqpos = getEqPos(x);
00244 int max = x.size();
00245 Vector res = new Vector();
00246
00247 for (int i=eqpos+1; i<max; i++)
00248 {
00249 res.add(x.get(i));
00250 }
00251 return res;
00252 }
00253 private static String fixScrewedUpThis(String s)
00254 {
00255 int screwedUpThis = s.indexOf("this()");
00256 if (screwedUpThis>-1)
00257 {
00258 String prefix = s.substring(0,screwedUpThis);
00259 String postfix = s.substring(screwedUpThis+6);
00260 s = prefix+"this"+postfix;
00261 }
00262 return s;
00263 }
00264
00265
00266
00267
00268
00269
00270 public static Vector flattenStmts(Stmt[] stmts)
00271 {
00272 Vector result = new Vector();
00273 if (stmts == null || stmts.length == 0) return result;
00274 String cond = "";
00275 int max = stmts.length;
00276
00277
00278 for (int i = 0; i < max; i++)
00279 {
00280
00281 if (stmts[i] instanceof GotoStmt) continue;
00282 Vector res = DecompilerStmtSwitch.evaluate(stmts[i]);
00283 DecompilerStmtSwitch.reset();
00284
00285
00286
00287 if ((res.size()>0) && (((String) res.get(0)).equals("if")))
00288 {
00289 replaceOccurence(res, tempTable);
00290 cond = fixScrewedUpThis(extractCondition(res));
00291
00292 if (cond.indexOf("quantification") != -1 || cond.indexOf("choose()") != -1)
00293 {
00294 int eq2null = cond.lastIndexOf("!= null");
00295
00296 if (eq2null != -1)
00297 {
00298 result.add("if "+cond.substring(0,eq2null)+" == null)");
00299 } else if (cond.indexOf("choose()") != -1)
00300 {
00301
00302 result.add("if (Bandera.choose())");
00303 } else
00304 {
00305 System.out.println("Warning: Can't handle condition '"+cond+"'");
00306 }
00307 cond = "";
00308 }
00309 } else
00310 if (isAssignment(res))
00311 {
00312 Vector lhs = extractLHS(res);
00313 Vector rhs = extractRHS(res);
00314 replaceOccurence(rhs, tempTable);
00315 String right = flattenToString(rhs);
00316 String left = flattenToString(lhs);
00317
00318 if (right.equals("@this")) right="this";
00319
00320
00321 right = stripImports(right);
00322
00323
00324 if (!right.equals("@caughtexception"))
00325 {
00326 if (!isAllJimpleTemp(lhs) && left.indexOf("qtvar") == -1)
00327 {
00328 replaceOccurence(lhs, tempTable);
00329 left = flattenToString(lhs);
00330
00331
00332 if ((DecompilerInfo.isInitializer()) && (DecompilerInfo.isField(left)) &&
00333 (DecompilerInfo.getNoOfParam()==0) && (isAllowField()))
00334 {
00335 DecompilerInfo.setFieldDefaultValue(left, right);
00336 } else
00337 {
00338 left = fixScrewedUpThis(left);
00339 right = fixScrewedUpThis(right);
00340
00341
00342 String isDef = (String) assignedVar.get(left);
00343 if (isDef != null)
00344 {
00345 if (cond.length()>0)
00346 {
00347 right = cond + " ? " + right + " : " + isDef;
00348 cond = "";
00349 }
00350 }
00351
00352 assignedVar.put(left,right);
00353 result.add(left + " = " + right + ";");
00354 }
00355 } else
00356 {
00357
00358 String isDef = (String) tempTable.get(left);
00359 if (isDef != null)
00360 {
00361 if (cond.length()>0)
00362 {
00363 right = cond + " ? " + right + " : " + isDef;
00364 cond = "";
00365 }
00366 }
00367 tempTable.put(left, right);
00368 }
00369 }
00370 } else
00371 {
00372 String firstToken = "", secondToken = "";
00373
00374 if (res.size()>2)
00375 {
00376 firstToken = (String) res.get(0);
00377 secondToken = (String) res.get(1);
00378 }
00379
00380
00381 if (secondToken.equals("("))
00382 {
00383 if (isJimpleID(firstToken))
00384 {
00385 res.removeElementAt(0);
00386 replaceOccurence(res,tempTable);
00387 secondToken = ((String) tempTable.get(firstToken))+flattenToString(res);
00388 tempTable.put(firstToken,secondToken);
00389 } else
00390 {
00391 String workAround = (String) assignedVar.get(firstToken);
00392 if (workAround!=null)
00393 {
00394 res.removeElementAt(0);
00395 replaceOccurence(res,tempTable);
00396 secondToken = workAround+flattenToString(res);
00397 assignedVar.put(firstToken,secondToken);
00398 }
00399 }
00400 } else
00401 {
00402 replaceOccurence(res, tempTable);
00403 String s = stripImports(flattenToString(res));
00404 s = fixScrewedUpThis(s);
00405
00406
00407 if ((!s.equals("this()")) && (s.length()>0))
00408 {
00409 if (DecompilerInfo.getMethodRetType().equals("boolean"))
00410 {
00411 if (s.equals("return 1")) s = "return true"; else
00412 if (s.equals("return 0")) s = "return false"; else
00413 if (s.startsWith("return") && s.endsWith("? 1 : 0"))
00414 {
00415 s = s.substring(0,s.length()-8).trim();
00416 }
00417 }
00418 int bizzareBugPos = s.indexOf("? 1 : 0");
00419 if (bizzareBugPos != -1 && s.indexOf("quantification") == -1)
00420 {
00421 s = s.substring(0,bizzareBugPos)+s.substring(bizzareBugPos+7);
00422 }
00423 result.add(s + ";");
00424 }
00425 }
00426 }
00427 }
00428 return result;
00429 }
00430 public static String flattenToString(Vector x)
00431 {
00432 if (x == null) return "";
00433 StringBuffer buf = new StringBuffer();
00434 int max = x.size();
00435
00436 for (int i=0; i<max; i++)
00437 {
00438 buf.append((String) x.get(i));
00439 }
00440 return buf.toString().trim();
00441 }
00442 public static Hashtable getAssignedVarTable()
00443 {
00444
00445
00446 return assignedVar;
00447 }
00448 private static int getEqPos(Vector x)
00449 {
00450 if (x.contains("=")) return x.indexOf("=");
00451 if (x.contains(":=")) return x.indexOf(":=");
00452 return -1;
00453 }
00454 private static int getJimpleVarID(String str)
00455 {
00456 return Integer.parseInt(str.substring(9));
00457 }
00458 private static int getParamID(String x)
00459 {
00460 return Integer.parseInt(x.substring(10));
00461 }
00462 public static Hashtable getTempTable() { return tempTable; }
00463 private static int howManyIfs(Stmt[] stmts)
00464 {
00465 int result = 0;
00466 int max = stmts.length;
00467
00468 for (int i = 0; i<max; i++)
00469 {
00470 if (stmts[i] instanceof IfStmt) result++;
00471 }
00472
00473 return result;
00474 }
00475
00476
00477
00478
00479 public static boolean isAbstracted(Abstraction lt) {
00480 return (((lt instanceof IntegralAbstraction) && !(lt instanceof ConcreteIntegralAbstraction)) ||
00481 ((lt instanceof RealAbstraction) && !(lt instanceof ConcreteRealAbstraction)));
00482 }
00483 private static boolean isAllJimpleTemp(Vector x)
00484 {
00485 int max = x.size();
00486
00487 for (int i = 0; i<max; i++)
00488 {
00489 String s = ((String) x.get(i)).trim();
00490 if ((s.length()>0) && (!isJimpleID(s))) return false;
00491 }
00492 return true;
00493 }
00494
00495
00496
00497
00498 public static boolean isAllowField() {
00499 return allowField;
00500 }
00501 private static boolean isAssignment(Vector x)
00502 {
00503 return x.contains("=") || x.contains(":=");
00504 }
00505
00506
00507
00508
00509 public static boolean isDebugInfo() {
00510 return debugInfo;
00511 }
00512 public static boolean isEmptyAnnotation(Annotation a)
00513 {
00514 if (a==null) return true;
00515 Stmt[] stmts = a.getStatements();
00516
00517 if (stmts.length>1) return false;
00518 if (stmts.length==0) return true;
00519 if (stmts[0] instanceof NopStmt) return true;
00520
00521 return false;
00522 }
00523 public static boolean isJimpleID(String id)
00524 {
00525 return ((id.startsWith("JJJCTEMP$")) || (id.startsWith("$ret")) || (id.startsWith("SLABS$")));
00526 }
00527 private static void replaceOccurence(Vector x, Hashtable table)
00528 {
00529 if (table==null) return;
00530 int max = x.size();
00531
00532 for(int i=0; i<max; i++)
00533 {
00534 String id = (String) x.get(i);
00535 if (isJimpleID(id) || id.indexOf("qtvar") != -1)
00536 {
00537 if (table.containsKey(id))
00538 {
00539
00540 String tok = (String) table.get(id);
00541
00542
00543
00544 if ((tok.startsWith("new ")) && (i<(max-1)))
00545 {
00546 String nextTok = (String) x.get(i+1);
00547 if (nextTok.equals(".")) tok = "(" + tok + ")";
00548 }
00549 x.set(i,tok);
00550 } else
00551 {
00552
00553 if (id.equals("JJJCTEMP$0"))
00554 {
00555 x.set(i, "this");
00556 } else
00557 System.out.println("Slabs error: Can't find temp variable "+id+" in method "+DecompilerInfo.getMethodName());
00558 }
00559 }
00560 }
00561 }
00562 public static void resetAssignedVar()
00563 {
00564 assignedVar = new Hashtable();
00565 }
00566 public static void resetTempTable()
00567 {
00568 tempTable = new Hashtable();
00569 }
00570
00571
00572
00573
00574 public static void setAllowField(boolean newAllowField) {
00575 allowField = newAllowField;
00576 }
00577
00578
00579
00580
00581 public static void setDebugInfo(boolean newDebugInfo) {
00582 debugInfo = newDebugInfo;
00583 }
00584 public static int stmtIndex(Stmt s, Stmt[] stmts)
00585 {
00586 int max = stmts.length;
00587
00588 for (int i=0; i<max; i++)
00589 {
00590 if (stmts[i]==s) return i;
00591 }
00592 return -1;
00593 }
00594 public static String stripImports(String s)
00595 {
00596 if (s.startsWith("edu.ksu.cis.bandera.slabs.lib."))
00597 {
00598 s = s.substring("edu.ksu.cis.bandera.slabs.lib.".length());
00599 Decompiler.addImports("edu.ksu.cis.bandera.slabs.lib.*");
00600 } else
00601 {
00602
00603 }
00604 return s;
00605 }
00606 }