asm: try native binutils before fallback architectures (#2669)

* asm: try native binutils before fallback architectures

Some binutils builds support multiple architectures,
like the x86_64 assembler supports i386 too in most
package builds and vice versa. We support this by trying
the other binutils as well when looking for the right tool.
That support is optional though and there are packages
that don't include the "cross" compilation.

When assembling for the host's native architecture, we
still prefer the explicitly named `x86_64-linux-gnu-as`
instead of the native `as` binary. That native binary is
tried as a last resort after looking for any other explictly
named binary. If the fallback package is installed but
compiled without the cross-compiler support, we'd still
find the `i386-as` binary while looking for `x86_64-as`
before trying the native `as` binary.
That would fail to assemble.

This patch moves the native `as` binary forward in the list
to try it before checking the other fallback architecture ones.

Fixes #2509

* Update CHANGELOG
This commit is contained in:
peace-maker
2026-02-20 10:07:48 +01:00
committed by GitHub
parent 839915e18d
commit 243e6faffa
2 changed files with 19 additions and 9 deletions
+3 -1
View File
@@ -112,6 +112,7 @@ The table below shows which release corresponds to each branch, and what date th
- [#2629][2629] Add `terminate()` method to process class that sends SIGTERM
- [#2643][2643] Refactor getdents.py, add support for SYS_getdents64
- [#2647][2647] packing: Add `overlap` to overlap structures easily
- [#2669][2669] asm: try native binutils before fallback architectures
[2675]: https://github.com/Gallopsled/pwntools/pull/2675
[2652]: https://github.com/Gallopsled/pwntools/pull/2652
@@ -148,8 +149,9 @@ The table below shows which release corresponds to each branch, and what date th
[2641]: https://github.com/Gallopsled/pwntools/pull/2641
[2646]: https://github.com/Gallopsled/pwntools/pull/2646
[2629]: https://github.com/Gallopsled/pwntools/pull/2629
[2638]: https://github.com/Gallopsled/pwntools/pull/2643
[2643]: https://github.com/Gallopsled/pwntools/pull/2643
[2647]: https://github.com/Gallopsled/pwntools/pull/2647
[2669]: https://github.com/Gallopsled/pwntools/pull/2669
## 4.15.0 (`stable`)
+16 -8
View File
@@ -188,31 +188,37 @@ def which_binutils(util, check_version=False):
# Fix up pwntools vs Debian triplet naming, and account
# for 'thumb' being its own pwntools architecture.
arches = [arch] + {
aliases = {
'thumb': ['arm', 'aarch64'],
'i386': ['x86_64', 'amd64'],
'i686': ['x86_64', 'amd64'],
'amd64': ['x86_64', 'i386'],
'amd64': ['x86_64'],
'loongarch64': ['loong64'],
}.get(arch, [])
# Some binutils can support multiple architectures. Try them as fallbacks.
fallback_arches = {
'i386': ['x86_64', 'amd64'],
'amd64': ['i386'],
'arm': ['aarch64'],
'mips': ['mipsel'],
'mipsel': ['mips'],
'mips64': ['mips', 'mipsel'],
'mips64el': ['mipsel', 'mips'],
'mips64': ['mips64el', 'mips', 'mipsel'],
'mips64el': ['mips64', 'mipsel', 'mips'],
'powerpc64': ['powerpc'],
'sparc64': ['sparc'],
'riscv32': ['riscv64', 'riscv'],
'riscv64': ['riscv32', 'riscv'],
'loongarch64': ['loong64'],
}.get(arch, [])
arches = [arch] + aliases + fallback_arches
# If one of the candidate architectures matches the native
# architecture, use that as a last resort.
# architecture, use that as a last resort before trying fallbacks.
machine = platform.machine()
machine = 'i386' if machine == 'i686' else machine
try:
with context.local(arch = machine):
if context.arch in arches:
arches.append(None)
arches = [arch] + aliases + [None] + fallback_arches
except AttributeError:
log.warn_once("Your local binutils won't be used because architecture %r is not supported." % machine)
@@ -225,6 +231,8 @@ def which_binutils(util, check_version=False):
if platform.system() == 'Windows':
utils = [util + '.exe']
# Try the explicit tools for the target architecture first,
# then the native one optionally, then fallbacks.
for arch in arches:
for gutil in utils:
# e.g. objdump