mirror of
https://github.com/isledecomp/isle.git
synced 2026-01-31 12:11:15 +00:00
Mark order-adjusted modules. Show library order.
This commit is contained in:
parent
769750a5f3
commit
45178f5591
@ -29,6 +29,7 @@ class ModuleMap:
|
|||||||
def __init__(self, pdb, binfile) -> None:
|
def __init__(self, pdb, binfile) -> None:
|
||||||
cvdump = Cvdump(pdb).section_contributions().modules().run()
|
cvdump = Cvdump(pdb).section_contributions().modules().run()
|
||||||
self.module_lookup = {m.id: (m.lib, m.obj) for m in cvdump.modules}
|
self.module_lookup = {m.id: (m.lib, m.obj) for m in cvdump.modules}
|
||||||
|
self.library_lookup = {m.obj: m.lib for m in cvdump.modules}
|
||||||
self.section_contrib = [
|
self.section_contrib = [
|
||||||
(
|
(
|
||||||
binfile.get_abs_addr(sizeref.section, sizeref.offset),
|
binfile.get_abs_addr(sizeref.section, sizeref.offset),
|
||||||
@ -39,6 +40,9 @@ def __init__(self, pdb, binfile) -> None:
|
|||||||
if binfile.is_valid_section(sizeref.section)
|
if binfile.is_valid_section(sizeref.section)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def get_lib_for_module(self, module: str) -> Optional[str]:
|
||||||
|
return self.library_lookup.get(module)
|
||||||
|
|
||||||
def get_all_cmake_modules(self) -> List[str]:
|
def get_all_cmake_modules(self) -> List[str]:
|
||||||
return [
|
return [
|
||||||
obj
|
obj
|
||||||
@ -77,6 +81,15 @@ def match_type_abbreviation(mtype: Optional[SymbolType]) -> str:
|
|||||||
return mtype.name.lower()[:3]
|
return mtype.name.lower()[:3]
|
||||||
|
|
||||||
|
|
||||||
|
def get_cmakefiles_prefix(module: str) -> str:
|
||||||
|
"""For the given .obj, get the "CMakeFiles/something.dir/" prefix.
|
||||||
|
For lack of a better option, this is the library for this module."""
|
||||||
|
if module.startswith("CMakeFiles"):
|
||||||
|
return "/".join(module.split("/", 2)[:2]) + "/"
|
||||||
|
|
||||||
|
return module
|
||||||
|
|
||||||
|
|
||||||
def truncate_module_name(prefix: str, module: str) -> str:
|
def truncate_module_name(prefix: str, module: str) -> str:
|
||||||
"""Remove the CMakeFiles prefix and the .obj suffix for the given module.
|
"""Remove the CMakeFiles prefix and the .obj suffix for the given module.
|
||||||
Input: CMakeFiles/lego1.dir/, CMakeFiles/lego1.dir/LEGO1/define.cpp.obj
|
Input: CMakeFiles/lego1.dir/, CMakeFiles/lego1.dir/LEGO1/define.cpp.obj
|
||||||
@ -173,27 +186,33 @@ def iter_sorted(self) -> Iterator[Tuple[int, int]]:
|
|||||||
yield (avg, mod)
|
yield (avg, mod)
|
||||||
|
|
||||||
|
|
||||||
def suggest_order(results: List[RoadmapRow], cmake_modules: List[str], match_type: str):
|
def suggest_order(results: List[RoadmapRow], module_map: ModuleMap, match_type: str):
|
||||||
"""Suggest the order of modules for CMakeLists.txt"""
|
"""Suggest the order of modules for CMakeLists.txt"""
|
||||||
|
|
||||||
dc = DeltaCollector(match_type)
|
dc = DeltaCollector(match_type)
|
||||||
for row in results:
|
for row in results:
|
||||||
dc.read_row(row)
|
dc.read_row(row)
|
||||||
|
|
||||||
leftover_modules = set(cmake_modules)
|
# First, show the order of .obj files for the "CMake Modules"
|
||||||
|
# Meaning: the modules where the .obj file begins with "CMakeFiles".
|
||||||
|
# These are the libraries where we directly control the order.
|
||||||
|
# The library name (from cvdump) doesn't make it obvious that these are
|
||||||
|
# our libraries so we derive the name based on the CMakeFiles prefix.
|
||||||
|
leftover_modules = set(module_map.get_all_cmake_modules())
|
||||||
|
|
||||||
# A little convoluted, but we want to take the first two tokens
|
# A little convoluted, but we want to take the first two tokens
|
||||||
# of the string with '/' as the delimiter.
|
# of the string with '/' as the delimiter.
|
||||||
# i.e. CMakeFiles/isle.dir/
|
# i.e. CMakeFiles/isle.dir/
|
||||||
# The idea is to print exactly what appears in CMakeLists.txt.
|
# The idea is to print exactly what appears in CMakeLists.txt.
|
||||||
cmake_prefixes = sorted(
|
cmake_prefixes = sorted(set(get_cmakefiles_prefix(mod) for mod in leftover_modules))
|
||||||
set("/".join(mod.split("/", 2)[:2]) + "/" for mod in leftover_modules)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
# Save this off because we'll use it again later.
|
||||||
computed_order = list(dc.iter_sorted())
|
computed_order = list(dc.iter_sorted())
|
||||||
|
|
||||||
for prefix in cmake_prefixes:
|
for prefix in cmake_prefixes:
|
||||||
print(prefix)
|
print(prefix)
|
||||||
|
|
||||||
|
last_earliest = 0
|
||||||
# Show modules ordered by the computed average of addresses
|
# Show modules ordered by the computed average of addresses
|
||||||
for _, module in computed_order:
|
for _, module in computed_order:
|
||||||
if not module.startswith(prefix):
|
if not module.startswith(prefix):
|
||||||
@ -206,16 +225,22 @@ def suggest_order(results: List[RoadmapRow], cmake_modules: List[str], match_typ
|
|||||||
if displacements is not None and len(displacements) > 0:
|
if displacements is not None and len(displacements) > 0:
|
||||||
avg_displacement = int(statistics.mean(displacements))
|
avg_displacement = int(statistics.mean(displacements))
|
||||||
|
|
||||||
|
# Call attention to any modules where ordering by earliest
|
||||||
|
# address is different from the computed order we display.
|
||||||
earliest = dc.earliest.get(module)
|
earliest = dc.earliest.get(module)
|
||||||
|
ooo_mark = "*" if earliest < last_earliest else " "
|
||||||
|
last_earliest = earliest
|
||||||
|
|
||||||
code_file = truncate_module_name(prefix, module)
|
code_file = truncate_module_name(prefix, module)
|
||||||
print(f"0x{earliest:08x} {avg_displacement:10} {code_file}")
|
print(f"0x{earliest:08x}{ooo_mark} {avg_displacement:10} {code_file}")
|
||||||
|
|
||||||
# These modules are included in the final binary (in some form) but
|
# These modules are included in the final binary (in some form) but
|
||||||
# they are not represented by whichever type of symbol we were checking.
|
# don't contribute any symbols of the type we are checking.
|
||||||
# n.b. There could still be other modules that are part of CMakeLists.txt
|
# n.b. There could still be other modules that are part of
|
||||||
# but are not included in the pdb for whatever reason.
|
# CMakeLists.txt but are not included in the pdb for whatever reason.
|
||||||
# In other words: don't take the list we provide as the final word on what
|
# In other words: don't take the list we provide as the final word on
|
||||||
# should or should not be included. This is merely a suggestion of the order.
|
# what should or should not be included.
|
||||||
|
# This is merely a suggestion of the order.
|
||||||
for module in leftover_modules:
|
for module in leftover_modules:
|
||||||
if not module.startswith(prefix):
|
if not module.startswith(prefix):
|
||||||
continue
|
continue
|
||||||
@ -226,6 +251,25 @@ def suggest_order(results: List[RoadmapRow], cmake_modules: List[str], match_typ
|
|||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
# Now display the order of all libaries in the final file.
|
||||||
|
library_order = {}
|
||||||
|
|
||||||
|
for module, start in dc.earliest.items():
|
||||||
|
lib = module_map.get_lib_for_module(module)
|
||||||
|
if lib is None:
|
||||||
|
lib = get_cmakefiles_prefix(module)
|
||||||
|
|
||||||
|
if start < library_order.get(lib, 0xFFFFFFFFF):
|
||||||
|
library_order[lib] = start
|
||||||
|
|
||||||
|
print("Library order (average address shown):")
|
||||||
|
for lib, start in sorted(library_order.items(), key=lambda x: x[1]):
|
||||||
|
# Strip off any OS path for brevity
|
||||||
|
if not lib.startswith("CMakeFiles"):
|
||||||
|
lib = os.path.basename(lib)
|
||||||
|
|
||||||
|
print(f"{lib:40} {start:08x}")
|
||||||
|
|
||||||
|
|
||||||
def print_text_report(results: List[RoadmapRow]):
|
def print_text_report(results: List[RoadmapRow]):
|
||||||
"""Print the result with original and recomp addresses."""
|
"""Print the result with original and recomp addresses."""
|
||||||
@ -398,7 +442,7 @@ def to_roadmap_row(match):
|
|||||||
results = list(map(to_roadmap_row, engine.get_all()))
|
results = list(map(to_roadmap_row, engine.get_all()))
|
||||||
|
|
||||||
if args.order is not None:
|
if args.order is not None:
|
||||||
suggest_order(results, module_map.get_all_cmake_modules(), args.order)
|
suggest_order(results, module_map, args.order)
|
||||||
return
|
return
|
||||||
|
|
||||||
if args.csv is None:
|
if args.csv is None:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user