Skip to content

Commit 6033ed3

Browse files
authored
Use subprocess.run in elf2bin (#8799)
Properly handle Popen object, it takes care of everything we need to do like .communicate() and handle timeouts. Introduce a small timeout to run so we also know when that happens Clean-up with pythonic path join and formatting through f"" strings
1 parent 39080e3 commit 6033ed3

File tree

1 file changed

+65
-20
lines changed

1 file changed

+65
-20
lines changed

tools/elf2bin.py

+65-20
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from __future__ import print_function
2222
import argparse
23+
import io
2324
import re
2425
import os
2526
import subprocess
@@ -33,37 +34,75 @@
3334
crcsize_offset = 4096 + 16
3435
crcval_offset = 4096 + 16 + 4
3536

37+
38+
class Elf2BinException(Exception):
39+
pass
40+
41+
3642
def get_elf_entry(elf, path):
37-
p = subprocess.Popen([path + "/xtensa-lx106-elf-readelf", '-h', elf], stdout=subprocess.PIPE, universal_newlines=True )
38-
lines = p.stdout.readlines()
39-
for line in lines:
43+
result = subprocess.run(
44+
[os.path.join(path, "xtensa-lx106-elf-readelf"), "-h", elf],
45+
check=True,
46+
timeout=15,
47+
stdout=subprocess.PIPE,
48+
universal_newlines=True,
49+
)
50+
51+
lines = io.StringIO(result.stdout)
52+
for line in lines.readlines():
4053
if 'Entry point address' in line:
4154
words = re.split('\s+', line)
4255
entry_point = words[-2]
4356
return int(entry_point, 16)
44-
raise Exception('Unable to find entry point in file "' + elf + '"')
57+
58+
raise Elf2BinException(f'Unable to find entry point in file "{elf}"')
59+
4560

4661
def get_segment_size_addr(elf, segment, path):
47-
p = subprocess.Popen([path + '/xtensa-lx106-elf-objdump', '-h', '-j', segment, elf], stdout=subprocess.PIPE, universal_newlines=True )
48-
lines = p.stdout.readlines()
49-
for line in lines:
62+
result = subprocess.run(
63+
[os.path.join(path, "xtensa-lx106-elf-objdump"), "-h", "-j", segment, elf],
64+
check=True,
65+
timeout=15,
66+
stdout=subprocess.PIPE,
67+
universal_newlines=True,
68+
)
69+
70+
lines = io.StringIO(result.stdout)
71+
for line in lines.readlines():
5072
if segment in line:
5173
words = re.split('\s+', line)
5274
size = int(words[3], 16)
5375
addr = int(words[4], 16)
5476
return [ size, addr ]
55-
raise Exception('Unable to find size and start point in file "' + elf + '" for "' + segment + '"')
77+
78+
raise Elf2BinException(
79+
f'Unable to find size and start point in file "{elf}" for "{segment}"'
80+
)
81+
5682

5783
def read_segment(elf, segment, path):
5884
fd, tmpfile = tempfile.mkstemp()
5985
os.close(fd)
60-
subprocess.check_call([path + "/xtensa-lx106-elf-objcopy", '-O', 'binary', '--only-section=' + segment, elf, tmpfile], stdout=subprocess.PIPE)
61-
with open(tmpfile, "rb") as f:
62-
raw = f.read()
63-
os.remove(tmpfile)
86+
try:
87+
subprocess.check_call(
88+
[
89+
os.path.join(path, "xtensa-lx106-elf-objcopy"),
90+
"-O",
91+
"binary",
92+
f"--only-section={segment}",
93+
elf,
94+
tmpfile,
95+
],
96+
stdout=subprocess.PIPE,
97+
)
98+
with open(tmpfile, "rb") as f:
99+
raw = f.read()
100+
finally:
101+
os.remove(tmpfile)
64102

65103
return raw
66104

105+
67106
def write_bin(out, args, elf, segments, to_addr):
68107
entry = int(get_elf_entry( elf, args.path ))
69108
header = [ 0xe9, len(segments), fmodeb[args.flash_mode], ffreqb[args.flash_freq] + 16 * fsizeb[args.flash_size],
@@ -85,7 +124,7 @@ def write_bin(out, args, elf, segments, to_addr):
85124
try:
86125
for data in raw:
87126
checksum = checksum ^ ord(data)
88-
except Exception:
127+
except:
89128
for data in raw:
90129
checksum = checksum ^ data
91130
total_size += 1
@@ -95,11 +134,14 @@ def write_bin(out, args, elf, segments, to_addr):
95134
out.write(bytearray([checksum]))
96135
if to_addr != 0:
97136
if total_size + 8 > to_addr:
98-
raise Exception('Bin image of ' + elf + ' is too big, actual size ' + str(total_size + 8) + ', target size ' + str(to_addr) + '.')
137+
raise Elf2BinException(
138+
f'Bin image of "{elf}" is too big! Actual size {str(total_size + 8)}, target size {str(to_addr)}'
139+
)
99140
while total_size < to_addr:
100141
out.write(bytearray([0xaa]))
101142
total_size += 1
102143

144+
103145
def crc8266(ldata):
104146
"Return the CRC of ldata using same algorithm as eboot"
105147
crc = 0xffffffff
@@ -119,6 +161,7 @@ def crc8266(ldata):
119161
crc = int(crc ^ 0x04c11db7)
120162
return crc
121163

164+
122165
def store_word(raw, offset, val):
123166
"Place a 4-byte word in 8266-dependent order in the raw image"
124167
raw[offset] = val & 255
@@ -127,6 +170,7 @@ def store_word(raw, offset, val):
127170
raw[offset + 3] = (val >> 24) & 255
128171
return raw
129172

173+
130174
def add_crc(out):
131175
with open(out, "rb") as binfile:
132176
raw = bytearray(binfile.read())
@@ -141,15 +185,16 @@ def add_crc(out):
141185
with open(out, "wb") as binfile:
142186
binfile.write(raw)
143187

188+
144189
def gzip_bin(mode, out):
145190
import gzip
146191

147192
firmware_path = out
148-
gzip_path = firmware_path + '.gz'
149-
orig_path = firmware_path + '.orig'
193+
gzip_path = f"{firmware_path}.gz"
194+
orig_path = f"{firmware_path}.orig"
150195
if os.path.exists(gzip_path):
151196
os.remove(gzip_path)
152-
print('GZipping firmware ' + firmware_path)
197+
print(f'GZipping firmware {firmware_path}')
153198
with open(firmware_path, 'rb') as firmware_file, \
154199
gzip.open(gzip_path, 'wb') as dest:
155200
data = firmware_file.read()
@@ -162,10 +207,11 @@ def gzip_bin(mode, out):
162207
if mode == "PIO":
163208
if os.path.exists(orig_path):
164209
os.remove(orig_path)
165-
print('Moving original firmware to ' + orig_path)
210+
print(f'Moving original firmware to {orig_path}')
166211
os.rename(firmware_path, orig_path)
167212
os.rename(gzip_path, firmware_path)
168213

214+
169215
def main():
170216
parser = argparse.ArgumentParser(description='Create a BIN file from eboot.elf and Arduino sketch.elf for upload by esptool.py')
171217
parser.add_argument('-e', '--eboot', action='store', required=True, help='Path to the Arduino eboot.elf bootloader')
@@ -179,8 +225,7 @@ def main():
179225

180226
args = parser.parse_args()
181227

182-
print('Creating BIN file "{out}" using "{eboot}" and "{app}"'.format(
183-
out=args.out, eboot=args.eboot, app=args.app))
228+
print(f'Creating BIN file "{args.out}" using "{args.eboot}" and "{args.app}"')
184229

185230
with open(args.out, "wb") as out:
186231
def wrapper(**kwargs):

0 commit comments

Comments
 (0)