X-Git-Url: http://dolda2000.com/gitweb/?p=pycfml.git;a=blobdiff_plain;f=classfile%2Ffile.py;h=d361b47311c4d1074331a271da31453fe92616e4;hp=47e910300923e84d8f437934e3e19bbf54b1fcd1;hb=188fa298c78404f0cb1ed5291cfa53e5be0fb4b2;hpb=964561d602931b91c16c71d251a90cb0bd0125d2 diff --git a/classfile/file.py b/classfile/file.py index 47e9103..d361b47 100644 --- a/classfile/file.py +++ b/classfile/file.py @@ -101,6 +101,32 @@ class sig(object): def __eq__(s, o): return isinstance(o, sig) and o.nm == s.nm and o.tp == s.tp +class methodhandle(object): + def __init__(self, kind, ref): + self.kind = kind + self.ref = ref + def __hash__(self): + return hash(methodhandle) + self.kind * 31 + self.ref + def __eq__(s, o): + return isinstance(o, methodhandle) and o.kind == s.kind and o.ref == s.ref + +class methodtype(object): + def __init__(self, desc): + self.desc = desc + def __hash__(self): + return hash(methodhandle) + self.desc + def __eq__(s, o): + return isinstance(o, methodtype) and o.desc == s.desc + +class callsite(object): + def __init__(self, boot, sig): + self.boot = boot + self.sig = sig + def __hash__(self): + return hash(callsite) + self.boot * 31 + self.sig + def __eq__(s, o): + return isinstance(o, callsite) and o.boot == s.boot and o.sig == s.sig + class fieldref(object): def __init__(self, cls, sig): self.cls = cls @@ -235,12 +261,19 @@ class classfile(object): return imethodref(buf.uint16(), buf.uint16()), False elif t == CONSTANT_NameAndType: return sig(buf.uint16(), buf.uint16()), False + elif t == CONSTANT_MethodHandle: + return methodhandle(buf.uint8(), buf.uint16()), False + elif t == CONSTANT_MethodType: + return methodtype(buf.uint16()), False + elif t == CONSTANT_InvokeDynamic: + return callsite(buf.uint16(), buf.uint16()), False else: raise binfmt.fmterror("unknown constant tag: " + str(t)) def saveconstant(self, buf, const): if isinstance(const, str): - buf.uint8(CONSTANT_Utf8).extend(binfmt.mutf8enc(const)) + enc = binfmt.mutf8enc(const) + buf.uint8(CONSTANT_Utf8).uint16(len(enc)).extend(enc) elif isinstance(const, classref): buf.uint8(CONSTANT_Class).uint16(const.nm) elif isinstance(const, conststr): @@ -261,6 +294,12 @@ class classfile(object): buf.uint8(CONSTANT_InterfaceMethodref).uint16(const.cls).uint16(const.sig) elif isinstance(const, sig): buf.uint8(CONSTANT_NameAndType).uint16(const.nm).uint16(const.tp) + elif isinstance(const, methodhandle): + buf.uint8(CONSTANT_MethodHandle).uint8(const.kind).uint16(const.ref) + elif isinstance(const, methodtype): + buf.uint8(CONSTANT_MethodType).uint16(const.desc) + elif isinstance(const, callsite): + buf.uint8(CONSTANT_InvokeDynamic).uint16(const.boot).uint16(const.sig) else: raise Exception("unexpected object type in constant pool: " + const) @@ -660,7 +699,7 @@ class classfile(object): buf.uint32(self.MAGIC) buf.uint16(self.ver.minor).uint16(self.ver.major) - buf.uint16(len(self.cp) + 1) + buf.uint16(len(self.cp)) for const in self.cp: if const is not None: self.saveconstant(buf, const) @@ -694,7 +733,7 @@ class classfile(object): for inner in self.innerclasses: data.uint16(inner.cls).uint16(inner.outer).uint16(inner.nm).uint16(inner.acc) attrs.append((self.intern("InnerClasses"), data)) if self.enclosingmethod is not None: - attrs.append((self.intern("EnclosingMethod", enc().uint16(self.enclosingmethod[0]).uint16(self.enclosingmethod[1])))) + attrs.append((self.intern("EnclosingMethod"), enc().uint16(self.enclosingmethod[0]).uint16(self.enclosingmethod[1]))) if len(self.rtann) > 0: data = enc() data.uint16(len(self.rtann))