mirror of https://github.com/Shizmob/smol
fix smoldd
This commit is contained in:
parent
5c38b05c85
commit
7e384a44a6
167
smoldd.py
167
smoldd.py
|
@ -1,167 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import glob
|
||||
import os.path
|
||||
import shutil
|
||||
import subprocess
|
||||
import struct
|
||||
import sys
|
||||
|
||||
from smolshared import *
|
||||
|
||||
def readbyte(blob, off):
|
||||
return struct.unpack('<B', blob[off:off+1])[0], (off+1)
|
||||
|
||||
def readint(blob, off):
|
||||
return struct.unpack('<I', blob[off:off+4])[0], (off+4)
|
||||
|
||||
def readlong(blob, off):
|
||||
return struct.unpack('<Q', blob[off:off+8])[0], (off+8)
|
||||
|
||||
def readstr(blob, off):
|
||||
text = bytearray()
|
||||
while True:
|
||||
char, off = readbyte(blob, off)
|
||||
if char == 0:
|
||||
break
|
||||
|
||||
text.append(char)
|
||||
|
||||
return text.decode('utf-8'), off
|
||||
|
||||
def get_def_libpaths(cc_bin, is32bit):
|
||||
if is32bit:
|
||||
return ['/usr/lib32/','/lib32/']
|
||||
|
||||
out = subprocess.check_output([cc_bin, '-print-search-dirs'],
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
stuff = dict({})
|
||||
for l in out.decode('utf-8').splitlines():
|
||||
blah = l.split(': ')
|
||||
stuff[blah[0]] = blah[1].lstrip('=').split(':')
|
||||
|
||||
return stuff["libraries"]
|
||||
|
||||
def find_libs(bits, deflibs, libname):
|
||||
dirs = os.environ['LD_LIBRARY_PATH'].split(':') + deflibs
|
||||
|
||||
for d in dirs:
|
||||
for f in glob.glob(glob.escape(d + libname) + '*'):
|
||||
yield f
|
||||
|
||||
def build_hashtab(scanelf_bin, lib):
|
||||
out = subprocess.check_output([scanelf_bin, '-B', '-F', '%s', '-s', '%pd%*', lib],
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
blah = set(out.decode('utf-8').split('\n'))
|
||||
ret = dict({})
|
||||
|
||||
for x in blah:
|
||||
y = x.split()
|
||||
if len(y) != 7:
|
||||
continue
|
||||
ret[hash_djb2(y[6])] = y[6]
|
||||
|
||||
return ret
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('input', type=argparse.FileType('rb'),
|
||||
default=sys.stdin.buffer, help="input file")
|
||||
parser.add_argument('--cc',
|
||||
default=shutil.which('cc'), help="C compiler binary")
|
||||
parser.add_argument('--scanelf',
|
||||
default=shutil.which('scanelf'), help="scanelf binary")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
blob = args.input.read()
|
||||
|
||||
machnum = struct.unpack('<H', blob[18:18+2])[0]
|
||||
|
||||
is32bit = machnum == archmagic['i386']
|
||||
|
||||
deflibs = get_def_libpaths(args.cc, is32bit)
|
||||
|
||||
phoff, phsz, phnum = 0, 0, 0
|
||||
if is32bit:
|
||||
phoff = struct.unpack('<I', blob[28:28+4])[0]
|
||||
phsz = struct.unpack('<H', blob[42:42+2])[0]
|
||||
phnum = struct.unpack('<H', blob[44:52+2])[0]
|
||||
elif machnum == archmagic['x86_64']:
|
||||
phoff = struct.unpack('<Q', blob[32:32+8])[0]
|
||||
phsz = struct.unpack('<H', blob[54:54+2])[0]
|
||||
phnum = struct.unpack('<H', blob[56:56+2])[0]
|
||||
else:
|
||||
eprintf("Unknown architecture " + str(machnum))
|
||||
sys.exit(1)
|
||||
|
||||
for i in range(phnum):
|
||||
off = phoff + i * phsz
|
||||
#print(hex(off))
|
||||
|
||||
ptyp, poff, pva, ppa, pfsz, pmsz, pfl, pal = 0,0,0,0,0,0,0,0
|
||||
if is32bit:
|
||||
ptyp, poff, pva, ppa, pfsz, pmsz, pfl, pal = \
|
||||
struct.unpack('<ILLLIIII', blob[off:off+phsz])
|
||||
else:
|
||||
ptyp, pfl, poff, pva, ppa, pfsz, pmsz, pal = \
|
||||
struct.unpack('<IIQQQQQQ', blob[off:off+phsz])
|
||||
|
||||
if ptyp != 2: # PT_DYNAMIC
|
||||
continue
|
||||
|
||||
#print(hex(poff))
|
||||
|
||||
# right after the dynamic section, the smol 'symtab'/'hashtab' is found
|
||||
#
|
||||
# note that on i386, every lib name is followed by an E9 byte
|
||||
# if the next libname/first byte of the hash is null, the table has
|
||||
# come to an end.
|
||||
|
||||
if is32bit:
|
||||
j = poff
|
||||
strtaboff = 0
|
||||
while j < poff + pfsz:
|
||||
tag, j = readint(blob, j)
|
||||
ptr, j = readint(blob, j)
|
||||
|
||||
if tag == 5: # DT_STRTAB
|
||||
strtaboff = ptr
|
||||
elif tag == 1: # DT_NEEDED
|
||||
bakoff = j
|
||||
|
||||
smoltaboff = strtaboff + ptr - (pva - poff)
|
||||
j = smoltaboff
|
||||
|
||||
libname, j = readstr(blob, j)
|
||||
if len(libname) == 0:
|
||||
break
|
||||
|
||||
sys.stdout.write("* " + libname)
|
||||
|
||||
libs = list(find_libs(32, deflibs, libname))
|
||||
print(" -> NOT FOUND" if len(libs) == 0 else (" -> " + libs[0]))
|
||||
ht = dict({}) if len(libs) == 0 else build_hashtab(args.scanelf, libs[0])
|
||||
|
||||
while True:
|
||||
hashv, j = readint(blob, j)
|
||||
|
||||
if (hashv & 0xFF) == 0:
|
||||
break
|
||||
|
||||
sys.stdout.write(" * " + hex(hashv))
|
||||
print(" -> NOT FOUND" if hashv not in ht else (" -> " + ht[hashv]))
|
||||
|
||||
j = bakoff
|
||||
|
||||
break
|
||||
else: # 64-bit
|
||||
eprintf("Currently unsuppored, sorry.")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
|
||||
# stolen from the contrib folder in https://github.com/blackle/LZMA-Vizualizer
|
||||
# (i.e. I'm stealing it from myself)
|
||||
|
||||
# custom elf parser because a standard one wouldn't be trustable because the
|
||||
# ELFs we're parsing will be a bit wonky anyway
|
||||
|
||||
from struct import unpack
|
||||
from typing import *
|
||||
|
||||
ELFCLASS32 = 1
|
||||
ELFCLASS64 = 2
|
||||
|
||||
EM_386 = 3
|
||||
EM_X86_64 = 62
|
||||
|
||||
PT_NULL = 0
|
||||
PT_LOAD = 1
|
||||
PT_DYNAMIC = 2
|
||||
PT_INTERP = 3
|
||||
|
||||
DT_NULL = 0
|
||||
DT_NEEDED = 1
|
||||
DT_STRTAB = 5
|
||||
DT_SYMTAB = 6
|
||||
|
||||
class Phdr(NamedTuple):
|
||||
ptype: int
|
||||
off : int
|
||||
vaddr: int
|
||||
paddr: int
|
||||
filesz: int
|
||||
memsz: int
|
||||
flags: int
|
||||
align: int
|
||||
|
||||
class Dyn(NamedTuple):
|
||||
tag: int
|
||||
val: int
|
||||
|
||||
class ELF(NamedTuple):
|
||||
data : bytes
|
||||
ident : bytes
|
||||
eclass: int
|
||||
mach : int
|
||||
entry : int
|
||||
phdrs : Sequence[Phdr]
|
||||
dyn : Sequence[Dyn]
|
||||
is32bit: bool
|
||||
|
||||
# yeah, there's some code duplication here
|
||||
# idgaf
|
||||
|
||||
def parse_phdr32(data: bytes, phoff:int, phentsz:int, phnum:int) -> Sequence[Phdr]:
|
||||
ps = []
|
||||
for off in range(phoff, phoff+phentsz*phnum, phentsz):
|
||||
ptype, off, vaddr, paddr, filesz, memsz, flags, align = \
|
||||
unpack('<IIIIIIII', data[off:off+8*4])
|
||||
p = Phdr(ptype, off, vaddr, paddr, filesz, memsz, flags, align)
|
||||
ps.append(p)
|
||||
|
||||
return ps
|
||||
|
||||
def parse_dyn32(data: bytes, dynp: Phdr) -> Dyn:
|
||||
ds = []
|
||||
|
||||
off = dynp.off
|
||||
while True:
|
||||
tag, val = unpack('<II', data[off:off+2*4])
|
||||
ds.append(Dyn(tag, val))
|
||||
|
||||
if tag == DT_NULL: break
|
||||
off = off + 2*4
|
||||
|
||||
return ds
|
||||
|
||||
def parse_32(data: bytes) -> ELF:
|
||||
ident = data[:16]
|
||||
eclass = data[4]
|
||||
mach = unpack('<H', data[18:18+2])[0]
|
||||
entry = unpack('<I', data[24:24+4])[0]
|
||||
|
||||
phoff = unpack('<I', data[28:28+4])[0]
|
||||
phentsz = unpack('<H', data[42:42+2])[0]
|
||||
phnum = unpack('<H', data[44:44+2])[0]
|
||||
|
||||
phdrs = parse_phdr32(data, phoff, phentsz, phnum)
|
||||
dyn = None
|
||||
|
||||
for p in phdrs:
|
||||
if p.ptype == PT_DYNAMIC:
|
||||
dyn = parse_dyn32(data, p)
|
||||
break
|
||||
|
||||
return ELF(data, ident, eclass, mach, entry, phdrs, dyn, True)
|
||||
|
||||
def parse_phdr64(data: bytes, phoff:int, phentsz:int, phnum:int) -> Sequence[Phdr]:
|
||||
ps = []
|
||||
for off in range(phoff, phoff+phentsz*phnum, phentsz):
|
||||
# TODO
|
||||
ptype, flags, off, vaddr, paddr, filesz, memsz, align = \
|
||||
unpack('<IIQQQQQQ', data[off:off+2*4+6*8])
|
||||
p = Phdr(ptype, off, vaddr, paddr, filesz, memsz, flags, align)
|
||||
ps.append(p)
|
||||
|
||||
return ps
|
||||
|
||||
def parse_dyn64(data: bytes, dynp: Phdr) -> Dyn:
|
||||
ds = []
|
||||
|
||||
off = dynp.off
|
||||
while True:
|
||||
tag, val = unpack('<QQ', data[off:off+2*8])
|
||||
ds.append(Dyn(tag, val))
|
||||
|
||||
if tag == DT_NULL: break
|
||||
off = off + 2*8
|
||||
|
||||
return ds
|
||||
|
||||
def parse_64(data: bytes) -> ELF:
|
||||
ident = data[:16]
|
||||
eclass = data[4]
|
||||
mach = unpack('<H', data[18:18+2])[0]
|
||||
entry = unpack('<Q', data[24:24+8])[0]
|
||||
|
||||
phoff = unpack('<Q', data[32:32+8])[0]
|
||||
phentsz = unpack('<H', data[54:54+2])[0]
|
||||
phnum = unpack('<H', data[56:56+2])[0]
|
||||
|
||||
phdrs = parse_phdr64(data, phoff, phentsz, phnum)
|
||||
dyn = None
|
||||
|
||||
for p in phdrs:
|
||||
if p.ptype == PT_DYNAMIC:
|
||||
dyn = parse_dyn64(data, p)
|
||||
break
|
||||
|
||||
return ELF(data, ident, eclass, mach, entry, phdrs, dyn, False)
|
||||
|
||||
def parse(data: bytes) -> ELF:
|
||||
assert data[:4] == b'\x7FELF', "Not a valid ELF file" # good enough
|
||||
|
||||
ecls = data[4]
|
||||
if ecls == ELFCLASS32: return parse_32(data)
|
||||
elif ecls == ELFCLASS64: return parse_64(data)
|
||||
else:
|
||||
emch = unpack('<H', data[18:18+2])[0]
|
||||
if emch == EM_386: return parse_32(data)
|
||||
elif emch == EM_X86_64: return parse_64(data)
|
||||
|
||||
assert False, "bad E_CLASS %d" % ecls
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
|
||||
# stolen from the contrib folder in https://github.com/blackle/LZMA-Vizualizer
|
||||
# (i.e. I'm stealing it from myself)
|
||||
|
||||
import re
|
||||
from typing import *
|
||||
|
||||
class CommonSym(NamedTuple):
|
||||
name: str
|
||||
size: int
|
||||
file: str
|
||||
class Discard(NamedTuple):
|
||||
name: str
|
||||
size: int
|
||||
file: str
|
||||
class MemCfg(NamedTuple):
|
||||
name: str
|
||||
org : int
|
||||
size: int
|
||||
class MMap(NamedTuple):
|
||||
sect: str
|
||||
org : int
|
||||
#size: int
|
||||
sym : str
|
||||
file: str
|
||||
class XRef(NamedTuple):
|
||||
name: str
|
||||
deff: str
|
||||
reff: Sequence[str]
|
||||
|
||||
class LinkMap(NamedTuple):
|
||||
common : Sequence[CommonSym]
|
||||
discard: Sequence[Discard]
|
||||
memcfg : Sequence[MemCfg]
|
||||
mmap : Sequence[MMap]
|
||||
xref : Sequence[XRef]
|
||||
|
||||
def parse_common( ls: Sequence[str]) -> Sequence[CommonSym]: return [] # TODO
|
||||
def parse_discard(ls: Sequence[str]) -> Sequence[Discard ]: return [] # TODO
|
||||
def parse_memcfg( ls: Sequence[str]) -> Sequence[MemCfg ]: return [] # TODO
|
||||
def parse_xref( ls: Sequence[str]) -> Sequence[XRef ]: return [] # TODO
|
||||
|
||||
def parse_mmap(ls: Sequence[str]) -> Sequence[MMap]:
|
||||
rrr = []
|
||||
|
||||
bigsect = None
|
||||
section = None
|
||||
curfile = None
|
||||
#size = -1
|
||||
|
||||
for l in ls:
|
||||
def matcher(mobj):
|
||||
return mobj.group(0).replace(' ', '_')
|
||||
l = re.sub(r"\*\(.*\)", matcher, l)
|
||||
#print(repr(l))
|
||||
s = l.strip(); w = s.split()
|
||||
|
||||
if s.startswith('LOAD ') or s.startswith('OUTPUT('): continue#break
|
||||
|
||||
if l[0] != ' ':
|
||||
bigsect = w[0]
|
||||
del w[0]
|
||||
elif l[1] != ' ':
|
||||
section = w[0]
|
||||
del w[0]
|
||||
|
||||
if len(w) == 0 or w[0] == "[!provide]":
|
||||
continue # addr placed on next line for prettyprinting reasons
|
||||
|
||||
#print(repr(l), w[0])
|
||||
assert w[0].startswith("0x"), "welp, bad symbol addr"
|
||||
|
||||
addr = int(w[0], 16)
|
||||
|
||||
size = -1
|
||||
symn = ""
|
||||
if w[1].startswith("0x"): # filename will prolly follow
|
||||
size = int(w[1], 16)
|
||||
curfile = w[2] if len(w) > 2 else ""
|
||||
else: symn = w[1]
|
||||
|
||||
if len(symn) > 0:
|
||||
rrr.append(MMap(section, addr, symn, curfile))
|
||||
|
||||
return rrr
|
||||
|
||||
def parse(s: str) -> LinkMap:
|
||||
COMMON = 0
|
||||
DISCARD = 1
|
||||
MEMCFG = 2
|
||||
MMAP = 3
|
||||
XREF = 4
|
||||
|
||||
curpt = -1
|
||||
|
||||
commonl, discardl, memcfgl, mmapl, xrefl = [], [], [], [], []
|
||||
|
||||
for l in s.split('\n'):
|
||||
if len(l.strip()) == 0: continue
|
||||
|
||||
ls = l.strip()
|
||||
if ls == "Allocating common symbols": curpt = COMMON
|
||||
elif ls == "Discarded input sections": curpt = DISCARD
|
||||
elif ls == "Memory Configuration": curpt = MEMCFG
|
||||
elif ls == "Linker script and memory map": curpt = MMAP
|
||||
elif ls == 'Cross Reference Table': curpt = XREF
|
||||
elif curpt == COMMON : commonl.append(l)
|
||||
elif curpt == DISCARD: discardl.append(l)
|
||||
elif curpt == MEMCFG : memcfgl.append(l)
|
||||
elif curpt == MMAP : mmapl.append(l)
|
||||
elif curpt == XREF : xrefl.append(l)
|
||||
else:
|
||||
assert False, "bad line %s" % ls
|
||||
|
||||
return LinkMap(parse_common(commonl), parse_discard(discardl), \
|
||||
parse_memcfg(memcfgl), parse_mmap(mmapl), parse_xref(xrefl))
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os.path, struct, sys
|
||||
import argparse, glob, shutil, subprocess
|
||||
|
||||
import hackyelf, linkmap
|
||||
from smolshared import *
|
||||
from smolparse import *
|
||||
|
||||
def readbyte(blob, off): return struct.unpack('<B', blob[off:off+1])[0], (off+1)
|
||||
def readint(blob, off): return struct.unpack('<I', blob[off:off+4])[0], (off+4)
|
||||
def readlong(blob, off): return struct.unpack('<Q', blob[off:off+8])[0], (off+8)
|
||||
def readstr(blob, off):
|
||||
text = bytearray()
|
||||
while True:
|
||||
char, off = readbyte(blob, off)
|
||||
if char == 0: break
|
||||
|
||||
text.append(char)
|
||||
|
||||
return text.decode('utf-8'), off
|
||||
|
||||
def get_def_libpaths(cc_bin, is32bit):
|
||||
# FIXME: HACK
|
||||
if is32bit: return ['/usr/lib32/','/lib32/']
|
||||
|
||||
return get_cc_paths(cc_bin)['libraries']
|
||||
|
||||
def find_libs(deflibs, libname):
|
||||
dirs = os.environ['LD_LIBRARY_PATH'].split(':') + deflibs
|
||||
|
||||
for d in dirs:
|
||||
for f in glob.glob(glob.escape(d + '/' + libname) + '*'): yield f
|
||||
|
||||
def build_hashtab(scanelf_bin, lib):
|
||||
out = subprocess.check_output([scanelf_bin, '-B', '-F', '%s', '-s', '%pd%*', lib],
|
||||
stderr=subprocess.DEVNULL)
|
||||
|
||||
blah = set(out.decode('utf-8').split('\n'))
|
||||
ret = dict({})
|
||||
|
||||
for x in blah:
|
||||
y = x.split()
|
||||
if len(y) != 7: continue
|
||||
ret[hash_djb2(y[6])] = y[6]
|
||||
|
||||
return ret
|
||||
|
||||
def addr2off(elf, addr):
|
||||
for x in elf.phdrs:
|
||||
if x.ptype != hackyelf.PT_LOAD: continue
|
||||
|
||||
if addr >= x.vaddr and addr < x.vaddr + x.memsz:
|
||||
aoff = addr - x.vaddr
|
||||
assert aoff < x.filesz, ".bss address!"
|
||||
return aoff + x.off
|
||||
|
||||
assert False, "Address %08x not in the static address range!" % addr
|
||||
|
||||
def get_needed_libs(elf, blob):
|
||||
assert elf.dyn is not None, "No DYNAMIC table present in the ELF file!"
|
||||
|
||||
strtabs = [x.val for x in elf.dyn if x.tag == hackyelf.DT_STRTAB]
|
||||
assert len(strtabs) == 1, "Only one DT_STRTAB may be present in an ELF file."
|
||||
strtab = strtabs[0]
|
||||
|
||||
return [readstr(blob,addr2off(elf, strtab+x.val))[0]
|
||||
for x in elf.dyn if x.tag == hackyelf.DT_NEEDED]
|
||||
|
||||
def get_hashtbl(elf, blob, args):
|
||||
htaddr = None
|
||||
if args.map is not None:
|
||||
lmap = linkmap.parse(args.map.read())
|
||||
tabs = [x for x in lmap.mmap if x.sym == '_symbols']
|
||||
assert len(tabs) == 1, "One '_symbols' symbol must be present."
|
||||
htaddr = tabs[0].org
|
||||
elif elf.is32bit:
|
||||
txtoff = addr2off(elf, elf.entry)
|
||||
# scan for 'push IMM32'
|
||||
while blob[txtoff] != 0x68:
|
||||
txtoff = txtoff + 1
|
||||
assert txtoff < len(blob), "wtf??? (can't find a push IMM32 instruction which pushes the hashtable address)"
|
||||
txtoff = txtoff + 1
|
||||
|
||||
htaddr = struct.unpack('<I', blob[txtoff:txtoff+4])[0]
|
||||
else: # 64-bit
|
||||
txtoff = addr2off(elf, elf.entry)
|
||||
# scan for 'push IMM32'
|
||||
# but the first one we'll encounter pushes the entrypoint addr!
|
||||
while blob[txtoff] != 0x68:
|
||||
txtoff = txtoff + 1
|
||||
assert txtoff < len(blob), "wtf??? (can't find a push IMM32 instruction which pushes the entrypoint address)"
|
||||
txtoff = txtoff + 1
|
||||
# now we can look for the interesting address
|
||||
while blob[txtoff] != 0x68:
|
||||
txtoff = txtoff + 1
|
||||
assert txtoff < len(blob), "wtf??? (can't find a push IMM32 instruction which pushes the hashtable address)"
|
||||
txtoff = txtoff + 1
|
||||
|
||||
htaddr = struct.unpack('<I', blob[txtoff:txtoff+4])[0]
|
||||
|
||||
assert htaddr is not None, "wtf? (no hashtable address)"
|
||||
print("Hash table address: 0x%08x" % htaddr)
|
||||
htoff = addr2off(elf, htaddr)
|
||||
|
||||
tbl = []
|
||||
while True:
|
||||
if len(blob)-htoff < 4:
|
||||
if struct.unpack('<B', blob[htoff:htoff+1])[0] == 0:
|
||||
break
|
||||
val = struct.unpack('<I', blob[htoff:htoff+4])[0]
|
||||
if (val & 0xFF) == 0: break
|
||||
tbl.append(val)
|
||||
htoff = htoff + (4 if elf.is32bit else 8)
|
||||
|
||||
return tbl
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('input', type=argparse.FileType('rb'),
|
||||
default=sys.stdin.buffer, help="input file")
|
||||
parser.add_argument('--cc',
|
||||
default=shutil.which('cc'), help="C compiler binary")
|
||||
parser.add_argument('--scanelf',
|
||||
default=shutil.which('scanelf'), help="scanelf binary")
|
||||
parser.add_argument('--map', type=argparse.FileType('r'), help=\
|
||||
"Get the address of the symbol hash table from the "+\
|
||||
"linker map output instead of attempting to parse the"+\
|
||||
" binary.")
|
||||
args = parser.parse_args()
|
||||
|
||||
blob = args.input.read()
|
||||
elf = hackyelf.parse(blob)
|
||||
|
||||
deflibs = get_def_libpaths(args.cc, elf.is32bit)
|
||||
needed = get_needed_libs(elf, blob)
|
||||
neededpaths = dict((l,list(find_libs(deflibs, l))[0]) for l in needed)
|
||||
|
||||
htbl = get_hashtbl(elf, blob, args)
|
||||
|
||||
libhashes = dict((l, build_hashtab(args.scanelf, neededpaths[l])) for l in needed)
|
||||
|
||||
hashresolves = dict({})
|
||||
noresolves = []
|
||||
# TODO: group by libs
|
||||
for x in htbl:
|
||||
done = False
|
||||
for l in libhashes.keys():
|
||||
v = libhashes[l]
|
||||
if x in v:
|
||||
if l not in hashresolves: hashresolves[l] = dict({})
|
||||
hashresolves[l][x] = v[x]
|
||||
done = True
|
||||
break
|
||||
if not done: noresolves.append(x)
|
||||
|
||||
for l in hashresolves.keys():
|
||||
print("%s:" % l)
|
||||
v = hashresolves[l]
|
||||
for x in v.keys():
|
||||
print("\t%08x -> %s" % (x, v[x]))
|
||||
|
||||
if len(noresolves) > 0:
|
||||
print("UNRESOLVED:")
|
||||
for x in noresolves: print("\t%08x" % x)
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
rv = main()
|
||||
if rv is None: pass
|
||||
else:
|
||||
try: sys.exit(int(rv))
|
||||
except: sys.exit(1)
|
||||
|
|
@ -105,7 +105,7 @@ def get_cc_paths(cc_bin):
|
|||
|
||||
return paths
|
||||
|
||||
def is_valid_elf(f):
|
||||
def is_valid_elf(f): # Good Enough(tm)
|
||||
with open(f, 'rb') as ff: return ff.read(4) == b'\x7FELF'
|
||||
|
||||
def find_lib(spaths, wanted):
|
||||
|
|
Loading…
Reference in New Issue