forked from Imagelibrary/littlefs
scripts: Include global/section info in collect_syms, added Sym
We have this info, might as well expose it for scripts to use. Unfortunately this extra info did make tuple unpacking a bit of a mess, especially in scripts that don't use this extra info, so I've added a small Sym class similar to DwarfEntry in collect_dwarf_info. This is useful for some ongoing stack.py rework.
This commit is contained in:
@@ -260,6 +260,21 @@ def multiprocessing_cache(f):
|
||||
|
||||
return multiprocessing_cache
|
||||
|
||||
class Sym(co.namedtuple('Sym', [
|
||||
'name', 'global_', 'section', 'addr', 'size'])):
|
||||
__slots__ = ()
|
||||
def __new__(cls, name, global_, section, addr, size):
|
||||
return super().__new__(cls, name, global_, section, addr, size)
|
||||
|
||||
def __repr__(self):
|
||||
return '%s(%r, %r, %r, 0x%x, 0x%x)' % (
|
||||
self.__class__.__name__,
|
||||
self.name,
|
||||
self.global_,
|
||||
self.section,
|
||||
self.addr,
|
||||
self.size)
|
||||
|
||||
class SymInfo:
|
||||
def __init__(self, syms):
|
||||
self.syms = syms
|
||||
@@ -270,12 +285,13 @@ class SymInfo:
|
||||
# organize by symbol, note multiple symbols can share a name
|
||||
if not hasattr(self, '_by_sym'):
|
||||
by_sym = {}
|
||||
for sym, addr, size in self.syms:
|
||||
if sym not in by_sym:
|
||||
by_sym[sym] = []
|
||||
if (addr, size) not in by_sym[sym]:
|
||||
by_sym[sym].append((addr, size))
|
||||
for sym in self.syms:
|
||||
if sym.name not in by_sym:
|
||||
by_sym[sym.name] = []
|
||||
if sym not in by_sym[sym.name]:
|
||||
by_sym[sym.name].append(sym)
|
||||
self._by_sym = by_sym
|
||||
|
||||
return self._by_sym.get(k, d)
|
||||
|
||||
else:
|
||||
@@ -285,21 +301,21 @@ class SymInfo:
|
||||
if not hasattr(self, '_by_addr'):
|
||||
# sort and keep largest/first when duplicates
|
||||
syms = self.syms.copy()
|
||||
syms.sort(key=lambda x: (x[1], -x[2], x[0]))
|
||||
syms.sort(key=lambda x: (x.addr, -x.size))
|
||||
|
||||
by_addr = []
|
||||
for name, addr, size in syms:
|
||||
for sym in syms:
|
||||
if (len(by_addr) == 0
|
||||
or by_addr[-1][0] != addr):
|
||||
by_addr.append((name, addr, size))
|
||||
or by_addr[-1].addr != sym.addr):
|
||||
by_addr.append(sym)
|
||||
self._by_addr = by_addr
|
||||
|
||||
# find sym by range
|
||||
i = bisect.bisect(self._by_addr, k,
|
||||
key=lambda x: x[1])
|
||||
key=lambda x: x.addr)
|
||||
# check that we're actually in this sym's size
|
||||
if i > 0 and k < self._by_addr[i-1][1]+self._by_addr[i-1][2]:
|
||||
return self._by_addr[i-1][0]
|
||||
if i > 0 and k < self._by_addr[i-1].addr+self._by_addr[i-1].size:
|
||||
return self._by_addr[i-1]
|
||||
else:
|
||||
return d
|
||||
|
||||
@@ -318,8 +334,17 @@ class SymInfo:
|
||||
def __iter__(self):
|
||||
return iter(self.syms)
|
||||
|
||||
def globals(self):
|
||||
return SymInfo([sym for sym in self.syms
|
||||
if sym.global_])
|
||||
|
||||
def section(self, section):
|
||||
return SymInfo([sym for sym in self.syms
|
||||
# note we accept prefixes
|
||||
if s.startswith(section)])
|
||||
|
||||
@multiprocessing_cache
|
||||
def collect_syms(obj_path, sections=None, global_=False, *,
|
||||
def collect_syms(obj_path, global_=False, sections=None, *,
|
||||
objdump_path=OBJDUMP_PATH,
|
||||
**args):
|
||||
symbol_pattern = re.compile(
|
||||
@@ -353,7 +378,8 @@ def collect_syms(obj_path, sections=None, global_=False, *,
|
||||
# u => unique global
|
||||
# => neither
|
||||
# ! => local + global
|
||||
if global_ and scope in 'l ':
|
||||
global__ = scope not in 'l '
|
||||
if global_ and not global__:
|
||||
continue
|
||||
# filter by section? note we accept prefixes
|
||||
if (sections is not None
|
||||
@@ -364,7 +390,7 @@ def collect_syms(obj_path, sections=None, global_=False, *,
|
||||
if not size:
|
||||
continue
|
||||
# note multiple symbols can share a name
|
||||
syms.append((name, addr, size))
|
||||
syms.append(Sym(name, global__, section, addr, size))
|
||||
proc.wait()
|
||||
if proc.returncode != 0:
|
||||
raise sp.CalledProcessError(proc.returncode, proc.args)
|
||||
@@ -633,16 +659,16 @@ def collect_decompressed(path, *,
|
||||
sym_addr_ = addr_ - off
|
||||
|
||||
# track possible deltas?
|
||||
for sym_addr, size in syms[sym]:
|
||||
delta = sym_addr - sym_addr_
|
||||
for sym_ in syms[sym]:
|
||||
delta = sym_.addr - sym_addr_
|
||||
if delta not in deltas[dso]:
|
||||
deltas[dso][delta] = sum(
|
||||
abs(a_+delta - a)
|
||||
for s, (a_, _) in syms_[dso].items()
|
||||
for a, _ in syms[s])
|
||||
for delta in deltas[dso].keys():
|
||||
deltas[dso][delta] += abs(sym_addr_+delta - sym_addr)
|
||||
syms_[dso][sym] = sym_addr_, size
|
||||
deltas[dso][delta] += abs(sym_addr_+delta - sym_.addr)
|
||||
syms_[dso][sym] = sym_addr_, sym_.size
|
||||
|
||||
# guess the best delta
|
||||
delta, _ = min(deltas[dso].items(),
|
||||
|
||||
Reference in New Issue
Block a user