├── docs ├── n3343.pdf ├── n3375.pdf ├── n3376.doc ├── n3376.pdf ├── 01373-JEFF-Rex.pdf ├── 02042-jeff-spec.pdf ├── JEFF_SF_14March2002.pdf └── info_isoiec20970en.pdf ├── .gitattributes ├── unp_dalp.py ├── README.md ├── .gitignore ├── opcodes.py └── dump_jeff.py /docs/n3343.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skochinsky/jeff-tools/HEAD/docs/n3343.pdf -------------------------------------------------------------------------------- /docs/n3375.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skochinsky/jeff-tools/HEAD/docs/n3375.pdf -------------------------------------------------------------------------------- /docs/n3376.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skochinsky/jeff-tools/HEAD/docs/n3376.doc -------------------------------------------------------------------------------- /docs/n3376.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skochinsky/jeff-tools/HEAD/docs/n3376.pdf -------------------------------------------------------------------------------- /docs/01373-JEFF-Rex.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skochinsky/jeff-tools/HEAD/docs/01373-JEFF-Rex.pdf -------------------------------------------------------------------------------- /docs/02042-jeff-spec.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skochinsky/jeff-tools/HEAD/docs/02042-jeff-spec.pdf -------------------------------------------------------------------------------- /docs/JEFF_SF_14March2002.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skochinsky/jeff-tools/HEAD/docs/JEFF_SF_14March2002.pdf -------------------------------------------------------------------------------- /docs/info_isoiec20970en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skochinsky/jeff-tools/HEAD/docs/info_isoiec20970en.pdf -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /unp_dalp.py: -------------------------------------------------------------------------------- 1 | #unpack applets from a .dalp XML file 2 | import sys, os.path 3 | 4 | import xml.etree.ElementTree as ET 5 | infn = sys.argv[1] 6 | tree = ET.parse(infn) 7 | root = tree.getroot() 8 | name = root.find('packageInfo').find('name').text 9 | if not name: 10 | name = os.path.splitext(os.path.basename(infn))[0] 11 | 12 | for applet in root.find('applets'): 13 | ver = applet.find('appletVersion').text 14 | fwver = applet.find('fwVersion').text 15 | blob = applet.find('appletBlob').text 16 | platf = applet.find('platform').text 17 | print "Applet: v%s for %s fw v%s" % (ver, platf, fwver) 18 | open("%s_%s_%s_v%s.bin" % (name, platf, fwver, ver), "wb").write(blob.decode('base64')) 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | dump_jeff.py 2 | ======== 3 | 4 | This script allows you to dump the JEFF files used by Intel ME's DAL (Dynamic Application Loader). 5 | It supports the following input formats: 6 | - raw JEFF file ('JEFF signature') 7 | - JEFF packaged as an ME applet with signed manifest header ($MN2 magic) (currently ME 8-9.5 only) 8 | - any binary containing an uncompressed JEFF file inside (e.g. JOM_mod.bin produced by unpacking an ME firmware) 9 | 10 | Usage: dump_jeff.py [options] file.jeff >output.txt 11 | Where options are: 12 | -d: dump JEFF structure (default). 13 | This dumps the detailed structure of the JEFF file, including classes, fields and methods with disassembly. For the description 14 | of the JEFF format and instructions, see the JEFF standard documens in the docs/ directory. 15 | -s: print class definition summary. 16 | Prints only a list of classes, fields (with offsets) and methods 17 | -j: print Jasmin-style disassembly (experimental) 18 | Prints the JEFF file as a Jasmin-style Java assembly (jeff instructions are transformed into equivalent Java ones). 19 | The result can be directly assembled using Krakatau into .class files (and then decompiled). 20 | 21 | unp_dalp.py 22 | ======== 23 | 24 | This script unpacks DAL applets from a .dalp file (such files are used by Intel to package several ME applets into one XML). 25 | 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | eggs/ 15 | lib/ 16 | lib64/ 17 | parts/ 18 | sdist/ 19 | var/ 20 | *.egg-info/ 21 | .installed.cfg 22 | *.egg 23 | 24 | # PyInstaller 25 | # Usually these files are written by a python script from a template 26 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 27 | *.manifest 28 | *.spec 29 | 30 | # Installer logs 31 | pip-log.txt 32 | pip-delete-this-directory.txt 33 | 34 | # Unit test / coverage reports 35 | htmlcov/ 36 | .tox/ 37 | .coverage 38 | .cache 39 | nosetests.xml 40 | coverage.xml 41 | 42 | # Translations 43 | *.mo 44 | *.pot 45 | 46 | # Django stuff: 47 | *.log 48 | 49 | # Sphinx documentation 50 | docs/_build/ 51 | 52 | # PyBuilder 53 | target/ 54 | 55 | # ========================= 56 | # Operating System Files 57 | # ========================= 58 | 59 | # OSX 60 | # ========================= 61 | 62 | .DS_Store 63 | .AppleDouble 64 | .LSOverride 65 | 66 | # Icon must end with two \r 67 | Icon 68 | 69 | # Thumbnails 70 | ._* 71 | 72 | # Files that might appear on external disk 73 | .Spotlight-V100 74 | .Trashes 75 | 76 | # Directories potentially created on remote AFP share 77 | .AppleDB 78 | .AppleDesktop 79 | Network Trash Folder 80 | Temporary Items 81 | .apdisk 82 | 83 | # Windows 84 | # ========================= 85 | 86 | # Windows image file caches 87 | Thumbs.db 88 | ehthumbs.db 89 | 90 | # Folder config file 91 | Desktop.ini 92 | 93 | # Recycle Bin used on file shares 94 | $RECYCLE.BIN/ 95 | 96 | # Windows Installer files 97 | *.cab 98 | *.msi 99 | *.msm 100 | *.msp 101 | 102 | # Windows binaries 103 | *.exe 104 | -------------------------------------------------------------------------------- /opcodes.py: -------------------------------------------------------------------------------- 1 | opcodetbl = [ 2 | ("jeff_nop", 0), # 0x00 3 | ("jeff_aconst_null", 0), # 0x01 4 | ("jeff_iconst_m1", 0), # 0x02 5 | ("jeff_iconst_0", 0), # 0x03 6 | ("jeff_iconst_1", 0), # 0x04 7 | ("jeff_iconst_2", 0), # 0x05 8 | ("jeff_iconst_3", 0), # 0x06 9 | ("jeff_iconst_4", 0), # 0x07 10 | ("jeff_iconst_5", 0), # 0x08 11 | ("jeff_lconst_0", 0), # 0x09 12 | ("jeff_lconst_1", 0), # 0x0a 13 | ("jeff_fconst_0", 0), # 0x0b 14 | ("jeff_fconst_1", 0), # 0x0c 15 | ("jeff_fconst_2", 0), # 0x0d 16 | ("jeff_dconst_0", 0), # 0x0e 17 | ("jeff_dconst_1", 0), # 0x0f 18 | ("jeff_bipush", 1), # 0x10 19 | ("jeff_sipush", -1), # 0x11 20 | ("jeff_unused_0x12", 0), # 0x12 21 | ("jeff_unused_0x13", 0), # 0x13 22 | ("jeff_unused_0x14", 0), # 0x14 23 | ("jeff_iload", 1), # 0x15 24 | ("jeff_lload", 1), # 0x16 25 | ("jeff_fload", 1), # 0x17 26 | ("jeff_dload", 1), # 0x18 27 | ("jeff_aload", 1), # 0x19 28 | ("jeff_iload_0", 0), # 0x1a 29 | ("jeff_iload_1", 0), # 0x1b 30 | ("jeff_iload_2", 0), # 0x1c 31 | ("jeff_iload_3", 0), # 0x1d 32 | ("jeff_lload_0", 0), # 0x1e 33 | ("jeff_lload_1", 0), # 0x1f 34 | ("jeff_lload_2", 0), # 0x20 35 | ("jeff_lload_3", 0), # 0x21 36 | ("jeff_fload_0", 0), # 0x22 37 | ("jeff_fload_1", 0), # 0x23 38 | ("jeff_fload_2", 0), # 0x24 39 | ("jeff_fload_3", 0), # 0x25 40 | ("jeff_dload_0", 0), # 0x26 41 | ("jeff_dload_1", 0), # 0x27 42 | ("jeff_dload_2", 0), # 0x28 43 | ("jeff_dload_3", 0), # 0x29 44 | ("jeff_aload_0", 0), # 0x2a 45 | ("jeff_aload_1", 0), # 0x2b 46 | ("jeff_aload_2", 0), # 0x2c 47 | ("jeff_aload_3", 0), # 0x2d 48 | ("jeff_iaload", 0), # 0x2e 49 | ("jeff_laload", 0), # 0x2f 50 | ("jeff_faload", 0), # 0x30 51 | ("jeff_daload", 0), # 0x31 52 | ("jeff_aaload", 0), # 0x32 53 | ("jeff_baload", 0), # 0x33 54 | ("jeff_caload", 0), # 0x34 55 | ("jeff_saload", 0), # 0x35 56 | ("jeff_istore", 1), # 0x36 57 | ("jeff_lstore", 1), # 0x37 58 | ("jeff_fstore", 1), # 0x38 59 | ("jeff_dstore", 1), # 0x39 60 | ("jeff_astore", 1), # 0x3a 61 | ("jeff_istore_0", 0), # 0x3b 62 | ("jeff_istore_1", 0), # 0x3c 63 | ("jeff_istore_2", 0), # 0x3d 64 | ("jeff_istore_3", 0), # 0x3e 65 | ("jeff_lstore_0", 0), # 0x3f 66 | ("jeff_lstore_1", 0), # 0x40 67 | ("jeff_lstore_2", 0), # 0x41 68 | ("jeff_lstore_3", 0), # 0x42 69 | ("jeff_fstore_0", 0), # 0x43 70 | ("jeff_fstore_1", 0), # 0x44 71 | ("jeff_fstore_2", 0), # 0x45 72 | ("jeff_fstore_3", 0), # 0x46 73 | ("jeff_dstore_0", 0), # 0x47 74 | ("jeff_dstore_1", 0), # 0x48 75 | ("jeff_dstore_2", 0), # 0x49 76 | ("jeff_dstore_3", 0), # 0x4a 77 | ("jeff_astore_0", 0), # 0x4b 78 | ("jeff_astore_1", 0), # 0x4c 79 | ("jeff_astore_2", 0), # 0x4d 80 | ("jeff_astore_3", 0), # 0x4e 81 | ("jeff_iastore", 0), # 0x4f 82 | ("jeff_lastore", 0), # 0x50 83 | ("jeff_fastore", 0), # 0x51 84 | ("jeff_dastore", 0), # 0x52 85 | ("jeff_aastore", 0), # 0x53 86 | ("jeff_bastore", 0), # 0x54 87 | ("jeff_castore", 0), # 0x55 88 | ("jeff_sastore", 0), # 0x56 89 | ("jeff_pop", 0), # 0x57 90 | ("jeff_pop2", 0), # 0x58 91 | ("jeff_dup", 0), # 0x59 92 | ("jeff_dup_x1", 0), # 0x5a 93 | ("jeff_dup_x2", 0), # 0x5b 94 | ("jeff_dup2", 0), # 0x5c 95 | ("jeff_dup2_x1", 0), # 0x5d 96 | ("jeff_dup2_x2", 0), # 0x5e 97 | ("jeff_swap", 0), # 0x5f 98 | ("jeff_iadd", 0), # 0x60 99 | ("jeff_ladd", 0), # 0x61 100 | ("jeff_fadd", 0), # 0x62 101 | ("jeff_dadd", 0), # 0x63 102 | ("jeff_isub", 0), # 0x64 103 | ("jeff_lsub", 0), # 0x65 104 | ("jeff_fsub", 0), # 0x66 105 | ("jeff_dsub", 0), # 0x67 106 | ("jeff_imul", 0), # 0x68 107 | ("jeff_lmul", 0), # 0x69 108 | ("jeff_fmul", 0), # 0x6a 109 | ("jeff_dmul", 0), # 0x6b 110 | ("jeff_idiv", 0), # 0x6c 111 | ("jeff_ldiv", 0), # 0x6d 112 | ("jeff_fdiv", 0), # 0x6e 113 | ("jeff_ddiv", 0), # 0x6f 114 | ("jeff_irem", 0), # 0x70 115 | ("jeff_lrem", 0), # 0x71 116 | ("jeff_frem", 0), # 0x72 117 | ("jeff_drem", 0), # 0x73 118 | ("jeff_ineg", 0), # 0x74 119 | ("jeff_lneg", 0), # 0x75 120 | ("jeff_fneg", 0), # 0x76 121 | ("jeff_dneg", 0), # 0x77 122 | ("jeff_ishl", 0), # 0x78 123 | ("jeff_lshl", 0), # 0x79 124 | ("jeff_ishr", 0), # 0x7a 125 | ("jeff_lshr", 0), # 0x7b 126 | ("jeff_iushr", 0), # 0x7c 127 | ("jeff_lushr", 0), # 0x7d 128 | ("jeff_iand", 0), # 0x7e 129 | ("jeff_land", 0), # 0x7f 130 | ("jeff_ior", 0), # 0x80 131 | ("jeff_lor", 0), # 0x81 132 | ("jeff_ixor", 0), # 0x82 133 | ("jeff_lxor", 0), # 0x83 134 | ("jeff_iinc", -1), # 0x84 135 | ("jeff_i2l", 0), # 0x85 136 | ("jeff_i2f", 0), # 0x86 137 | ("jeff_i2d", 0), # 0x87 138 | ("jeff_l2i", 0), # 0x88 139 | ("jeff_l2f", 0), # 0x89 140 | ("jeff_l2d", 0), # 0x8a 141 | ("jeff_f2i", 0), # 0x8b 142 | ("jeff_f2l", 0), # 0x8c 143 | ("jeff_f2d", 0), # 0x8d 144 | ("jeff_d2i", 0), # 0x8e 145 | ("jeff_d2l", 0), # 0x8f 146 | ("jeff_d2f", 0), # 0x90 147 | ("jeff_i2b", 0), # 0x91 148 | ("jeff_i2c", 0), # 0x92 149 | ("jeff_i2s", 0), # 0x93 150 | ("jeff_lcmp", 0), # 0x94 151 | ("jeff_fcmpl", 0), # 0x95 152 | ("jeff_fcmpg", 0), # 0x96 153 | ("jeff_dcmpl", 0), # 0x97 154 | ("jeff_dcmpg", 0), # 0x98 155 | ("jeff_ifeq", -1), # 0x99 156 | ("jeff_ifne", -1), # 0x9a 157 | ("jeff_iflt", -1), # 0x9b 158 | ("jeff_ifge", -1), # 0x9c 159 | ("jeff_ifgt", -1), # 0x9d 160 | ("jeff_ifle", -1), # 0x9e 161 | ("jeff_if_icmpeq", -1), # 0x9f 162 | ("jeff_if_icmpne", -1), # 0xa0 163 | ("jeff_if_icmplt", -1), # 0xa1 164 | ("jeff_if_icmpge", -1), # 0xa2 165 | ("jeff_if_icmpgt", -1), # 0xa3 166 | ("jeff_if_icmple", -1), # 0xa4 167 | ("jeff_if_acmpeq", -1), # 0xa5 168 | ("jeff_if_acmpne", -1), # 0xa6 169 | ("jeff_goto", -1), # 0xa7 170 | ("jeff_jsr", -1), # 0xa8 171 | ("jeff_ret", 1), # 0xa9 172 | ("jeff_tableswitch", -1), # 0xaa 173 | ("jeff_lookupswitch", -1), # 0xab 174 | ("jeff_ireturn", 0), # 0xac 175 | ("jeff_lreturn", 0), # 0xad 176 | ("jeff_freturn", 0), # 0xae 177 | ("jeff_dreturn", 0), # 0xaf 178 | ("jeff_areturn", 0), # 0xb0 179 | ("jeff_return", 0), # 0xb1 180 | ("jeff_getstatic", -1), # 0xb2 181 | ("jeff_putstatic", -1), # 0xb3 182 | ("jeff_getfield", -1), # 0xb4 183 | ("jeff_putfield", -1), # 0xb5 184 | ("jeff_invokevirtual", -1), # 0xb6 185 | ("jeff_invokespecial", -1), # 0xb7 186 | ("jeff_invokestatic", -1), # 0xb8 187 | ("jeff_invokeinterface",-1), # 0xb9 188 | ("jeff_unused_0xba", 0), # 0xba 189 | ("jeff_new", -1), # 0xbb 190 | ("jeff_newarray", -1), # 0xbc 191 | ("jeff_unused_0xbd", 0), # 0xbd 192 | ("jeff_arraylength", 0), # 0xbe 193 | ("jeff_athrow", 0), # 0xbf 194 | ("jeff_checkcast", -1), # 0xc0 195 | ("jeff_instanceof", -1), # 0xc1 196 | ("jeff_monitorenter", 0), # 0xc2 197 | ("jeff_monitorexit", 0), # 0xc3 198 | ("jeff_unused_0xc4", 0), # 0xc4 199 | ("jeff_multianewarray", -1), # 0xc5 200 | ("jeff_ifnull", -1), # 0xc6 201 | ("jeff_ifnonnull", -1), # 0xc7 202 | ("jeff_unused_0xc8", 0), # 0xc8 203 | ("jeff_unused_0xc9", 0), # 0xc9 204 | ("jeff_breakpoint", 0), # 0xca 205 | ("jeff_newconstarray", -1), # 0xcb 206 | ("jeff_slookupswitch", -1), # 0xcc 207 | ("jeff_stableswitch", -1), # 0xcd 208 | ("jeff_ret_w", 2), # 0xce 209 | ("jeff_iinc_w", -1), # 0xcf 210 | ("jeff_sldc", -1), # 0xd0 211 | ("jeff_ildc", -1), # 0xd1 212 | ("jeff_lldc", -1), # 0xd2 213 | ("jeff_fldc", -1), # 0xd3 214 | ("jeff_dldc", -1), # 0xd4 215 | ("jeff_dload_w", 2), # 0xd5 216 | ("jeff_dstore_w", 2), # 0xd6 217 | ("jeff_fload_w", 2), # 0xd7 218 | ("jeff_fstore_w", 2), # 0xd8 219 | ("jeff_iload_w", 2), # 0xd9 220 | ("jeff_istore_w", 2), # 0xda 221 | ("jeff_lload_w", 2), # 0xdb 222 | ("jeff_lstore_w", 2), # 0xdc 223 | ("jeff_aload_w", 2), # 0xdd 224 | ("jeff_astore_w", 2), # 0xde 225 | ] 226 | 227 | for i in range(len(opcodetbl)): 228 | oname = opcodetbl[i][0] 229 | globals()[oname] = i 230 | 231 | class BytecodePrinter: 232 | def __init__(self, jclass, ofcode, codelen): 233 | self.jeff = jclass.jeff 234 | self.jclass = jclass 235 | self.ofcode = ofcode 236 | self.codelen = codelen 237 | 238 | def seek(self, off): 239 | self.offset = off 240 | 241 | def align(self, sz): 242 | mask = sz-1 243 | check = self.offset + self.jclass.offset 244 | if check & mask: 245 | check = (check + mask) & ~mask 246 | self.offset = check - self.jclass.offset 247 | 248 | def read_8(self): 249 | self.offset += 1 250 | return ord(self.f[self.offset-1]) 251 | 252 | def read_16(self, aligned = False): 253 | if self.bigendian: 254 | fmt = ">H" 255 | else: 256 | fmt = " 328 | # VMOFFSET ofDefault 329 | # TU1 <0-2 byte pad> 330 | # TS2 nLowValue | TS4 nLowValue 331 | # TS2 nHighValue | TS4 nHighValue 332 | # VMOFFSET ofJump [nHighValue - nLowValue + 1] 333 | ofDefault = self.jeff.read_16(True) 334 | if b == jeff_stableswitch: 335 | nLowValue = self.jeff.read_16s() 336 | nHighValue = self.jeff.read_16s() 337 | else: 338 | nLowValue = self.jeff.read_32s(True) 339 | nHighValue = self.jeff.read_32s() 340 | ncases = nHighValue - nLowValue + 1 341 | ofJump = [self.jeff.read_16() for i in range(ncases)] 342 | opnd = [ nLowValue, ofJump, ofDefault ] 343 | elif b in [jeff_newarray, jeff_checkcast, jeff_instanceof]: 344 | # VMTYPE tDescriptor 345 | # TU1 nDimension (optional) 346 | # TU1 <0-1 byte pad> 347 | # VMOFFSET ofClassIndex (optional) 348 | descr = self.jeff.read_descriptor(self.jclass) 349 | opnd = [ descr ] 350 | elif b == jeff_newconstarray: 351 | # VMTYPE tArrayType 352 | # TU1 <0-1 byte pad> 353 | # TU2 nLength 354 | # VMOFFSET ofConstData 355 | tArrayType = self.jeff.read_8() 356 | nLength = self.jeff.read_16(True) 357 | ofConstData = self.jeff.read_16() 358 | opnd = [ tArrayType, nLength, ofConstData ] 359 | elif b in [jeff_iinc, jeff_iinc_w]: 360 | if b == jeff_iinc: 361 | nIndex = self.jeff.read_8() 362 | nConstant = self.jeff.read_8s() 363 | else: 364 | nIndex = self.jeff.read_16(True) 365 | nConstant = self.jeff.read_16s() 366 | opnd = [nIndex, nConstant] 367 | else: 368 | raise Exception("Unhandled opcode %02X" % b) 369 | else: 370 | raise Exception("Unhandled opsize: %d" % o[1]) 371 | insns.append((pc, b, opnd)) 372 | return insns 373 | 374 | def print_jeff(self, indent = 0): 375 | insns = self._disasm() 376 | for pc, b, opnd in insns: 377 | o = opcodetbl[b] 378 | print " "*indent, "%04X: %02X %s" % (pc, b, o[0]), 379 | if o[1] == 0: 380 | print "" 381 | elif o[1] in [1, 2]: 382 | v = opnd[0] 383 | print "%d ; (0x%x)" % (v, v) 384 | print "%d ; (0x%x)" % (v, v) 385 | elif o[1] == -1: 386 | if b in [jeff_getfield, jeff_getstatic, jeff_putfield, jeff_putstatic]: 387 | # VMOFFSET ofFieldInfo 388 | ofFieldInfo = opnd[0] 389 | fidFieldIndex = self.jeff.get_32(self.jclass.offset + ofFieldInfo) 390 | ofClassIndex = self.jeff.get_16(self.jclass.offset + ofFieldInfo + 4) 391 | cidx = self.jclass.get_index(ofClassIndex) 392 | cname = self.jeff.get_classname(cidx) 393 | fldname = self.jeff.get_field(fidFieldIndex) 394 | print " " % (cname, fldname) 395 | elif b in [jeff_invokespecial, jeff_invokevirtual, jeff_invokestatic, jeff_invokeinterface]: 396 | # VMOFFSET ofMethodInfo 397 | ofMethodInfo = opnd[0] 398 | midMethodIndex = self.jeff.get_32(self.jclass.offset + ofMethodInfo) 399 | ofClassIndex = self.jeff.get_16(self.jclass.offset + ofMethodInfo + 4) 400 | cidx = self.jclass.get_index(ofClassIndex) 401 | cname = self.jeff.get_classname(cidx) 402 | mname = self.jeff.get_method(midMethodIndex) 403 | print " " % (cname, mname) 404 | elif b in [jeff_sldc, jeff_ildc, jeff_fldc, jeff_lldc, jeff_dldc]: 405 | # VMOFFSET ofConstant 406 | ofConstant = opnd[0] 407 | print "o%X=" % ofConstant 408 | if b == jeff_sldc: 409 | print "" % (self.jclass.get_sconst(ofConstant)) 410 | elif b == jeff_ildc: 411 | i = self.jclass.get_iconst(ofConstant) 412 | print "" % (i, i&0xFFFFFFFF) 413 | elif b == jeff_lldc: 414 | i = self.jclass.get_lconst(ofConstant) 415 | print "" % (i, i&0xFFFFFFFFFFFFFFFF) 416 | elif b == jeff_fldc: 417 | f = self.jclass.get_fconst(ofConstant) 418 | print "" % (f) 419 | elif b == jeff_dldc: 420 | f = self.jclass.get_dconst(ofConstant) 421 | print "" % (f) 422 | elif b in [jeff_goto, jeff_if_acmpeq, jeff_if_acmpne, 423 | jeff_if_icmpeq, jeff_if_icmpne, jeff_if_icmplt, 424 | jeff_if_icmpge, jeff_if_icmpgt, jeff_if_icmple, 425 | jeff_ifeq, jeff_ifne, jeff_iflt, jeff_ifge, 426 | jeff_ifgt, jeff_ifle, jeff_ifnonnull, jeff_ifnull, 427 | jeff_jsr]: 428 | # VMOFFSET ofJump 429 | ofJump = opnd[0] 430 | print "0x%04X" % ofJump 431 | elif b in [jeff_slookupswitch, jeff_lookupswitch]: 432 | nMatch, ofJump, ofDefault = opnd 433 | print "\n", 434 | print " "*indent, " default: %04X" % ofDefault 435 | for i in range(len(ofJump)): 436 | print " "*indent, " case %3d: %04X" % (nMatch[i], ofJump[i]) 437 | elif b in [jeff_tableswitch, jeff_stableswitch]: 438 | nLowValue, ofJump, ofDefault = opnd 439 | print "\n", 440 | print " "*indent, " default: %04X" % ofDefault 441 | for i in range(len(ofJump)): 442 | print " "*indent, " case %3d: %04X" % (nLowValue+i, ofJump[i]) 443 | elif b in [jeff_newarray, jeff_checkcast, jeff_instanceof]: 444 | # VMTYPE tDescriptor 445 | # TU1 nDimension (optional) 446 | # TU1 <0-1 byte pad> 447 | # VMOFFSET ofClassIndex (optional) 448 | descr = opnd[0] 449 | print "" % descr 450 | elif b == jeff_new: 451 | # VMOFFSET ofClassIndex 452 | ofClassIndex = opnd[0] 453 | cidx = self.jclass.get_index(ofClassIndex) 454 | cname = self.jeff.get_classname(cidx) 455 | print "" % (cname) 456 | elif b == jeff_sipush: 457 | # TS2 nValue 458 | nValue = opnd[0] 459 | print "<%d (0x%X)>" % (nValue, nValue&0xFFFFFFFF) 460 | elif b == jeff_newconstarray: 461 | # VMTYPE tArrayType 462 | # TU1 <0-1 byte pad> 463 | # TU2 nLength 464 | # VMOFFSET ofConstData 465 | tArrayType = opnd[0] 466 | nLength = opnd[1] 467 | ofConstData = opnd[2] 468 | vals = self.jclass.get_array(tArrayType, ofConstData, nLength) 469 | print vals 470 | elif b in [jeff_iinc, jeff_iinc_w]: 471 | nIndex, nConstant = opnd 472 | print "%d %d" % (nIndex, nConstant) 473 | else: 474 | print "" 475 | break 476 | else: 477 | print "" % o[1] 478 | break 479 | 480 | def dump_consts(self, insns, indent): 481 | for pc, b, opnd in insns: 482 | o = opcodetbl[b] 483 | mnem = o[0] 484 | if b in [jeff_sldc, jeff_ildc, jeff_fldc, jeff_lldc, jeff_dldc]: 485 | # VMOFFSET ofConstant 486 | ofConstant = opnd[0] 487 | print " "*indent, ".const [o%d] =" % ofConstant, 488 | if b == jeff_sldc: 489 | print 'Utf8 "%s"'% (self.jclass.get_sconst(ofConstant)) 490 | elif b == jeff_ildc: 491 | i = self.jclass.get_iconst(ofConstant) 492 | print "Int %d ; 0x%X" % (i, i&0xFFFFFFFF) 493 | elif b == jeff_lldc: 494 | i = self.jclass.get_lconst(ofConstant) 495 | print "Long %ldL; 0x%X" % (i, i&0xFFFFFFFFFFFFFFFF) 496 | elif b == jeff_fldc: 497 | f = self.jclass.get_fconst(ofConstant) 498 | print "Float %f" % (f) 499 | elif b == jeff_dldc: 500 | f = self.jclass.get_dconst(ofConstant) 501 | print "Double %f" % (f) 502 | 503 | def gather_labels(self, insns): 504 | labels = [] 505 | for pc, b, opnd in insns: 506 | o = opcodetbl[b] 507 | mnem = o[0] 508 | if b in [jeff_goto, jeff_if_acmpeq, jeff_if_acmpne, 509 | jeff_if_icmpeq, jeff_if_icmpne, jeff_if_icmplt, 510 | jeff_if_icmpge, jeff_if_icmpgt, jeff_if_icmple, 511 | jeff_ifeq, jeff_ifne, jeff_iflt, jeff_ifge, 512 | jeff_ifgt, jeff_ifle, jeff_ifnonnull, jeff_ifnull, 513 | jeff_jsr]: 514 | # VMOFFSET ofJump 515 | ofJump = opnd[0] 516 | labels.append(ofJump) 517 | elif b in [jeff_slookupswitch, jeff_lookupswitch]: 518 | nMatch, ofJump, ofDefault = opnd 519 | for i in range(len(ofJump)): 520 | labels.append(ofJump[i]) 521 | labels.append(ofDefault) 522 | elif b in [jeff_tableswitch, jeff_stableswitch]: 523 | nLowValue, ofJump, ofDefault = opnd 524 | for i in range(len(ofJump)): 525 | labels.append(ofJump[i]) 526 | labels.append(ofDefault) 527 | return labels 528 | 529 | 530 | 531 | def printconstarray(self, tArrayType, ofConstData, nLength, indent): 532 | # 533 | #sipush 256 534 | #newarray int|byte|short|boolean|char|long 535 | #dup ; copy array ref 536 | #iconst_0 ; index 537 | #sipush 146 ; value 538 | #iastore ; store value 539 | # dup 540 | # ... 541 | #sipush 255 542 | #bipush 10 543 | #iastore 544 | 545 | t = tArrayType & 0xF 546 | arrtyp, values = self.jclass.get_array_values(tArrayType, ofConstData, nLength) 547 | if arrtyp in ["byte", "char", "boolean"]: 548 | storeins = "bastore" 549 | elif arrtyp == "short": 550 | storeins = "sastore" 551 | elif arrtyp == "int": 552 | storeins = "iastore" 553 | 554 | print " "*indent, 555 | if nLength<=32767: 556 | print "sipush %d" % nLength 557 | else: 558 | print "ldc %d" % nLength 559 | print " "*indent, "newarray %s" % arrtyp 560 | for i, v in enumerate(values): 561 | print " "*indent, "dup" 562 | if i<=5: 563 | print " "*indent, "iconst_%d" % i 564 | elif i<=32767: 565 | print " "*indent, "sipush %d" % i 566 | else: 567 | print " "*indent, "ldc %d" % i 568 | if -127<=v<=127: 569 | print " "*indent, "bipush %d" % v 570 | elif -32768<=v<=32767: 571 | print " "*indent, "sipush %d" % v 572 | else: 573 | print " "*indent, "ldc %d" % v 574 | print " "*indent, "%s" % storeins 575 | 576 | 577 | 578 | def print_java(self, indent = 0): 579 | insns = self._disasm() 580 | # self.dump_consts(insns, indent) 581 | labels = self.gather_labels(insns) 582 | 583 | for pc, b, opnd in insns: 584 | o = opcodetbl[b] 585 | mnem = o[0] 586 | if mnem.startswith("jeff_"): mnem = mnem[5:] 587 | print " "*indent, 588 | if labels and (pc in labels): 589 | print "LABEL_%04X:" % pc 590 | print " "*indent, 591 | if not b in [jeff_sldc, jeff_ildc, jeff_fldc, jeff_lldc, jeff_dldc,jeff_newconstarray, 592 | jeff_tableswitch, jeff_stableswitch, jeff_slookupswitch, jeff_lookupswitch, 593 | jeff_newarray, jeff_iinc, jeff_iinc_w]: 594 | print "%s" % (mnem), 595 | if o[1] == 0: 596 | print "" 597 | elif o[1] in [1, 2]: 598 | v = opnd[0] 599 | if b==jeff_bipush and v&0x80: 600 | v -= 0x100 601 | elif b==jeff_sipush and v&0x8000: 602 | v -= 0x10000 603 | print "%d ; (0x%x)" % (v, opnd[0]) 604 | elif o[1] == -1: 605 | if b in [jeff_getfield, jeff_getstatic, jeff_putfield, jeff_putstatic]: 606 | # VMOFFSET ofFieldInfo 607 | ofFieldInfo = opnd[0] 608 | fidFieldIndex = self.jeff.get_32(self.jclass.offset + ofFieldInfo) 609 | ofClassIndex = self.jeff.get_16(self.jclass.offset + ofFieldInfo + 4) 610 | cidx = self.jclass.get_index(ofClassIndex) 611 | cname = self.jeff.get_classname(cidx) 612 | f = self.jeff.get_field(fidFieldIndex) 613 | print "%s/%s %s" % (cname, f.name, f.descr.get_jtype()) 614 | elif b in [jeff_invokespecial, jeff_invokevirtual, jeff_invokestatic, jeff_invokeinterface]: 615 | # VMOFFSET ofMethodInfo 616 | ofMethodInfo = opnd[0] 617 | midMethodIndex = self.jeff.get_32(self.jclass.offset + ofMethodInfo) 618 | ofClassIndex = self.jeff.get_16(self.jclass.offset + ofMethodInfo + 4) 619 | cidx = self.jclass.get_index(ofClassIndex) 620 | cname = self.jeff.get_javaname(cidx) 621 | # mname = self.jeff.get_method(midMethodIndex) 622 | md = self.jeff.get_method(midMethodIndex) 623 | if b == jeff_invokeinterface: 624 | print "%s/%s%s" % (cname, md.name, md.get_jtypen()) 625 | else: 626 | print "%s/%s%s" % (cname, md.name, md.get_jtype()) 627 | elif b in [jeff_sldc, jeff_ildc, jeff_fldc, jeff_lldc, jeff_dldc]: 628 | # VMOFFSET ofConstant 629 | ofConstant = opnd[0] 630 | if b == jeff_lldc: 631 | i = self.jclass.get_lconst(ofConstant) 632 | print "ldc2_w %dL" % i 633 | elif b == jeff_sldc: 634 | #convert string index to offset 635 | #ofConstant = self.jclass._soff_by_idx(ofConstant) - self.jclass.offset 636 | rs = repr(self.jclass.get_sconst(ofConstant)) 637 | print 'ldc "%s"' % (rs[1:-1]) 638 | else: 639 | print "ldc [o%d]" % (ofConstant) 640 | elif b in [jeff_goto, jeff_if_acmpeq, jeff_if_acmpne, 641 | jeff_if_icmpeq, jeff_if_icmpne, jeff_if_icmplt, 642 | jeff_if_icmpge, jeff_if_icmpgt, jeff_if_icmple, 643 | jeff_ifeq, jeff_ifne, jeff_iflt, jeff_ifge, 644 | jeff_ifgt, jeff_ifle, jeff_ifnonnull, jeff_ifnull, 645 | jeff_jsr]: 646 | # VMOFFSET ofJump 647 | ofJump = opnd[0] 648 | print "LABEL_%04X" % ofJump 649 | elif b in [jeff_slookupswitch, jeff_lookupswitch]: 650 | nMatch, ofJump, ofDefault = opnd 651 | print "lookupswitch" 652 | for i in range(len(ofJump)): 653 | print " "*indent, " %3d: LABEL_%04X" % (nMatch[i], ofJump[i]) 654 | print " "*indent, " default: LABEL_%04X" % ofDefault 655 | elif b in [jeff_tableswitch, jeff_stableswitch]: 656 | nLowValue, ofJump, ofDefault = opnd 657 | print "tableswitch %d" % (nLowValue) 658 | for i in range(len(ofJump)): 659 | print " "*indent, " LABEL_%04X ; case %d" % (ofJump[i], nLowValue+i) 660 | print " "*indent, " default: LABEL_%04X" % ofDefault 661 | elif b in [jeff_newarray, jeff_checkcast, jeff_instanceof]: 662 | # VMTYPE tDescriptor 663 | # TU1 nDimension (optional) 664 | # TU1 <0-1 byte pad> 665 | # VMOFFSET ofClassIndex (optional) 666 | descr = opnd[0] 667 | if b == jeff_newarray: 668 | if descr.is_object(): 669 | print "anewarray %s" % descr.get_jtype(True) 670 | else: 671 | print "newarray %s" % descr.arrtype() 672 | else: 673 | print descr.get_jtype() 674 | elif b == jeff_new: 675 | # VMOFFSET ofClassIndex 676 | ofClassIndex = opnd[0] 677 | cidx = self.jclass.get_index(ofClassIndex) 678 | cname = self.jeff.get_javaname(cidx) 679 | print "%s" % (cname) 680 | elif b == jeff_sipush: 681 | # TS2 nValue 682 | nValue = opnd[0] 683 | print "%d ; (0x%X)" % (nValue, nValue&0xFFFFFFFF) 684 | elif b == jeff_newconstarray: 685 | # VMTYPE tArrayType 686 | # TU1 <0-1 byte pad> 687 | # TU2 nLength 688 | # VMOFFSET ofConstData 689 | tArrayType = opnd[0] 690 | nLength = opnd[1] 691 | ofConstData = opnd[2] 692 | self.printconstarray(tArrayType, ofConstData, nLength, indent) 693 | # vals = self.jclass.get_array(tArrayType, ofConstData, nLength) 694 | # print vals 695 | elif b in [jeff_iinc, jeff_iinc_w]: 696 | nIndex, nConstant = opnd 697 | if b == jeff_iinc_w: print "wide", 698 | print "iinc %d %d" % (nIndex, nConstant) 699 | else: 700 | print "" 701 | break 702 | else: 703 | print "" % o[1] 704 | break 705 | -------------------------------------------------------------------------------- /dump_jeff.py: -------------------------------------------------------------------------------- 1 | # Intel ME DAL module dumper 2 | # Copyright (c) 2013 Igor Skochinsky 3 | # Version 0.1 2015-12-24 4 | # 5 | # This software is provided 'as-is', without any express or implied 6 | # warranty. In no event will the authors be held liable for any damages 7 | # arising from the use of this software. 8 | # 9 | # Permission is granted to anyone to use this software for any purpose, 10 | # including commercial applications, and to alter it and redistribute it 11 | # freely, subject to the following restrictions: 12 | # 13 | # 1. The origin of this software must not be misrepresented; you must not 14 | # claim that you wrote the original software. If you use this software 15 | # in a product, an acknowledgment in the product documentation would be 16 | # appreciated but is not required. 17 | # 18 | # 2. Altered source versions must be plainly marked as such, and must not be 19 | # misrepresented as being the original software. 20 | # 21 | # 3. This notice may not be removed or altered from any source 22 | # distribution. 23 | 24 | 25 | import ctypes 26 | import struct 27 | import sys 28 | import os 29 | import array 30 | 31 | uint8_t = ctypes.c_ubyte 32 | char = ctypes.c_char 33 | uint32_t = ctypes.c_uint 34 | uint64_t = ctypes.c_uint64 35 | uint16_t = ctypes.c_ushort 36 | 37 | def replace_bad(value, deletechars): 38 | for c in deletechars: 39 | value = value.replace(c,'_') 40 | return value 41 | 42 | def read_struct(li, struct): 43 | s = struct() 44 | slen = ctypes.sizeof(s) 45 | bytes = li.read(slen) 46 | fit = min(len(bytes), slen) 47 | ctypes.memmove(ctypes.addressof(s), bytes, fit) 48 | return s 49 | 50 | def get_struct(str_, off, struct): 51 | s = struct() 52 | slen = ctypes.sizeof(s) 53 | bytes = str_[off:off+slen] 54 | fit = min(len(bytes), slen) 55 | ctypes.memmove(ctypes.addressof(s), bytes, fit) 56 | return s 57 | 58 | def DwordAt(f, off): 59 | return struct.unpack("= 2 175 | 176 | BASIC_TYPES = [ 177 | "void", # 0x00 0 or absent absent 178 | "short", # 0x01 0 or absent absent 179 | "int", # 0x02 0 or absent absent 180 | "long", # 0x03 0 or absent absent 181 | "byte", # 0x04 0 or absent absent 182 | "char", # 0x05 0 or absent absent 183 | "float", # 0x06 0 or absent absent 184 | "double", # 0x07 0 or absent absent 185 | "boolean", # 0x08 0 or absent absent 186 | "", # 0x09 187 | "reference", # 0x0A 188 | "", # 0x0B 189 | "", # 0x0C 190 | "", # 0x0D 191 | "", # 0x0E 192 | "", # 0x0F 193 | ] 194 | 195 | BASIC_TYPESJ = [ 196 | "V", # 0x00 0 or absent absent 197 | "S", # 0x01 0 or absent absent 198 | "I", # 0x02 0 or absent absent 199 | "J", # 0x03 0 or absent absent 200 | "B", # 0x04 0 or absent absent 201 | "C", # 0x05 0 or absent absent 202 | "F", # 0x06 0 or absent absent 203 | "D", # 0x07 0 or absent absent 204 | "Z", # 0x08 0 or absent absent 205 | "", # 0x09 206 | "", # 0x0A 207 | "", # 0x0B 208 | "", # 0x0C 209 | "", # 0x0D 210 | "", # 0x0E 211 | "", # 0x0F 212 | ] 213 | 214 | def type2str(typ, dim=0, showflags = True): 215 | nm = BASIC_TYPES[typ & 0xF] 216 | if dim != 0: 217 | nm += "[]" * dim 218 | if typ & VM_TYPE_TWO_CELL: 219 | nm += " VM_TYPE_TWO_CELL" 220 | if typ & VM_TYPE_REF: 221 | nm += " VM_TYPE_REF" 222 | if typ & VM_TYPE_MONO: 223 | nm += " VM_TYPE_MONO" 224 | if typ & VM_TYPE_MULTI: 225 | nm += " VM_TYPE_MULTI" 226 | return nm 227 | 228 | """ 229 | struct VMFileHeader 230 | { 231 | TU1 nMagicWord1; 232 | TU1 nMagicWord2; 233 | TU1 nMagicWord3; 234 | TU1 nMagicWord4; 235 | TU1 nFormatVersionMajor; 236 | TU1 nFormatVersionMinor; 237 | TU1 nByteOrder; 238 | TU1 nOptions; 239 | TU4 nFileLength; 240 | TU2 nFileVersion; 241 | TU2 nTotalPackageCount; 242 | TU2 nInternalClassCount; 243 | TU2 nTotalClassCount; 244 | TU4 nTotalFieldCount; 245 | TU4 nTotalMethodCount; 246 | VMDOFFSET dofAttributeSection; 247 | VMDOFFSET dofSymbolicData; 248 | VMDOFFSET dofConstantDataPool; 249 | VMDOFFSET dofFileSignature; 250 | VMDOFFSET dofClassHeader[]; 251 | }; 252 | """ 253 | 254 | VM_ORDER_INT_BIG = 0x01 # If this flag is set, integer values are stored using the big-endian convention. 255 | # Otherwise, they are stored using the little-endian convention. 256 | VM_ORDER_INT_64_INV = 0x02 # If this flag is set, the two 32-bit parts of the 64-bit integer values are inverted. 257 | VM_ORDER_FLOAT_BIG = 0x04 # If this flag is set, JFLOAT and JDOUBLE values are stored using the big-endian convention. 258 | # Otherwise, they are stored using the little-endian convention. 259 | VM_ORDER_FLOAT_64_INV = 0x08 # If this flag is set, the two 32-bit parts of the JDOUBLE values are inverted. 260 | 261 | 262 | VM_USE_LONG_TYPE = 0x01 # One of the classes uses the "long" type (in the fields types, the methods signatures, the constant values or the bytecode instructions). 263 | VM_USE_UCS_BMP = 0x02 # All the characters encoded in the strings of this file are in the "Basic Multilingual Plane", 264 | # therefore their encoding is in the range U+0000 to U+FFFF included. 265 | VM_USE_FLOAT_TYPE = 0x04 # One of the classes uses the "float" type and/or the "double" type 266 | # (in the fields types, the methods signatures, the constant values or the bytecode instructions). 267 | VM_USE_STRICT_FLOAT = 0x08 # One of the classes contains bytecodes with strict floating-point computation (the "strictfp" keyword is used in the source file). 268 | VM_USE_NATIVE_METHOD = 0x10 # One of the classes contains native methods. 269 | VM_USE_FINALIZER = 0x20 # One of the classes has an instance finalizer or a class finalizer. 270 | VM_USE_MONITOR = 0x40 # One of the classes uses the flag ACC_SYNCHRONIZED or the bytecodes jeff_monitorenter or jeff_monitorexit in one of its methods. 271 | 272 | class VMFileHeaderStart(ctypes.LittleEndianStructure): 273 | _fields_ = [ 274 | ("nMagicWord1", TU1), # 'J' 275 | ("nMagicWord2", TU1), # 'E' 276 | ("nMagicWord3", TU1), # 'F' 277 | ("nMagicWord4", TU1), # 'F' 278 | ("nFormatVersionMajor", TU1), # 1 279 | ("nFormatVersionMinor", TU1), # 0 280 | ("nByteOrder", TU1), # VM_ORDER_xxx 281 | ("nOptions", TU1), # VM_USE_xxx 282 | ] 283 | 284 | vmnheader_fields_endian = [ 285 | ("nFileLength", TU4), # Size in bytes of the file (all elements included). 286 | ("nFileVersion", TU2), # Version number of the file itself (major<<8 | minor) 287 | ("nTotalPackageCount", TU2), # The total number of unique packages referenced in the file 288 | # (for the internal classes and the external classes). 289 | ("nInternalClassCount", TU2), # The number of classes in the file (internal classes). 290 | ("nTotalClassCount", TU2), # The total number of the classes referenced in the file (internal classes and external classes). 291 | ("nTotalFieldCount", TU4), # The total number of field symbolic names used in the file. 292 | ("nTotalMethodCount", TU4), # The total number of method symbolic names used in the file. 293 | ("dofAttributeSection", VMDOFFSET), # Offset of the Optional Attribute Section (0 if absent) 294 | ("dofSymbolicData", VMDOFFSET), # Offset of the symbolic data section (0 if absent) 295 | ("dofConstantDataPool", VMDOFFSET), # Offset of the constant data pool (0 if absent) 296 | ("dofFileSignature", VMDOFFSET), # Offset of the file signature (0 if absent) 297 | # ("dofClassHeader", VMDOFFSET[] # Offsets of the VMClassHeader structures for all internal classes 298 | ] 299 | 300 | class VMFileHeaderRestLE(ctypes.LittleEndianStructure): 301 | _fields_ = vmnheader_fields_endian 302 | 303 | class VMFileHeaderRestBE(ctypes.BigEndianStructure): 304 | _fields_ = vmnheader_fields_endian 305 | 306 | def print_hdr(h1, h2, dofClassHeader): 307 | print "File magic: JEFF" 308 | print "Format version: %d.%d" % (h1.nFormatVersionMajor, h1.nFormatVersionMinor) 309 | print "Byte order: 0x%02X" % (h1.nByteOrder) 310 | if h1.nByteOrder & VM_ORDER_INT_BIG: 311 | print " VM_ORDER_INT_BIG" 312 | if h1.nByteOrder & VM_ORDER_INT_64_INV: 313 | print " VM_ORDER_INT_64_INV" 314 | if h1.nByteOrder & VM_ORDER_FLOAT_BIG: 315 | print " VM_ORDER_FLOAT_BIG" 316 | if h1.nByteOrder & VM_ORDER_FLOAT_64_INV: 317 | print " VM_ORDER_FLOAT_64_INV" 318 | 319 | print "Options: 0x%02X" % (h1.nOptions) 320 | if h1.nOptions & VM_ORDER_FLOAT_64_INV: 321 | print " VM_USE_LONG_TYPE" 322 | if h1.nOptions & VM_USE_UCS_BMP: 323 | print " VM_USE_UCS_BMP" 324 | if h1.nOptions & VM_USE_FLOAT_TYPE: 325 | print " VM_USE_FLOAT_TYPE" 326 | if h1.nOptions & VM_USE_STRICT_FLOAT: 327 | print " VM_USE_STRICT_FLOAT" 328 | if h1.nOptions & VM_USE_NATIVE_METHOD: 329 | print " VM_USE_NATIVE_METHOD" 330 | if h1.nOptions & VM_USE_FINALIZER: 331 | print " VM_USE_FINALIZER" 332 | if h1.nOptions & VM_USE_MONITOR: 333 | print " VM_USE_MONITOR" 334 | 335 | print "File length: 0x%02X" % (h2.nFileLength) 336 | print "File version: %d.%d" % (h2.nFileVersion>>8, h2.nFileVersion&0xFF) 337 | print "Total packages: %d" % (h2.nTotalPackageCount) 338 | print "Internal classes: %d" % (h2.nInternalClassCount) 339 | print "Total classes: %d" % (h2.nTotalClassCount) 340 | print "Total fields: %d" % (h2.nTotalFieldCount) 341 | print "Total methods: %d" % (h2.nTotalMethodCount) 342 | print "Attribute section: 0x%04X" % (h2.dofAttributeSection) 343 | print "Symbolic data: 0x%04X" % (h2.dofSymbolicData) 344 | print "Const data pool: 0x%04X" % (h2.dofConstantDataPool) 345 | print "File signature: 0x%04X" % (h2.dofFileSignature) 346 | print "Class headers:", 347 | for i in range(len(dofClassHeader)): 348 | if i % 8 == 0: 349 | print "" 350 | print "0x%04X " % dofClassHeader[i], 351 | print "" 352 | 353 | class JeffFile: 354 | def get_struct(self, s): 355 | r = get_struct(self.f, self.offset, s) 356 | self.offset += ctypes.sizeof(r) 357 | return r 358 | 359 | def tell(self): 360 | return self.offset 361 | 362 | def seek(self, off): 363 | self.offset = off 364 | 365 | def skip(self, cnt): 366 | self.offset += cnt 367 | 368 | def align(self, sz): 369 | mask = sz-1 370 | if self.offset & mask: 371 | self.offset = (self.offset+mask) & ~mask 372 | 373 | def _read_one(self, aligned, fmt): 374 | if self.bigendian: 375 | fmt = ">" + fmt 376 | else: 377 | fmt = "<" + fmt 378 | sz = struct.calcsize(fmt) 379 | if aligned: 380 | self.align(sz) 381 | r = struct.unpack(fmt, self.f[self.offset:self.offset+sz])[0] 382 | self.offset += sz 383 | return r 384 | 385 | def read_8(self, aligned = False): 386 | return self._read_one(aligned, 'B') 387 | 388 | def read_8s(self, aligned = False): 389 | return self._read_one(aligned, 'b') 390 | 391 | def read_16(self, aligned = False): 392 | return self._read_one(aligned, 'H') 393 | 394 | def read_16s(self, aligned = False): 395 | return self._read_one(aligned, 'h') 396 | 397 | def read_32(self, aligned = False): 398 | return self._read_one(aligned, 'I') 399 | 400 | def read_32s(self, aligned = False): 401 | return self._read_one(aligned, 'i') 402 | 403 | def read_32f(self, aligned = False): 404 | return self._read_one(aligned, 'f') 405 | 406 | def read_64(self, aligned = False): 407 | return self._read_one(aligned, 'Q') 408 | 409 | def read_64s(self, aligned = False): 410 | return self._read_one(aligned, 'q') 411 | 412 | def read_64d(self, aligned = False): 413 | return self._read_one(aligned, 'd') 414 | 415 | def read_descriptor(self, jclass): 416 | return VMDescriptor(self, jclass) 417 | 418 | def read_bytes(self, count): 419 | r = self.f[self.offset:self.offset+count] 420 | self.offset += count 421 | return r 422 | 423 | def read_string(self): 424 | nStringLength = self.read_16() 425 | return self.read_bytes(nStringLength) 426 | 427 | def _get_helper(self, fn, offs): 428 | saved = self.offset 429 | self.offset = offs 430 | r = fn() 431 | self.offset = saved 432 | return r 433 | 434 | def get_string(self, offs): 435 | return self._get_helper(self.read_string, offs) 436 | 437 | def get_8(self, offs): 438 | return self._get_helper(self.read_8, offs) 439 | 440 | def get_16(self, offs): 441 | return self._get_helper(self.read_16, offs) 442 | 443 | def get_16s(self, offs): 444 | return self._get_helper(self.read_16s, offs) 445 | 446 | def get_32(self, offs): 447 | return self._get_helper(self.read_32, offs) 448 | 449 | def get_32s(self, offs): 450 | return self._get_helper(self.read_32s, offs) 451 | 452 | def get_classname(self, idx): 453 | if idx == 0xFFFF: 454 | return "" 455 | if idx >= len(self.symdata.classNames): 456 | return "" % idx 457 | nm = self.symdata.classNames[idx] 458 | if idx >= self.nInternalClassCount: 459 | return self.symdata.packageNames[self.symdata.pidExtClassPackage[idx - self.nInternalClassCount]] + "." + nm 460 | return nm 461 | 462 | def get_pkgname(self, idx): 463 | return self.symdata.packageNames[idx] 464 | 465 | def get_javaname(self, cidx): 466 | if cidx >= self.nInternalClassCount: 467 | pidx = self.symdata.pidExtClassPackage[cidx - self.nInternalClassCount] 468 | else: 469 | pidx = self.classes[cidx].pidPackage 470 | pkgname = self.symdata.packageNames[pidx] 471 | cname = self.symdata.classNames[cidx] 472 | return pkgname.replace(".", "/") + "/" + cname 473 | 474 | def get_field(self, idx): 475 | if idx >= len(self.symdata.fieldInfos): 476 | return "" % idx 477 | return self.symdata.fieldInfos[idx] 478 | 479 | def get_method(self, idx): 480 | if idx >= len(self.symdata.methodInfos): 481 | return "" % idx 482 | return self.symdata.methodInfos[idx] 483 | 484 | def _print(self, indent=0): 485 | print " "*indent, "JEFF file header:" 486 | print_hdr(self.h1, self.h2, self.dofClassHeader) 487 | print " "*indent, "file attributes:" 488 | self.attributes._print(indent+2) 489 | print " "*indent, "file symbolic data:" 490 | self.symdata._print(indent+2) 491 | print " "*indent, "classes:" 492 | for i in range(len(self.classes)): 493 | print "\nClass %d (offset 0x%04X):\n===========================" % (i, self.dofClassHeader[i]) 494 | self.classes[i]._print(2) 495 | 496 | def __init__(self, f, offset = 0): 497 | self.offset = 0 498 | self.f = f[offset:] 499 | h1 = self.get_struct(VMFileHeaderStart) 500 | if ( h1.nMagicWord1 != ord('J') or 501 | h1.nMagicWord2 != ord('E') or 502 | h1.nMagicWord3 != ord('F') or 503 | h1.nMagicWord4 != ord('F')): 504 | raise Exception("Bad signature! Not a JEFF file?") 505 | 506 | self.linked = h1.nFormatVersionMajor == 254 507 | if not self.linked and (h1.nFormatVersionMajor > 1 or (h1.nFormatVersionMajor == 1 and h1.nFormatVersionMinor > 0)): 508 | print "Warning: file format (%d.%d) newer than expected (1.0)" % (h1.nFormatVersionMajor, h1.nFormatVersionMinor) 509 | 510 | self.bigendian = h1.nByteOrder & VM_ORDER_INT_BIG 511 | if self.bigendian: 512 | h2 = self.get_struct(VMFileHeaderRestBE) 513 | else: 514 | h2 = self.get_struct(VMFileHeaderRestLE) 515 | 516 | self.h1 = h1 517 | self.h2 = h2 518 | self.f = f[offset:offset+h2.nFileLength] 519 | self.dofClassHeader = [self.read_32() for i in range(h2.nInternalClassCount)] 520 | for x in h2._fields_: 521 | setattr(self, x[0], getattr(h2, x[0])) 522 | self.attributes = JeffAtributes(self) 523 | self.symdata = JeffSymbolicData(self) 524 | self.classes = [JeffClass(self, off) for off in self.dofClassHeader] 525 | 526 | """ 527 | VMAttributeSection { 528 | VMDOFFSET dofFileAttributeList; 529 | VMDOFFSET dofClassAttributes[nInternalClassCount]; 530 | TU2 nAttributeTypeCount; 531 | TU2 nClassAttributeCount; 532 | VMAttributeType sAttributeType[nAttributeTypeCount]; 533 | VMClassAttributes sClassAttributes[nClassAttributeCount] 534 | TU2 nAttributeTableCount; 535 | VMAttributeTable sAttributeTable[nAttributeTableCount]; 536 | } 537 | 538 | VMAttributeType { 539 | VMDOFFSET dofTypeName; 540 | TU2 nTypeFlags; 541 | TU2 nTypeLength; 542 | } 543 | 544 | VMClassAttributes { 545 | VMDOFFSET dofClassAttributeList; 546 | VMDOFFSET dofFieldAttributeList[nFieldCount]; 547 | VMDOFFSET dofMethodAttributeList[nMethodCount]; 548 | } 549 | 550 | VMAttributeTable { 551 | TU2 nAttributeCount; 552 | { 553 | TU2 nAttributeType; 554 | TU1 <0-2 byte pad> 555 | TU4 nTypeLength; // only if VM_ATTR_CST_LENGTH is not set in the type's nTypeFlags 556 | TU1 nData[nTypeLength]; 557 | } VMAttribute[nAttributeCount] 558 | } 559 | """ 560 | 561 | # values for VMAttributeType's nTypeFlags 562 | VM_ATTR_INDEXES = 0x0001 # The attribute contains some index values of type 563 | # VMPINDEX, VMCINDEX, VMMINDEX or VMFINDEX. 564 | VM_ATTR_VMOFFSETS = 0x0002 # The attribute contains some values of type VMOFFSET. 565 | VM_ATTR_VMDOFFSETS = 0x0004 # The attribute contains some values of type VMDOFFSET. 566 | VM_ATTR_BYTE_ORDER = 0x0008 # The elements stored in nData (See the 567 | # VMAttributeTable structure) contain byte ordered 568 | # values. Must be set if the VM_ATTR_INDEXES, VM_ATTR_VMOFFSETS, 569 | # or VM_ATTR_VMDOFFSETS flags are specified. 570 | VM_ATTR_CST_LENGTH = 0x0010 # The length of the attribute is constant and given by 571 | # the nTypeLength item. This flag can only be used if 572 | # the length of the attribute structure is not subject to 573 | # variations caused by the type alignment and if the 574 | # length can be encoded with a TU2 variable. 575 | 576 | class VMAttributeType: 577 | def __init__(self, jeff): 578 | self.dofTypeName = jeff.read_32() 579 | self.nTypeFlags = jeff.read_16() 580 | self.nTypeLength = jeff.read_16() 581 | self.name = jeff.get_string(self.dofTypeName) 582 | 583 | def _print(self, indent = 0): 584 | print " "*indent, "Type name: %r" % self.name 585 | print " "*indent, "Type flags (%02X):" % self.nTypeFlags, 586 | if self.nTypeFlags & VM_ATTR_INDEXES: 587 | print "VM_ATTR_INDEXES", 588 | if self.nTypeFlags & VM_ATTR_VMOFFSETS: 589 | print "VM_ATTR_VMOFFSETS", 590 | if self.nTypeFlags & VM_ATTR_VMDOFFSETS: 591 | print "VM_ATTR_VMDOFFSETS", 592 | if self.nTypeFlags & VM_ATTR_BYTE_ORDER: 593 | print "VM_ATTR_BYTE_ORDER", 594 | if self.nTypeFlags & VM_ATTR_CST_LENGTH: 595 | print "VM_ATTR_CST_LENGTH", 596 | print "" 597 | if self.nTypeFlags & VM_ATTR_CST_LENGTH: 598 | print " "*indent, "Type length: %d" % self.nTypeLength 599 | 600 | class VMAttribute: 601 | def __init__(self, jeff, types): 602 | self.nAttributeType = jeff.read_16() 603 | self.jeff = jeff 604 | self.typ = types[self.nAttributeType] 605 | if self.typ.nTypeFlags & VM_ATTR_CST_LENGTH: 606 | nTypeLength = self.typ.nTypeLength 607 | else: 608 | nTypeLength = jeff.read_32(True) 609 | self.nData = jeff.read_bytes(nTypeLength) 610 | 611 | def _print(self, indent = 0): 612 | print " "*indent, "Attribute type:" 613 | self.typ._print(indent+2) 614 | print " "*indent, "Attribute data: %r" % (self.nData) 615 | 616 | class VMAttributeTable: 617 | def __init__(self, jeff, types): 618 | nAttributeCount = jeff.read_16() 619 | self.jeff = jeff 620 | self.types = types 621 | self.attributes = [VMAttribute(jeff, types) for i in range(nAttributeCount)] 622 | def __getitem__(self, key): 623 | return self.attributes[key] 624 | 625 | def _print(self, indent = 0): 626 | for i in range(len(self.attributes)): 627 | print " "*indent, "attribute %d:" % i 628 | self.attributes[i]._print(indent+2) 629 | 630 | 631 | class JeffAtributes: 632 | def __init__(self, jeff): 633 | self.jeff = jeff 634 | self.FileAttribute = None 635 | self.ClassAttributes = [] 636 | if jeff.dofAttributeSection != 0: 637 | jeff.offset = jeff.dofAttributeSection 638 | dofFileAttributeList = jeff.read_32() 639 | dofClassAttributes = [jeff.read_32() for i in range(jeff.nInternalClassCount)] 640 | nAttributeTypeCount = jeff.read_16() 641 | nClassAttributeCount = jeff.read_16() 642 | self.types = [VMAttributeType(jeff) for i in range(nAttributeTypeCount)] 643 | if dofFileAttributeList != 0: 644 | jeff.offset = dofFileAttributeList 645 | self.FileAttribute = VMAttributeTable(jeff, self.types) 646 | for ca in dofClassAttributes: 647 | if ca != 0: 648 | jeff.offset = dofFileAttributeList 649 | self.ClassAttributes.append(VMAttributeTable(jeff, self.types)) 650 | else: 651 | self.ClassAttributes.append(None) 652 | 653 | def _print(self, indent = 0): 654 | if self.FileAttribute: 655 | print " "*indent, "File attributes:" 656 | self.FileAttribute._print(indent + 2) 657 | if self.ClassAttributes: 658 | print " "*indent, "Class attributes:" 659 | for i in range(len(self.ClassAttributes)): 660 | ca = self.ClassAttributes[i] 661 | if ca: 662 | print " "*(indent+2), "Class %d:" % i 663 | ca._print(indent+4) 664 | 665 | """ 666 | VMClassHeader { 667 | VMOFFSET ofThisClassIndex; 668 | VMPINDEX pidPackage; 669 | VMACCESS aAccessFlag; 670 | TU2 nClassData; 671 | VMOFFSET ofClassConstructor; 672 | VMOFFSET ofInterfaceTable; 673 | VMOFFSET ofFieldTable; 674 | VMOFFSET ofMethodTable; 675 | VMOFFSET ofReferencedFieldTable; 676 | VMOFFSET ofReferencedMethodTable; 677 | VMOFFSET ofReferencedClassTable; 678 | VMOFFSET ofConstantDataSection; 679 | VMOFFSET ofSuperClassIndex; // not present for interface 680 | TU2 nInstanceData; // not present for interface 681 | VMOFFSET ofInstanceConstructor; // not present for interface 682 | } 683 | 684 | VMInterfaceTable { 685 | TU2 nInterfaceCount; 686 | VMOFFSET ofInterfaceIndex [nInterfaceCount]; 687 | } 688 | 689 | VMFieldInfoTable { 690 | TU2 nFieldCount; 691 | TU1 <0-2 byte pad> 692 | { 693 | VMFINDEX fidFieldIndex; 694 | VMOFFSET ofThisClassIndex; 695 | VMTYPE tFieldType; 696 | TU1 nTypeDimension; 697 | VMACCESS aAccessFlag; 698 | TU2 nFieldDataOffset; 699 | } VMFieldInfo [nFieldCount]; 700 | } 701 | 702 | VMMethodInfoTable { 703 | TU2 nMethodCount; 704 | TU1 <0-2 byte pad> 705 | { 706 | VMMINDEX midMethodIndex; 707 | VMOFFSET ofThisClassIndex; 708 | VMNCELL ncStackArgument; 709 | VMACCESS aAccessFlag; 710 | VMOFFSET ofCode; 711 | } VMMethodInfo [nMethodCount]; 712 | TU4 nNativeReference[]; 713 | } 714 | 715 | VMReferencedFieldTable { 716 | TU2 nFieldCount; 717 | TU1 <0-2 byte pad> 718 | { 719 | VMFINDEX fidFieldIndex; 720 | VMOFFSET ofClassIndex; 721 | VMTYPE tFieldType; 722 | TU1 nTypeDimension; 723 | } VMReferencedField [nFieldCount]; 724 | } 725 | 726 | VMReferencedMethodTable { 727 | TU2 nMethodCount; 728 | TU1 <0-2 byte pad> 729 | { 730 | VMMINDEX midMethodIndex; 731 | VMOFFSET ofClassIndex; 732 | VMNCELL ncStackArgument; 733 | } VMReferencedMethod [nMethodCount]; 734 | } 735 | 736 | VMReferencedClassTable { 737 | TU2 nReferencedClassCount; 738 | VMCINDEX cidReferencedClass [nReferencedClassCount]; 739 | } 740 | 741 | VMBytecodeBlock { 742 | VMNCELL ncMaxStack; 743 | VMNCELL ncMaxLocals; 744 | VMOFFSET ofExceptionCatchTable; 745 | TU2 nByteCodeSize; 746 | TU1 bytecode[nByteCodeSize]; 747 | } 748 | 749 | VMExceptionCatchTable { 750 | TU2 nCatchCount; 751 | { 752 | VMOFFSET ofStartPc; 753 | VMOFFSET ofEndPc; 754 | VMOFFSET ofHandlerPc; 755 | VMOFFSET ofExceptionIndex; 756 | } VMExceptionCatch [nCatchCount]; 757 | } 758 | 759 | VMConstantDataSection { 760 | TU2 nConstFlags; 761 | TU2 nDoubleNumber; 762 | TU2 nLongNumber; 763 | TU2 nFloatNumber; 764 | TU2 nIntNumber; 765 | TU2 nShortNumber; 766 | TU2 nByteNumber; 767 | TU2 nStringNumber; 768 | JDOUBLE nDoubleValue[nDoubleNumber]; 769 | JLONG nLongValue[nLongNumber]; 770 | JFLOAT nFloatValue[nFloatNumber]; 771 | JINT nIntValue[nIntNumber]; 772 | JSHORT nShortValue[nShortNumber]; 773 | JBYTE nByteValue[nByteNumber]; 774 | TU1 <0-1 byte pad> 775 | VMString strConstString[nStringNumber]; 776 | } 777 | 778 | """ 779 | 780 | class VMFieldInfo: 781 | def __init__(self, jeff): 782 | self.jeff = jeff 783 | self.fidFieldIndex = jeff.read_32() 784 | self.ofThisClassIndex = jeff.read_16() 785 | self.tFieldType = jeff.read_8() 786 | self.nTypeDimension = jeff.read_8() 787 | self.aAccessFlag = jeff.read_16() 788 | self.nFieldDataOffset = jeff.read_16() 789 | 790 | def _dump(self, indent = 0): 791 | f = self.jeff.get_field(self.fidFieldIndex) 792 | print ".field %s %s %s" % (" ".join(acc2flagsj(self.aAccessFlag)), f.name, f.descr.get_jtype()) 793 | 794 | def _print(self, indent = 0): 795 | print " "*indent, "fidFieldIndex: 0x%02X (%s)" % (self.fidFieldIndex, self.jeff.get_field(self.fidFieldIndex)) 796 | print " "*indent, "ofThisClassIndex: 0x%02X" % (self.ofThisClassIndex) 797 | print " "*indent, "tFieldType: 0x%02X (%s)" % (self.tFieldType, type2str(self.tFieldType)) 798 | print " "*indent, "nTypeDimension: 0x%02X" % (self.nTypeDimension) 799 | print " "*indent, "aAccessFlag: 0x%02X (%s)" % (self.aAccessFlag, "|".join(acc2flags(self.aAccessFlag))) 800 | print " "*indent, "nFieldDataOffset: 0x%02X" % (self.nFieldDataOffset) 801 | 802 | class VMMethodInfo: 803 | def __init__(self, jeff, jclass): 804 | self.jeff = jeff 805 | self.jclass = jclass 806 | self.midMethodIndex = jeff.read_32() 807 | self.ofThisClassIndex = jeff.read_16() 808 | self.ncStackArgument = jeff.read_16() 809 | self.aAccessFlag = jeff.read_16() 810 | self.ofCode = jeff.read_16() 811 | if self.ofCode != 0 and ((self.aAccessFlag & ACC_NATIVE) == 0): 812 | savepos = jeff.tell() 813 | jeff.seek(self.ofCode + jclass.offset) 814 | self.code = VMBytecodeBlock(jeff, jclass) 815 | jeff.seek(savepos) 816 | 817 | def _dump(self, indent = 0): 818 | md = self.jeff.get_method(self.midMethodIndex) 819 | print ".method %s %s : %s" % (" ".join(acc2flagsj(self.aAccessFlag, True)), md.name, md.get_jtype()) 820 | if self.aAccessFlag & ACC_NATIVE: 821 | print ";", " "*(indent+2), "native method %d" % (self.jeff.get_16(self.jclass.offset + self.ofCode)) 822 | elif self.ofCode != 0: 823 | self.code._dump(indent+2) 824 | b = BytecodePrinter(self.jclass, self.ofCode, len(self.code.bytecode)) 825 | print "" 826 | print ";", " "*(indent+2), "Bytecode disassembly:" 827 | b.print_java(indent+4) 828 | #b = BytecodePrinter(self.jclass, self.ofCode, len(self.code.bytecode)) 829 | #b._print(indent+4) 830 | print ".end method" 831 | 832 | def _print(self, indent = 0): 833 | print " "*indent, "midMethodIndex: 0x%02X (%s)" % (self.midMethodIndex, self.jeff.get_method(self.midMethodIndex)) 834 | print " "*indent, "ofThisClassIndex: 0x%02X" % (self.ofThisClassIndex) 835 | print " "*indent, "ncStackArgument: 0x%02X" % (self.ncStackArgument) 836 | print " "*indent, "aAccessFlag: 0x%02X (%s)" % (self.aAccessFlag, "|".join(acc2flags(self.aAccessFlag, True))) 837 | print " "*indent, "ofCode: 0x%02X" % (self.ofCode), 838 | if self.aAccessFlag & ACC_NATIVE: 839 | print "(%d)" % (self.jeff.get_16(self.jclass.offset + self.ofCode)) 840 | else: 841 | print "" 842 | if self.ofCode != 0: 843 | print " "*indent, "Bytecode block:" 844 | self.code._print(indent+2) 845 | b = BytecodePrinter(self.jclass, self.ofCode, len(self.code.bytecode)) 846 | print "" 847 | print " "*(indent+2), "Bytecode disassembly:" 848 | b.print_jeff(indent+4) 849 | 850 | class VMExceptionCatch: 851 | def __init__(self, jeff): 852 | self.ofStartPc = jeff.read_16() 853 | self.ofEndPc = jeff.read_16() 854 | self.ofHandlerPc = jeff.read_16() 855 | self.ofExceptionIndex = jeff.read_16() 856 | 857 | from opcodes import BytecodePrinter 858 | 859 | class VMBytecodeBlock: 860 | def __init__(self, jeff, jclass): 861 | self.jeff = jeff 862 | self.jclass = jclass 863 | self.ncMaxStack = jeff.read_16() 864 | self.ncMaxLocals = jeff.read_16() 865 | self.ofExceptionCatchTable = jeff.read_16() 866 | nByteCodeSize = jeff.read_16() 867 | self.bytecode = jeff.read_bytes(nByteCodeSize) 868 | if self.ofExceptionCatchTable != 0: 869 | jeff.seek(jclass.offset + self.ofExceptionCatchTable) 870 | nCatchCount = jeff.read_16() 871 | self.catches = [VMExceptionCatch(jeff) for i in range(nCatchCount)] 872 | else: 873 | self.catches = [] 874 | 875 | def _dump(self, indent = 0): 876 | print " "*indent, ".limit stack %d" % (self.ncMaxStack) 877 | print " "*indent, ".limit locals %d" % (self.ncMaxLocals) 878 | for c in self.catches: 879 | if c.ofExceptionIndex == 0xFFFF: 880 | ctype = "[0]" 881 | else: 882 | cidx = self.jclass.get_index(c.ofExceptionIndex) 883 | ctype = self.jeff.get_javaname(cidx) 884 | # print ".catch %s from L%04X to L%04X using L%04X" % (ctype, c.ofStartPc, c.ofEndPc, c.ofHandlerPc) 885 | 886 | def _print(self, indent = 0): 887 | print " "*indent, "ncMaxStack: 0x%02X" % (self.ncMaxStack) 888 | print " "*indent, "ncMaxLocals: 0x%02X" % (self.ncMaxLocals) 889 | print " "*indent, "ofExceptionCatchTable: 0x%02X" % (self.ofExceptionCatchTable) 890 | print " "*indent, "nByteCodeSize: 0x%02X" % (len(self.bytecode)) 891 | if self.ofExceptionCatchTable != 0: 892 | print "" 893 | print " "*indent, "===Exception Table List====" 894 | print " "*indent, "nCatchCount: 0x%02X" % (len(self.catches)) 895 | print " "*indent, " # ofStartPc ofEndPc ofHandlerPc ofExceptionIndex" 896 | for i in range(len(self.catches)): 897 | c = self.catches[i] 898 | if c.ofExceptionIndex != 0: 899 | cidx = self.jclass.get_index(c.ofExceptionIndex) 900 | ename = self.jeff.get_classname(cidx) 901 | else: 902 | ename = "..." 903 | 904 | print " "*indent, "%2d 0x%04X 0x%04X 0x%04X 0x%02X (%s)" % (i, c.ofStartPc, c.ofEndPc, c.ofHandlerPc, c.ofExceptionIndex, ename) 905 | 906 | 907 | class JeffClass: 908 | def __init__(self, jeff, offs): 909 | self.jeff = jeff 910 | self.offset = offs 911 | jeff.seek(offs) 912 | self.ofThisClassIndex = jeff.read_16() 913 | self.pidPackage = jeff.read_16() 914 | self.aAccessFlag = jeff.read_16() 915 | self.nClassData = jeff.read_16() 916 | self.ofClassConstructor = jeff.read_16() 917 | self.ofInterfaceTable = jeff.read_16() 918 | self.ofFieldTable = jeff.read_16() 919 | self.ofMethodTable = jeff.read_16() 920 | self.ofReferencedFieldTable = jeff.read_16() 921 | self.ofReferencedMethodTable = jeff.read_16() 922 | self.ofReferencedClassTable = jeff.read_16() 923 | self.ofConstantDataSection = jeff.read_16() 924 | if (self.aAccessFlag & ACC_INTERFACE) == 0: 925 | self.ofSuperClassIndex = jeff.read_16() 926 | self.nInstanceData = jeff.read_16() 927 | self.ofInstanceConstructor = jeff.read_16() 928 | 929 | self._read_fields() 930 | self._read_methods() 931 | self._read_ifaces() 932 | 933 | def get_index(self, fld): 934 | if self.jeff.linked: 935 | return fld 936 | else: 937 | return self.jeff.get_16(self.offset + fld) 938 | 939 | def _soff_by_idx(self, idx): 940 | "Seek to the string in constant data section by its index" 941 | 942 | # see VMConstantDataSection 943 | if self.ofConstantDataSection == 0: 944 | return 0 945 | savepos = self.jeff.tell() 946 | self.jeff.seek(self.offset + self.ofConstantDataSection) 947 | nConstFlags = self.jeff.read_16() 948 | nDoubleNumber = self.jeff.read_16() if (nConstFlags & 0x01) else 0 949 | nLongNumber = self.jeff.read_16() if (nConstFlags & 0x02) else 0 950 | nFloatNumber = self.jeff.read_16() if (nConstFlags & 0x04) else 0 951 | nIntNumber = self.jeff.read_16() if (nConstFlags & 0x08) else 0 952 | nShortNumber = self.jeff.read_16() if (nConstFlags & 0x10) else 0 953 | nByteNumber = self.jeff.read_16() if (nConstFlags & 0x20) else 0 954 | nStringNumber = self.jeff.read_16() if (nConstFlags & 0x40) else 0 955 | if nDoubleNumber or nLongNumber: 956 | self.jeff.align(8) 957 | self.jeff.skip(8*(nDoubleNumber+nLongNumber)) 958 | if nFloatNumber or nIntNumber: 959 | self.jeff.align(4) 960 | self.jeff.skip(4*(nFloatNumber+nIntNumber)) 961 | self.jeff.skip(2*nShortNumber + nByteNumber) 962 | self.jeff.align(2) 963 | if idx >= nStringNumber: 964 | res = 0 965 | else: 966 | for i in range(idx): 967 | self.jeff.read_string() 968 | self.jeff.align(2) 969 | res = self.jeff.tell() 970 | self.jeff.seek(savepos) 971 | return res 972 | 973 | """ 974 | VMString { 975 | TU2 nStringLength; 976 | TU1 nStringValue[nStringLength]; 977 | } 978 | """ 979 | 980 | def get_sconst(self, ofConstant, count = 1): 981 | soff = self.offset + ofConstant 982 | if self.jeff.linked: 983 | # ofConstant is the index of the string in the constant pool 984 | soff = self._soff_by_idx(ofConstant) 985 | if soff == 0: 986 | return "" % ofConstant 987 | # print "string index %d, offset 0x%x" % (ofConstant, soff) 988 | r = [] 989 | for i in range(count): 990 | s = self.jeff.get_string(soff) 991 | soff += (len(s) + 3) & ~1 992 | r.append(s) 993 | if count == 1: 994 | return r[0] 995 | else: 996 | return r 997 | 998 | def _const_helper(self, ofConstant, count, reader): 999 | savepos = self.jeff.tell() 1000 | self.jeff.seek(self.offset + ofConstant) 1001 | r = [reader() for i in range(count)] 1002 | self.jeff.seek(savepos) 1003 | return r 1004 | 1005 | def get_iconst(self, ofConstant, count = 1): 1006 | r = self._const_helper(ofConstant, count, self.jeff.read_32s) 1007 | if count==1: 1008 | return r[0] 1009 | else: 1010 | return r 1011 | 1012 | def get_lconst(self, ofConstant, count = 1): 1013 | r = self._const_helper(ofConstant, count, self.jeff.read_64s) 1014 | if count==1: 1015 | return r[0] 1016 | else: 1017 | return r 1018 | 1019 | def get_array(self, tArrayType, ofConstData, nLength): 1020 | t = tArrayType & 0xF 1021 | arrtyp = type2str(t, 1, False) 1022 | if t in [VM_TYPE_BYTE, VM_TYPE_CHAR, VM_TYPE_BOOLEAN]: 1023 | vals = self._const_helper(ofConstData, nLength, self.jeff.read_8) 1024 | if t == VM_TYPE_CHAR: 1025 | vals = map(chr, vals) 1026 | elif t == VM_TYPE_SHORT: 1027 | vals = self._const_helper(ofConstData, nLength, self.jeff.read_16s) 1028 | elif t == VM_TYPE_INT: 1029 | vals = self._const_helper(ofConstData, nLength, self.jeff.read_32s) 1030 | else: 1031 | return "" % arrtyp 1032 | 1033 | return "<%s %r>" % (arrtyp, vals) 1034 | 1035 | def get_array_values(self, tArrayType, ofConstData, nLength): 1036 | t = tArrayType & 0xF 1037 | arrtyp = type2str(t, 0, False) 1038 | if t in [VM_TYPE_BYTE, VM_TYPE_CHAR, VM_TYPE_BOOLEAN]: 1039 | vals = self._const_helper(ofConstData, nLength, self.jeff.read_8) 1040 | elif t == VM_TYPE_SHORT: 1041 | vals = self._const_helper(ofConstData, nLength, self.jeff.read_16s) 1042 | elif t == VM_TYPE_INT: 1043 | vals = self._const_helper(ofConstData, nLength, self.jeff.read_32s) 1044 | else: 1045 | raise Exception("unhandled array type: %s" % arrtyp) 1046 | return (arrtyp, vals) 1047 | 1048 | def _read_fields(self): 1049 | if self.ofFieldTable == 0: 1050 | self.fields = [] 1051 | return 1052 | self.jeff.seek(self.offset + self.ofFieldTable) 1053 | nFieldCount = self.jeff.read_16() 1054 | self.jeff.align(4) 1055 | self.fields = [VMFieldInfo(self.jeff) for i in range(nFieldCount)] 1056 | 1057 | def _read_methods(self): 1058 | self.methods = [] 1059 | if self.ofMethodTable == 0: 1060 | return 1061 | self.jeff.seek(self.offset + self.ofMethodTable) 1062 | nMethodCount = self.jeff.read_16() 1063 | self.jeff.align(4) 1064 | nNativeCount = 0 1065 | for i in range(nMethodCount): 1066 | m = VMMethodInfo(self.jeff, self) 1067 | if m.aAccessFlag & ACC_NATIVE: 1068 | nNativeCount += 1 1069 | self.methods.append(m) 1070 | self.nNativeReference = [self.jeff.read_32() for i in range(nNativeCount)] 1071 | 1072 | def _read_ifaces(self): 1073 | if self.ofInterfaceTable == 0: 1074 | self.interfaces = [] 1075 | return 1076 | self.jeff.seek(self.offset + self.ofInterfaceTable) 1077 | nIntfCount = self.jeff.read_16() 1078 | self.interfaces = [self.get_index(self.jeff.read_16()) for i in range(nIntfCount)] 1079 | 1080 | def _print(self, indent=0): 1081 | cidx = self.get_index(self.ofThisClassIndex) 1082 | #print " "*indent, "Package: '%s'" % (self.jeff.get_pkgname(self.pidPackage)) 1083 | #print " "*indent, "Class: '%s'" % (self.jeff.get_classname(cidx)) 1084 | 1085 | print " "*indent, "ofThisClassIndex: 0x%02X (%s)" % (self.ofThisClassIndex, self.jeff.get_classname(cidx)) 1086 | print " "*indent, "pidPackage: 0x%02X (%s)" % (self.pidPackage, self.jeff.get_pkgname(self.pidPackage)) 1087 | print " "*indent, "aAccessFlag: 0x%02X (%s)" % (self.aAccessFlag, "|".join(acc2flags(self.aAccessFlag))) 1088 | print " "*indent, "nClassData: 0x%02X" % (self.nClassData) 1089 | print " "*indent, "ofClassConstructor: 0x%02X" % (self.ofClassConstructor) 1090 | print " "*indent, "ofInterfaceTable: 0x%02X" % (self.ofInterfaceTable) 1091 | print " "*indent, "ofFieldTable: 0x%02X" % (self.ofFieldTable) 1092 | print " "*indent, "ofMethodTable: 0x%02X" % (self.ofMethodTable) 1093 | print " "*indent, "ofReferencedFieldTable: 0x%02X" % (self.ofReferencedFieldTable) 1094 | print " "*indent, "ofReferencedMethodTable: 0x%02X" % (self.ofReferencedMethodTable) 1095 | print " "*indent, "ofConstantDataSection: 0x%02X" % (self.ofConstantDataSection) 1096 | if (self.aAccessFlag & ACC_INTERFACE) == 0: 1097 | sidx = self.get_index(self.ofSuperClassIndex) 1098 | print " "*indent, "ofSuperClassIndex: 0x%02X (%s)" % (self.ofSuperClassIndex, self.jeff.get_classname(sidx)) 1099 | print " "*indent, "nInstanceData: 0x%02X" % (self.nInstanceData) 1100 | print " "*indent, "ofInstanceConstructor: 0x%02X" % (self.ofInstanceConstructor) 1101 | 1102 | if self.interfaces: 1103 | print "" 1104 | print " "*indent, "Interfaces:", ", ".join([self.jeff.get_classname(self.interfaces[i]) for i in range(len(self.interfaces))]) 1105 | 1106 | if self.fields: 1107 | print "" 1108 | for i in range(len(self.fields)): 1109 | print "" 1110 | print " "*indent, "Field %d:" % i 1111 | self.fields[i]._print(indent+2) 1112 | 1113 | if self.methods: 1114 | print "" 1115 | for i in range(len(self.methods)): 1116 | print "" 1117 | print " "*indent, "Method %d:" % i 1118 | self.methods[i]._print(indent+2) 1119 | if self.nNativeReference: 1120 | print " "*indent, "Native references: %s" % " ".join("0x%04X" %n for n in self.nNativeReference) 1121 | 1122 | print "" 1123 | 1124 | def _dump_consts(self, indent=0, as_java = False): 1125 | "Print constant section" 1126 | 1127 | # see VMConstantDataSection 1128 | if self.ofConstantDataSection == 0: 1129 | return 0 1130 | savepos = self.jeff.tell() 1131 | self.jeff.seek(self.offset + self.ofConstantDataSection) 1132 | nConstFlags = self.jeff.read_16() 1133 | nDoubleNumber = self.jeff.read_16() if (nConstFlags & 0x01) else 0 1134 | nLongNumber = self.jeff.read_16() if (nConstFlags & 0x02) else 0 1135 | nFloatNumber = self.jeff.read_16() if (nConstFlags & 0x04) else 0 1136 | nIntNumber = self.jeff.read_16() if (nConstFlags & 0x08) else 0 1137 | nShortNumber = self.jeff.read_16() if (nConstFlags & 0x10) else 0 1138 | nByteNumber = self.jeff.read_16() if (nConstFlags & 0x20) else 0 1139 | nStringNumber = self.jeff.read_16() if (nConstFlags & 0x40) else 0 1140 | pos = self.jeff.tell() - self.offset 1141 | if nDoubleNumber or nLongNumber: 1142 | self.jeff.align(8) 1143 | pos = self.jeff.tell() - self.offset 1144 | if nDoubleNumber: 1145 | pos = self.jeff.tell() - self.offset 1146 | vals = self._const_helper(pos, nDoubleNumber, self.jeff.read_64d) 1147 | for i,v in enumerate(vals): 1148 | print " "*indent, ".const [o%d] = Double %f" % (pos, v) 1149 | pos+=8 1150 | 1151 | if nLongNumber: 1152 | vals = self._const_helper(pos, nLongNumber, self.jeff.read_64s) 1153 | for i,v in enumerate(vals): 1154 | # print " "*indent, ".const [o%d] = Long %dL ; 0x%X" % (pos, v, v&0xFFFFFFFFFFFFFFFF) 1155 | pos+=8 1156 | 1157 | if nFloatNumber or nIntNumber: 1158 | self.jeff.align(4) 1159 | pos = self.jeff.tell() - self.offset 1160 | 1161 | if nFloatNumber: 1162 | vals = self._const_helper(pos, nFloatNumber, self.jeff.read_32f) 1163 | for i,v in enumerate(vals): 1164 | print " "*indent, ".const [o%d] = Float %f" % (pos, v) 1165 | pos+=4 1166 | 1167 | if nIntNumber: 1168 | vals = self._const_helper(pos, nIntNumber, self.jeff.read_32s) 1169 | for i,v in enumerate(vals): 1170 | print " "*indent, ".const [o%d] = Int %d ; 0x%08X" % (pos, v, v&0xFFFFFFFF) 1171 | pos+=4 1172 | 1173 | if nShortNumber: 1174 | vals = self._const_helper(pos, nShortNumber, self.jeff.read_16s) 1175 | for i,v in enumerate(vals): 1176 | # print " "*indent, ".const [o%d] = Short %d ; 0x%04X" % (pos, v, v&0xFFFF) 1177 | pos+=2 1178 | 1179 | if nByteNumber: 1180 | vals = self._const_helper(pos, nByteNumber, self.jeff.read_8s) 1181 | for i,v in enumerate(vals): 1182 | # print " "*indent, ".const [%d] = Byte %d ; 0x%02X" % (pos, v, v&0xFF) 1183 | pos+=1 1184 | 1185 | self.jeff.seek(self.offset + pos) 1186 | self.jeff.align(2) 1187 | for i in range(nStringNumber): 1188 | pos = self.jeff.tell() - self.offset 1189 | s = self.jeff.read_string() 1190 | rs = repr(s) 1191 | # print " "*indent, '.const [o%d] = String "%s"' % (pos, rs[1:-1]) 1192 | self.jeff.align(2) 1193 | 1194 | self.jeff.seek(savepos) 1195 | 1196 | def _dump(self, indent=0, as_java = False): 1197 | cidx = self.get_index(self.ofThisClassIndex) 1198 | fullname = self.jeff.get_javaname(cidx) 1199 | print ".class %s %s" % (" ".join(acc2flagsj(self.aAccessFlag)), fullname) 1200 | 1201 | sidx = 0xFFFF 1202 | if (self.aAccessFlag & ACC_INTERFACE) == 0 and self.ofSuperClassIndex != 0: 1203 | sidx = self.get_index(self.ofSuperClassIndex) 1204 | 1205 | if sidx != 0xFFFF: 1206 | print ".super %s" % self.jeff.get_javaname(sidx) 1207 | else: 1208 | if fullname=='java/lang/Object': 1209 | print ".super [0]" 1210 | else: 1211 | print ".super java/lang/Object" 1212 | 1213 | if self.interfaces: 1214 | print "" 1215 | for iidx in self.interfaces: 1216 | print ".implements %s" % self.jeff.get_javaname(iidx) 1217 | 1218 | self._dump_consts(indent, as_java) 1219 | 1220 | if self.fields: 1221 | print "" 1222 | for f in self.fields: 1223 | print "" 1224 | f._dump(indent+2) 1225 | 1226 | if self.methods: 1227 | print "" 1228 | for i, m in enumerate(self.methods): 1229 | print "" 1230 | m._dump(indent+2) 1231 | 1232 | print ".end class" 1233 | 1234 | """ 1235 | VMSymbolicDataSection { 1236 | VMPINDEX pidExtClassPackage[nTotalClassCount-nInternalClassCount]; 1237 | TU1 <0-2 byte pad> 1238 | VMDOFFSET dofPackageName[nTotalPackageCount]; 1239 | VMDOFFSET dofClassName[nTotalClassCount]; 1240 | { 1241 | VMDOFFSET dofFieldName; 1242 | VMDOFFSET dofFieldDescriptor; 1243 | } VMFieldSymbolicInfo[nTotalFieldCount] 1244 | { 1245 | VMDOFFSET dofMethodName; 1246 | VMDOFFSET dofMethodDescriptor; 1247 | } VMMethodSymbolicInfo[nTotalMethodCount] 1248 | } 1249 | 1250 | VMDescriptor 1251 | { 1252 | VMTYPE tDataType; 1253 | TU1 nDataTypeDimension; // value is only present if the type is an n-dimensional array, where n >= 2. 1254 | TU1 <0-1 byte pad> 1255 | VMCINDEX cidDataTypeIndex; // The class index associated with the data type. This item is present only if 1256 | // the tDataType is not a primitive type or an array of primitive types. 1257 | } 1258 | """ 1259 | 1260 | class VMDescriptor: 1261 | def __init__(self, jeff, jclass = None): 1262 | self.jeff = jeff 1263 | self.tDataType = jeff.read_8() 1264 | if self.tDataType & VM_TYPE_MULTI: 1265 | self.nDataTypeDimension = jeff.read_8() 1266 | elif self.tDataType & VM_TYPE_MONO: 1267 | self.nDataTypeDimension = 1 1268 | else: 1269 | self.nDataTypeDimension = 0 1270 | if (self.tDataType & 0xF) == VM_TYPE_OBJECT: 1271 | self.cidDataTypeIndex = jeff.read_16(True) 1272 | if jclass: 1273 | self.cidDataTypeIndex = jclass.get_index(self.cidDataTypeIndex) 1274 | 1275 | def is_object(self): 1276 | return (self.tDataType & 0xF) == VM_TYPE_OBJECT 1277 | 1278 | def get_jtype(self, forarray = False): 1279 | if (self.tDataType & 0xF) == VM_TYPE_OBJECT: 1280 | nm = "L%s;" % self.jeff.get_javaname(self.cidDataTypeIndex) 1281 | else: 1282 | nm = BASIC_TYPESJ[self.tDataType & 0xF] 1283 | if forarray: 1284 | assert(self.nDataTypeDimension==1) 1285 | return nm 1286 | if self.nDataTypeDimension != 0: 1287 | nm = "[" * self.nDataTypeDimension + nm 1288 | return nm 1289 | 1290 | def arrtype(self): 1291 | if self.nDataTypeDimension != 1: 1292 | raise Exception("descriptor %s is not a 1-dimensional array type!", self.__str__()) 1293 | if (self.tDataType & 0xF) == VM_TYPE_OBJECT: 1294 | nm = self.jeff.get_classname(self.cidDataTypeIndex) 1295 | else: 1296 | nm = BASIC_TYPES[self.tDataType & 0xF] 1297 | return nm 1298 | 1299 | def __str__(self): 1300 | if (self.tDataType & 0xF) == VM_TYPE_OBJECT: 1301 | nm = self.jeff.get_classname(self.cidDataTypeIndex) 1302 | else: 1303 | nm = BASIC_TYPES[self.tDataType & 0xF] 1304 | if self.nDataTypeDimension != 0: 1305 | nm += "[]" * self.nDataTypeDimension 1306 | return nm 1307 | 1308 | class JeffFieldDescInfo: 1309 | def __init__(self, jeff): 1310 | self.jeff = jeff 1311 | self.name = jeff.get_string(jeff.read_32()) 1312 | dofDescr = jeff.read_32() 1313 | saveoff = jeff.offset 1314 | jeff.offset = dofDescr 1315 | self.descr = VMDescriptor(jeff) 1316 | jeff.offset = saveoff 1317 | 1318 | def __str__(self): 1319 | return "%s %s" % (self.descr, self.name) 1320 | 1321 | def _print(self, indent=0): 1322 | print " "*indent, "%s;" % (self) 1323 | 1324 | """ 1325 | VMMethodDescriptor { 1326 | TU2 nArgCount; 1327 | VMDescriptor sArgumentType[nArgCount]; 1328 | VMDescriptor sReturnType; 1329 | } 1330 | """ 1331 | 1332 | class VMMethodDescriptor: 1333 | def __init__(self, jeff): 1334 | self.jeff = jeff 1335 | nArgCount = jeff.read_16() 1336 | self.sArgumentType = [VMDescriptor(jeff) for i in range(nArgCount)] 1337 | self.sReturnType = VMDescriptor(jeff) 1338 | 1339 | class JeffMethodDescInfo: 1340 | def __init__(self, jeff): 1341 | self.jeff = jeff 1342 | self.name = jeff.get_string(jeff.read_32()) 1343 | dofDescr = jeff.read_32() 1344 | saveoff = jeff.offset 1345 | jeff.offset = dofDescr 1346 | self.descr = VMMethodDescriptor(jeff) 1347 | jeff.offset = saveoff 1348 | 1349 | def get_jtype(self): 1350 | tret = self.descr.sReturnType.get_jtype() 1351 | targs = [d.get_jtype() for d in self.descr.sArgumentType] 1352 | return "(%s)%s" % ("".join(targs), tret) 1353 | 1354 | def get_jtypen(self): 1355 | tret = self.descr.sReturnType.get_jtype() 1356 | targs = [d.get_jtype() for d in self.descr.sArgumentType] 1357 | return "(%s)%s %d" % ("".join(targs), tret, len(self.descr.sArgumentType)) 1358 | 1359 | def __str__(self): 1360 | return "%s %s(%s)" % (self.descr.sReturnType, self.name, ", ".join(str(a) for a in self.descr.sArgumentType)) 1361 | 1362 | def _print(self, indent=0): 1363 | print " "*indent, "%s" % (self) 1364 | 1365 | class JeffSymbolicData: 1366 | def __init__(self, jeff): 1367 | self.jeff = jeff 1368 | jeff.offset = jeff.dofSymbolicData 1369 | self.pidExtClassPackage = [jeff.read_16() for i in range(jeff.nTotalClassCount - jeff.nInternalClassCount)] 1370 | jeff.offset = (jeff.offset + 3) & ~3 1371 | self.packageNames = [jeff.get_string(jeff.read_32()) for i in range(jeff.nTotalPackageCount)] 1372 | self.classNames = [jeff.get_string(jeff.read_32()) for i in range(jeff.nTotalClassCount)] 1373 | self.fieldInfos = [JeffFieldDescInfo(jeff) for i in range(jeff.nTotalFieldCount)] 1374 | self.methodInfos = [JeffMethodDescInfo(jeff) for i in range(jeff.nTotalMethodCount)] 1375 | 1376 | def _print(self, indent=0): 1377 | print " "*indent, "Package names:" 1378 | print " "*(indent+2), ", ".join(self.packageNames) 1379 | print " "*indent, "Class names:" 1380 | print " "*(indent+2), ", ".join(self.classNames) 1381 | print " "*indent, "Internal classes:" 1382 | print " "*(indent+2), ", ".join(self.classNames[i] for i in range(self.jeff.nInternalClassCount)) 1383 | print " "*indent, "External classes:" 1384 | print " "*(indent+2), ", ".join(self.packageNames[self.pidExtClassPackage[i]]+"."+self.classNames[i+self.jeff.nInternalClassCount] for i in range(self.jeff.nTotalClassCount-self.jeff.nInternalClassCount)) 1385 | print " "*indent, "Fields:" 1386 | for f in self.fieldInfos: 1387 | f._print(indent+2) 1388 | print " "*indent, "Methods:" 1389 | for m in self.methodInfos: 1390 | m._print(indent+2) 1391 | 1392 | def usage(): 1393 | print "Usage: dump_jeff.py [options] file.jeff" 1394 | print " Options:" 1395 | print " -d: dump JEFF structure (default)" 1396 | print " -s: print class definition summary" 1397 | print " -j: print Jasmin-style disassembly (experimental)" 1398 | sys.exit(1) 1399 | 1400 | if len(sys.argv) < 2: 1401 | usage() 1402 | 1403 | do_dump = True 1404 | do_summary = False 1405 | do_jasmin = False 1406 | for a in sys.argv[1:]: 1407 | if a=="-d": do_dump = True 1408 | elif a=="-j": do_jasmin = True 1409 | elif a=="-s": do_summary = True 1410 | elif a[:1]=='-': usage() 1411 | elif a: fn = a 1412 | 1413 | jeff = None 1414 | f = open(fn, "rb").read() 1415 | if f[:4]=='JEFF': 1416 | jeff = JeffFile(f) 1417 | elif f[:4] == '\x04\x00\x00\x00' and f[0x1C:0x20]=='$MN2' and f[0x284:0x28A] == 'Medal\x00': 1418 | print "" 1419 | maniflen = DwordAt(f, 0x18)*4 1420 | skip = ord(f[maniflen]) 1421 | if skip > 8: 1422 | print "bad skip value?! (%d)" % skip 1423 | sys.exit(1) 1424 | extralen = DwordAt(f, maniflen + skip) 1425 | if extralen > 0xFF: 1426 | extralen = struct.unpack("> I", f[maniflen + skip:maniflen + skip+4])[0] 1427 | pos = maniflen + extralen + skip 1428 | print hex(pos) 1429 | while pos < len(f): 1430 | dtag, dlen = f[pos:pos+4], DwordAt(f, pos+4) 1431 | print "tag: %s, len: 0x%x" % (dtag, dlen) 1432 | pos += 8 1433 | data = f[pos:pos+dlen] 1434 | if dtag == 'JEFF': 1435 | jeff = JeffFile(data) 1436 | elif dtag == 'SMAN': 1437 | print "Applet properties:" 1438 | print "========================================" 1439 | print data 1440 | print "========================================" 1441 | elif dtag == 'BHBT': 1442 | print "BHBT tag" 1443 | joff, jlen = struct.unpack("