You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ClassReader.java 32KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454
  1. /*
  2. * Copyright 2004-2011 H2 Group.
  3. * Copyright 2011 James Moger.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package com.iciql.bytecode;
  18. import java.io.ByteArrayOutputStream;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.util.ArrayList;
  22. import java.util.HashMap;
  23. import java.util.Map;
  24. import java.util.Stack;
  25. import com.iciql.IciqlException;
  26. import com.iciql.Token;
  27. /**
  28. * This class converts a method to a SQL Token by interpreting (decompiling) the
  29. * bytecode of the class.
  30. */
  31. public class ClassReader {
  32. private static final boolean DEBUG = false;
  33. private byte[] data;
  34. private int pos;
  35. private Constant[] constantPool;
  36. private int startByteCode;
  37. private String methodName;
  38. private String convertMethodName;
  39. private Token result;
  40. private Stack<Token> stack = new Stack<Token>();
  41. private ArrayList<Token> variables = new ArrayList<Token>();
  42. private boolean endOfMethod;
  43. private boolean condition;
  44. private int nextPc;
  45. private Map<String, Object> fieldMap = new HashMap<String, Object>();
  46. private static void debug(String s) {
  47. if (DEBUG) {
  48. System.out.println(s);
  49. }
  50. }
  51. public Token decompile(Object instance, Map<String, Object> fields, String method) {
  52. this.fieldMap = fields;
  53. this.convertMethodName = method;
  54. Class<?> clazz = instance.getClass();
  55. String className = clazz.getName();
  56. debug("class name " + className);
  57. ByteArrayOutputStream buff = new ByteArrayOutputStream();
  58. try {
  59. InputStream in = clazz.getClassLoader().getResource(className.replace('.', '/') + ".class").openStream();
  60. while (true) {
  61. int x = in.read();
  62. if (x < 0) {
  63. break;
  64. }
  65. buff.write(x);
  66. }
  67. } catch (IOException e) {
  68. throw new IciqlException("Could not read class bytecode", e);
  69. }
  70. data = buff.toByteArray();
  71. int header = readInt();
  72. debug("header: " + Integer.toHexString(header));
  73. int minorVersion = readShort();
  74. int majorVersion = readShort();
  75. debug("version: " + majorVersion + "." + minorVersion);
  76. int constantPoolCount = readShort();
  77. constantPool = new Constant[constantPoolCount];
  78. for (int i = 1; i < constantPoolCount; i++) {
  79. int type = readByte();
  80. switch (type) {
  81. case 1:
  82. constantPool[i] = ConstantString.get(readString());
  83. break;
  84. case 3: {
  85. int x = readInt();
  86. constantPool[i] = ConstantNumber.get(x);
  87. break;
  88. }
  89. case 4: {
  90. int x = readInt();
  91. constantPool[i] = ConstantNumber.get("" + Float.intBitsToFloat(x), x, Constant.Type.FLOAT);
  92. break;
  93. }
  94. case 5: {
  95. long x = readLong();
  96. constantPool[i] = ConstantNumber.get(x);
  97. i++;
  98. break;
  99. }
  100. case 6: {
  101. long x = readLong();
  102. constantPool[i] = ConstantNumber.get("" + Double.longBitsToDouble(x), x, Constant.Type.DOUBLE);
  103. i++;
  104. break;
  105. }
  106. case 7: {
  107. int x = readShort();
  108. constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.CLASS_REF);
  109. break;
  110. }
  111. case 8: {
  112. int x = readShort();
  113. constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.STRING_REF);
  114. break;
  115. }
  116. case 9: {
  117. int x = readInt();
  118. constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.FIELD_REF);
  119. break;
  120. }
  121. case 10: {
  122. int x = readInt();
  123. constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.METHOD_REF);
  124. break;
  125. }
  126. case 11: {
  127. int x = readInt();
  128. constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.INTERFACE_METHOD_REF);
  129. break;
  130. }
  131. case 12: {
  132. int x = readInt();
  133. constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.NAME_AND_TYPE);
  134. break;
  135. }
  136. default:
  137. throw new IciqlException("Unsupported constant pool tag: " + type);
  138. }
  139. }
  140. int accessFlags = readShort();
  141. debug("access flags: " + accessFlags);
  142. int classRef = readShort();
  143. debug("class: " + constantPool[constantPool[classRef].intValue()]);
  144. int superClassRef = readShort();
  145. debug(" extends " + constantPool[constantPool[superClassRef].intValue()]);
  146. int interfaceCount = readShort();
  147. for (int i = 0; i < interfaceCount; i++) {
  148. int interfaceRef = readShort();
  149. debug(" implements " + constantPool[constantPool[interfaceRef].intValue()]);
  150. }
  151. int fieldCount = readShort();
  152. for (int i = 0; i < fieldCount; i++) {
  153. readField();
  154. }
  155. int methodCount = readShort();
  156. for (int i = 0; i < methodCount; i++) {
  157. readMethod();
  158. }
  159. readAttributes();
  160. return result;
  161. }
  162. private void readField() {
  163. int accessFlags = readShort();
  164. int nameIndex = readShort();
  165. int descIndex = readShort();
  166. debug(" " + constantPool[descIndex] + " " + constantPool[nameIndex] + " " + accessFlags);
  167. readAttributes();
  168. }
  169. private void readMethod() {
  170. int accessFlags = readShort();
  171. int nameIndex = readShort();
  172. int descIndex = readShort();
  173. String desc = constantPool[descIndex].toString();
  174. methodName = constantPool[nameIndex].toString();
  175. debug(" " + desc + " " + methodName + " " + accessFlags);
  176. readAttributes();
  177. }
  178. private void readAttributes() {
  179. int attributeCount = readShort();
  180. for (int i = 0; i < attributeCount; i++) {
  181. int attributeNameIndex = readShort();
  182. String attributeName = constantPool[attributeNameIndex].toString();
  183. debug(" attribute " + attributeName);
  184. int attributeLength = readInt();
  185. int end = pos + attributeLength;
  186. if ("Code".equals(attributeName)) {
  187. readCode();
  188. }
  189. pos = end;
  190. }
  191. }
  192. void decompile() {
  193. int maxStack = readShort();
  194. int maxLocals = readShort();
  195. debug("stack: " + maxStack + " locals: " + maxLocals);
  196. int codeLength = readInt();
  197. startByteCode = pos;
  198. int end = pos + codeLength;
  199. while (pos < end) {
  200. readByteCode();
  201. }
  202. debug("");
  203. pos = startByteCode + codeLength;
  204. int exceptionTableLength = readShort();
  205. pos += 2 * exceptionTableLength;
  206. readAttributes();
  207. }
  208. private void readCode() {
  209. variables.clear();
  210. stack.clear();
  211. int maxStack = readShort();
  212. int maxLocals = readShort();
  213. debug("stack: " + maxStack + " locals: " + maxLocals);
  214. int codeLength = readInt();
  215. startByteCode = pos;
  216. if (methodName.startsWith(convertMethodName)) {
  217. result = getResult();
  218. }
  219. pos = startByteCode + codeLength;
  220. int exceptionTableLength = readShort();
  221. pos += 2 * exceptionTableLength;
  222. readAttributes();
  223. }
  224. private Token getResult() {
  225. while (true) {
  226. readByteCode();
  227. if (endOfMethod) {
  228. return stack.pop();
  229. }
  230. if (condition) {
  231. Token c = stack.pop();
  232. Stack<Token> currentStack = new Stack<Token>();
  233. currentStack.addAll(stack);
  234. ArrayList<Token> currentVariables = new ArrayList<Token>();
  235. currentVariables.addAll(variables);
  236. int branch = nextPc;
  237. Token a = getResult();
  238. stack = currentStack;
  239. variables = currentVariables;
  240. pos = branch + startByteCode;
  241. Token b = getResult();
  242. if (a.equals("0") && b.equals("1")) {
  243. return c;
  244. } else if (a.equals("1") && b.equals("0")) {
  245. return Not.get(c);
  246. } else if (b.equals("0")) {
  247. return And.get(Not.get(c), a);
  248. } else if (a.equals("0")) {
  249. return And.get(c, b);
  250. } else if (b.equals("1")) {
  251. return Or.get(c, a);
  252. } else if (a.equals("1")) {
  253. return And.get(Not.get(c), b);
  254. }
  255. return CaseWhen.get(c, b, a);
  256. }
  257. if (nextPc != 0) {
  258. pos = nextPc + startByteCode;
  259. }
  260. }
  261. }
  262. private void readByteCode() {
  263. int startPos = pos - startByteCode;
  264. int opCode = readByte();
  265. String op;
  266. endOfMethod = false;
  267. condition = false;
  268. nextPc = 0;
  269. switch (opCode) {
  270. case 0:
  271. op = "nop";
  272. break;
  273. case 1:
  274. op = "aconst_null";
  275. stack.push(Null.INSTANCE);
  276. break;
  277. case 2:
  278. op = "iconst_m1";
  279. stack.push(ConstantNumber.get("-1"));
  280. break;
  281. case 3:
  282. op = "iconst_0";
  283. stack.push(ConstantNumber.get("0"));
  284. break;
  285. case 4:
  286. op = "iconst_1";
  287. stack.push(ConstantNumber.get("1"));
  288. break;
  289. case 5:
  290. op = "iconst_2";
  291. stack.push(ConstantNumber.get("2"));
  292. break;
  293. case 6:
  294. op = "iconst_3";
  295. stack.push(ConstantNumber.get("3"));
  296. break;
  297. case 7:
  298. op = "iconst_4";
  299. stack.push(ConstantNumber.get("4"));
  300. break;
  301. case 8:
  302. op = "iconst_5";
  303. stack.push(ConstantNumber.get("5"));
  304. break;
  305. case 9:
  306. op = "lconst_0";
  307. stack.push(ConstantNumber.get("0"));
  308. break;
  309. case 10:
  310. op = "lconst_1";
  311. stack.push(ConstantNumber.get("1"));
  312. break;
  313. case 11:
  314. op = "fconst_0";
  315. stack.push(ConstantNumber.get("0.0"));
  316. break;
  317. case 12:
  318. op = "fconst_1";
  319. stack.push(ConstantNumber.get("1.0"));
  320. break;
  321. case 13:
  322. op = "fconst_2";
  323. stack.push(ConstantNumber.get("2.0"));
  324. break;
  325. case 14:
  326. op = "dconst_0";
  327. stack.push(ConstantNumber.get("0.0"));
  328. break;
  329. case 15:
  330. op = "dconst_1";
  331. stack.push(ConstantNumber.get("1.0"));
  332. break;
  333. case 16: {
  334. int x = (byte) readByte();
  335. op = "bipush " + x;
  336. stack.push(ConstantNumber.get(x));
  337. break;
  338. }
  339. case 17: {
  340. int x = (short) readShort();
  341. op = "sipush " + x;
  342. stack.push(ConstantNumber.get(x));
  343. break;
  344. }
  345. case 18: {
  346. Token s = getConstant(readByte());
  347. op = "ldc " + s;
  348. stack.push(s);
  349. break;
  350. }
  351. case 19: {
  352. Token s = getConstant(readShort());
  353. op = "ldc_w " + s;
  354. stack.push(s);
  355. break;
  356. }
  357. case 20: {
  358. Token s = getConstant(readShort());
  359. op = "ldc2_w " + s;
  360. stack.push(s);
  361. break;
  362. }
  363. case 21: {
  364. int x = readByte();
  365. op = "iload " + x;
  366. stack.push(getVariable(x));
  367. break;
  368. }
  369. case 22: {
  370. int x = readByte();
  371. op = "lload " + x;
  372. stack.push(getVariable(x));
  373. break;
  374. }
  375. case 23: {
  376. int x = readByte();
  377. op = "fload " + x;
  378. stack.push(getVariable(x));
  379. break;
  380. }
  381. case 24: {
  382. int x = readByte();
  383. op = "dload " + x;
  384. stack.push(getVariable(x));
  385. break;
  386. }
  387. case 25: {
  388. int x = readByte();
  389. op = "aload " + x;
  390. stack.push(getVariable(x));
  391. break;
  392. }
  393. case 26:
  394. op = "iload_0";
  395. stack.push(getVariable(0));
  396. break;
  397. case 27:
  398. op = "iload_1";
  399. stack.push(getVariable(1));
  400. break;
  401. case 28:
  402. op = "iload_2";
  403. stack.push(getVariable(2));
  404. break;
  405. case 29:
  406. op = "iload_3";
  407. stack.push(getVariable(3));
  408. break;
  409. case 30:
  410. op = "lload_0";
  411. stack.push(getVariable(0));
  412. break;
  413. case 31:
  414. op = "lload_1";
  415. stack.push(getVariable(1));
  416. break;
  417. case 32:
  418. op = "lload_2";
  419. stack.push(getVariable(2));
  420. break;
  421. case 33:
  422. op = "lload_3";
  423. stack.push(getVariable(3));
  424. break;
  425. case 34:
  426. op = "fload_0";
  427. stack.push(getVariable(0));
  428. break;
  429. case 35:
  430. op = "fload_1";
  431. stack.push(getVariable(1));
  432. break;
  433. case 36:
  434. op = "fload_2";
  435. stack.push(getVariable(2));
  436. break;
  437. case 37:
  438. op = "fload_3";
  439. stack.push(getVariable(3));
  440. break;
  441. case 38:
  442. op = "dload_0";
  443. stack.push(getVariable(0));
  444. break;
  445. case 39:
  446. op = "dload_1";
  447. stack.push(getVariable(1));
  448. break;
  449. case 40:
  450. op = "dload_2";
  451. stack.push(getVariable(2));
  452. break;
  453. case 41:
  454. op = "dload_3";
  455. stack.push(getVariable(3));
  456. break;
  457. case 42:
  458. op = "aload_0";
  459. stack.push(getVariable(0));
  460. break;
  461. case 43:
  462. op = "aload_1";
  463. stack.push(getVariable(1));
  464. break;
  465. case 44:
  466. op = "aload_2";
  467. stack.push(getVariable(2));
  468. break;
  469. case 45:
  470. op = "aload_3";
  471. stack.push(getVariable(3));
  472. break;
  473. case 46: {
  474. Token index = stack.pop();
  475. Token ref = stack.pop();
  476. op = "iaload";
  477. stack.push(ArrayGet.get(ref, index));
  478. break;
  479. }
  480. case 47: {
  481. Token index = stack.pop();
  482. Token ref = stack.pop();
  483. op = "laload";
  484. stack.push(ArrayGet.get(ref, index));
  485. break;
  486. }
  487. case 48: {
  488. Token index = stack.pop();
  489. Token ref = stack.pop();
  490. op = "faload";
  491. stack.push(ArrayGet.get(ref, index));
  492. break;
  493. }
  494. case 49: {
  495. Token index = stack.pop();
  496. Token ref = stack.pop();
  497. op = "daload";
  498. stack.push(ArrayGet.get(ref, index));
  499. break;
  500. }
  501. case 50: {
  502. Token index = stack.pop();
  503. Token ref = stack.pop();
  504. op = "aaload";
  505. stack.push(ArrayGet.get(ref, index));
  506. break;
  507. }
  508. case 51: {
  509. Token index = stack.pop();
  510. Token ref = stack.pop();
  511. op = "baload";
  512. stack.push(ArrayGet.get(ref, index));
  513. break;
  514. }
  515. case 52: {
  516. Token index = stack.pop();
  517. Token ref = stack.pop();
  518. op = "caload";
  519. stack.push(ArrayGet.get(ref, index));
  520. break;
  521. }
  522. case 53: {
  523. Token index = stack.pop();
  524. Token ref = stack.pop();
  525. op = "saload";
  526. stack.push(ArrayGet.get(ref, index));
  527. break;
  528. }
  529. case 54: {
  530. int var = readByte();
  531. op = "istore " + var;
  532. setVariable(var, stack.pop());
  533. break;
  534. }
  535. case 55: {
  536. int var = readByte();
  537. op = "lstore " + var;
  538. setVariable(var, stack.pop());
  539. break;
  540. }
  541. case 56: {
  542. int var = readByte();
  543. op = "fstore " + var;
  544. setVariable(var, stack.pop());
  545. break;
  546. }
  547. case 57: {
  548. int var = readByte();
  549. op = "dstore " + var;
  550. setVariable(var, stack.pop());
  551. break;
  552. }
  553. case 58: {
  554. int var = readByte();
  555. op = "astore " + var;
  556. setVariable(var, stack.pop());
  557. break;
  558. }
  559. case 59:
  560. op = "istore_0";
  561. setVariable(0, stack.pop());
  562. break;
  563. case 60:
  564. op = "istore_1";
  565. setVariable(1, stack.pop());
  566. break;
  567. case 61:
  568. op = "istore_2";
  569. setVariable(2, stack.pop());
  570. break;
  571. case 62:
  572. op = "istore_3";
  573. setVariable(3, stack.pop());
  574. break;
  575. case 63:
  576. op = "lstore_0";
  577. setVariable(0, stack.pop());
  578. break;
  579. case 64:
  580. op = "lstore_1";
  581. setVariable(1, stack.pop());
  582. break;
  583. case 65:
  584. op = "lstore_2";
  585. setVariable(2, stack.pop());
  586. break;
  587. case 66:
  588. op = "lstore_3";
  589. setVariable(3, stack.pop());
  590. break;
  591. case 67:
  592. op = "fstore_0";
  593. setVariable(0, stack.pop());
  594. break;
  595. case 68:
  596. op = "fstore_1";
  597. setVariable(1, stack.pop());
  598. break;
  599. case 69:
  600. op = "fstore_2";
  601. setVariable(2, stack.pop());
  602. break;
  603. case 70:
  604. op = "fstore_3";
  605. setVariable(3, stack.pop());
  606. break;
  607. case 71:
  608. op = "dstore_0";
  609. setVariable(0, stack.pop());
  610. break;
  611. case 72:
  612. op = "dstore_1";
  613. setVariable(1, stack.pop());
  614. break;
  615. case 73:
  616. op = "dstore_2";
  617. setVariable(2, stack.pop());
  618. break;
  619. case 74:
  620. op = "dstore_3";
  621. setVariable(3, stack.pop());
  622. break;
  623. case 75:
  624. op = "astore_0";
  625. setVariable(0, stack.pop());
  626. break;
  627. case 76:
  628. op = "astore_1";
  629. setVariable(1, stack.pop());
  630. break;
  631. case 77:
  632. op = "astore_2";
  633. setVariable(2, stack.pop());
  634. break;
  635. case 78:
  636. op = "astore_3";
  637. setVariable(3, stack.pop());
  638. break;
  639. case 79: {
  640. // String value = stack.pop();
  641. // String index = stack.pop();
  642. // String ref = stack.pop();
  643. op = "iastore";
  644. // TODO side effect - not supported
  645. break;
  646. }
  647. case 80:
  648. op = "lastore";
  649. // TODO side effect - not supported
  650. break;
  651. case 81:
  652. op = "fastore";
  653. // TODO side effect - not supported
  654. break;
  655. case 82:
  656. op = "dastore";
  657. // TODO side effect - not supported
  658. break;
  659. case 83:
  660. op = "aastore";
  661. // TODO side effect - not supported
  662. break;
  663. case 84:
  664. op = "bastore";
  665. // TODO side effect - not supported
  666. break;
  667. case 85:
  668. op = "castore";
  669. // TODO side effect - not supported
  670. break;
  671. case 86:
  672. op = "sastore";
  673. // TODO side effect - not supported
  674. break;
  675. case 87:
  676. op = "pop";
  677. stack.pop();
  678. break;
  679. case 88:
  680. op = "pop2";
  681. // TODO currently we don't know the stack types
  682. stack.pop();
  683. stack.pop();
  684. break;
  685. case 89: {
  686. op = "dup";
  687. Token x = stack.pop();
  688. stack.push(x);
  689. stack.push(x);
  690. break;
  691. }
  692. case 90: {
  693. op = "dup_x1";
  694. Token a = stack.pop();
  695. Token b = stack.pop();
  696. stack.push(a);
  697. stack.push(b);
  698. stack.push(a);
  699. break;
  700. }
  701. case 91: {
  702. // TODO currently we don't know the stack types
  703. op = "dup_x2";
  704. Token a = stack.pop();
  705. Token b = stack.pop();
  706. Token c = stack.pop();
  707. stack.push(a);
  708. stack.push(c);
  709. stack.push(b);
  710. stack.push(a);
  711. break;
  712. }
  713. case 92: {
  714. // TODO currently we don't know the stack types
  715. op = "dup2";
  716. Token a = stack.pop();
  717. Token b = stack.pop();
  718. stack.push(b);
  719. stack.push(a);
  720. stack.push(b);
  721. stack.push(a);
  722. break;
  723. }
  724. case 93: {
  725. // TODO currently we don't know the stack types
  726. op = "dup2_x1";
  727. Token a = stack.pop();
  728. Token b = stack.pop();
  729. Token c = stack.pop();
  730. stack.push(b);
  731. stack.push(a);
  732. stack.push(c);
  733. stack.push(b);
  734. stack.push(a);
  735. break;
  736. }
  737. case 94: {
  738. // TODO currently we don't know the stack types
  739. op = "dup2_x2";
  740. Token a = stack.pop();
  741. Token b = stack.pop();
  742. Token c = stack.pop();
  743. Token d = stack.pop();
  744. stack.push(b);
  745. stack.push(a);
  746. stack.push(d);
  747. stack.push(c);
  748. stack.push(b);
  749. stack.push(a);
  750. break;
  751. }
  752. case 95: {
  753. op = "swap";
  754. Token a = stack.pop();
  755. Token b = stack.pop();
  756. stack.push(a);
  757. stack.push(b);
  758. break;
  759. }
  760. case 96: {
  761. Token b = stack.pop();
  762. Token a = stack.pop();
  763. op = "iadd";
  764. stack.push(Operation.get(a, Operation.Type.ADD, b));
  765. break;
  766. }
  767. case 97: {
  768. Token b = stack.pop();
  769. Token a = stack.pop();
  770. op = "ladd";
  771. stack.push(Operation.get(a, Operation.Type.ADD, b));
  772. break;
  773. }
  774. case 98: {
  775. Token b = stack.pop();
  776. Token a = stack.pop();
  777. op = "fadd";
  778. stack.push(Operation.get(a, Operation.Type.ADD, b));
  779. break;
  780. }
  781. case 99: {
  782. Token b = stack.pop();
  783. Token a = stack.pop();
  784. op = "dadd";
  785. stack.push(Operation.get(a, Operation.Type.ADD, b));
  786. break;
  787. }
  788. case 100: {
  789. Token b = stack.pop();
  790. Token a = stack.pop();
  791. op = "isub";
  792. stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
  793. break;
  794. }
  795. case 101: {
  796. Token b = stack.pop();
  797. Token a = stack.pop();
  798. op = "lsub";
  799. stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
  800. break;
  801. }
  802. case 102: {
  803. Token b = stack.pop();
  804. Token a = stack.pop();
  805. op = "fsub";
  806. stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
  807. break;
  808. }
  809. case 103: {
  810. Token b = stack.pop();
  811. Token a = stack.pop();
  812. op = "dsub";
  813. stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
  814. break;
  815. }
  816. case 104: {
  817. Token b = stack.pop();
  818. Token a = stack.pop();
  819. op = "imul";
  820. stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
  821. break;
  822. }
  823. case 105: {
  824. Token b = stack.pop();
  825. Token a = stack.pop();
  826. op = "lmul";
  827. stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
  828. break;
  829. }
  830. case 106: {
  831. Token b = stack.pop();
  832. Token a = stack.pop();
  833. op = "fmul";
  834. stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
  835. break;
  836. }
  837. case 107: {
  838. Token b = stack.pop();
  839. Token a = stack.pop();
  840. op = "dmul";
  841. stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
  842. break;
  843. }
  844. case 108: {
  845. Token b = stack.pop();
  846. Token a = stack.pop();
  847. op = "idiv";
  848. stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
  849. break;
  850. }
  851. case 109: {
  852. Token b = stack.pop();
  853. Token a = stack.pop();
  854. op = "ldiv";
  855. stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
  856. break;
  857. }
  858. case 110: {
  859. Token b = stack.pop();
  860. Token a = stack.pop();
  861. op = "fdiv";
  862. stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
  863. break;
  864. }
  865. case 111: {
  866. Token b = stack.pop();
  867. Token a = stack.pop();
  868. op = "ddiv";
  869. stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
  870. break;
  871. }
  872. case 112: {
  873. Token b = stack.pop();
  874. Token a = stack.pop();
  875. op = "irem";
  876. stack.push(Operation.get(a, Operation.Type.MOD, b));
  877. break;
  878. }
  879. case 113: {
  880. Token b = stack.pop();
  881. Token a = stack.pop();
  882. op = "lrem";
  883. stack.push(Operation.get(a, Operation.Type.MOD, b));
  884. break;
  885. }
  886. case 114: {
  887. Token b = stack.pop();
  888. Token a = stack.pop();
  889. op = "frem";
  890. stack.push(Operation.get(a, Operation.Type.MOD, b));
  891. break;
  892. }
  893. case 115: {
  894. Token b = stack.pop();
  895. Token a = stack.pop();
  896. op = "drem";
  897. stack.push(Operation.get(a, Operation.Type.MOD, b));
  898. break;
  899. }
  900. // case 116:
  901. // op = "ineg";
  902. // break;
  903. // case 117:
  904. // op = "lneg";
  905. // break;
  906. // case 118:
  907. // op = "fneg";
  908. // break;
  909. // case 119:
  910. // op = "dneg";
  911. // break;
  912. // case 120:
  913. // op = "ishl";
  914. // break;
  915. // case 121:
  916. // op = "lshl";
  917. // break;
  918. // case 122:
  919. // op = "ishr";
  920. // break;
  921. // case 123:
  922. // op = "lshr";
  923. // break;
  924. // case 124:
  925. // op = "iushr";
  926. // break;
  927. // case 125:
  928. // op = "lushr";
  929. // break;
  930. // case 126:
  931. // op = "iand";
  932. // break;
  933. // case 127:
  934. // op = "land";
  935. // break;
  936. // case 128:
  937. // op = "ior";
  938. // break;
  939. // case 129:
  940. // op = "lor";
  941. // break;
  942. // case 130:
  943. // op = "ixor";
  944. // break;
  945. // case 131:
  946. // op = "lxor";
  947. // break;
  948. // case 132: {
  949. // int var = readByte();
  950. // int off = (byte) readByte();
  951. // op = "iinc " + var + " " + off;
  952. // break;
  953. // }
  954. // case 133:
  955. // op = "i2l";
  956. // break;
  957. // case 134:
  958. // op = "i2f";
  959. // break;
  960. // case 135:
  961. // op = "i2d";
  962. // break;
  963. // case 136:
  964. // op = "l2i";
  965. // break;
  966. // case 137:
  967. // op = "l2f";
  968. // break;
  969. // case 138:
  970. // op = "l2d";
  971. // break;
  972. // case 139:
  973. // op = "f2i";
  974. // break;
  975. // case 140:
  976. // op = "f2l";
  977. // break;
  978. // case 141:
  979. // op = "f2d";
  980. // break;
  981. // case 142:
  982. // op = "d2i";
  983. // break;
  984. // case 143:
  985. // op = "d2l";
  986. // break;
  987. // case 144:
  988. // op = "d2f";
  989. // break;
  990. // case 145:
  991. // op = "i2b";
  992. // break;
  993. // case 146:
  994. // op = "i2c";
  995. // break;
  996. // case 147:
  997. // op = "i2s";
  998. // break;
  999. case 148: {
  1000. Token b = stack.pop(), a = stack.pop();
  1001. stack.push(new Function("SIGN", Operation.get(a, Operation.Type.SUBTRACT, b)));
  1002. op = "lcmp";
  1003. break;
  1004. }
  1005. // case 149:
  1006. // op = "fcmpl";
  1007. // break;
  1008. // case 150:
  1009. // op = "fcmpg";
  1010. // break;
  1011. // case 151:
  1012. // op = "dcmpl";
  1013. // break;
  1014. // case 152:
  1015. // op = "dcmpg";
  1016. // break;
  1017. case 153:
  1018. condition = true;
  1019. nextPc = getAbsolutePos(pos, readShort());
  1020. stack.push(Operation.get(stack.pop(), Operation.Type.EQUALS, ConstantNumber.get(0)));
  1021. op = "ifeq " + nextPc;
  1022. break;
  1023. case 154:
  1024. condition = true;
  1025. nextPc = getAbsolutePos(pos, readShort());
  1026. stack.push(Operation.get(stack.pop(), Operation.Type.NOT_EQUALS, ConstantNumber.get(0)));
  1027. op = "ifne " + nextPc;
  1028. break;
  1029. case 155:
  1030. condition = true;
  1031. nextPc = getAbsolutePos(pos, readShort());
  1032. stack.push(Operation.get(stack.pop(), Operation.Type.SMALLER, ConstantNumber.get(0)));
  1033. op = "iflt " + nextPc;
  1034. break;
  1035. case 156:
  1036. condition = true;
  1037. nextPc = getAbsolutePos(pos, readShort());
  1038. stack.push(Operation.get(stack.pop(), Operation.Type.BIGGER_EQUALS, ConstantNumber.get(0)));
  1039. op = "ifge " + nextPc;
  1040. break;
  1041. case 157:
  1042. condition = true;
  1043. nextPc = getAbsolutePos(pos, readShort());
  1044. stack.push(Operation.get(stack.pop(), Operation.Type.BIGGER, ConstantNumber.get(0)));
  1045. op = "ifgt " + nextPc;
  1046. break;
  1047. case 158:
  1048. condition = true;
  1049. nextPc = getAbsolutePos(pos, readShort());
  1050. stack.push(Operation.get(stack.pop(), Operation.Type.SMALLER_EQUALS, ConstantNumber.get(0)));
  1051. op = "ifle " + nextPc;
  1052. break;
  1053. case 159: {
  1054. condition = true;
  1055. nextPc = getAbsolutePos(pos, readShort());
  1056. Token b = stack.pop(), a = stack.pop();
  1057. stack.push(Operation.get(a, Operation.Type.EQUALS, b));
  1058. op = "if_icmpeq " + nextPc;
  1059. break;
  1060. }
  1061. case 160: {
  1062. condition = true;
  1063. nextPc = getAbsolutePos(pos, readShort());
  1064. Token b = stack.pop(), a = stack.pop();
  1065. stack.push(Operation.get(a, Operation.Type.NOT_EQUALS, b));
  1066. op = "if_icmpne " + nextPc;
  1067. break;
  1068. }
  1069. case 161: {
  1070. condition = true;
  1071. nextPc = getAbsolutePos(pos, readShort());
  1072. Token b = stack.pop(), a = stack.pop();
  1073. stack.push(Operation.get(a, Operation.Type.SMALLER, b));
  1074. op = "if_icmplt " + nextPc;
  1075. break;
  1076. }
  1077. case 162: {
  1078. condition = true;
  1079. nextPc = getAbsolutePos(pos, readShort());
  1080. Token b = stack.pop(), a = stack.pop();
  1081. stack.push(Operation.get(a, Operation.Type.BIGGER_EQUALS, b));
  1082. op = "if_icmpge " + nextPc;
  1083. break;
  1084. }
  1085. case 163: {
  1086. condition = true;
  1087. nextPc = getAbsolutePos(pos, readShort());
  1088. Token b = stack.pop(), a = stack.pop();
  1089. stack.push(Operation.get(a, Operation.Type.BIGGER, b));
  1090. op = "if_icmpgt " + nextPc;
  1091. break;
  1092. }
  1093. case 164: {
  1094. condition = true;
  1095. nextPc = getAbsolutePos(pos, readShort());
  1096. Token b = stack.pop(), a = stack.pop();
  1097. stack.push(Operation.get(a, Operation.Type.SMALLER_EQUALS, b));
  1098. op = "if_icmple " + nextPc;
  1099. break;
  1100. }
  1101. case 165: {
  1102. condition = true;
  1103. nextPc = getAbsolutePos(pos, readShort());
  1104. Token b = stack.pop(), a = stack.pop();
  1105. stack.push(Operation.get(a, Operation.Type.EQUALS, b));
  1106. op = "if_acmpeq " + nextPc;
  1107. break;
  1108. }
  1109. case 166: {
  1110. condition = true;
  1111. nextPc = getAbsolutePos(pos, readShort());
  1112. Token b = stack.pop(), a = stack.pop();
  1113. stack.push(Operation.get(a, Operation.Type.NOT_EQUALS, b));
  1114. op = "if_acmpne " + nextPc;
  1115. break;
  1116. }
  1117. case 167:
  1118. nextPc = getAbsolutePos(pos, readShort());
  1119. op = "goto " + nextPc;
  1120. break;
  1121. // case 168:
  1122. // // TODO not supported yet
  1123. // op = "jsr " + getAbsolutePos(pos, readShort());
  1124. // break;
  1125. // case 169:
  1126. // // TODO not supported yet
  1127. // op = "ret " + readByte();
  1128. // break;
  1129. // case 170: {
  1130. // int start = pos;
  1131. // pos += 4 - ((pos - startByteCode) & 3);
  1132. // int def = readInt();
  1133. // int low = readInt(), high = readInt();
  1134. // int n = high - low + 1;
  1135. // op = "tableswitch default:" + getAbsolutePos(start, def);
  1136. // StringBuilder buff = new StringBuilder();
  1137. // for (int i = 0; i < n; i++) {
  1138. // buff.append(' ').append(low++).
  1139. // append(":").
  1140. // append(getAbsolutePos(start, readInt()));
  1141. // }
  1142. // op += buff.toString();
  1143. // // pos += n * 4;
  1144. // break;
  1145. // }
  1146. // case 171: {
  1147. // int start = pos;
  1148. // pos += 4 - ((pos - startByteCode) & 3);
  1149. // int def = readInt();
  1150. // int n = readInt();
  1151. // op = "lookupswitch default:" + getAbsolutePos(start, def);
  1152. // StringBuilder buff = new StringBuilder();
  1153. // for (int i = 0; i < n; i++) {
  1154. // buff.append(' ').
  1155. // append(readInt()).
  1156. // append(":").
  1157. // append(getAbsolutePos(start, readInt()));
  1158. // }
  1159. // op += buff.toString();
  1160. // // pos += n * 8;
  1161. // break;
  1162. // }
  1163. case 172:
  1164. op = "ireturn";
  1165. endOfMethod = true;
  1166. break;
  1167. case 173:
  1168. op = "lreturn";
  1169. endOfMethod = true;
  1170. break;
  1171. case 174:
  1172. op = "freturn";
  1173. endOfMethod = true;
  1174. break;
  1175. case 175:
  1176. op = "dreturn";
  1177. endOfMethod = true;
  1178. break;
  1179. case 176:
  1180. op = "areturn";
  1181. endOfMethod = true;
  1182. break;
  1183. case 177:
  1184. op = "return";
  1185. // no value returned
  1186. stack.push(null);
  1187. endOfMethod = true;
  1188. break;
  1189. // case 178:
  1190. // op = "getstatic " + getField(readShort());
  1191. // break;
  1192. // case 179:
  1193. // op = "putstatic " + getField(readShort());
  1194. // break;
  1195. case 180: {
  1196. String field = getField(readShort());
  1197. Token p = stack.pop();
  1198. String s = p + "." + field.substring(field.lastIndexOf('.') + 1, field.indexOf(' '));
  1199. if (s.startsWith("this.")) {
  1200. s = s.substring(5);
  1201. }
  1202. stack.push(Variable.get(s, fieldMap.get(s)));
  1203. op = "getfield " + field;
  1204. break;
  1205. }
  1206. // case 181:
  1207. // op = "putfield " + getField(readShort());
  1208. // break;
  1209. case 182: {
  1210. String method = getMethod(readShort());
  1211. op = "invokevirtual " + method;
  1212. if (method.equals("java/lang/String.equals (Ljava/lang/Object;)Z")) {
  1213. Token a = stack.pop();
  1214. Token b = stack.pop();
  1215. stack.push(Operation.get(a, Operation.Type.EQUALS, b));
  1216. } else if (method.equals("java/lang/Integer.intValue ()I")) {
  1217. // ignore
  1218. } else if (method.equals("java/lang/Long.longValue ()J")) {
  1219. // ignore
  1220. }
  1221. break;
  1222. }
  1223. case 183: {
  1224. String method = getMethod(readShort());
  1225. op = "invokespecial " + method;
  1226. break;
  1227. }
  1228. case 184:
  1229. op = "invokestatic " + getMethod(readShort());
  1230. break;
  1231. // case 185: {
  1232. // int methodRef = readShort();
  1233. // readByte();
  1234. // readByte();
  1235. // op = "invokeinterface " + getMethod(methodRef);
  1236. // break;
  1237. // }
  1238. case 187: {
  1239. String className = constantPool[constantPool[readShort()].intValue()].toString();
  1240. op = "new " + className;
  1241. break;
  1242. }
  1243. // case 188:
  1244. // op = "newarray " + readByte();
  1245. // break;
  1246. // case 189:
  1247. // op = "anewarray " + cpString[readShort()];
  1248. // break;
  1249. // case 190:
  1250. // op = "arraylength";
  1251. // break;
  1252. // case 191:
  1253. // op = "athrow";
  1254. // break;
  1255. // case 192:
  1256. // op = "checkcast " + cpString[readShort()];
  1257. // break;
  1258. // case 193:
  1259. // op = "instanceof " + cpString[readShort()];
  1260. // break;
  1261. // case 194:
  1262. // op = "monitorenter";
  1263. // break;
  1264. // case 195:
  1265. // op = "monitorexit";
  1266. // break;
  1267. // case 196: {
  1268. // opCode = readByte();
  1269. // switch (opCode) {
  1270. // case 21:
  1271. // op = "wide iload " + readShort();
  1272. // break;
  1273. // case 22:
  1274. // op = "wide lload " + readShort();
  1275. // break;
  1276. // case 23:
  1277. // op = "wide fload " + readShort();
  1278. // break;
  1279. // case 24:
  1280. // op = "wide dload " + readShort();
  1281. // break;
  1282. // case 25:
  1283. // op = "wide aload " + readShort();
  1284. // break;
  1285. // case 54:
  1286. // op = "wide istore " + readShort();
  1287. // break;
  1288. // case 55:
  1289. // op = "wide lstore " + readShort();
  1290. // break;
  1291. // case 56:
  1292. // op = "wide fstore " + readShort();
  1293. // break;
  1294. // case 57:
  1295. // op = "wide dstore " + readShort();
  1296. // break;
  1297. // case 58:
  1298. // op = "wide astore " + readShort();
  1299. // break;
  1300. // case 132: {
  1301. // int var = readShort();
  1302. // int off = (short) readShort();
  1303. // op = "wide iinc " + var + " " + off;
  1304. // break;
  1305. // }
  1306. // case 169:
  1307. // op = "wide ret " + readShort();
  1308. // break;
  1309. // default:
  1310. // throw new IciqlException(
  1311. // "Unsupported wide opCode " + opCode);
  1312. // }
  1313. // break;
  1314. // }
  1315. // case 197:
  1316. // op = "multianewarray " + cpString[readShort()] + " " + readByte();
  1317. // break;
  1318. // case 198: {
  1319. // condition = true;
  1320. // nextPc = getAbsolutePos(pos, readShort());
  1321. // Token a = stack.pop();
  1322. // stack.push("(" + a + " IS NULL)");
  1323. // op = "ifnull " + nextPc;
  1324. // break;
  1325. // }
  1326. // case 199: {
  1327. // condition = true;
  1328. // nextPc = getAbsolutePos(pos, readShort());
  1329. // Token a = stack.pop();
  1330. // stack.push("(" + a + " IS NOT NULL)");
  1331. // op = "ifnonnull " + nextPc;
  1332. // break;
  1333. // }
  1334. case 200:
  1335. op = "goto_w " + getAbsolutePos(pos, readInt());
  1336. break;
  1337. case 201:
  1338. op = "jsr_w " + getAbsolutePos(pos, readInt());
  1339. break;
  1340. default:
  1341. throw new IciqlException("Unsupported opCode " + opCode);
  1342. }
  1343. debug(" " + startPos + ": " + op);
  1344. }
  1345. private void setVariable(int x, Token value) {
  1346. while (x >= variables.size()) {
  1347. variables.add(Variable.get("p" + variables.size(), null));
  1348. }
  1349. variables.set(x, value);
  1350. }
  1351. private Token getVariable(int x) {
  1352. if (x == 0) {
  1353. return Variable.THIS;
  1354. }
  1355. while (x >= variables.size()) {
  1356. variables.add(Variable.get("p" + variables.size(), null));
  1357. }
  1358. return variables.get(x);
  1359. }
  1360. private String getField(int fieldRef) {
  1361. int field = constantPool[fieldRef].intValue();
  1362. int classIndex = field >>> 16;
  1363. int nameAndType = constantPool[field & 0xffff].intValue();
  1364. String className = constantPool[constantPool[classIndex].intValue()] + "." + constantPool[nameAndType >>> 16]
  1365. + " " + constantPool[nameAndType & 0xffff];
  1366. return className;
  1367. }
  1368. private String getMethod(int methodRef) {
  1369. int method = constantPool[methodRef].intValue();
  1370. int classIndex = method >>> 16;
  1371. int nameAndType = constantPool[method & 0xffff].intValue();
  1372. String className = constantPool[constantPool[classIndex].intValue()] + "." + constantPool[nameAndType >>> 16]
  1373. + " " + constantPool[nameAndType & 0xffff];
  1374. return className;
  1375. }
  1376. private Constant getConstant(int constantRef) {
  1377. Constant c = constantPool[constantRef];
  1378. switch (c.getType()) {
  1379. case INT:
  1380. case FLOAT:
  1381. case DOUBLE:
  1382. case LONG:
  1383. return c;
  1384. case STRING_REF:
  1385. return constantPool[c.intValue()];
  1386. default:
  1387. throw new IciqlException("Not a constant: " + constantRef);
  1388. }
  1389. }
  1390. private String readString() {
  1391. int size = readShort();
  1392. byte[] buff = data;
  1393. int p = pos, end = p + size;
  1394. char[] chars = new char[size];
  1395. int j = 0;
  1396. for (; p < end; j++) {
  1397. int x = buff[p++] & 0xff;
  1398. if (x < 0x80) {
  1399. chars[j] = (char) x;
  1400. } else if (x >= 0xe0) {
  1401. chars[j] = (char) (((x & 0xf) << 12) + ((buff[p++] & 0x3f) << 6) + (buff[p++] & 0x3f));
  1402. } else {
  1403. chars[j] = (char) (((x & 0x1f) << 6) + (buff[p++] & 0x3f));
  1404. }
  1405. }
  1406. pos = p;
  1407. return new String(chars, 0, j);
  1408. }
  1409. private int getAbsolutePos(int start, int offset) {
  1410. return start - startByteCode - 1 + (short) offset;
  1411. }
  1412. private int readByte() {
  1413. return data[pos++] & 0xff;
  1414. }
  1415. private int readShort() {
  1416. byte[] buff = data;
  1417. return ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
  1418. }
  1419. private int readInt() {
  1420. byte[] buff = data;
  1421. return (buff[pos++] << 24) + ((buff[pos++] & 0xff) << 16) + ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
  1422. }
  1423. private long readLong() {
  1424. return ((long) (readInt()) << 32) + (readInt() & 0xffffffffL);
  1425. }
  1426. }