def include_heuristics(filename, platform, error): """Try to find missing includes from error message.""" include = None msg = str(error) if "before: " in msg: key = msg.rsplit("before: ", 1)[1].strip() include = cparser.StructVisitor.all_known_types.get(key, None) if include is None: return False, None # Problem with typedef, TODO: improve this error handling if filename == include: return False, None new_error = create_dissector(filename, platform, folders, [include]) if new_error != error: FileConfig.add_include(filename, include) if new_error is None: return True, None # Worked return False, new_error # Try more return False, None # Give up
def include_heuristics(filename, platform, error): """Try to find missing includes from error message.""" include = None msg = str(error) if 'before: ' in msg: key = msg.rsplit('before: ', 1)[1].strip() include = cparser.StructVisitor.all_known_types.get(key, None) if include is None: return False, None # Problem with typedef, TODO: improve this error handling if filename == include: return False, None new_error = create_dissector(filename, platform, folders, [include]) if new_error != error: FileConfig.add_include(filename, include) if new_error is None: return True, None # Worked return False, new_error # Try more return False, None # Give up
def parse_headers(headers): """Parse 'headers' to create a Wireshark protocol dissector.""" folders = {os.path.dirname(i) for i in headers} # Folders to -Include failed = [] # Filenames, platforms pairs we have failed to parse so far def include_heuristics(filename, platform, error): """Try to find missing includes from error message.""" include = None msg = str(error) if "before: " in msg: key = msg.rsplit("before: ", 1)[1].strip() include = cparser.StructVisitor.all_known_types.get(key, None) if include is None: return False, None # Problem with typedef, TODO: improve this error handling if filename == include: return False, None new_error = create_dissector(filename, platform, folders, [include]) if new_error != error: FileConfig.add_include(filename, include) if new_error is None: return True, None # Worked return False, new_error # Try more return False, None # Give up def print_status(tries=[]): """Print a status message with how many headers failed to parse.""" if tries and tries[-1] == 0: return tries.append(len({i for i, j, k in failed})) if tries[-1] == 0: msg = "Successfully parsed all %i" % len(headers) else: msg = "Failed to parse %i out of %i" % (tries[-1], len(headers)) print("[%i] %s header files" % (len(tries), msg)) def filenames_have_shared_path(f1, f2): p1 = os.path.dirname(f1) p2 = os.path.dirname(f2) c = os.path.commonprefix([p1, p2]) return c == p1 or c == p2 print("[0] Attempting to parse %i header files" % len(headers)) # First try, in the order given through the CLI for filename in headers: for platform in Options.platforms: error = create_dissector(filename, platform, folders) if error is not None: failed.append([filename, platform, error]) print_status() # Try to include files based on decoding the error messages work_list = failed[:] for tmp in range(2, 4): for i in reversed(range(len(work_list))): status, new_error = include_heuristics(*work_list[i]) if not status and new_error is not None: work_list[i][2] = new_error else: if status: failed.remove(work_list[i]) work_list.pop(i) print_status() # Try to include all who worked as it might help failed_names = [filename for filename, platform, error in failed] includes = [f for f in headers if f not in failed_names and filenames_have_shared_path(filename, f)] for i in reversed(range(len(failed))): filename, platform, tmp = failed.pop(i) error = create_dissector(filename, platform, folders, includes) if error is None: # Worked, record it in case anyone else needs this file for inc in includes: FileConfig.add_include(filename, inc) includes.append(filename) else: failed.append([filename, platform, error]) print_status() # Try to include files based on decoding the error messages work_list = failed[:] for tmp in range(5, 7): for i in reversed(range(len(work_list))): status, new_error = include_heuristics(*work_list[i]) if not status and new_error is not None: work_list[i][2] = new_error else: if status: failed.remove(work_list[i]) work_list.pop(i) print_status() # Give up! for filename, platform, error in failed: print('Skipped "%s":%s as it raised %s' % (filename, platform.name, repr(error))) return len({i for i, j, k in failed})
def parse_headers(headers): """Parse 'headers' to create a Wireshark protocol dissector.""" folders = {os.path.dirname(i) for i in headers} # Folders to -Include failed = [] # Filenames, platforms pairs we have failed to parse so far def include_heuristics(filename, platform, error): """Try to find missing includes from error message.""" include = None msg = str(error) if 'before: ' in msg: key = msg.rsplit('before: ', 1)[1].strip() include = cparser.StructVisitor.all_known_types.get(key, None) if include is None: return False, None # Problem with typedef, TODO: improve this error handling if filename == include: return False, None new_error = create_dissector(filename, platform, folders, [include]) if new_error != error: FileConfig.add_include(filename, include) if new_error is None: return True, None # Worked return False, new_error # Try more return False, None # Give up def print_status(tries=[]): """Print a status message with how many headers failed to parse.""" if tries and tries[-1] == 0: return tries.append(len({i for i, j, k in failed})) if tries[-1] == 0: msg = 'Successfully parsed all %i' % len(headers) else: msg = 'Failed to parse %i out of %i' % (tries[-1], len(headers)) print('[%i] %s header files' % (len(tries), msg)) def filenames_have_shared_path(f1, f2): p1 = os.path.dirname(f1) p2 = os.path.dirname(f2) c = os.path.commonprefix([p1, p2]) return c == p1 or c == p2 print('[0] Attempting to parse %i header files' % len(headers)) # First try, in the order given through the CLI for filename in headers: for platform in Options.platforms: error = create_dissector(filename, platform, folders) if error is not None: failed.append([filename, platform, error]) print_status() # Try to include files based on decoding the error messages work_list = failed[:] for tmp in range(2, 4): for i in reversed(range(len(work_list))): status, new_error = include_heuristics(*work_list[i]) if not status and new_error is not None: work_list[i][2] = new_error else: if status: failed.remove(work_list[i]) work_list.pop(i) print_status() # Try to include all who worked as it might help failed_names = [filename for filename, platform, error in failed] includes = [ f for f in headers if f not in failed_names and filenames_have_shared_path(filename, f) ] for i in reversed(range(len(failed))): filename, platform, tmp = failed.pop(i) error = create_dissector(filename, platform, folders, includes) if error is None: # Worked, record it in case anyone else needs this file for inc in includes: FileConfig.add_include(filename, inc) includes.append(filename) else: failed.append([filename, platform, error]) print_status() # Try to include files based on decoding the error messages work_list = failed[:] for tmp in range(5, 7): for i in reversed(range(len(work_list))): status, new_error = include_heuristics(*work_list[i]) if not status and new_error is not None: work_list[i][2] = new_error else: if status: failed.remove(work_list[i]) work_list.pop(i) print_status() # Give up! for filename, platform, error in failed: print('Skipped "%s":%s as it raised %s' % (filename, platform.name, repr(error))) return len({i for i, j, k in failed})