javaClassEditor.lua 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203
  1. --Java class editor
  2. --[[
  3. This will show an userinterface for editing java classes and will return a list of "patch" commands
  4. that can be used with the runtime java class edit commands
  5. e.g:
  6. DefineLabel(spot)
  7. InsertBytecode(spot, command)
  8. ModifyBytecode(spot, command)
  9. DeleteBytecode(spot) (could be ModifyBytecode(spot,"nop") )
  10. The user should not have to know about exceptions and how their positions change with each insert/delete
  11. gui:
  12. listview:
  13. index|byteindex|label |exception|instruction|
  14. -----|---------|------|---------|-----------|
  15. 0 |0 | | |nop | Insert
  16. 0 |1 |l1: |ex1: |branch l1 | Delete
  17. Modify
  18. --]]
  19. --http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html
  20. java_bytecodes={}
  21. --[[
  22. paramtypes:
  23. s1=signed 1 byte
  24. s2=signed 2 byte
  25. s4=signed 4 byte
  26. u1=unsigned 1 byte
  27. u2=unsigned 2 byte
  28. u4=unsigned 4 byte
  29. 02=null 2 bytes
  30. wide=special wide operand
  31. pad4=pad till 4 byte alignment
  32. [s4]=array of 4 byte signed values
  33. [s4s4]=array of 2 4 byte signed values
  34. --]]
  35. function signExtendByte(byte)
  36. --byte is a value between 0 and 255
  37. --if bit 7 is 1, it's a negative
  38. if bAnd(byte,0x80)~=0 then
  39. return byte-0x100
  40. else
  41. return byte
  42. end
  43. end
  44. function signExtendWord(word)
  45. if bAnd(word,0x8000)~=0 then
  46. return word-0x10000
  47. else
  48. return word
  49. end
  50. end
  51. function signExtendDword(dword)
  52. --assuming dword is in the range of 0 to 0xffffffff
  53. if bAnd(dword,0x80000000)~=0 then
  54. return dword-0x100000000
  55. else
  56. return dword
  57. end
  58. end
  59. function calculateTableSwitch(address, bytes)
  60. local result=nil
  61. if bytes[address]==0xaa then
  62. local padding=0
  63. if (address-1) % 4>0 then
  64. padding=4-(address-1) % 4
  65. end
  66. --local defaultbyte=byteTableToDword({bytes[8],bytes[7],bytes[6],bytes[5]})
  67. local low=byteTableToDword({bytes[address+1+padding+7],bytes[address+1+padding+6],bytes[address+1+padding+5],bytes[address+1+padding+4]})
  68. local high=byteTableToDword({bytes[address+1+padding+11],bytes[address+1+padding+10],bytes[address+1+padding+9],bytes[address+1+padding+8]})
  69. result=padding+4+4+4+((high-low)+1)*4 --paramsize
  70. end
  71. return result;
  72. end
  73. function calculateLookupSwitch(address, bytes)
  74. local result=nil
  75. if bytes[address]==0xab then
  76. local padding=0
  77. if (address-1) % 4>0 then
  78. padding=4-(address-1) % 4
  79. end
  80. --local defaultbyte=byteTableToDword({bytes[8],bytes[7],bytes[6],bytes[5]})
  81. local npairs=byteTableToDword({bytes[address+1+padding+7],bytes[address+1+padding+6],bytes[address+1+padding+5],bytes[address+1+padding+4]})
  82. result=padding+4+4+npairs*8 --paramsize
  83. end
  84. return result;
  85. end
  86. java_bytecodes[0x00]={operation="nop", description="Do nothing"}
  87. java_bytecodes[0x01]={operation="aconst_null", description="Push null"}
  88. java_bytecodes[0x02]={operation="iconst_m1", description="Push int -1"}
  89. java_bytecodes[0x03]={operation="iconst_0", description="Push int 0"}
  90. java_bytecodes[0x04]={operation="iconst_1", description="Push int 1"}
  91. java_bytecodes[0x05]={operation="iconst_2", description="Push int 2"}
  92. java_bytecodes[0x06]={operation="iconst_3", description="Push int 3"}
  93. java_bytecodes[0x07]={operation="iconst_4", description="Push int 4"}
  94. java_bytecodes[0x08]={operation="iconst_5", description="Push int 5"}
  95. java_bytecodes[0x09]={operation="lconst_0", description="Push long 0"}
  96. java_bytecodes[0x0a]={operation="lconst_1", description="Push long 1"}
  97. java_bytecodes[0x0b]={operation="fconst_0", description="Push float 0.0"}
  98. java_bytecodes[0x0c]={operation="fconst_1", description="Push float 1.0"}
  99. java_bytecodes[0x0d]={operation="fconst_2", description="Push float 2.0"}
  100. java_bytecodes[0x0e]={operation="dconst_0", description="Push double 0.0"}
  101. java_bytecodes[0x0f]={operation="dconst_1", description="Push double 1.0"}
  102. java_bytecodes[0x10]={operation="bipush", parameters={bytecount=1, {paramname="const", paramtype="s1"}}, description="Push byte"}
  103. java_bytecodes[0x11]={operation="sipush", parameters={bytecount=2, {paramname="const", paramtype="s2"}}, description="Push short"}
  104. java_bytecodes[0x12]={operation="ldc", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, description="Push item from run-time constant pool"}
  105. java_bytecodes[0x13]={operation="ldc_w", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Push item from run-time constant pool(wide)"}
  106. java_bytecodes[0x14]={operation="ldc2_w", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Push long or double from run-time constant pool(wide)"}
  107. java_bytecodes[0x15]={operation="iload", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, wideparameters={bytecount=2, {paramname="index", paramtype="u2"}},description="Load int from local variable"}
  108. java_bytecodes[0x16]={operation="lload", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, wideparameters={bytecount=2, {paramname="index", paramtype="u2"}},description="Load long from local variable"}
  109. java_bytecodes[0x17]={operation="fload", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, wideparameters={bytecount=2, {paramname="index", paramtype="u2"}},description="Load float from local variable"}
  110. java_bytecodes[0x18]={operation="dload", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, wideparameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Load double from local variable"}
  111. java_bytecodes[0x19]={operation="aload", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, wideparameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Load reference from local variable"}
  112. java_bytecodes[0x1a]={operation="iload_0", description="Load int from local variable at index 0"}
  113. java_bytecodes[0x1b]={operation="iload_1", description="Load int from local variable at index 1"}
  114. java_bytecodes[0x1c]={operation="iload_2", description="Load int from local variable at index 2"}
  115. java_bytecodes[0x1d]={operation="iload_3", description="Load int from local variable at index 3"}
  116. java_bytecodes[0x1e]={operation="lload_0", description="Load long from local variable at index 0"}
  117. java_bytecodes[0x1f]={operation="lload_1", description="Load long from local variable at index 1"}
  118. java_bytecodes[0x20]={operation="lload_2", description="Load long from local variable at index 2"}
  119. java_bytecodes[0x21]={operation="lload_3", description="Load long from local variable at index 3"}
  120. java_bytecodes[0x22]={operation="fload_0", description="Load float from local variable at index 0"}
  121. java_bytecodes[0x23]={operation="fload_1", description="Load float from local variable at index 1"}
  122. java_bytecodes[0x24]={operation="fload_2", description="Load float from local variable at index 2"}
  123. java_bytecodes[0x25]={operation="fload_3", description="Load float from local variable at index 3"}
  124. java_bytecodes[0x26]={operation="dload_0", description="Load double from local variable at index 0"}
  125. java_bytecodes[0x27]={operation="dload_1", description="Load double from local variable at index 1"}
  126. java_bytecodes[0x28]={operation="dload_2", description="Load double from local variable at index 2"}
  127. java_bytecodes[0x29]={operation="dload_3", description="Load double from local variable at index 3"}
  128. java_bytecodes[0x2a]={operation="aload_0", description="Load reference from local variable at index 0"}
  129. java_bytecodes[0x2b]={operation="aload_1", description="Load reference from local variable at index 1"}
  130. java_bytecodes[0x2c]={operation="aload_2", description="Load reference from local variable at index 2"}
  131. java_bytecodes[0x2d]={operation="aload_3", description="Load reference from local variable at index 3"}
  132. java_bytecodes[0x2e]={operation="iaload", description="Load int from array"}
  133. java_bytecodes[0x2f]={operation="laload", description="Load long from array"}
  134. java_bytecodes[0x30]={operation="faload", description="Load float from array"}
  135. java_bytecodes[0x31]={operation="daload", description="Load double from array"}
  136. java_bytecodes[0x32]={operation="aaload", description="Load reference from array"}
  137. java_bytecodes[0x33]={operation="baload", description="Load byte or boolean from array"}
  138. java_bytecodes[0x34]={operation="caload", description="Load char from array"}
  139. java_bytecodes[0x35]={operation="saload", description="Load short from array"}
  140. java_bytecodes[0x36]={operation="istore", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, wideparameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Store float into local variable"}
  141. java_bytecodes[0x37]={operation="lstore", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, wideparameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Store float into local variable"}
  142. java_bytecodes[0x38]={operation="fstore", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, wideparameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Store float into local variable"}
  143. java_bytecodes[0x39]={operation="dstore", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, wideparameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Store double into local variable"}
  144. java_bytecodes[0x3a]={operation="astore", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, wideparameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Store reference into local variable"}
  145. java_bytecodes[0x3b]={operation="istore_0", description="Store int into local variable at index 0"}
  146. java_bytecodes[0x3c]={operation="istore_1", description="Store int into local variable at index 1"}
  147. java_bytecodes[0x3d]={operation="istore_2", description="Store int into local variable at index 2"}
  148. java_bytecodes[0x3e]={operation="istore_3", description="Store int into local variable at index 3"}
  149. java_bytecodes[0x3f]={operation="lstore_0", description="Store long into local variable at index 0"}
  150. java_bytecodes[0x40]={operation="lstore_1", description="Store long into local variable at index 1"}
  151. java_bytecodes[0x41]={operation="lstore_2", description="Store long into local variable at index 2"}
  152. java_bytecodes[0x42]={operation="lstore_3", description="Store long into local variable at index 3"}
  153. java_bytecodes[0x43]={operation="fstore_0", description="Store float into local variable at index 0"}
  154. java_bytecodes[0x44]={operation="fstore_1", description="Store float into local variable at index 1"}
  155. java_bytecodes[0x45]={operation="fstore_2", description="Store float into local variable at index 2"}
  156. java_bytecodes[0x46]={operation="fstore_3", description="Store float into local variable at index 3"}
  157. java_bytecodes[0x47]={operation="dstore_0", description="Store double into local variable at index 0"}
  158. java_bytecodes[0x48]={operation="dstore_1", description="Store double into local variable at index 1"}
  159. java_bytecodes[0x49]={operation="dstore_2", description="Store double into local variable at index 2"}
  160. java_bytecodes[0x4a]={operation="dstore_3", description="Store double into local variable at index 3"}
  161. java_bytecodes[0x4b]={operation="astore_0", description="Store reference into local variable at index 0"}
  162. java_bytecodes[0x4c]={operation="astore_1", description="Store reference into local variable at index 1"}
  163. java_bytecodes[0x4d]={operation="astore_2", description="Store reference into local variable at index 2"}
  164. java_bytecodes[0x4e]={operation="astore_3", description="Store reference into local variable at index 3"}
  165. java_bytecodes[0x4f]={operation="iastore", description="Store into int array"}
  166. java_bytecodes[0x50]={operation="lastore", description="Store into long array"}
  167. java_bytecodes[0x51]={operation="fastore", description="Store into float array"}
  168. java_bytecodes[0x52]={operation="dastore", description="Store into double array"}
  169. java_bytecodes[0x53]={operation="aastore", description="Store into reference array"}
  170. java_bytecodes[0x54]={operation="bastore", description="Store into byte or boolean array"}
  171. java_bytecodes[0x55]={operation="castore", description="Store into char array"}
  172. java_bytecodes[0x56]={operation="sastore", description="Store into short array"}
  173. java_bytecodes[0x57]={operation="pop", description="Pop the top operand stack value"}
  174. java_bytecodes[0x58]={operation="pop", description="Pop the top one or two operand stack values"}
  175. java_bytecodes[0x59]={operation="dup", description="Duplicate the top operand stack value"}
  176. java_bytecodes[0x5a]={operation="dup_x1", description="Duplicate the top operand stack value and insert two values down"}
  177. java_bytecodes[0x5b]={operation="dup_x2", description="Duplicate the top operand stack value and insert three values down"}
  178. java_bytecodes[0x5c]={operation="dup2", description="Duplicate the top one or two operand stack values"}
  179. java_bytecodes[0x5d]={operation="dup2_x1", description="Duplicate the top one or two operand stack values and insert two or three values down"}
  180. java_bytecodes[0x5e]={operation="dup2_x2", description="Duplicate the top one or two operand stack values and insert two, three, or four values down "}
  181. java_bytecodes[0x5f]={operation="swap", description="Swap the two operand stack values"}
  182. java_bytecodes[0x60]={operation="iadd", description="Add int"}
  183. java_bytecodes[0x61]={operation="ladd", description="Add long"}
  184. java_bytecodes[0x62]={operation="fadd", description="Add float"}
  185. java_bytecodes[0x63]={operation="dadd", description="Add double"}
  186. java_bytecodes[0x64]={operation="isub", description="Subtract int"}
  187. java_bytecodes[0x65]={operation="lsub", description="Subtract long"}
  188. java_bytecodes[0x66]={operation="fsub", description="Subtract float"}
  189. java_bytecodes[0x67]={operation="dsub", description="Subtract double"}
  190. java_bytecodes[0x68]={operation="imul", description="Multiply int"}
  191. java_bytecodes[0x69]={operation="lmul", description="Multiply long"}
  192. java_bytecodes[0x6a]={operation="fmul", description="Multiply float"}
  193. java_bytecodes[0x6b]={operation="dmul", description="Multiply double"}
  194. java_bytecodes[0x6c]={operation="idiv", description="Divide int"}
  195. java_bytecodes[0x6d]={operation="ldiv", description="Divide long"}
  196. java_bytecodes[0x6e]={operation="fdiv", description="Divide float"}
  197. java_bytecodes[0x6f]={operation="ddiv", description="Divide double"}
  198. java_bytecodes[0x70]={operation="irem", description="Remainder int"}
  199. java_bytecodes[0x71]={operation="lrem", description="Remainder long"}
  200. java_bytecodes[0x72]={operation="frem", description="Remainder float"}
  201. java_bytecodes[0x73]={operation="drem", description="Remainder double"}
  202. java_bytecodes[0x74]={operation="ineg", description="Negate int"}
  203. java_bytecodes[0x75]={operation="lneg", description="Negate long"}
  204. java_bytecodes[0x76]={operation="fneg", description="Negate float"}
  205. java_bytecodes[0x77]={operation="dneg", description="Negate double"}
  206. java_bytecodes[0x78]={operation="ishl", description="Shift left int"}
  207. java_bytecodes[0x79]={operation="lshl", description="Shift left long"}
  208. java_bytecodes[0x7a]={operation="ishr", description="Shift right int"}
  209. java_bytecodes[0x7b]={operation="lshr", description="Aritmetic shift right long"}
  210. java_bytecodes[0x7c]={operation="iushr", description="Logical shift right int"}
  211. java_bytecodes[0x7d]={operation="lushr", description="Logical shift right long"}
  212. java_bytecodes[0x7e]={operation="iand", description="Boolean AND int"}
  213. java_bytecodes[0x7f]={operation="land", description="Boolean AND long"}
  214. java_bytecodes[0x80]={operation="ior", description="Boolean OR int"}
  215. java_bytecodes[0x81]={operation="lor", description="Boolean OR long"}
  216. java_bytecodes[0x82]={operation="ixor", description="Boolean XOR int"}
  217. java_bytecodes[0x83]={operation="lxor", description="Boolean XOR long"}
  218. java_bytecodes[0x84]={operation="iinc", parameters={bytecount=2, {paramname="index", paramtype="u1"}, {paramname="const", paramtype="s1"}}, wideparameters={bytecount=4, {paramname="index", paramtype="u2"}, {paramname="const", paramtype="s2"}}, description="Increment local variable by constant"}
  219. java_bytecodes[0x85]={operation="i2l", description="Convert int to long"}
  220. java_bytecodes[0x86]={operation="i2f", description="Convert int to float"}
  221. java_bytecodes[0x87]={operation="i2d", description="Convert int to double"}
  222. java_bytecodes[0x88]={operation="l2i", description="Convert long to int"}
  223. java_bytecodes[0x89]={operation="l2f", description="Convert long to float"}
  224. java_bytecodes[0x8a]={operation="l2d", description="Convert long to double"}
  225. java_bytecodes[0x8b]={operation="f2i", description="Convert float to int"}
  226. java_bytecodes[0x8c]={operation="f2l", description="Convert float to long"}
  227. java_bytecodes[0x8d]={operation="f2d", description="Convert float to double"}
  228. java_bytecodes[0x8e]={operation="d2i", description="Convert double to int"}
  229. java_bytecodes[0x8f]={operation="d2l", description="Convert double to long"}
  230. java_bytecodes[0x90]={operation="d2f", description="Convert double to float"}
  231. java_bytecodes[0x91]={operation="i2b", description="Convert int to byte"}
  232. java_bytecodes[0x92]={operation="i2c", description="Convert int to char"}
  233. java_bytecodes[0x93]={operation="i2s", description="Convert int to short"}
  234. java_bytecodes[0x94]={operation="lcmp", description="Compare long"}
  235. java_bytecodes[0x95]={operation="fcmpl", description="Compare float"}
  236. java_bytecodes[0x96]={operation="fcmpg", description="Compare float"}
  237. java_bytecodes[0x97]={operation="dcmpl", description="Compare double"}
  238. java_bytecodes[0x98]={operation="dcmpg", description="Compare double"}
  239. java_bytecodes[0x99]={operation="ifeq", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison with 0 is equal"}
  240. java_bytecodes[0x9a]={operation="ifne", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison with 0 is not equal"}
  241. java_bytecodes[0x9b]={operation="iflt", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison with 0 is less"}
  242. java_bytecodes[0x9c]={operation="ifge", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison with 0 is greater or equal"}
  243. java_bytecodes[0x9d]={operation="ifgt", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison with 0 is greater"}
  244. java_bytecodes[0x9e]={operation="ifle", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison with 0 is less or equal"}
  245. java_bytecodes[0x9f]={operation="if_icmpeq", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison is equal"}
  246. java_bytecodes[0xa0]={operation="if_icmpne", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison is not equal"}
  247. java_bytecodes[0xa1]={operation="if_icmplt", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison is less"}
  248. java_bytecodes[0xa2]={operation="if_icmpge", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison is greater or equal"}
  249. java_bytecodes[0xa3]={operation="if_icmpgt", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison is greater"}
  250. java_bytecodes[0xa4]={operation="if_icmple", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if int comparison is less or equal"}
  251. java_bytecodes[0xa5]={operation="if_acmpeq", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if reference comparison is true"}
  252. java_bytecodes[0xa6]={operation="if_acmpne", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if reference comparison is false"}
  253. java_bytecodes[0xa7]={operation="goto", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch always"}
  254. java_bytecodes[0xa8]={operation="jsr", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Jump subroutine"}
  255. java_bytecodes[0xa9]={operation="ret", parameters={bytecount=1, {paramname="index", paramtype="u1"}}, description="Return from subroutine"}
  256. java_bytecodes[0xaa]={operation="tableswitch", parameters={bytecount=calculateTableSwitch, {paramname="padding", paramtype="pad4"}, {paramname="default", paramtype="s4"},{paramname="low", paramtype="s4"},{paramname="high", paramtype="s4"},{paramname="array",paramtype="[s4]"}}, description="Access jump table by key match and jump"}
  257. java_bytecodes[0xab]={operation="lookupswitch", parameters={bytecount=calculateLookupSwitch, {paramname="padding", paramtype="pad4"}, {paramname="default", paramtype="s4"},{paramname="npairs", paramtype="s4"},{paramname="array",paramtype="[s4s4]"}}, description="Access jump table by key match and jump"}
  258. java_bytecodes[0xac]={operation="ireturn", description="Return int from method"}
  259. java_bytecodes[0xad]={operation="lreturn", description="Return long from method"}
  260. java_bytecodes[0xae]={operation="freturn", description="Return float from method"}
  261. java_bytecodes[0xaf]={operation="dreturn", description="Return double from method"}
  262. java_bytecodes[0xb0]={operation="areturn", description="Return reference from method"}
  263. java_bytecodes[0xb1]={operation="return", description="Return void from method"}
  264. java_bytecodes[0xb2]={operation="getstatic", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Get static field from class"}
  265. java_bytecodes[0xb3]={operation="putstatic", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Set static field in class"}
  266. java_bytecodes[0xb4]={operation="getfield", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Fetch field from object"}
  267. java_bytecodes[0xb5]={operation="putfield", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Set field in object"}
  268. java_bytecodes[0xb6]={operation="invokevirtual", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Invoke instance method; dispatch based on class"}
  269. java_bytecodes[0xb7]={operation="invokespecial", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Invoke instance method; special handling for superclass, private, and instance initialization method invocations"}
  270. java_bytecodes[0xb8]={operation="invokestatic", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Invoke static method"}
  271. java_bytecodes[0xb9]={operation="invokeinterface", parameters={bytecount=4, {paramname="index", paramtype="u2"}, {paramname="count", paramtype="u1"}, {paramname="null", paramtype="01"}}, description="Invoke interface method"}
  272. java_bytecodes[0xba]={operation="invokedynamic", parameters={bytecount=4, {paramname="index", paramtype="u2"}, {paramname="null", paramtype="02"}}, description="Invoke dynamic method"}
  273. java_bytecodes[0xbb]={operation="new", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Create new object"}
  274. java_bytecodes[0xbc]={operation="newarray", parameters={bytecount=2, {paramname="atype", paramtype="u1"}}, description="Create new array"}
  275. java_bytecodes[0xbd]={operation="anewarray", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Create new array of reference"}
  276. java_bytecodes[0xbe]={operation="arraylength", description="Get length of array"}
  277. java_bytecodes[0xbf]={operation="athrow", description="Throw exception or error"}
  278. java_bytecodes[0xc0]={operation="checkcast", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Check wheter object is of given type"}
  279. java_bytecodes[0xc1]={operation="instanceof", parameters={bytecount=2, {paramname="index", paramtype="u2"}}, description="Determine if object is of given type"}
  280. java_bytecodes[0xc2]={operation="monitorenter", description="Enter monitor for object"}
  281. java_bytecodes[0xc3]={operation="monitorexit", description="Exit monitor for object"}
  282. java_bytecodes[0xc4]={operation="wide", parameters={bytecount=nil, {paramname="instruction", paramtype="wide"}}, description="Extend local variable index by additional bytes"}
  283. java_bytecodes[0xc5]={operation="multianewarray", parameters={bytecount=3, {paramname="index", paramtype="u2"}, {paramname="dimensions", paramtype="u1"}}, description="Create new multidimensional array"}
  284. java_bytecodes[0xc6]={operation="ifnull", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if reference is null"}
  285. java_bytecodes[0xc7]={operation="ifnonnull", parameters={bytecount=2, {paramname="branchoffset", paramtype="s2"}}, description="Branch if reference is not null"}
  286. java_bytecodes[0xc8]={operation="goto_w", parameters={bytecount=4, {paramname="branchoffset", paramtype="s4"}}, description="Branch always(wide)"}
  287. java_bytecodes[0xc9]={operation="jsr_w", parameters={bytecount=4, {paramname="branchoffset", paramtype="s4"}}, description="Jump subroutine(wide)"}
  288. java_operations={}
  289. function java_buildoptobytecodetable()
  290. --parse through java_bytecodes and fill in java_operations
  291. for x,y in pairs(java_bytecodes) do
  292. java_operations[y.operation]=java_bytecodes[x]
  293. java_operations[y.operation].byte=x
  294. end
  295. end
  296. function bytecodeDisassembler(bytes)
  297. --note: Bytes start at index 1. Some instructions like values on an alignment of 4 byte, so keep in mind that that is (address-1) % 4
  298. local i,j
  299. result={}
  300. result.labels={}
  301. local byteindex=1
  302. local index=1
  303. while byteindex<=#bytes do
  304. local startindex=byteindex
  305. local wide=false
  306. if bytes[byteindex]==0xc4 then --wide
  307. wide=true
  308. byteindex=byteindex+1
  309. end
  310. local data=java_bytecodes[bytes[byteindex]]
  311. result[index]={}
  312. result[index].data=data
  313. result[index].operation=data.operation
  314. result[index].parameter=''
  315. result[index].byteindex=startindex-1
  316. local parameters=data.parameters
  317. if wide then
  318. parameters=data.wideparameters
  319. end
  320. if parameters~=nil then
  321. for i=1,#parameters do
  322. if parameters[i].paramtype=='s1' then
  323. result[index].parameter=result[index].parameter..signExtendByte(bytes[byteindex+1])..' '
  324. elseif parameters[i].paramtype=='s2' then
  325. result[index].parameter=result[index].parameter..signExtendWord(byteTableToWord({bytes[byteindex+2], bytes[byteindex+1]}))..' '
  326. elseif parameters[i].paramtype=='s4' then
  327. result[index].parameter=result[index].parameter..signExtendWord(byteTableToDword({bytes[byteindex+4], bytes[byteindex+3], bytes[byteindex+2], bytes[byteindex+1]}))..' '
  328. elseif parameters[i].paramtype=='u1' then
  329. result[index].parameter=result[index].parameter..bytes[byteindex+1]..' '
  330. elseif parameters[i].paramtype=='u2' then
  331. result[index].parameter=result[index].parameter..byteTableToWord({bytes[byteindex+2], bytes[byteindex+1]})..' '
  332. elseif parameters[i].paramtype=='u4' then
  333. result[index].parameter=result[index].parameter..byteTableToDword({bytes[byteindex+4], bytes[byteindex+3], bytes[byteindex+2], bytes[byteindex+1]})..' '
  334. end
  335. if (i==1) and (parameters[i].paramname=="branchoffset") then
  336. local destination=tonumber(result[index].byteindex+result[index].parameter)
  337. local label=nil
  338. for j=1, #result.labels do
  339. --check if it's already defined
  340. if result.labels[j].destination==destination then
  341. label=result.labels[j]
  342. break
  343. end
  344. end
  345. if label==nil then
  346. --new label, define it
  347. label={}
  348. label.destination=destination
  349. label.labelname='lbl'..(#result.labels+1)
  350. label.origins={}
  351. table.insert(result.labels, label)
  352. end
  353. result[index].parameter='lbl'..#result.labels
  354. table.insert(label.origins, startindex)
  355. end
  356. end
  357. end
  358. if parameters==nil then
  359. result[index].bytesize=1
  360. else
  361. if type(parameters.bytecount)=='function' then
  362. result[index].bytesize=1+parameters.bytecount(byteindex, bytes)
  363. else
  364. result[index].bytesize=1+parameters.bytecount
  365. end
  366. end
  367. --copy the bytes
  368. result[index].bytes={}
  369. for j=startindex, startindex+result[index].bytesize-1 do
  370. result[index].bytes[1+(j-startindex)]=bytes[j]
  371. end
  372. byteindex=byteindex+result[index].bytesize
  373. index=index+1
  374. end
  375. return result
  376. end
  377. function singleLineBytecodeAssembler(address, instruction, labels, updatelabels)
  378. local result=nil
  379. local operation
  380. local parameterstring
  381. local userparameters={}
  382. local wide=false
  383. local i,j,s
  384. s=0
  385. i=0
  386. for s in string.gmatch(instruction, "%S+") do
  387. if i==0 then
  388. if s~='wide' then
  389. operation=s
  390. i=i+1
  391. else
  392. wide=true
  393. end
  394. else
  395. userparameters[i]=s
  396. i=i+1
  397. end
  398. end
  399. parameterstring=''
  400. for i=1, #userparameters do
  401. parameterstring=parameterstring..userparameters[i]..' '
  402. end
  403. local data=java_operations[operation]
  404. if data~=nil then
  405. if type(data.bytecount)=='function' then
  406. error(data.operation..' is currently not implemented')
  407. end
  408. result={}
  409. result.bytes={}
  410. result.data=data
  411. result.operation=data.operation
  412. result.byteindex=address
  413. result.parameters=userparams
  414. result.parameter=parameterstring
  415. local parameters
  416. if wide then
  417. parameters=data.wideparameters
  418. if parameters==nil then
  419. error('wide can not be used with '..data.operation)
  420. end
  421. table.insert(result, 0xc4)
  422. else
  423. parameters=data.parameters
  424. end
  425. table.insert(result.bytes, data.byte)
  426. if parameters~=nil then
  427. if #userparameters~=#parameters then
  428. error('Invalid amount of parameters provided for '..data.operation)
  429. end
  430. for i=1, #parameters do
  431. local bytes={}
  432. if (i==1) and (parameters[i].paramname=="branchoffset") then --this instruction has a label reference
  433. --convert the parameter to the current label
  434. local label=nil
  435. if labels~=nil then
  436. for j=1, #labels do
  437. if labels[j].labelname==result.parameters[i] then
  438. label=labels[j]
  439. result.parameters[i]=labels[j].destination-address
  440. end
  441. end
  442. end
  443. if tonumber(result.parameters[i])==nil then
  444. error("The label "..userparameters[i].."is not yet defined")
  445. end
  446. if (updatelabels~=nil) and (updatelabels==true) then
  447. if label==nil then --add it
  448. label={}
  449. label.destination=result.parameters[i]
  450. label.labelname='lbl'..(#labels+1)
  451. label.origins={}
  452. table.insert(labels, label)
  453. end
  454. table.insert(label.origins, address)
  455. end
  456. end
  457. if parameters[i].paramtype=='s1' then
  458. bytes={tonumber(userparameters[i]) % 256}
  459. elseif parameters[i].paramtype=='s2' then
  460. bytes=wordToByteTable(tonumber(userparameters[i]) % 65536)
  461. elseif parameters[i].paramtype=='s4' then
  462. bytes=dwordToByteTable(tonumber(userparameters[i]) % 65536)
  463. elseif parameters[i].paramtype=='u1' then
  464. bytes={tonumber(userparameters[i]) % 256}
  465. elseif parameters[i].paramtype=='u2' then
  466. bytes=wordToByteTable(tonumber(userparameters[i]) % 65536)
  467. elseif parameters[i].paramtype=='u4' then
  468. bytes=dwordToByteTable(tonumber(userparameters[i]) % 65536)
  469. else
  470. error('This instruction is currently not implemented')
  471. end
  472. for j=1, #bytes do
  473. table.insert(result.bytes, bytes[j])
  474. end
  475. end
  476. end
  477. result.bytesize=#result.bytes
  478. else
  479. error('unknown instruction:'..operation);
  480. end
  481. return result
  482. end
  483. function javaclass_applyAssembleCommand(class, method, byteindex, instruction, insert)
  484. local codeattribute=javaclass_method_findCodeAttribute(method)
  485. local labels=codeattribute.code.labels
  486. local exceptions=codeattribute.exception_table
  487. --get the size of the instruction to be assembled (plus side: unlike intel with it's horrible and easily reachable 128 byte limit for small branches, java gives 32768 bytes, so less chance of an insertion causing problems)
  488. local newcode
  489. local codeattribute_codeIndex=nil
  490. newcode=singleLineBytecodeAssembler(byteindex, instruction, labels,false) --get the size, but don't mess with the labels
  491. local i,j
  492. local startindex=byteindex
  493. local offset=0
  494. --update the labels and exception table based on the size
  495. startindex=byteindex
  496. if insert then
  497. offset=newcode.bytesize
  498. else
  499. local oldcode=nil
  500. for i=1, #codeattribute.code do
  501. if codeattribute.code[i].byteindex==byteindex then
  502. oldcode=codeattribute.code[i]
  503. break
  504. end
  505. end
  506. if oldcode==nil then
  507. error('You can only replace instructions on an instruction boundary')
  508. end
  509. offset=newcode.bytesize-oldcode.bytesize
  510. end
  511. javaclass_updateOffsets(class, method, startindex, offset)
  512. --labels and other byteindex are updated. Now you can insert/modify the instruction
  513. newcode=singleLineBytecodeAssembler(byteindex, instruction, labels,true)
  514. local currentbyteindex=0
  515. for i=1, #codeattribute.code do
  516. if insert then
  517. --the byteindex has already been updated
  518. if currentbyteindex==byteindex then
  519. table.insert(codeattribute.code, i, newcode)
  520. break
  521. end
  522. else
  523. if currentbyteindex==byteindex then
  524. codeattribute.code[i]=newcode
  525. break
  526. end
  527. end
  528. currentbyteindex=currentbyteindex+codeattribute.code[i].bytesize
  529. end
  530. end
  531. function javaclass_updateOffsets(class, method, startindex, offset)
  532. print("si="..startindex.." offset="..offset)
  533. local i,j
  534. local codeattribute=javaclass_method_findCodeAttribute(method)
  535. local code=codeattribute.code
  536. local labels=codeattribute.code.labels
  537. local exceptions=codeattribute.exception_table
  538. for i=1, #labels do
  539. if labels[i].destination>=startindex then --the destination has been updated
  540. labels[i].destination=labels[i].destination+offset
  541. end
  542. for j=1, #labels[i].origins do
  543. local originaladdress=labels[i].origins[j]
  544. if originaladdress>=startindex then --this got shifted as well
  545. labels[i].origins[j]=originaladdress+offset
  546. end
  547. --adjust this branch instruction (note though, if originaddress was bigger than destination address, there should be no branchoffset change)
  548. --find the instruction in the code
  549. local k
  550. for k=1, #codeattribute.code do
  551. if codeattribute.code[k].byteindex==originaladdress then --check the original address (the byteindex hasn't been updated)
  552. local size=codeattribute.code[k].dataparameters[1].paramtype:sub(2,2) --branches only have type s2 or s4
  553. local newbranchoffset=labels[i].destination-labels[i].origins[j]
  554. local newbytes
  555. if size=='2' then --remember, it's big endian
  556. newbytes=wordToByteTable(newbranchoffset)
  557. codeattribute.code[k].bytes[2]=newbytes[2]
  558. codeattribute.code[k].bytes[3]=newbytes[1]
  559. elseif size=='4' then
  560. newbytes=dwordToByteTable(newbranchoffset)
  561. codeattribute.code[k].bytes[2]=newbytes[4]
  562. codeattribute.code[k].bytes[3]=newbytes[3]
  563. codeattribute.code[k].bytes[4]=newbytes[2]
  564. codeattribute.code[k].bytes[5]=newbytes[1]
  565. end
  566. end
  567. end
  568. end
  569. end
  570. --update tableswitch and lookupswitch commands
  571. for i=1,#code do
  572. if code[i].data.byte==0xaa then
  573. --tableswitch
  574. local defaultbyteindex=code[i].byteindex+1
  575. local defaultindex=2
  576. --find alignment padding
  577. local rest=defaultbyteindex%4
  578. if rest>0 then
  579. defaultindex=defaultindex+(4-rest)
  580. defaultbyteindex=defaultbyteindex+(4-rest)
  581. end
  582. local lowindex=defaultindex+4
  583. local highindex=lowindex+4
  584. local offsetindex=highindex+4
  585. local low=byteTableToDword({code[i].bytes[lowindex+3], code[i].bytes[lowindex+2], code[i].bytes[lowindex+1], code[i].bytes[lowindex]}) --big endian
  586. local high=byteTableToDword({code[i].bytes[highindex+3], code[i].bytes[highindex+2], code[i].bytes[highindex+1], code[i].bytes[highindex]})
  587. local count=high-low+1
  588. for j=1,count do
  589. local currentoffsetindex=offsetindex+(i-1)*4
  590. local currentoffset=byteTableToDword({code[i].bytes[currentoffsetindex+3], code[i].bytes[currentoffsetindex+2], code[i].bytes[currentoffsetindex+1], code[i].bytes[currentoffsetindex]})
  591. if currentoffset>=startindex then
  592. --update the address it points to
  593. currentoffset=currentoffset+offset
  594. local newbytes=dwordToByteTable(currentoffset)
  595. code.bytes[currentoffsetindex]=newbytes[4]
  596. code.bytes[currentoffsetindex+1]=newbytes[3]
  597. code.bytes[currentoffsetindex+2]=newbytes[2]
  598. code.bytes[currentoffsetindex+3]=newbytes[1]
  599. end
  600. end
  601. elseif code[i].data.byte==0xab then
  602. --lookupswitch
  603. local defaultbyteindex=code[i].byteindex+1
  604. local defaultindex=2
  605. --find alignment padding
  606. local rest=defaultbyteindex%4
  607. if rest>0 then
  608. defaultindex=defaultindex+(4-rest)
  609. defaultbyteindex=defaultbyteindex+(4-rest)
  610. end
  611. local countindex=defaultindex+4
  612. local count=byteTableToDword({code[i].bytes[countindex+3], code[i].bytes[countindex+2], code[i].bytes[countindex+1], code[i].bytes[countindex]})
  613. for j=1,count do
  614. local currentoffsetindex=countindex+(j-1)*8+4
  615. local currentoffset=byteTableToDword({code[i].bytes[currentoffsetindex+3], code[i].bytes[currentoffsetindex+2], code[i].bytes[currentoffsetindex+1], code[i].bytes[currentoffsetindex]})
  616. if currentoffset>=startindex then
  617. --update the address it points to
  618. currentoffset=currentoffset+offset
  619. local newbytes=dwordToByteTable(currentoffset)
  620. code.bytes[currentoffsetindex]=newbytes[4]
  621. code.bytes[currentoffsetindex+1]=newbytes[3]
  622. code.bytes[currentoffsetindex+2]=newbytes[2]
  623. code.bytes[currentoffsetindex+3]=newbytes[1]
  624. end
  625. end
  626. end
  627. end
  628. --update the exception table
  629. for i=1, #exceptions do
  630. if exceptions[i].start_pc>=startindex then
  631. exceptions[i].start_pc=exceptions[i].start_pc+offset
  632. end
  633. if exceptions[i].start_pc>=startindex then
  634. exceptions[i].end_pc=exceptions[i].end_pc+offset
  635. end
  636. if exceptions[i].start_pc>=startindex then
  637. exceptions[i].handler_pc=exceptions[i].handler_pc+offset
  638. end
  639. end
  640. --finally update the byteindexes
  641. for i=1, #codeattribute.code do
  642. if codeattribute.code[i].byteindex>=startindex then
  643. codeattribute.code[i].byteindex=codeattribute.code[i].byteindex+offset
  644. end
  645. end
  646. end
  647. function javaclasseditor_editMethod_fillInstructionsListview(lv, method)
  648. local i
  649. local codeattribute=javaclass_method_findCodeAttribute(method)
  650. local code=codeattribute.code
  651. local labels=code.labels
  652. local exceptions=codeattribute.exception_table
  653. local haslabels=false
  654. local hasexceptions=false
  655. lv.Items.clear()
  656. for i=1, #code do
  657. local j
  658. local item=lv.Items.add()
  659. local bytestring=''
  660. item.Caption=i-1
  661. for j=1, code[i].bytesize do
  662. bytestring=bytestring..string.format("%.2x ", code[i].bytes[j])
  663. end
  664. item.SubItems.Add(code[i].byteindex .. ':'..bytestring) --display as 0 start
  665. local labelname=''
  666. if #labels>0 then
  667. haslabels=true
  668. for j=1, #labels do
  669. if code[i].byteindex==labels[j].destination then
  670. labelname='lbl'..j
  671. break
  672. end
  673. end
  674. end
  675. local exceptionstr=''
  676. if #exceptions>0 then
  677. hasexceptions=true
  678. for j=1, #exceptions do
  679. if code[i].byteindex==exceptions[j].start_pc then
  680. exceptionstr=exceptionstr..'start'..j..' '
  681. end
  682. if code[i].byteindex==exceptions[j].end_pc then
  683. exceptionstr=exceptionstr..'end'..j..' '
  684. end
  685. if code[i].byteindex==exceptions[j].handler_pc then
  686. exceptionstr=exceptionstr..'handler'..j..' '
  687. end
  688. end
  689. end
  690. item.SubItems.Add(labelname)
  691. item.SubItems.Add(exceptionstr)
  692. item.SubItems.Add(code[i].operation..' '..code[i].parameter)
  693. end
  694. end
  695. function javaclasseditor_editMethod_insertLine(sender)
  696. local classMethod=getRef(sender.Tag)
  697. local codeattribute=javaclass_method_findCodeAttribute(classMethod.method)
  698. local code=codeattribute.code
  699. local lv=classMethod.method.editor.lvInstructions
  700. local linenr
  701. if lv.Selected==nil then
  702. linenr=0
  703. else
  704. linenr=lv.Selected.Index
  705. end
  706. local byteindex=code[linenr+1].byteindex
  707. local line=inputQuery('Insert line', 'Input the java assembly code you wish to insert at line '..linenr..'(byteindex '..byteindex..')','')
  708. if line~=nil then
  709. --showMessage('Assembling '..line)
  710. --assemble
  711. javaclass_applyAssembleCommand(classMethod.class, classMethod.method, byteindex, line, true)
  712. --show update
  713. javaclasseditor_editMethod_fillInstructionsListview(classMethod.method.editor.lvInstructions, classMethod.method)
  714. end
  715. end
  716. function javaclasseditor_editMethod_editLine(sender)
  717. local classMethod=getRef(sender.Tag)
  718. local codeattribute=javaclass_method_findCodeAttribute(classMethod.method)
  719. local code=codeattribute.code
  720. local lv=classMethod.method.editor.lvInstructions
  721. local linenr
  722. if lv.Selected==nil then
  723. return
  724. else
  725. linenr=lv.Selected.Index
  726. end
  727. local byteindex=code[linenr+1].byteindex
  728. local originalcode=code[linenr+1].operation..' '..code[linenr+1].parameter
  729. local line=inputQuery('Edit line', 'Input the java assembly code you wish to insert at line '..linenr..'(byteindex '..byteindex..')',originalcode)
  730. if line~=nil then
  731. javaclass_applyAssembleCommand(classMethod.class, classMethod.method, byteindex, line, false)
  732. --show update
  733. javaclasseditor_editMethod_fillInstructionsListview(classMethod.method.editor.lvInstructions, classMethod.method)
  734. end
  735. end
  736. function javaclasseditor_editMethod_defineLabel(sender)
  737. local classMethod=getRef(sender.Tag)
  738. local codeattribute=javaclass_method_findCodeAttribute(classMethod.method)
  739. local code=codeattribute.code
  740. local labels=code.labels
  741. local lv=classMethod.method.editor.lvInstructions
  742. local linenr
  743. if lv.Selected==nil then
  744. return
  745. else
  746. linenr=lv.Selected.Index
  747. end
  748. local byteindex=code[linenr+1].byteindex
  749. local labelname=inputQuery('Define new label', 'Give a labelname for line '..linenr..'(byteindex '..byteindex..')','')
  750. if (labelname~=nil) and (labelname~='') then
  751. local i
  752. --check if it already exists
  753. for i=1,#labels do
  754. if labels[i].labelname==labelname then
  755. error('There is already a label with this name')
  756. end
  757. end
  758. --still here, so the it wasn't in the list
  759. local newlabel={}
  760. newlabel.labelname=labelname
  761. newlabel.destination=byteindex
  762. newlabel.origins={}
  763. table.insert(labels, newlabel)
  764. end
  765. end
  766. function javaclasseditor_editMethod_applyUpdates(method)
  767. --converts the bytes of the interpreted code into the .info field of the code attribute (used by the writer)
  768. local i
  769. local codeattribute=javaclass_method_findCodeAttribute(method)
  770. local code=codeattribute.code
  771. codeattribute.max_stack=tonumber(method.editor.edtMaxStack.Text)
  772. codeattribute.max_locals=tonumber(method.editor.edtMaxLocals.Text)
  773. ca=codeattribute
  774. local s={} --write stream
  775. s.data=''
  776. s.index=0 --not really needed by writes but helps with debugging
  777. java_write_u2(s, codeattribute.max_stack)
  778. java_write_u2(s, codeattribute.max_locals)
  779. local bytesize=0
  780. for i=1,#code do
  781. bytesize=bytesize+#code[i].bytes
  782. end
  783. java_write_u4(s, bytesize) --code_length
  784. for i=1,#code do
  785. local j
  786. for j=1,#code[i].bytes do
  787. s.data=s.data..string.char(code[i].bytes[j])
  788. end
  789. end
  790. s.index=s.index+#code
  791. --exception table (genius to allow code size to be specified by 4 bytes but not exception addresses)
  792. java_write_u2(s, codeattribute.exception_table_length);
  793. for i=1, codeattribute.exception_table_length do
  794. java_write_u2(s, codeattribute.exception_table[i].start_pc)
  795. java_write_u2(s, codeattribute.exception_table[i].end_pc)
  796. java_write_u2(s, codeattribute.exception_table[i].handler_pc)
  797. java_write_u2(s, codeattribute.exception_table[i].catch_type)
  798. end
  799. java_write_u2(s, codeattribute.attributes_count)
  800. java_writeAttributes(s, codeattribute.attributes, codeattribute.attributes_count)
  801. print(string.format("old bsize=%d new bsize=%d", codeattribute.code_length, bytesize))
  802. print(string.format("old size=%d new size=%d", #codeattribute.info, #s.data))
  803. codeattribute.info=s.data
  804. codeattribute.attribute_length=#codeattribute.info
  805. end
  806. function btnApplyChangesClick(sender)
  807. --apply the changes
  808. local classMethod=getRef(sender.Tag)
  809. local method=classMethod.method
  810. javaclasseditor_editMethod_applyUpdates(method)
  811. if method.editor.callbackfunction~=nil then
  812. method.editor.callbackfunction(classMethod.class, method.editor.callbackparam)
  813. end
  814. end
  815. function javaclasseditor_editMethod(class, method, callbackfunction, callbackparam)
  816. --create a gui for this method
  817. --note that throughout this file we call the parsed class "class". It's not the jclass object
  818. if method.editor==nil then
  819. local ca=javaclass_method_findCodeAttribute(method)
  820. local classMethodRef=createRef({class=class, method=method})
  821. --build a gui
  822. method.editor={}
  823. method.editor.form=createForm()
  824. method.editor.form.onClose=nil --do not destroy on close
  825. method.editor.form.tag=classMethodRef --this way gui launched functions can find the base form and fetch this data if it needs it
  826. method.editor.form.borderstyle=bsSizeable
  827. method.editor.form.width=640
  828. method.editor.form.height=480
  829. method.editor.form.caption="Method: "..class.constant_pool[class.constant_pool[class.this_class].name_index].utf8.."."..class.constant_pool[method.name_index].utf8
  830. method.editor.form.Position=poScreenCenter
  831. method.editor.lblMaxStack=createLabel(method.editor.form)
  832. method.editor.lblMaxLocals=createLabel(method.editor.form)
  833. method.editor.lblMaxStack.caption="Max Stack"
  834. method.editor.lblMaxLocals.caption="Max Locals"
  835. method.editor.edtMaxStack=createEdit(method.editor.form)
  836. method.editor.edtMaxLocals=createEdit(method.editor.form)
  837. method.editor.edtMaxStack.Text=ca.max_stack
  838. method.editor.edtMaxLocals.Text=ca.max_locals
  839. method.editor.lblMaxStack.AnchorSideLeft.Control=method.editor.form
  840. method.editor.lblMaxStack.AnchorSideLeft.Side=asrLeft
  841. method.editor.lblMaxStack.AnchorSideTop.Control=method.editor.form
  842. method.editor.lblMaxStack.AnchorSideTop.Side=asrTop
  843. method.editor.lblMaxStack.Anchors="[akTop, akLeft]"
  844. method.editor.edtMaxStack.AnchorSideLeft.Control=method.editor.form
  845. method.editor.edtMaxStack.AnchorSideLeft.Side=asrLeft
  846. method.editor.edtMaxStack.AnchorSideTop.Control=method.editor.lblMaxStack
  847. method.editor.edtMaxStack.AnchorSideTop.Side=asrBottom
  848. method.editor.edtMaxStack.Anchors="[akTop, akLeft]"
  849. method.editor.lblMaxLocals.AnchorSideLeft.Control=method.editor.edtMaxStack
  850. method.editor.lblMaxLocals.AnchorSideLeft.Side=asrRight
  851. method.editor.lblMaxLocals.AnchorSideTop.Control=method.editor.form
  852. method.editor.lblMaxLocals.AnchorSideTop.Side=asrTop
  853. method.editor.lblMaxLocals.BorderSpacing.Left=6
  854. method.editor.lblMaxLocals.Anchors="[akTop, akLeft]"
  855. method.editor.edtMaxLocals.AnchorSideLeft.Control=method.editor.lblMaxLocals
  856. method.editor.edtMaxLocals.AnchorSideLeft.Side=asrLeft
  857. method.editor.edtMaxLocals.AnchorSideTop.Control=method.editor.edtMaxStack
  858. method.editor.edtMaxLocals.AnchorSideTop.Side=asrTop
  859. method.editor.edtMaxLocals.Anchors="[akTop, akLeft]"
  860. method.editor.btnApplyChanges=createButton(method.editor.form)
  861. method.editor.btnApplyChanges.AutoSize=true
  862. method.editor.btnApplyChanges.Caption="Save changes"
  863. method.editor.btnApplyChanges.OnClick=btnApplyChangesClick
  864. method.editor.btnApplyChanges.Tag=classMethodRef
  865. method.editor.btnApplyChanges.AnchorSideLeft.Control=method.editor.edtMaxLocals
  866. method.editor.btnApplyChanges.AnchorSideLeft.Side=asrRight
  867. method.editor.btnApplyChanges.AnchorSideTop.Control=method.editor.edtMaxLocals
  868. method.editor.btnApplyChanges.AnchorSideTop.Side=asrTop
  869. method.editor.lblMaxLocals.BorderSpacing.Left=12
  870. method.editor.btnApplyChanges.Anchors="[akTop, akLeft]"
  871. method.editor.lvInstructions=createListView(method.editor.form)
  872. method.editor.lvInstructions.Name="lvInstructions"
  873. local columns=method.editor.lvInstructions.Columns
  874. local lcIndex=columns.add()
  875. local lcByteIndex=columns.add()
  876. local lcLabel=columns.add()
  877. local lcException=columns.add()
  878. local lcInstruction=columns.add()
  879. lcIndex.Caption="Index"
  880. lcByteIndex.Caption="ByteIndex"
  881. lcLabel.Caption="Label"
  882. lcException.Caption="Exception"
  883. lcInstruction.Caption="Instruction"
  884. lcByteIndex.width=100
  885. lcInstruction.AutoSize=true
  886. method.editor.lvInstructions.AutoWidthLastColumn=true
  887. method.editor.lvInstructions.RowSelect=true
  888. method.editor.lvInstructions.HideSelection=false
  889. method.editor.lvInstructions.ReadOnly=true
  890. method.editor.lvInstructions.AnchorSideLeft.Control=method.editor.form
  891. method.editor.lvInstructions.AnchorSideLeft.Side=asrLeft
  892. method.editor.lvInstructions.AnchorSideTop.Control=method.editor.edtMaxStack
  893. method.editor.lvInstructions.AnchorSideTop.Side=asrBottom
  894. method.editor.lvInstructions.BorderSpacing.Top=6
  895. method.editor.lvInstructions.AnchorSideRight.Control=method.editor.form
  896. method.editor.lvInstructions.AnchorSideRight.Side=asrRight
  897. method.editor.lvInstructions.AnchorSideBottom.Control=method.editor.form
  898. method.editor.lvInstructions.AnchorSideBottom.Side=asrBottom
  899. method.editor.lvInstructions.Anchors="[akTop, akLeft, akRight, akBottom]"
  900. --create a popupmenu for adding/editing lines, and adding new labels
  901. method.editor.pmEdit=createPopupMenu(method.editor.form)
  902. method.editor.pmEdit.Tag=classMethodRef
  903. local miInsertLine=createMenuItem(method.editor.pmEdit)
  904. miInsertLine.caption="Insert line"
  905. miInsertLine.onClick=javaclasseditor_editMethod_insertLine
  906. miInsertLine.Shortcut="Ctrl+I"
  907. miInsertLine.Tag=classMethodRef
  908. local miEditLine=createMenuItem(method.editor.pmEdit)
  909. miEditLine.caption="Edit line"
  910. miEditLine.onClick=javaclasseditor_editMethod_editLine
  911. miEditLine.Shortcut="Ctrl+E"
  912. miEditLine.Tag=classMethodRef
  913. local miDefineLine=createMenuItem(method.editor.pmEdit)
  914. miDefineLine.caption="Define label"
  915. miDefineLine.onClick=javaclasseditor_editMethod_defineLabel
  916. miDefineLine.Shortcut="Ctrl+L"
  917. miDefineLine.Tag=classMethodRef
  918. method.editor.lvInstructions.OnDblClick=javaclasseditor_editMethod_editLine
  919. method.editor.lvInstructions.Tag=classMethodRef
  920. method.editor.pmEdit.Items.add(miInsertLine)
  921. method.editor.pmEdit.Items.add(miEditLine)
  922. method.editor.pmEdit.Items.add(miDefineLine)
  923. method.editor.lvInstructions.PopupMenu=method.editor.pmEdit
  924. method.editor.callbackfunction=callbackfunction
  925. method.editor.callbackparam=callbackparam
  926. end
  927. javaclasseditor_editMethod_fillInstructionsListview(method.editor.lvInstructions, method)
  928. method.editor.form.show()
  929. end
  930. java_buildoptobytecodetable()