mirror of
https://github.com/openXC7/prjxray.git
synced 2026-08-30 17:52:08 +02:00
The temporary bits file was created with NamedTemporaryFile() and kept open while the bitread subprocess wrote to it by name. On Windows that is a sharing violation (the open handle blocks the child's write), so bit2fasm always failed there. Create the file with delete=False, close it immediately, and unlink it via the ExitStack instead. No behaviour change on POSIX beyond the file being closed while bitread runs.
133 lines
4.1 KiB
Python
Executable File
133 lines
4.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright (C) 2017-2020 The Project X-Ray Authors.
|
|
#
|
|
# Use of this source code is governed by a ISC-style
|
|
# license that can be found in the LICENSE file or at
|
|
# https://opensource.org/licenses/ISC
|
|
#
|
|
# SPDX-License-Identifier: ISC
|
|
'''
|
|
Take bitstream .bit files and decode them to FASM.
|
|
'''
|
|
|
|
import contextlib
|
|
import os
|
|
import fasm
|
|
import fasm.output
|
|
from prjxray import fasm_disassembler
|
|
from prjxray import bitstream
|
|
from prjxray.db import Database
|
|
from prjxray.util import OpenSafeFile
|
|
import subprocess
|
|
import tempfile
|
|
|
|
|
|
def bit_to_bits(bitread, part_yaml, bit_file, bits_file, frame_range=None):
|
|
""" Calls bitread to create bits (ASCII) from bit file (binary) """
|
|
if frame_range:
|
|
frame_range_arg = '-F {}'.format(frame_range)
|
|
else:
|
|
frame_range_arg = ''
|
|
|
|
subprocess.check_output(
|
|
'{} --part_file {} {} -o {} -z -y {}'.format(
|
|
bitread, part_yaml, frame_range_arg, bits_file, bit_file),
|
|
shell=True)
|
|
|
|
|
|
def bits_to_fasm(db_root, part, bits_file, verbose, canonical):
|
|
db = Database(db_root, part)
|
|
grid = db.grid()
|
|
disassembler = fasm_disassembler.FasmDisassembler(db)
|
|
|
|
with OpenSafeFile(bits_file) as f:
|
|
bitdata = bitstream.load_bitdata(f)
|
|
|
|
model = fasm.output.merge_and_sort(
|
|
disassembler.find_features_in_bitstream(bitdata, verbose=verbose),
|
|
zero_function=disassembler.is_zero_feature,
|
|
sort_key=grid.tile_key,
|
|
)
|
|
|
|
print(fasm.fasm_tuple_to_string(model, canonical=canonical), end='')
|
|
|
|
|
|
def main():
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(
|
|
description='Convert 7-series bit file to FASM.')
|
|
|
|
database_dir = os.getenv("XRAY_DATABASE_DIR")
|
|
database = os.getenv("XRAY_DATABASE")
|
|
db_root_kwargs = {}
|
|
if database_dir is None or database is None:
|
|
db_root_kwargs['required'] = True
|
|
else:
|
|
db_root_kwargs['required'] = False
|
|
db_root_kwargs['default'] = os.path.join(database_dir, database)
|
|
|
|
default_part = os.getenv("XRAY_PART")
|
|
part_kwargs = {}
|
|
if default_part is None:
|
|
part_kwargs['required'] = True
|
|
else:
|
|
part_kwargs['required'] = False
|
|
part_kwargs['default'] = default_part
|
|
|
|
if os.getenv("XRAY_TOOLS_DIR") is None:
|
|
default_bitread = 'bitread'
|
|
else:
|
|
default_bitread = os.path.join(os.getenv("XRAY_TOOLS_DIR"), 'bitread')
|
|
|
|
parser.add_argument('--db-root', help="Database root.", **db_root_kwargs)
|
|
parser.add_argument(
|
|
'--bits-file',
|
|
help="Output filename for bitread output, default is deleted tempfile.",
|
|
default=None)
|
|
parser.add_argument(
|
|
'--part', help="Name of part being targetted.", **part_kwargs)
|
|
parser.add_argument(
|
|
'--bitread',
|
|
help="bitread tool to to use",
|
|
default=default_bitread)
|
|
parser.add_argument(
|
|
'--frame_range', help="Frame range to use with bitread.")
|
|
parser.add_argument('bit_file', help='')
|
|
parser.add_argument(
|
|
'--verbose',
|
|
help='Print lines for unknown tiles and bits',
|
|
action='store_true')
|
|
parser.add_argument(
|
|
'--canonical', help='Output canonical bitstream.', action='store_true')
|
|
args = parser.parse_args()
|
|
|
|
with contextlib.ExitStack() as stack:
|
|
if args.bits_file:
|
|
bits_file = stack.enter_context(open(args.bits_file, 'wb'))
|
|
else:
|
|
# On Windows an open NamedTemporaryFile cannot be re-opened by
|
|
# the bitread subprocess (sharing violation): create it closed
|
|
# and clean it up ourselves.
|
|
bits_file = tempfile.NamedTemporaryFile(delete=False)
|
|
bits_file.close()
|
|
stack.callback(os.unlink, bits_file.name)
|
|
|
|
bit_to_bits(
|
|
bitread=args.bitread,
|
|
part_yaml=os.path.join(args.db_root, args.part, "part.yaml"),
|
|
bit_file=args.bit_file,
|
|
bits_file=bits_file.name,
|
|
frame_range=args.frame_range,
|
|
)
|
|
|
|
bits_to_fasm(
|
|
args.db_root, args.part, bits_file.name, args.verbose,
|
|
args.canonical)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|