Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
2.6 kB · 66 lines
Python
at main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667"""Just enough of the JVM class file format to rename a class and retarget one.
Layout: magic(4) minor(2) major(2) cp_count(2) constant_pool[...] rest.Only the constant pool is parsed; everything after it is copied through, whichis safe because the rest of the file refers to the pool by index."""import struct
JAVA_1_4_MAJOR = 48
UTF8, LONG, DOUBLE = 1, 5, 6FIXED_SIZES = {7: 2, 8: 2, 16: 2, 19: 2, 20: 2, 3: 4, 4: 4, 9: 4, 10: 4, 11: 4, 12: 4, 17: 4, 18: 4, 15: 3, 5: 8, 6: 8}INVOKE_DYNAMIC_TAGS = {15, 16, 17, 18}
class ClassFile: def __init__(self, data): if data[:4] != b"\xca\xfe\xba\xbe": raise ValueError("not a class file") self.minor, self.major, count = struct.unpack(">HHH", data[4:10]) self.pool = [] # (tag, payload bytes); payload excludes the tag byte offset, index = 10, 1 while index < count: tag = data[offset] if tag == UTF8: length = struct.unpack(">H", data[offset + 1:offset + 3])[0] size = 2 + length else: size = FIXED_SIZES[tag] self.pool.append((tag, data[offset + 1:offset + 1 + size])) offset += 1 + size # Longs and doubles take two pool slots. index += 2 if tag in (LONG, DOUBLE) else 1 self.rest = data[offset:] self._count = count
def utf8_strings(self): return [payload[2:].decode("utf-8", "replace") for tag, payload in self.pool if tag == UTF8]
def tags(self): return {tag for tag, _ in self.pool}
def replace_in_utf8(self, replacements): """Apply {old: new} to whole Utf8 entries and to L<old>; inside descriptors.""" changed = 0 for i, (tag, payload) in enumerate(self.pool): if tag != UTF8: continue text = payload[2:] new_text = text for old, new in replacements.items(): if new_text == old.encode(): new_text = new.encode() new_text = new_text.replace(b"L" + old.encode() + b";", b"L" + new.encode() + b";") if new_text != text: self.pool[i] = (UTF8, struct.pack(">H", len(new_text)) + new_text) changed += 1 return changed
def to_bytes(self): out = [b"\xca\xfe\xba\xbe", struct.pack(">HHH", self.minor, self.major, self._count)] for tag, payload in self.pool: out.append(bytes([tag]) + payload) out.append(self.rest) return b"".join(out)