import struct,sys
d=open('apk/classes.dex','rb').read()
def u4(o): return struct.unpack_from('<I',d,o)[0]
def u2(o): return struct.unpack_from('<H',d,o)[0]
def uleb(o):
    r=0;s=0
    while True:
        b=d[o];o+=1;r|=(b&0x7f)<<s;s+=7
        if not b&0x80: break
    return r,o
H=dict(zip("sis sio tis tio pis pio fis fio mis mio cds cdo".split(),struct.unpack_from('<12I',d,56)))
S=[]
for i in range(H['sis']):
    o=u4(H['sio']+4*i); n,p=uleb(o); e=d.index(b'\0',p); S.append(d[p:e].decode('utf-8','replace'))
T=[S[u4(H['tio']+4*i)] for i in range(H['tis'])]
M=[]
for i in range(H['mis']):
    o=H['mio']+8*i; ci,pi,ni=struct.unpack_from('<HHI',d,o); M.append((T[ci],S[ni]))
F=[]
for i in range(H['fis']):
    o=H['fio']+8*i; ci,ti,ni=struct.unpack_from('<HHI',d,o); F.append((T[ci],S[ni]))
target=sys.argv[1]
for i in range(H['cds']):
    o=H['cdo']+32*i
    ci,flags,sup,ifs,src,ann,data,sv=struct.unpack_from('<8I',d,o)
    if T[ci]!=target or not data: continue
    p=data
    sf,p=uleb(p); inf,p=uleb(p); dm,p=uleb(p); vm,p=uleb(p)
    for _ in range(sf):
        _,p=uleb(p); _,p=uleb(p)
    for _ in range(inf):
        _,p=uleb(p); _,p=uleb(p)
    idx=0
    for grp,cnt in (('direct',dm),('virtual',vm)):
        idx=0
        for _ in range(cnt):
            di,p=uleb(p); acc,p=uleb(p); co,p=uleb(p)
            idx+=di
            cls,nm=M[idx]
            if co==0:
                print(f"{grp} {nm}: <no code>"); continue
            regs=u2(co); ins=u2(co+2); outs=u2(co+4); tries=u2(co+6); isz=u4(co+12)
            print(f"\n=== {nm}  regs={regs} ins={ins} outs={outs} insns={isz} units ===")
            base=co+16
            words=[u2(base+2*k) for k in range(isz)]
            k=0
            while k<isz:
                w=words[k]; op=w&0xff
                if op==0x0e: print("  return-void"); k+=1
                elif op==0x0f: print(f"  return v{w>>8}"); k+=1
                elif op==0x12: print(f"  const/4 v{(w>>8)&0xf}, #{struct.unpack('b',bytes([((w>>12)&0xf)|(0xf0 if (w>>15)&1 else 0)]))[0] if False else ((w>>12)&0xf)-(16 if (w>>12)&0x8 else 0)}"); k+=1
                elif op==0x13: print(f"  const/16 v{w>>8}, #{struct.unpack('<h',struct.pack('<H',words[k+1]))[0]}"); k+=2
                elif op==0x14: print(f"  const v{w>>8}, #{words[k+1]|(words[k+2]<<16)}"); k+=3
                elif op in (0x6e,0x6f,0x70,0x71,0x72):
                    kinds={0x6e:'virtual',0x6f:'super',0x70:'direct',0x71:'static',0x72:'interface'}
                    mi=words[k+1]; c,n=M[mi]; print(f"  invoke-{kinds[op]} {c}.{n}"); k+=3
                elif op==0x0a: print(f"  move-result v{w>>8}"); k+=1
                elif op==0x0c: print(f"  move-result-object v{w>>8}"); k+=1
                elif op==0x54: mi=words[k+1]; print(f"  iget-object v.., {F[mi][0]}.{F[mi][1]}"); k+=2
                elif op==0x52: mi=words[k+1]; print(f"  iget v.., {F[mi][0]}.{F[mi][1]}"); k+=2
                elif op==0x62: mi=words[k+1]; print(f"  sget-object v{w>>8}, {F[mi][0]}.{F[mi][1]}"); k+=2
                elif op==0x1a: print(f"  const-string v{w>>8}, \"{S[words[k+1]]}\""); k+=2
                else:
                    print(f"  op 0x{op:02x}"); k+=1
