@@ -178,40 +178,64 @@ def which_binutils(util, check_version=False):
178
178
"""
179
179
arch = context .arch
180
180
machine = platform .machine ()
181
+ path_dirs = environ ["PATH" ].split (os .pathsep )
181
182
182
- if arch == "amd64" :
183
- pattern = "*86*64*-*-{}" .format (util )
184
-
185
- for dir in environ ["PATH" ].split (os .pathsep ):
186
- for res in sorted (glob (path .join (dir , pattern ))):
187
- if check_version :
188
- ver = check_binutils_version (res )
189
- return res , ver
190
- return res
191
-
192
- # if target is native, try native command (e.g. "as")
193
- if machine in ("x86_64" , "amd64" ):
194
- for dir in environ ["PATH" ].split (os .pathsep ):
195
- res = path .join (dir , util )
196
- if os .path .exists (res ) and os .access (res , os .X_OK ):
183
+ utils = [util ]
184
+
185
+ # hack for homebrew-installed binutils on mac
186
+ if platform .system () == 'Darwin' :
187
+ utils = ['g' + util , util ]
188
+
189
+ if platform .system () == 'Windows' :
190
+ utils = [util + '.exe' ]
191
+
192
+ def get_patterns (prefix , tool ):
193
+ return [
194
+ "%s*linux*-%s" % (prefix , tool ),
195
+ "%s*-elf-%s" % (prefix , tool ),
196
+ "%s-none*-%s" % (prefix , tool ),
197
+ "%s-%s" % (prefix , tool )
198
+ ]
199
+
200
+ def search_patterns (patterns ):
201
+ for pattern in patterns :
202
+ for dir in path_dirs :
203
+ for res in sorted (glob (path .join (dir , pattern ))):
197
204
if check_version :
198
205
ver = check_binutils_version (res )
199
206
return res , ver
200
207
return res
208
+ return None
209
+
210
+ for gutil in utils :
211
+ if arch == "amd64" :
212
+ explicit_patterns = ["*86*64*-*-{}" .format (gutil )]
213
+ else :
214
+ explicit_patterns = get_patterns (arch , gutil )
201
215
202
- pattern = "i*86*-*-{}" .format (util )
203
- for dir in environ ["PATH" ].split (os .pathsep ):
204
- for res in sorted (glob (path .join (dir , pattern ))):
205
- if check_version :
206
- ver = check_binutils_version (res )
207
- return res , ver
208
- return res
216
+ found = search_patterns (explicit_patterns )
217
+ if found :
218
+ return found
209
219
210
- print_binutils_instructions (util , context )
220
+ # if host arch equals target, try native command
221
+ machine = 'i386' if machine == 'i686' else machine
222
+ try :
223
+ with context .local (arch = machine ):
224
+ if context .arch == arch :
225
+ for gutil in utils :
226
+ for dir in path_dirs :
227
+ res = path .join (dir , gutil )
228
+ if os .path .exists (res ) and os .access (res , os .X_OK ):
229
+ if check_version :
230
+ ver = check_binutils_version (res )
231
+ return res , ver
232
+ return res
233
+ except AttributeError :
234
+ log .warn_once ("Your local binutils won't be used because architecture %r is not supported." % machine )
211
235
212
236
# Fix up pwntools vs Debian triplet naming, and account
213
237
# for 'thumb' being its own pwntools architecture.
214
- arches = [ arch ] + {
238
+ aliases = {
215
239
'thumb' : ['arm' , 'aarch64' ],
216
240
'i386' : ['x86_64' , 'amd64' ],
217
241
'i686' : ['x86_64' , 'amd64' ],
@@ -222,47 +246,17 @@ def which_binutils(util, check_version=False):
222
246
'riscv32' : ['riscv32' , 'riscv64' , 'riscv' ],
223
247
'riscv64' : ['riscv64' , 'riscv32' , 'riscv' ],
224
248
'loongarch64' : ['loongarch64' , 'loong64' ],
225
- }.get (arch , [])
226
-
227
- # If one of the candidate architectures matches the native
228
- # architecture, use that as a last resort.
229
- machine = 'i386' if machine == 'i686' else machine
230
- try :
231
- with context .local (arch = machine ):
232
- if context .arch in arches :
233
- arches .append (None )
234
- except AttributeError :
235
- log .warn_once ("Your local binutils won't be used because architecture %r is not supported." % machine )
236
-
237
- utils = [util ]
238
-
239
- # hack for homebrew-installed binutils on mac
240
- if platform .system () == 'Darwin' :
241
- utils = ['g' + util , util ]
242
-
243
- if platform .system () == 'Windows' :
244
- utils = [util + '.exe' ]
249
+ }
245
250
246
- for arch in arches :
251
+ for alias in aliases . get ( arch , []) :
247
252
for gutil in utils :
248
- # e.g. objdump
249
- if arch is None :
250
- patterns = [gutil ]
251
-
252
- # e.g. aarch64-linux-gnu-objdump, avr-objdump
253
+ if arch == "amd64" and alias == "i386" :
254
+ alias_patterns = ["i*86*-*-{}" .format (gutil )]
253
255
else :
254
- patterns = ['%s*linux*-%s' % (arch , gutil ),
255
- '%s*-elf-%s' % (arch , gutil ),
256
- '%s-none*-%s' % (arch , gutil ),
257
- '%s-%s' % (arch , gutil )]
258
-
259
- for pattern in patterns :
260
- for dir in environ ['PATH' ].split (os .pathsep ):
261
- for res in sorted (glob (path .join (dir , pattern ))):
262
- if check_version :
263
- ver = check_binutils_version (res )
264
- return res , ver
265
- return res
256
+ alias_patterns = get_patterns (alias , gutil )
257
+ found = search_patterns (alias_patterns )
258
+ if found :
259
+ return found
266
260
267
261
# No dice!
268
262
print_binutils_instructions (util , context )
0 commit comments