REAL real fix for #5, also fix the hash size check,

This commit is contained in:
PoroCYon 2020-08-25 03:02:21 +02:00
parent e6268471ff
commit bfe3ba1f20
4 changed files with 66 additions and 37 deletions

View File

@ -10,13 +10,16 @@ def get_min_check_width(libraries, hashfn):
minv = 8 # can't go lower minv = 8 # can't go lower
for k, v in libraries.items(): for k, v in libraries.items():
for sym in v: for sym in v:
hv = hashfn(sym[0]) # sym == (name, reloc) hv = hashfn(sym)
#eprintf("hash: 0x%08x of %s"%(hv,sym))
if (hv & 0xffffffff) == 0: if (hv & 0xffffffff) == 0:
# this should (hopefully) NEVER happen # this should (hopefully) NEVER happen
error("Aiee, all-zero hash for sym '%s'!" % sym) error("E: Aiee, all-zero hash for sym '%s'!" % sym)
elif (hv & 0xFFFF) == 0: elif (hv & 0xFFFF) == 0:
#eprintf("32-bit hash")
minv = max(minv, 32) # need at least 32 bits minv = max(minv, 32) # need at least 32 bits
elif (hv & 0xFF) == 0: elif (hv & 0xFF) == 0:
#eprintf("16-bit hash")
minv = max(minv, 16) # need at least 16 bits minv = max(minv, 16) # need at least 16 bits
return minv return minv

View File

@ -277,30 +277,36 @@ def build_symbol_map(readelf_bin, libraries) -> Dict[str, Dict[str, ExportSym]]:
# this ordening is specific to ONE symbol! # this ordening is specific to ONE symbol!
def build_preferred_lib_order(sym, libs: Dict[str, ExportSym]) -> List[Tuple[str, ExportSym]]: def build_preferred_lib_order(sym, libs: Dict[str, ExportSym]) -> List[str]:
# libs: lib -> syminfo # libs: lib -> syminfo
realdefs = [(k, v) for k, v in libs.items() if v.scope != "WEAK" and v.ndx != "UND"] realdefs = [lib for lib, v in libs.items() if v.scope != "WEAK" and v.ndx != "UND"]
weakdefs = [(k, v) for k, v in libs.items() if v.scope == "WEAK" and v.ndx != "UND"] weakdefs = [lib for lib, v in libs.items() if v.scope == "WEAK" and v.ndx != "UND"]
weakunddefs = [(k, v) for k, v in libs.items() if v.scope == "WEAK" and v.ndx == "UND"] weakunddefs = [lib for lib, v in libs.items() if v.scope == "WEAK" and v.ndx == "UND"]
unddefs = [(k, v) for k, v in libs.items() if v.scope != "WEAK" and v.ndx == "UND"] unddefs = [lib for lib, v in libs.items() if v.scope != "WEAK" and v.ndx == "UND"]
#assert len(realdefs) + len(weakdefs) + len(weakunddefs) == len(libs) #ks = [v.name for k, v in libs.items()]
#print("k=",ks)
#assert all(k == ks[0] for k in ks)
if len(realdefs) > 1 or (len(realdefs) == 0 and len(weakdefs) > 1): if len(realdefs) > 1: #or (len(realdefs) == 0 and len(weakdefs) > 1):
error("E: symbol '%s' defined non-weakly in multiple libraries! (%s)" error("E: symbol '%s' defined non-weakly in multiple libraries! (%s)"
% (sym, ', '.join(libs.keys()))) % (sym, ', '.join(realdefs)))
if len(realdefs) == 0 and len(weakdefs) > 1:
eprintf("W: symbol '%s' defined amibguously weakly in multiple libraries! Will pick a random one... (%s)"
% (sym, ', '.join(weakdefs)))
if len(realdefs) == 0 and len(weakdefs) == 0: # must be in weakunddefs or unddefs if len(realdefs) == 0 and len(weakdefs) == 0: # must be in weakunddefs or unddefs
error("E: no default weak implementation found for symbol '%s'" % sym) error("E: no default weak implementation found for symbol '%s'" % sym)
return realdefs + weakdefs + weakunddefs #+ unddefs return realdefs + weakdefs + weakunddefs + unddefs
def has_good_subordening(needles, haystack): def has_good_subordening(needles, haystack):
haylist = [x[0] for x in haystack] haylist = [x[0] for x in haystack]
prevind = 0 prevind = 0
for k, _ in needles: for lib in needles:
curind = None curind = None
try: try:
curind = haylist.index(k) curind = haylist.index(lib)
except ValueError: # not in haystack --> eh, let's ignore except ValueError: # not in haystack --> eh, let's ignore
continue continue
@ -310,29 +316,47 @@ def has_good_subordening(needles, haystack):
return True return True
def add_with_ordening(haystack: List[Tuple[str, Dict[str, str]]], # [(libname, (symname -> reloctyp))] def add_with_ordening(haystack: List[Tuple[str, Dict[str, str]]], # [(libname, (symname -> reloctyp))]
needles: List[Tuple[str, ExportSym]], # [(lib, syminfo)] needles: List[str], # [lib]
sym: str, reloc: str) \ sym: str, reloc: str, last=False) \
-> List[Tuple[str, Dict[str, str]]]: -> List[Tuple[str, Dict[str, str]]]:
haylist = [x[0] for x in haystack] haylist = [x[0] for x in haystack]
startind = 0 startind = None if last else 0
for k, v in needles: ii = 0
for lib in needles:
#eprintf("k=",k,"v=",v) #eprintf("k=",k,"v=",v)
try: try:
newind = haylist.index(k) newind = haylist.index(lib)
assert newind >= startind, "???? (%d <= %d)" % (newind, startind) #eprintf("lib=%s newind=%d" % (lib, newind))
#assert newind >= startind, "???? (%d <= %d)" % (newind, startind)
startind = newind startind = newind
symrelocdict = haystack[startind][1] if ii == 0:
if v.name in symrelocdict: symrelocdict = haystack[startind][1]
assert False, "?????" assert not(sym in symrelocdict), "?????"
haystack[startind][1][v.name] = reloc haystack[startind][1][sym] = reloc
except ValueError: # not in haystack --> add! except ValueError: # not in haystack --> add!
startind = startind + 1 if startind is None:
haystack.insert(startind, (k, {v.name:reloc})) startind = len(haystack)
haylist.insert(startind, k) if not last:
startind = startind + 1
#eprintf("lib=%s NEWind=%d" % (lib, startind))
dv = {sym: reloc} if ii == 0 else {}
haystack.insert(startind, (lib, dv))
haylist.insert(startind, lib)
if last:
startind = startind + 1
ii = ii + 1
return haystack return haystack
def visable(ll):
rr = []
for k, v in ll:
if isinstance(v, ExportSym):
rr.append((k, v)) # v.name
else:
rr.append((k, v.keys()))
return rr
def resolve_extern_symbols(needed: Dict[str, List[str]], # symname -> reloctyps def resolve_extern_symbols(needed: Dict[str, List[str]], # symname -> reloctyps
available: Dict[str, Dict[str, ExportSym]], # symname -> (lib -> syminfo) available: Dict[str, Dict[str, ExportSym]], # symname -> (lib -> syminfo)
args) \ args) \
@ -351,7 +375,7 @@ def resolve_extern_symbols(needed: Dict[str, List[str]], # symname -> reloctyps
if args.det: if args.det:
bound = sorted(bound, key=lambda kv: (len(kv[0]), kv[0])) bound = sorted(bound, key=lambda kv: (len(kv[0]), kv[0]))
#eprintf("bound", bound) #eprintf("bound", bound,"\n")
liborder = [] # [(libname, (symname -> reloctyp))] liborder = [] # [(libname, (symname -> reloctyp))]
for k, v in bound: # k: sym (str) for k, v in bound: # k: sym (str)
@ -360,7 +384,8 @@ def resolve_extern_symbols(needed: Dict[str, List[str]], # symname -> reloctyps
reloc, libs = v[0], v[1] reloc, libs = v[0], v[1]
if len(libs) <= 1: if len(libs) <= 1:
continue continue
# preferred: [(lib, syminfo)] # preferred: [lib]
#eprintf("libs",visable(libs.items()))
preferred = build_preferred_lib_order(k, libs) preferred = build_preferred_lib_order(k, libs)
#eprintf("preferred",preferred) #eprintf("preferred",preferred)
if not has_good_subordening(preferred, liborder): if not has_good_subordening(preferred, liborder):
@ -372,10 +397,10 @@ def resolve_extern_symbols(needed: Dict[str, List[str]], # symname -> reloctyps
message = "W: unreconcilable library ordenings '%s' and '%s' "+\ message = "W: unreconcilable library ordenings '%s' and '%s' "+\
"for symbol '%s', you might want to enable `-fskip-zero-value'." "for symbol '%s', you might want to enable `-fskip-zero-value'."
if message is not None: if message is not None:
eprintf(message % (', '.join(liborder.keys()), ', '.join(preferred.keys()), k)) #eprintf(message % (', '.join(liborder.keys()), ', '.join(preferred.keys()), k))
liborder = add_with_ordening(liborder, preferred, k, reloc) liborder = add_with_ordening(liborder, preferred, k, reloc)
#eprintf("new order",liborder) #eprintf("new order",visable(liborder),"\n")
# add all those left without any possible preferred ordening # add all those left without any possible preferred ordening
for k, v in bound: for k, v in bound:
@ -385,9 +410,10 @@ def resolve_extern_symbols(needed: Dict[str, List[str]], # symname -> reloctyps
if len(libs) != 1: if len(libs) != 1:
continue continue
lib = libs.popitem() # (lib, syminfo) lib = libs.popitem() # (lib, syminfo)
liborder = add_with_ordening(liborder, [lib], k, reloc) #eprintf("lib",lib)
#eprintf("new order (no preference)",liborder) liborder = add_with_ordening(liborder, [lib[0]], k, reloc, True)
#eprintf("new order (no preference)",visable(liborder),"\n")
#eprintf("ordered", liborder) #eprintf("ordered", visable(liborder))
return OrderedDict(liborder) return OrderedDict(liborder)

View File

@ -120,11 +120,11 @@ def do_smol_run(args, arch):
tmp_asm_file, tmp_elf_file, args.asflags) tmp_asm_file, tmp_elf_file, args.asflags)
# link with LD into the final executable, w/ special linker script # link with LD into the final executable, w/ special linker script
ld_link_final(args.verbose, args.cc, arch, args.smolld, [objinput, tmp_elf_file], if args.debugout is not None: # do this first, so the linker map output will use the final output binary
args.output, args.ldflags, False)
if args.debugout is not None:
ld_link_final(args.verbose, args.cc, arch, args.smolld, [objinput, tmp_elf_file], ld_link_final(args.verbose, args.cc, arch, args.smolld, [objinput, tmp_elf_file],
args.debugout, args.ldflags, True) args.debugout, args.ldflags, True)
ld_link_final(args.verbose, args.cc, arch, args.smolld, [objinput, tmp_elf_file],
args.output, args.ldflags, False)
finally: finally:
if not args.keeptmp: if not args.keeptmp:
if objinputistemp: os.remove(objinput) if objinputistemp: os.remove(objinput)

View File

@ -209,5 +209,5 @@ if __name__ == '__main__':
if rv is None: pass if rv is None: pass
else: else:
try: sys.exit(int(rv)) try: sys.exit(int(rv))
except: sys.exit(1) except Exception: sys.exit(1)