Rupert Swarbrick | 4a50004 | 2020-07-20 15:39:16 +0100 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # Copyright lowRISC contributors. |
| 3 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 4 | # SPDX-License-Identifier: Apache-2.0 |
Rupert Swarbrick | 4a50004 | 2020-07-20 15:39:16 +0100 | [diff] [blame] | 5 | '''A wrapper around riscv32-unknown-elf-ld for OTBN |
| 6 | |
| 7 | This just adds the OTBN linker script and calls the underlying |
| 8 | linker.''' |
| 9 | |
| 10 | import os |
| 11 | import subprocess |
| 12 | import sys |
Rupert Swarbrick | b238135 | 2020-07-24 15:55:04 +0100 | [diff] [blame] | 13 | import tempfile |
Timothy Trippel | a7b30e6 | 2022-04-20 16:26:09 -0700 | [diff] [blame] | 14 | from contextlib import contextmanager |
Rupert Swarbrick | 0d0b2dc | 2020-08-17 17:35:22 +0100 | [diff] [blame] | 15 | from typing import Iterator, List, Optional |
Rupert Swarbrick | b238135 | 2020-07-24 15:55:04 +0100 | [diff] [blame] | 16 | |
Rupert Swarbrick | b238135 | 2020-07-24 15:55:04 +0100 | [diff] [blame] | 17 | from mako import exceptions # type: ignore |
Timothy Trippel | a7b30e6 | 2022-04-20 16:26:09 -0700 | [diff] [blame] | 18 | from mako.template import Template # type: ignore |
Rupert Swarbrick | b238135 | 2020-07-24 15:55:04 +0100 | [diff] [blame] | 19 | |
Rupert Swarbrick | b1ed9a9 | 2020-08-03 17:01:26 +0100 | [diff] [blame] | 20 | from shared.mem_layout import get_memory_layout |
Rupert Swarbrick | 823343f | 2020-08-17 14:43:59 +0100 | [diff] [blame] | 21 | from shared.toolchain import find_tool |
Rupert Swarbrick | b238135 | 2020-07-24 15:55:04 +0100 | [diff] [blame] | 22 | |
| 23 | |
| 24 | def interpolate_linker_script(in_path: str, out_path: str) -> None: |
Rupert Swarbrick | b1ed9a9 | 2020-08-03 17:01:26 +0100 | [diff] [blame] | 25 | mems = get_memory_layout() |
Rupert Swarbrick | 9535680 | 2021-10-26 13:12:31 +0100 | [diff] [blame] | 26 | imem_lma, imem_length = mems['IMEM'] |
| 27 | dmem_lma, dmem_bus_length = mems['DMEM'] |
| 28 | |
| 29 | dmem_length = dmem_bus_length * 2 |
Rupert Swarbrick | b238135 | 2020-07-24 15:55:04 +0100 | [diff] [blame] | 30 | |
| 31 | try: |
| 32 | template = Template(filename=in_path) |
Rupert Swarbrick | 9535680 | 2021-10-26 13:12:31 +0100 | [diff] [blame] | 33 | rendered = template.render(imem_lma=imem_lma, |
| 34 | imem_length=imem_length, |
| 35 | dmem_lma=dmem_lma, |
| 36 | dmem_length=dmem_length, |
| 37 | dmem_bus_length=dmem_bus_length) |
Rupert Swarbrick | b238135 | 2020-07-24 15:55:04 +0100 | [diff] [blame] | 38 | except OSError as err: |
| 39 | raise RuntimeError(str(err)) from None |
| 40 | except: # noqa: 722 |
| 41 | raise RuntimeError(exceptions.text_error_template().render()) from None |
| 42 | |
| 43 | try: |
| 44 | with open(out_path, 'w') as out_file: |
| 45 | out_file.write(rendered) |
| 46 | except FileNotFoundError: |
Timothy Trippel | a7b30e6 | 2022-04-20 16:26:09 -0700 | [diff] [blame] | 47 | raise RuntimeError( |
| 48 | 'Failed to open output file at {!r}.'.format(out_path)) from None |
Rupert Swarbrick | 4a50004 | 2020-07-20 15:39:16 +0100 | [diff] [blame] | 49 | |
| 50 | |
Rupert Swarbrick | 0d0b2dc | 2020-08-17 17:35:22 +0100 | [diff] [blame] | 51 | @contextmanager |
| 52 | def mk_linker_script() -> Iterator[str]: |
Timothy Trippel | a7b30e6 | 2022-04-20 16:26:09 -0700 | [diff] [blame] | 53 | ld_in = os.path.abspath( |
| 54 | os.path.join(os.path.dirname(__file__), '..', 'data', 'otbn.ld.tpl')) |
Rupert Swarbrick | b238135 | 2020-07-24 15:55:04 +0100 | [diff] [blame] | 55 | with tempfile.TemporaryDirectory(prefix='otbn-ld-') as tmpdir: |
| 56 | ld_out = os.path.join(tmpdir, 'otbn.ld') |
| 57 | try: |
| 58 | interpolate_linker_script(ld_in, ld_out) |
| 59 | except RuntimeError as err: |
Timothy Trippel | a7b30e6 | 2022-04-20 16:26:09 -0700 | [diff] [blame] | 60 | sys.stderr.write( |
| 61 | 'Failed to interpolate linker script: {}\n'.format(err)) |
Rupert Swarbrick | b238135 | 2020-07-24 15:55:04 +0100 | [diff] [blame] | 62 | return 1 |
| 63 | |
Rupert Swarbrick | 0d0b2dc | 2020-08-17 17:35:22 +0100 | [diff] [blame] | 64 | yield ld_out |
| 65 | |
| 66 | |
| 67 | def run_ld(ld_script: Optional[str], args: List[str]) -> int: |
| 68 | '''Run the underlying linker and return the status code''' |
Rupert Swarbrick | 823343f | 2020-08-17 14:43:59 +0100 | [diff] [blame] | 69 | ld_name = find_tool('ld') |
Rupert Swarbrick | c02c22e | 2020-11-18 08:02:45 +0000 | [diff] [blame] | 70 | # The --no-check-sections argument tells ld not to complain when we have |
| 71 | # more than one section with the same VMA. Since we have a Harvard |
| 72 | # architecture where data and instructions both start at zero, we expect |
| 73 | # that to happen. |
| 74 | cmd = [ld_name, '--no-check-sections'] |
Rupert Swarbrick | 0d0b2dc | 2020-08-17 17:35:22 +0100 | [diff] [blame] | 75 | if ld_script is not None: |
| 76 | cmd.append('--script={}'.format(ld_script)) |
| 77 | cmd += args |
| 78 | |
| 79 | try: |
| 80 | return subprocess.run(cmd).returncode |
| 81 | except FileNotFoundError: |
Timothy Trippel | a7b30e6 | 2022-04-20 16:26:09 -0700 | [diff] [blame] | 82 | sys.stderr.write( |
| 83 | 'Unknown command: {!r}. ' |
| 84 | '(is it installed and on your PATH?)\n'.format(ld_name)) |
Rupert Swarbrick | 0d0b2dc | 2020-08-17 17:35:22 +0100 | [diff] [blame] | 85 | return 127 |
| 86 | |
| 87 | |
Timothy Trippel | a7b30e6 | 2022-04-20 16:26:09 -0700 | [diff] [blame] | 88 | def main(argv: List[str]) -> int: |
Rupert Swarbrick | 0d0b2dc | 2020-08-17 17:35:22 +0100 | [diff] [blame] | 89 | # Only add the --script argument if the caller isn't supplying one |
| 90 | # themselves. This argument accumulates (so -T foo -T bar is like |
| 91 | # concatenating foo and bar), so we mustn't supply our own if the user |
| 92 | # has one. |
| 93 | needs_script = True |
Timothy Trippel | a7b30e6 | 2022-04-20 16:26:09 -0700 | [diff] [blame] | 94 | for arg in argv[1:]: |
Rupert Swarbrick | 0d0b2dc | 2020-08-17 17:35:22 +0100 | [diff] [blame] | 95 | if arg == '-T' or arg.startswith('--script='): |
| 96 | needs_script = False |
| 97 | break |
| 98 | |
| 99 | if needs_script: |
| 100 | with mk_linker_script() as script_path: |
Timothy Trippel | a7b30e6 | 2022-04-20 16:26:09 -0700 | [diff] [blame] | 101 | return run_ld(script_path, argv[1:]) |
Rupert Swarbrick | 0d0b2dc | 2020-08-17 17:35:22 +0100 | [diff] [blame] | 102 | else: |
Timothy Trippel | a7b30e6 | 2022-04-20 16:26:09 -0700 | [diff] [blame] | 103 | return run_ld(None, argv[1:]) |
Rupert Swarbrick | 4a50004 | 2020-07-20 15:39:16 +0100 | [diff] [blame] | 104 | |
| 105 | |
| 106 | if __name__ == '__main__': |
Timothy Trippel | a7b30e6 | 2022-04-20 16:26:09 -0700 | [diff] [blame] | 107 | sys.exit(main(sys.argv)) |