scripts: Added alignment info to structs.py
Dwarf-info doesn't actually provide alignment info with the current tools I'm using (but it does look like DW_AT_alignment was added in a recent version), so for now this is just a heuristic based on the largest base/pointer type. This heuristic is still useful info and probably correct for the types littlefs cares about (no SIMD here!). This is also another field that folds using max, so that's fun.
This commit is contained in:
+42
-9
@@ -128,22 +128,23 @@ class RInt(co.namedtuple('RInt', 'x')):
|
|||||||
# struct size results
|
# struct size results
|
||||||
class StructResult(co.namedtuple('StructResult', [
|
class StructResult(co.namedtuple('StructResult', [
|
||||||
'file', 'struct',
|
'file', 'struct',
|
||||||
'size',
|
'size', 'align',
|
||||||
'children'])):
|
'children'])):
|
||||||
_by = ['file', 'struct']
|
_by = ['file', 'struct']
|
||||||
_fields = ['size']
|
_fields = ['size', 'align']
|
||||||
_sort = ['size']
|
_sort = ['size', 'align']
|
||||||
_types = {'size': RInt}
|
_types = {'size': RInt, 'align': RInt}
|
||||||
|
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
def __new__(cls, file='', struct='', size=0, children=[]):
|
def __new__(cls, file='', struct='', size=0, align=0, children=[]):
|
||||||
return super().__new__(cls, file, struct,
|
return super().__new__(cls, file, struct,
|
||||||
RInt(size),
|
RInt(size), RInt(align),
|
||||||
children or [])
|
children or [])
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
return StructResult(self.file, self.struct,
|
return StructResult(self.file, self.struct,
|
||||||
self.size + other.size,
|
self.size + other.size,
|
||||||
|
max(self.align, other.align),
|
||||||
self.children + other.children)
|
self.children + other.children)
|
||||||
|
|
||||||
|
|
||||||
@@ -236,6 +237,14 @@ def collect_dwarf_info(obj_path, filter=None, *,
|
|||||||
def __contains__(self, k):
|
def __contains__(self, k):
|
||||||
return k in self.ats
|
return k in self.ats
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '%s(%d, 0x%x, %r, %r)' % (
|
||||||
|
self.__class__.__name__,
|
||||||
|
self.level,
|
||||||
|
self.off,
|
||||||
|
self.tag,
|
||||||
|
self.ats)
|
||||||
|
|
||||||
info_pattern = re.compile(
|
info_pattern = re.compile(
|
||||||
'^\s*(?:<(?P<level>[^>]*)>'
|
'^\s*(?:<(?P<level>[^>]*)>'
|
||||||
'\s*<(?P<off>[^>]*)>'
|
'\s*<(?P<off>[^>]*)>'
|
||||||
@@ -357,6 +366,28 @@ def collect(obj_paths, *,
|
|||||||
assert False
|
assert False
|
||||||
size = sizeof(entry)
|
size = sizeof(entry)
|
||||||
|
|
||||||
|
# find alignment, recursing if necessary
|
||||||
|
#
|
||||||
|
# Dwarf doesn't seem to give us this info, so we infer it from
|
||||||
|
# the size of children pointer/base types. This is _usually_
|
||||||
|
# correct.
|
||||||
|
def alignof(entry):
|
||||||
|
# pointer/base type? assume this size == alignment
|
||||||
|
if entry.tag in {
|
||||||
|
'DW_TAG_pointer_type',
|
||||||
|
'DW_TAG_base_type'}:
|
||||||
|
return int(entry['DW_AT_byte_size'])
|
||||||
|
# indirect type?
|
||||||
|
elif 'DW_AT_type' in entry:
|
||||||
|
type = int(entry['DW_AT_type'].strip('<>'), 0)
|
||||||
|
return alignof(info[type])
|
||||||
|
# struct/union probably
|
||||||
|
elif entry.children:
|
||||||
|
return max(alignof(child) for child in entry.children)
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
align = alignof(entry)
|
||||||
|
|
||||||
# find children, recursing if necessary
|
# find children, recursing if necessary
|
||||||
def childrenof(entry):
|
def childrenof(entry):
|
||||||
# pointer? these end up recursive but the underlying
|
# pointer? these end up recursive but the underlying
|
||||||
@@ -367,12 +398,14 @@ def collect(obj_paths, *,
|
|||||||
elif 'DW_AT_type' in entry:
|
elif 'DW_AT_type' in entry:
|
||||||
type = int(entry['DW_AT_type'].strip('<>'), 0)
|
type = int(entry['DW_AT_type'].strip('<>'), 0)
|
||||||
return childrenof(info[type])
|
return childrenof(info[type])
|
||||||
|
# struct/union probably
|
||||||
else:
|
else:
|
||||||
children = []
|
children = []
|
||||||
for child in entry.children:
|
for child in entry.children:
|
||||||
name = child['DW_AT_name'].split(':')[-1].strip()
|
name = child['DW_AT_name'].split(':')[-1].strip()
|
||||||
size = sizeof(child)
|
size = sizeof(child)
|
||||||
children.append(StructResult(file, name, size,
|
align = alignof(child)
|
||||||
|
children.append(StructResult(file, name, size, align,
|
||||||
childrenof(child)))
|
childrenof(child)))
|
||||||
return children
|
return children
|
||||||
children = childrenof(entry)
|
children = childrenof(entry)
|
||||||
@@ -380,10 +413,10 @@ def collect(obj_paths, *,
|
|||||||
# typdefs exist in a separate namespace, so we need to track
|
# typdefs exist in a separate namespace, so we need to track
|
||||||
# these separately
|
# these separately
|
||||||
if entry.tag == 'DW_TAG_typedef':
|
if entry.tag == 'DW_TAG_typedef':
|
||||||
typedefs[no] = StructResult(file, name, size, children)
|
typedefs[no] = StructResult(file, name, size, align, children)
|
||||||
typedefed.add(int(entry['DW_AT_type'].strip('<>'), 0))
|
typedefed.add(int(entry['DW_AT_type'].strip('<>'), 0))
|
||||||
else:
|
else:
|
||||||
types[no] = StructResult(file, name, size, children)
|
types[no] = StructResult(file, name, size, align, children)
|
||||||
|
|
||||||
# let typedefs take priority
|
# let typedefs take priority
|
||||||
results.extend(typedefs.values())
|
results.extend(typedefs.values())
|
||||||
|
|||||||
Reference in New Issue
Block a user