scripts: build: Add support for generating string literals in file2hex.py

Currently, file2hex.py supports conversion of binary data into hexadecimal
character list format only. The generated list can then be used to embed
the binary data by using the list to initialize an array. However, this
approach is highly inefficient for large binary files.

A close but considerably more efficient alternative is to use string
literals composed of hex characters (in escaped form) to initialize the
array, instead of an initializer list. Benchmarking (with GCC and clang)
indicates that compile time and host memory usage by the compiler can be
more than an order of magnitude less with string literal approach compared
to the initializer list form.

The only caveat is that string literals contain the null character as
terminator so where accurate length is required, the correct length must
be specified explicitly while defining the array.

Signed-off-by: Irfan Ahmad <irfan.ahmad@siemens.com>
This commit is contained in:
Irfan Ahmad 2025-01-17 02:47:43 +05:00 committed by Benjamin Cabé
commit f3d513da09

View file

@ -1,6 +1,7 @@
#!/usr/bin/env python3
#
# Copyright (c) 2017 Intel Corporation
# Copyright (c) 2025 Siemens AG
#
# SPDX-License-Identifier: Apache-2.0
@ -31,6 +32,8 @@ def parse_args():
parser.add_argument("-l", "--length", type=lambda x: int(x, 0), default=-1,
help="""Length in bytes to read from the input file.
Defaults to reading till the end of the input file.""")
parser.add_argument("-m", "--format", default="list",
help="Output format: 'list' (default) or 'literal' (string literal)")
parser.add_argument("-g", "--gzip", action="store_true",
help="Compress the file using gzip before output")
parser.add_argument("-t", "--gzip-mtime", type=int, default=0,
@ -56,6 +59,12 @@ def make_hex(chunk):
print(get_nice_string(hexlist) + ',')
def make_string_literal(chunk):
hexdata = codecs.encode(chunk, 'hex').decode("utf-8")
hexlist = map(''.join, zip(*[iter(hexdata)] * 2))
print(''.join("\\x" + str(x) for x in hexlist), end='')
def main():
parse_args()
@ -74,6 +83,22 @@ def main():
else:
with open(args.file, "rb") as fp:
fp.seek(args.offset)
if args.format == "literal":
if args.length < 0:
print('"', end='')
for chunk in iter(lambda: fp.read(1024), b''):
make_string_literal(chunk)
print('"', end='')
else:
print('"', end='')
remainder = args.length
for chunk in iter(lambda: fp.read(min(1024, remainder)), b''):
make_string_literal(chunk)
remainder = remainder - len(chunk)
print('"', end='')
else:
if args.length < 0:
for chunk in iter(lambda: fp.read(1024), b''):
make_hex(chunk)