-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathgen_lcf.py
85 lines (74 loc) · 2.54 KB
/
gen_lcf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import argparse
import jinja2
from pathlib import Path, PurePosixPath, PureWindowsPath
import re
import sys
from elftools.elf.elffile import ELFFile
from mkwutil.lib.slices import SliceTable
from mkwutil.sections import DOL_SECTIONS, REL_SECTIONS
MATCH_UNK = re.compile(r"^unk_([0-9a-f]{8})$")
# LCF must use forward slashes on linux/osx
def format_path(p):
if sys.platform == "win32" or sys.platform == "msys":
return str(PureWindowsPath(p))
return f'"{PurePosixPath(p)}"'
def gen_lcf(
src: Path,
dst: Path,
object_paths: list[Path],
slices_path: Path,
):
"""Generates the LCF."""
# Read slices.
slices = SliceTable.load_path(slices_path)
slices = slices.filter(SliceTable.ONLY_ENABLED)
# For dol and rel, we can also fill in section names.
if slices_path.name == "dol_slices.yml":
slices.set_sections(DOL_SECTIONS)
elif slices_path.name == "rel_slices.yml":
slices.set_sections(REL_SECTIONS)
else:
print(f"WARN: Using linker-defined symbols instead of inline assembly")
# Search for stripped objects.
stripped = set()
for _slice in slices:
if _slice.has_name() and "strip" in _slice.tags:
stripped.add(Path(_slice.name).stem)
# Create list of FORCEFILES.
force_files = []
for obj_path in object_paths:
if obj_path.stem in stripped:
continue
force_files.append(format_path(obj_path.parent / (obj_path.stem + ".o")))
# Compile template.
template = jinja2.Template(src.read_text())
# Render template to string.
lcf = template.render({"force_files": force_files})
# Write out to final LCF.
with open(dst, "w") as f:
f.write(lcf)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"--base", type=Path, required=True, help="Path to base linker script"
)
parser.add_argument(
"--out", type=Path, required=True, help="Path to linker script output"
)
parser.add_argument("--objs", type=Path, required=True, help="Path to objects list")
parser.add_argument(
"--prefix",
type=Path,
default="",
help="Dir prefix for references in linker script",
)
parser.add_argument(
"--slices", type=Path, required=True, help="Path to slices file"
)
args = parser.parse_args()
# Read list of objects.
objs = []
with open(args.objs, "r") as file:
for line in file:
objs.append(args.prefix / Path(line))
gen_lcf(args.base, args.out, objs, args.slices)