import struct
d=open('extracted/lib/armeabi-v7a/libil2cpp.so','rb').read()
e_shoff,=struct.unpack_from('<I',d,0x20)
e_shentsize,e_shnum,e_shstrndx=struct.unpack_from('<HHH',d,0x2e)
secs={}
raw=[]
for i in range(e_shnum):
    o=e_shoff+i*e_shentsize
    nm,typ,flags,addr,off,size,link,info,align,entsz=struct.unpack_from('<10I',d,o)
    raw.append((nm,addr,off,size))
stro=[r for r in raw][e_shstrndx][2]
def sn(x):
    e=d.index(b'\0',stro+x); return d[stro+x:e].decode()
for nm,addr,off,size in raw: secs[sn(nm)]=(addr,off,size)
TA,TO,TS=secs['.text']
print('.text va=0x%x off=0x%x size=%d  range=[0x%x,0x%x)'%(TA,TO,TS,TA,TA+TS))
def va2off(va):
    for n,(a,o,s) in secs.items():
        if a and a<=va<a+s and n!='.bss': return o+(va-a)
    return None
def is_text(va): return TA<=va<TA+TS

# scan writable data sections for an array of >=40000 consecutive .text pointers
import sys
best=[]
for sec in ['.data.rel.ro','.data','.got','.rodata']:
    if sec not in secs: continue
    a,o,s=secs[sec]
    print('scanning',sec,'size',s)
    i=0; n=s//4
    vals=struct.unpack_from('<%dI'%n,d,o)
    run=0; start=0
    for k in range(n):
        if is_text(vals[k]) or vals[k]==0:
            if run==0: start=k
            run+=1
        else:
            if run>=20000: best.append((run,sec,a+start*4,start))
            run=0
    if run>=20000: best.append((run,sec,a+start*4,start))
best.sort(reverse=True)
for r in best[:10]: print('run=%d sec=%s va=0x%x'%(r[0],r[1],r[2]))

print('--- find refs to array starts ---')
targets=[0x192be20,0x1969558]
for sec in ['.data.rel.ro','.data','.rodata']:
    a,o,s=secs[sec]; n=s//4
    vals=struct.unpack_from('<%dI'%n,d,o)
    for k in range(n):
        if vals[k] in targets:
            cnt=vals[k-1] if k>0 else -1
            print('ref @0x%x (%s) -> 0x%x   preceding_u32=%d'%(a+k*4,sec,vals[k],cnt))
