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'] | ||||
|  | ||||
| def collect(paths, **args): | ||||
|     results = co.defaultdict(lambda: 0) | ||||
|     pattern = re.compile( | ||||
|     decl_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_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*)$') | ||||
|  | ||||
|     results = co.defaultdict(lambda: 0) | ||||
|     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 | ||||
|         found = False | ||||
|         name = None | ||||
|         decl = None | ||||
|         size = None | ||||
|  | ||||
|         # note objdump-tool may contain extra args | ||||
| @@ -39,16 +71,22 @@ def collect(paths, **args): | ||||
|             errors='replace') | ||||
|         for line in proc.stdout: | ||||
|             # state machine here to find structs | ||||
|             m = pattern.match(line) | ||||
|             m = struct_pattern.match(line) | ||||
|             if m: | ||||
|                 if m.group('tag'): | ||||
|                     if name is not None and size is not None: | ||||
|                         results[(path, name)] = size | ||||
|                     if (name is not None | ||||
|                             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') | ||||
|                     name = None | ||||
|                     decl = None | ||||
|                     size = None | ||||
|                 elif found and 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'): | ||||
|                     size = int(m.group('size')) | ||||
|         proc.wait() | ||||
| @@ -59,18 +97,25 @@ def collect(paths, **args): | ||||
|             sys.exit(-1) | ||||
|  | ||||
|     flat_results = [] | ||||
|     for (file, struct), size in results.items(): | ||||
|     for (path, struct), (size, decl_file, decl_dir) in results.items(): | ||||
|         # map to source files | ||||
|         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 | ||||
|         # 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 | ||||
|  | ||||
|  | ||||
| def main(**args): | ||||
|     def openio(path, mode='r'): | ||||
|         if path == '-': | ||||
|   | ||||
		Reference in New Issue
	
	Block a user