mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 00:32:38 +01:00 
			
		
		
		
	Limit ./scripts/structs.py to report structs in local .h files
This requires parsing an additional section of the dwarfinfo (--dwarf=rawlines) to get the declaration file info. --- Interpreting the results of ./scripts/structs.py reporting is a bit more complicated than other scripts, structs aren't used in a consistent manner so the cost of a large struct depends on the context in which it is used. But that being said, there really isn't much reason to report internal-only structs. These structs really only exist for type-checking in internal algorithms, and their cost will end up reflected in other RAM measurements, either stack, heap, or other.
This commit is contained in:
		| @@ -16,16 +16,48 @@ import collections as co | |||||||
| OBJ_PATHS = ['*.o'] | OBJ_PATHS = ['*.o'] | ||||||
|  |  | ||||||
| def collect(paths, **args): | def collect(paths, **args): | ||||||
|     results = co.defaultdict(lambda: 0) |     decl_pattern = re.compile( | ||||||
|     pattern = re.compile( |         '^\s+(?P<no>[0-9]+)' | ||||||
|  |             '\s+(?P<dir>[0-9]+)' | ||||||
|  |             '\s+.*' | ||||||
|  |             '\s+(?P<file>[^\s]+)$') | ||||||
|  |     struct_pattern = re.compile( | ||||||
|         '^(?:.*DW_TAG_(?P<tag>[a-z_]+).*' |         '^(?:.*DW_TAG_(?P<tag>[a-z_]+).*' | ||||||
|             '|^.*DW_AT_name.*:\s*(?P<name>[^:\s]+)\s*' |             '|^.*DW_AT_name.*:\s*(?P<name>[^:\s]+)\s*' | ||||||
|  |             '|^.*DW_AT_decl_file.*:\s*(?P<decl>[0-9]+)\s*' | ||||||
|             '|^.*DW_AT_byte_size.*:\s*(?P<size>[0-9]+)\s*)$') |             '|^.*DW_AT_byte_size.*:\s*(?P<size>[0-9]+)\s*)$') | ||||||
|  |  | ||||||
|  |     results = co.defaultdict(lambda: 0) | ||||||
|     for path in paths: |     for path in paths: | ||||||
|  |         # find decl, we want to filter by structs in .h files | ||||||
|  |         decls = {} | ||||||
|  |         # note objdump-tool may contain extra args | ||||||
|  |         cmd = args['objdump_tool'] + ['--dwarf=rawline', path] | ||||||
|  |         if args.get('verbose'): | ||||||
|  |             print(' '.join(shlex.quote(c) for c in cmd)) | ||||||
|  |         proc = sp.Popen(cmd, | ||||||
|  |             stdout=sp.PIPE, | ||||||
|  |             stderr=sp.PIPE if not args.get('verbose') else None, | ||||||
|  |             universal_newlines=True, | ||||||
|  |             errors='replace') | ||||||
|  |         for line in proc.stdout: | ||||||
|  |             # find file numbers | ||||||
|  |             m = decl_pattern.match(line) | ||||||
|  |             if m: | ||||||
|  |                 decls[int(m.group('no'))] = ( | ||||||
|  |                     m.group('file'), | ||||||
|  |                     int(m.group('dir'))) | ||||||
|  |         proc.wait() | ||||||
|  |         if proc.returncode != 0: | ||||||
|  |             if not args.get('verbose'): | ||||||
|  |                 for line in proc.stderr: | ||||||
|  |                     sys.stdout.write(line) | ||||||
|  |             sys.exit(-1) | ||||||
|  |  | ||||||
|         # collect structs as we parse dwarf info |         # collect structs as we parse dwarf info | ||||||
|         found = False |         found = False | ||||||
|         name = None |         name = None | ||||||
|  |         decl = None | ||||||
|         size = None |         size = None | ||||||
|  |  | ||||||
|         # note objdump-tool may contain extra args |         # note objdump-tool may contain extra args | ||||||
| @@ -39,16 +71,22 @@ def collect(paths, **args): | |||||||
|             errors='replace') |             errors='replace') | ||||||
|         for line in proc.stdout: |         for line in proc.stdout: | ||||||
|             # state machine here to find structs |             # state machine here to find structs | ||||||
|             m = pattern.match(line) |             m = struct_pattern.match(line) | ||||||
|             if m: |             if m: | ||||||
|                 if m.group('tag'): |                 if m.group('tag'): | ||||||
|                     if name is not None and size is not None: |                     if (name is not None | ||||||
|                         results[(path, name)] = size |                             and decl is not None | ||||||
|  |                             and size is not None): | ||||||
|  |                         decl_file, decl_dir = decls.get(decl, ('', 0)) | ||||||
|  |                         results[(path, name)] = (size, decl_file, decl_dir) | ||||||
|                     found = (m.group('tag') == 'structure_type') |                     found = (m.group('tag') == 'structure_type') | ||||||
|                     name = None |                     name = None | ||||||
|  |                     decl = None | ||||||
|                     size = None |                     size = None | ||||||
|                 elif found and m.group('name'): |                 elif found and m.group('name'): | ||||||
|                     name = m.group('name') |                     name = m.group('name') | ||||||
|  |                 elif found and name and m.group('decl'): | ||||||
|  |                     decl = int(m.group('decl')) | ||||||
|                 elif found and name and m.group('size'): |                 elif found and name and m.group('size'): | ||||||
|                     size = int(m.group('size')) |                     size = int(m.group('size')) | ||||||
|         proc.wait() |         proc.wait() | ||||||
| @@ -59,18 +97,25 @@ def collect(paths, **args): | |||||||
|             sys.exit(-1) |             sys.exit(-1) | ||||||
|  |  | ||||||
|     flat_results = [] |     flat_results = [] | ||||||
|     for (file, struct), size in results.items(): |     for (path, struct), (size, decl_file, decl_dir) in results.items(): | ||||||
|         # map to source files |         # map to source files | ||||||
|         if args.get('build_dir'): |         if args.get('build_dir'): | ||||||
|             file = re.sub('%s/*' % re.escape(args['build_dir']), '', file) |             path = re.sub('%s/*' % re.escape(args['build_dir']), '', path) | ||||||
|  |         # only include structs declared in header files in the current | ||||||
|  |         # directory, ignore internal-only # structs (these are represented | ||||||
|  |         # in other measurements) | ||||||
|  |         if not args.get('everything'): | ||||||
|  |             if not (decl_file.endswith('.h') and decl_dir == 0): | ||||||
|  |                 continue | ||||||
|         # replace .o with .c, different scripts report .o/.c, we need to |         # replace .o with .c, different scripts report .o/.c, we need to | ||||||
|         # choose one if we want to deduplicate csv files |         # choose one if we want to deduplicate csv files | ||||||
|         file = re.sub('\.o$', '.c', file) |         path = re.sub('\.o$', '.c', path) | ||||||
|  |  | ||||||
|         flat_results.append((file, struct, size)) |         flat_results.append((path, struct, size)) | ||||||
|  |  | ||||||
|     return flat_results |     return flat_results | ||||||
|  |  | ||||||
|  |  | ||||||
| def main(**args): | def main(**args): | ||||||
|     def openio(path, mode='r'): |     def openio(path, mode='r'): | ||||||
|         if path == '-': |         if path == '-': | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user