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:
Christopher Haster
2024-12-05 10:35:30 -06:00
parent eb7fff8843
commit b4038e3c27
5 changed files with 223 additions and 91 deletions

View File

@@ -158,6 +158,21 @@ def openio(path, mode='r', buffering=-1):
else: else:
return open(path, mode, buffering) return open(path, mode, buffering)
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: class SymInfo:
def __init__(self, syms): def __init__(self, syms):
self.syms = syms self.syms = syms
@@ -168,12 +183,13 @@ class SymInfo:
# organize by symbol, note multiple symbols can share a name # organize by symbol, note multiple symbols can share a name
if not hasattr(self, '_by_sym'): if not hasattr(self, '_by_sym'):
by_sym = {} by_sym = {}
for sym, addr, size in self.syms: for sym in self.syms:
if sym not in by_sym: if sym.name not in by_sym:
by_sym[sym] = [] by_sym[sym.name] = []
if (addr, size) not in by_sym[sym]: if sym not in by_sym[sym.name]:
by_sym[sym].append((addr, size)) by_sym[sym.name].append(sym)
self._by_sym = by_sym self._by_sym = by_sym
return self._by_sym.get(k, d) return self._by_sym.get(k, d)
else: else:
@@ -183,21 +199,21 @@ class SymInfo:
if not hasattr(self, '_by_addr'): if not hasattr(self, '_by_addr'):
# sort and keep largest/first when duplicates # sort and keep largest/first when duplicates
syms = self.syms.copy() 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 = [] by_addr = []
for name, addr, size in syms: for sym in syms:
if (len(by_addr) == 0 if (len(by_addr) == 0
or by_addr[-1][0] != addr): or by_addr[-1].addr != sym.addr):
by_addr.append((name, addr, size)) by_addr.append(sym)
self._by_addr = by_addr self._by_addr = by_addr
# find sym by range # find sym by range
i = bisect.bisect(self._by_addr, k, 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 # 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]: if i > 0 and k < self._by_addr[i-1].addr+self._by_addr[i-1].size:
return self._by_addr[i-1][0] return self._by_addr[i-1]
else: else:
return d return d
@@ -216,7 +232,16 @@ class SymInfo:
def __iter__(self): def __iter__(self):
return iter(self.syms) return iter(self.syms)
def collect_syms(obj_path, sections=None, global_=False, *, 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)])
def collect_syms(obj_path, global_=False, sections=None, *,
objdump_path=OBJDUMP_PATH, objdump_path=OBJDUMP_PATH,
**args): **args):
symbol_pattern = re.compile( symbol_pattern = re.compile(
@@ -250,7 +275,8 @@ def collect_syms(obj_path, sections=None, global_=False, *,
# u => unique global # u => unique global
# => neither # => neither
# ! => local + global # ! => local + global
if global_ and scope in 'l ': global__ = scope not in 'l '
if global_ and not global__:
continue continue
# filter by section? note we accept prefixes # filter by section? note we accept prefixes
if (sections is not None if (sections is not None
@@ -261,7 +287,7 @@ def collect_syms(obj_path, sections=None, global_=False, *,
if not size: if not size:
continue continue
# note multiple symbols can share a name # note multiple symbols can share a name
syms.append((name, addr, size)) syms.append(Sym(name, global__, section, addr, size))
proc.wait() proc.wait()
if proc.returncode != 0: if proc.returncode != 0:
raise sp.CalledProcessError(proc.returncode, proc.args) raise sp.CalledProcessError(proc.returncode, proc.args)
@@ -487,14 +513,14 @@ def collect(obj_paths, *,
**args) **args)
# map function sizes to debug symbols # map function sizes to debug symbols
for sym, _, size in syms: for sym in syms:
# discard internal functions # discard internal functions
if not everything and sym.startswith('__'): if not everything and sym.name.startswith('__'):
continue continue
# find best matching dwarf entry, this may be slightly different # find best matching dwarf entry, this may be slightly different
# due to optimizations # due to optimizations
entry = info.get(sym) entry = info.get(sym.name)
# if we have no file guess from obj path # if we have no file guess from obj path
if entry is not None and 'DW_AT_decl_file' in entry: if entry is not None and 'DW_AT_decl_file' in entry:
@@ -514,7 +540,7 @@ def collect(obj_paths, *,
os.path.abspath(file)]) == os.getcwd(): os.path.abspath(file)]) == os.getcwd():
continue continue
results.append(CodeResult(file, sym, size)) results.append(CodeResult(file, sym.name, sym.size))
return results return results

View File

@@ -167,6 +167,21 @@ def openio(path, mode='r', buffering=-1):
else: else:
return open(path, mode, buffering) return open(path, mode, buffering)
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: class SymInfo:
def __init__(self, syms): def __init__(self, syms):
self.syms = syms self.syms = syms
@@ -177,12 +192,13 @@ class SymInfo:
# organize by symbol, note multiple symbols can share a name # organize by symbol, note multiple symbols can share a name
if not hasattr(self, '_by_sym'): if not hasattr(self, '_by_sym'):
by_sym = {} by_sym = {}
for sym, addr, size in self.syms: for sym in self.syms:
if sym not in by_sym: if sym.name not in by_sym:
by_sym[sym] = [] by_sym[sym.name] = []
if (addr, size) not in by_sym[sym]: if sym not in by_sym[sym.name]:
by_sym[sym].append((addr, size)) by_sym[sym.name].append(sym)
self._by_sym = by_sym self._by_sym = by_sym
return self._by_sym.get(k, d) return self._by_sym.get(k, d)
else: else:
@@ -192,21 +208,21 @@ class SymInfo:
if not hasattr(self, '_by_addr'): if not hasattr(self, '_by_addr'):
# sort and keep largest/first when duplicates # sort and keep largest/first when duplicates
syms = self.syms.copy() 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 = [] by_addr = []
for name, addr, size in syms: for sym in syms:
if (len(by_addr) == 0 if (len(by_addr) == 0
or by_addr[-1][0] != addr): or by_addr[-1].addr != sym.addr):
by_addr.append((name, addr, size)) by_addr.append(sym)
self._by_addr = by_addr self._by_addr = by_addr
# find sym by range # find sym by range
i = bisect.bisect(self._by_addr, k, 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 # 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]: if i > 0 and k < self._by_addr[i-1].addr+self._by_addr[i-1].size:
return self._by_addr[i-1][0] return self._by_addr[i-1]
else: else:
return d return d
@@ -225,7 +241,16 @@ class SymInfo:
def __iter__(self): def __iter__(self):
return iter(self.syms) return iter(self.syms)
def collect_syms(obj_path, sections=None, global_=False, *, 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)])
def collect_syms(obj_path, global_=False, sections=None, *,
objdump_path=OBJDUMP_PATH, objdump_path=OBJDUMP_PATH,
**args): **args):
symbol_pattern = re.compile( symbol_pattern = re.compile(
@@ -259,7 +284,8 @@ def collect_syms(obj_path, sections=None, global_=False, *,
# u => unique global # u => unique global
# => neither # => neither
# ! => local + global # ! => local + global
if global_ and scope in 'l ': global__ = scope not in 'l '
if global_ and not global__:
continue continue
# filter by section? note we accept prefixes # filter by section? note we accept prefixes
if (sections is not None if (sections is not None
@@ -270,7 +296,7 @@ def collect_syms(obj_path, sections=None, global_=False, *,
if not size: if not size:
continue continue
# note multiple symbols can share a name # note multiple symbols can share a name
syms.append((name, addr, size)) syms.append(Sym(name, global__, section, addr, size))
proc.wait() proc.wait()
if proc.returncode != 0: if proc.returncode != 0:
raise sp.CalledProcessError(proc.returncode, proc.args) raise sp.CalledProcessError(proc.returncode, proc.args)
@@ -649,13 +675,13 @@ def collect(obj_paths, *,
return children, notes return children, notes
# find each function's context # find each function's context
for sym, _, _ in syms: for sym in syms:
# discard internal functions # discard internal functions
if not everything and sym.startswith('__'): if not everything and sym.name.startswith('__'):
continue continue
# find best matching dwarf entry # find best matching dwarf entry
entry = info.get(sym) entry = info.get(sym.name)
# skip non-functions # skip non-functions
if entry is None or entry.tag != 'DW_TAG_subprogram': if entry is None or entry.tag != 'DW_TAG_subprogram':

View File

@@ -158,6 +158,21 @@ def openio(path, mode='r', buffering=-1):
else: else:
return open(path, mode, buffering) return open(path, mode, buffering)
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: class SymInfo:
def __init__(self, syms): def __init__(self, syms):
self.syms = syms self.syms = syms
@@ -168,12 +183,13 @@ class SymInfo:
# organize by symbol, note multiple symbols can share a name # organize by symbol, note multiple symbols can share a name
if not hasattr(self, '_by_sym'): if not hasattr(self, '_by_sym'):
by_sym = {} by_sym = {}
for sym, addr, size in self.syms: for sym in self.syms:
if sym not in by_sym: if sym.name not in by_sym:
by_sym[sym] = [] by_sym[sym.name] = []
if (addr, size) not in by_sym[sym]: if sym not in by_sym[sym.name]:
by_sym[sym].append((addr, size)) by_sym[sym.name].append(sym)
self._by_sym = by_sym self._by_sym = by_sym
return self._by_sym.get(k, d) return self._by_sym.get(k, d)
else: else:
@@ -183,21 +199,21 @@ class SymInfo:
if not hasattr(self, '_by_addr'): if not hasattr(self, '_by_addr'):
# sort and keep largest/first when duplicates # sort and keep largest/first when duplicates
syms = self.syms.copy() 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 = [] by_addr = []
for name, addr, size in syms: for sym in syms:
if (len(by_addr) == 0 if (len(by_addr) == 0
or by_addr[-1][0] != addr): or by_addr[-1].addr != sym.addr):
by_addr.append((name, addr, size)) by_addr.append(sym)
self._by_addr = by_addr self._by_addr = by_addr
# find sym by range # find sym by range
i = bisect.bisect(self._by_addr, k, 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 # 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]: if i > 0 and k < self._by_addr[i-1].addr+self._by_addr[i-1].size:
return self._by_addr[i-1][0] return self._by_addr[i-1]
else: else:
return d return d
@@ -216,7 +232,16 @@ class SymInfo:
def __iter__(self): def __iter__(self):
return iter(self.syms) return iter(self.syms)
def collect_syms(obj_path, sections=None, global_=False, *, 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)])
def collect_syms(obj_path, global_=False, sections=None, *,
objdump_path=OBJDUMP_PATH, objdump_path=OBJDUMP_PATH,
**args): **args):
symbol_pattern = re.compile( symbol_pattern = re.compile(
@@ -250,7 +275,8 @@ def collect_syms(obj_path, sections=None, global_=False, *,
# u => unique global # u => unique global
# => neither # => neither
# ! => local + global # ! => local + global
if global_ and scope in 'l ': global__ = scope not in 'l '
if global_ and not global__:
continue continue
# filter by section? note we accept prefixes # filter by section? note we accept prefixes
if (sections is not None if (sections is not None
@@ -261,7 +287,7 @@ def collect_syms(obj_path, sections=None, global_=False, *,
if not size: if not size:
continue continue
# note multiple symbols can share a name # note multiple symbols can share a name
syms.append((name, addr, size)) syms.append(Sym(name, global__, section, addr, size))
proc.wait() proc.wait()
if proc.returncode != 0: if proc.returncode != 0:
raise sp.CalledProcessError(proc.returncode, proc.args) raise sp.CalledProcessError(proc.returncode, proc.args)
@@ -487,14 +513,14 @@ def collect(obj_paths, *,
**args) **args)
# map function sizes to debug symbols # map function sizes to debug symbols
for sym, _, size in syms: for sym in syms:
# discard internal functions # discard internal functions
if not everything and sym.startswith('__'): if not everything and sym.name.startswith('__'):
continue continue
# find best matching dwarf entry, this may be slightly different # find best matching dwarf entry, this may be slightly different
# due to optimizations # due to optimizations
entry = info.get(sym) entry = info.get(sym.name)
# if we have no file guess from obj path # if we have no file guess from obj path
if entry is not None and 'DW_AT_decl_file' in entry: if entry is not None and 'DW_AT_decl_file' in entry:
@@ -514,7 +540,7 @@ def collect(obj_paths, *,
os.path.abspath(file)]) == os.getcwd(): os.path.abspath(file)]) == os.getcwd():
continue continue
results.append(DataResult(file, sym, size)) results.append(DataResult(file, sym.name, sym.size))
return results return results

View File

@@ -260,6 +260,21 @@ def multiprocessing_cache(f):
return multiprocessing_cache 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: class SymInfo:
def __init__(self, syms): def __init__(self, syms):
self.syms = syms self.syms = syms
@@ -270,12 +285,13 @@ class SymInfo:
# organize by symbol, note multiple symbols can share a name # organize by symbol, note multiple symbols can share a name
if not hasattr(self, '_by_sym'): if not hasattr(self, '_by_sym'):
by_sym = {} by_sym = {}
for sym, addr, size in self.syms: for sym in self.syms:
if sym not in by_sym: if sym.name not in by_sym:
by_sym[sym] = [] by_sym[sym.name] = []
if (addr, size) not in by_sym[sym]: if sym not in by_sym[sym.name]:
by_sym[sym].append((addr, size)) by_sym[sym.name].append(sym)
self._by_sym = by_sym self._by_sym = by_sym
return self._by_sym.get(k, d) return self._by_sym.get(k, d)
else: else:
@@ -285,21 +301,21 @@ class SymInfo:
if not hasattr(self, '_by_addr'): if not hasattr(self, '_by_addr'):
# sort and keep largest/first when duplicates # sort and keep largest/first when duplicates
syms = self.syms.copy() 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 = [] by_addr = []
for name, addr, size in syms: for sym in syms:
if (len(by_addr) == 0 if (len(by_addr) == 0
or by_addr[-1][0] != addr): or by_addr[-1].addr != sym.addr):
by_addr.append((name, addr, size)) by_addr.append(sym)
self._by_addr = by_addr self._by_addr = by_addr
# find sym by range # find sym by range
i = bisect.bisect(self._by_addr, k, 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 # 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]: if i > 0 and k < self._by_addr[i-1].addr+self._by_addr[i-1].size:
return self._by_addr[i-1][0] return self._by_addr[i-1]
else: else:
return d return d
@@ -318,8 +334,17 @@ class SymInfo:
def __iter__(self): def __iter__(self):
return iter(self.syms) 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 @multiprocessing_cache
def collect_syms(obj_path, sections=None, global_=False, *, def collect_syms(obj_path, global_=False, sections=None, *,
objdump_path=OBJDUMP_PATH, objdump_path=OBJDUMP_PATH,
**args): **args):
symbol_pattern = re.compile( symbol_pattern = re.compile(
@@ -353,7 +378,8 @@ def collect_syms(obj_path, sections=None, global_=False, *,
# u => unique global # u => unique global
# => neither # => neither
# ! => local + global # ! => local + global
if global_ and scope in 'l ': global__ = scope not in 'l '
if global_ and not global__:
continue continue
# filter by section? note we accept prefixes # filter by section? note we accept prefixes
if (sections is not None if (sections is not None
@@ -364,7 +390,7 @@ def collect_syms(obj_path, sections=None, global_=False, *,
if not size: if not size:
continue continue
# note multiple symbols can share a name # note multiple symbols can share a name
syms.append((name, addr, size)) syms.append(Sym(name, global__, section, addr, size))
proc.wait() proc.wait()
if proc.returncode != 0: if proc.returncode != 0:
raise sp.CalledProcessError(proc.returncode, proc.args) raise sp.CalledProcessError(proc.returncode, proc.args)
@@ -633,16 +659,16 @@ def collect_decompressed(path, *,
sym_addr_ = addr_ - off sym_addr_ = addr_ - off
# track possible deltas? # track possible deltas?
for sym_addr, size in syms[sym]: for sym_ in syms[sym]:
delta = sym_addr - sym_addr_ delta = sym_.addr - sym_addr_
if delta not in deltas[dso]: if delta not in deltas[dso]:
deltas[dso][delta] = sum( deltas[dso][delta] = sum(
abs(a_+delta - a) abs(a_+delta - a)
for s, (a_, _) in syms_[dso].items() for s, (a_, _) in syms_[dso].items()
for a, _ in syms[s]) for a, _ in syms[s])
for delta in deltas[dso].keys(): for delta in deltas[dso].keys():
deltas[dso][delta] += abs(sym_addr_+delta - sym_addr) deltas[dso][delta] += abs(sym_addr_+delta - sym_.addr)
syms_[dso][sym] = sym_addr_, size syms_[dso][sym] = sym_addr_, sym_.size
# guess the best delta # guess the best delta
delta, _ = min(deltas[dso].items(), delta, _ = min(deltas[dso].items(),

View File

@@ -167,6 +167,21 @@ def openio(path, mode='r', buffering=-1):
else: else:
return open(path, mode, buffering) return open(path, mode, buffering)
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: class SymInfo:
def __init__(self, syms): def __init__(self, syms):
self.syms = syms self.syms = syms
@@ -177,12 +192,13 @@ class SymInfo:
# organize by symbol, note multiple symbols can share a name # organize by symbol, note multiple symbols can share a name
if not hasattr(self, '_by_sym'): if not hasattr(self, '_by_sym'):
by_sym = {} by_sym = {}
for sym, addr, size in self.syms: for sym in self.syms:
if sym not in by_sym: if sym.name not in by_sym:
by_sym[sym] = [] by_sym[sym.name] = []
if (addr, size) not in by_sym[sym]: if sym not in by_sym[sym.name]:
by_sym[sym].append((addr, size)) by_sym[sym.name].append(sym)
self._by_sym = by_sym self._by_sym = by_sym
return self._by_sym.get(k, d) return self._by_sym.get(k, d)
else: else:
@@ -192,21 +208,21 @@ class SymInfo:
if not hasattr(self, '_by_addr'): if not hasattr(self, '_by_addr'):
# sort and keep largest/first when duplicates # sort and keep largest/first when duplicates
syms = self.syms.copy() 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 = [] by_addr = []
for name, addr, size in syms: for sym in syms:
if (len(by_addr) == 0 if (len(by_addr) == 0
or by_addr[-1][0] != addr): or by_addr[-1].addr != sym.addr):
by_addr.append((name, addr, size)) by_addr.append(sym)
self._by_addr = by_addr self._by_addr = by_addr
# find sym by range # find sym by range
i = bisect.bisect(self._by_addr, k, 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 # 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]: if i > 0 and k < self._by_addr[i-1].addr+self._by_addr[i-1].size:
return self._by_addr[i-1][0] return self._by_addr[i-1]
else: else:
return d return d
@@ -225,7 +241,16 @@ class SymInfo:
def __iter__(self): def __iter__(self):
return iter(self.syms) return iter(self.syms)
def collect_syms(obj_path, sections=None, global_=False, *, 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)])
def collect_syms(obj_path, global_=False, sections=None, *,
objdump_path=OBJDUMP_PATH, objdump_path=OBJDUMP_PATH,
**args): **args):
symbol_pattern = re.compile( symbol_pattern = re.compile(
@@ -259,7 +284,8 @@ def collect_syms(obj_path, sections=None, global_=False, *,
# u => unique global # u => unique global
# => neither # => neither
# ! => local + global # ! => local + global
if global_ and scope in 'l ': global__ = scope not in 'l '
if global_ and not global__:
continue continue
# filter by section? note we accept prefixes # filter by section? note we accept prefixes
if (sections is not None if (sections is not None
@@ -270,7 +296,7 @@ def collect_syms(obj_path, sections=None, global_=False, *,
if not size: if not size:
continue continue
# note multiple symbols can share a name # note multiple symbols can share a name
syms.append((name, addr, size)) syms.append(Sym(name, global__, section, addr, size))
proc.wait() proc.wait()
if proc.returncode != 0: if proc.returncode != 0:
raise sp.CalledProcessError(proc.returncode, proc.args) raise sp.CalledProcessError(proc.returncode, proc.args)
@@ -601,7 +627,9 @@ def collect_job(path, start, stop, syms, lines, *,
else: else:
# find sym # find sym
sym = syms.get(addr) sym = syms.get(addr)
if sym is None: if sym is not None:
sym = sym.name
else:
sym = hex(addr) sym = hex(addr)
# filter out internal/unknown functions # filter out internal/unknown functions