internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: Gallopsled/pwntools

Issue:
socket.socket doesnt have unrecv. bug in udp server
https://github.com/Gallopsled/pwntools/blob/5e279e7993f1f57cba2ba128f6bd8a27c19ea25f/pwnlib/tubes/server.py#L120

as mentioned above this is a bug.

line should be
```python
self.unrecv(data)
```
if its necessary at all


Discussion:
It could either do this, or use `socket.MSG_PEEK` socket flag. @zachriggle what looks better to you? Leaving the data in a kernel buffer, or in the tube buffer? (certainly the current behavior is a buggy `AttributeError`)
We should put it back into the tube buffer, `self.unrecv(...)` is correct

Resolving patch:
diff --git a/pwnlib/tubes/server.py b/pwnlib/tubes/server.py
--- a/pwnlib/tubes/server.py
+++ b/pwnlib/tubes/server.py
@@ -117,7 +117,7 @@ def accepter():
                             data, rhost = listen_sock.recvfrom(4096)
                             listen_sock.connect(rhost)
                             sock = listen_sock
-                            sock.unrecv(data)
+                            self.unrecv(data)
                         sock.settimeout(self.timeout)
                         break
                     except socket.error as e:


Test patch:
Repository: Gallopsled/pwntools

Issue:
Typo in docs for pwnlib.util.fiddling.bits
I think I spotted a typo in http://docs.pwntools.com/en/dev/util/fiddling.html#pwnlib.util.fiddling.bits
`Converts the argument a list of bits.` should be `Converts the argument into a list of bits.`


Discussion:

Resolving patch:
diff --git a/pwnlib/util/fiddling.py b/pwnlib/util/fiddling.py
--- a/pwnlib/util/fiddling.py
+++ b/pwnlib/util/fiddling.py
@@ -105,7 +105,7 @@ def urldecode(s, ignore_invalid = False):
 def bits(s, endian = 'big', zero = 0, one = 1):
     """bits(s, endian = 'big', zero = 0, one = 1) -> list
 
-    Converts the argument a list of bits.
+    Converts the argument into a list of bits.
 
     Arguments:
         s: A string or number to be converted into bits.


Test patch:
Repository: Gallopsled/pwntools

Issue:
ssh(...).process() fails when bash complains about LC_ALL
When working on a CTF challenge, I found a SSH server that breaks `ssh.process` because bash (before invoking the Python interpreter to run the remote script) emits some information complaining about LC_ALL.

```
[DEBUG] Received 0x46 bytes:
    b'bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)\r\n'
```

We expect to receive `1`, so this breaks things.


Discussion:

Resolving patch:
diff --git a/pwnlib/tubes/ssh.py b/pwnlib/tubes/ssh.py
--- a/pwnlib/tubes/ssh.py
+++ b/pwnlib/tubes/ssh.py
@@ -1076,12 +1076,14 @@ def is_exe(path):
 
         with self.progress(msg) as h:
 
-            script = 'for py in python2.7 python2 python; do test -x "$(which $py 2>&1)" && exec $py -c %s check; done; echo 2' % sh_string(script)
+            script = 'echo PWNTOOLS; for py in python2.7 python2 python; do test -x "$(which $py 2>&1)" && echo $py && exec $py -c %s check; done; echo 2' % sh_string(script)
             with context.quiet:
                 python = ssh_process(self, script, tty=True, raw=True, level=self.level, timeout=timeout)
 
             try:
-                result = safeeval.const(python.recvline())
+                python.recvline_contains('PWNTOOLS')        # Magic flag so that any sh/bash initialization errors are swallowed
+                python.recvline()                           # Python interpreter that was selected
+                result = safeeval.const(python.recvline())  # Status flag from the Python script
             except (EOFError, ValueError):
                 h.failure("Process creation failed")
                 self.warn_once('Could not find a Python interpreter on %s\n' % self.host \


Test patch:
Repository: Gallopsled/pwntools

Issue:
`atexit.register` does not work
### What I did
```python3
from pwn import *
atexit.register(print, "hello world")
exit()
```
### What I expected to see
```python3 test.py
hello world
```
### What I saw
Nothing

I noticed this because `asm()`, which adds an `atexit` handler to remove the `/tmp/pwn-asm-XXXXXX` folder, does not in fact remove it, meaning multiple script runs leads to many similar folders.


Discussion:
Looks like https://github.com/Gallopsled/pwntools/blob/ec9dfe108b85ac47983e9a98808fcdbb50cb0cdd/pwnlib/atexit.py#L98 is to blame, as `sys.exitfunc` has been removed in Python 3.X (https://docs.python.org/3.5/search.html?q=sys.exitfunc&check_keywords=yes&area=default), encouraging the use of `atexit` (the stdlib module) instead.

Resolving patch:
diff --git a/pwnlib/atexit.py b/pwnlib/atexit.py
--- a/pwnlib/atexit.py
+++ b/pwnlib/atexit.py
@@ -13,6 +13,7 @@
 import sys
 import threading
 import traceback
+import atexit as std_atexit
 
 from pwnlib.context import context
 
@@ -95,4 +96,8 @@ def _run_handlers():
 if hasattr(sys, "exitfunc"):
     register(sys.exitfunc)
 
-sys.exitfunc = _run_handlers
+if sys.version_info[0] < 3:
+    sys.exitfunc = _run_handlers
+else:
+    std_atexit.register(_run_handlers)
+


Test patch:
Repository: Gallopsled/pwntools

Issue:
"pwn template" emits a Python2 shebang
We should probably update this to use Python3 explicitly, since that's what we recommend.


Discussion:

Resolving patch:
diff --git a/pwnlib/commandline/template.py b/pwnlib/commandline/template.py
old mode 100644
new mode 100755
--- a/pwnlib/commandline/template.py
+++ b/pwnlib/commandline/template.py
@@ -2,8 +2,6 @@
 from __future__ import absolute_import
 from __future__ import division
 
-import re
-
 from pwn import *
 from pwnlib.commandline import common
 
@@ -25,14 +23,9 @@
 parser.add_argument('--color', help='Print the output in color', choices=['never', 'always', 'auto'], default='auto')
 
 def main(args):
-    cache = None
-
-    if cache:
-        cache = os.path.join(context.cache_dir, 'mako')
-
     lookup = TemplateLookup(
         directories      = [os.path.join(pwnlib.data.path, 'templates')],
-        module_directory = cache
+        module_directory = None
     )
 
     # For the SSH scenario, check that the binary is at the
@@ -44,10 +37,10 @@ def main(args):
         s = ssh(args.user, args.host, args.port or 22, args.password or None)
 
         try:
-            remote = args.path or args.exe
-            s.download(remote)
+            remote_file = args.path or args.exe
+            s.download(remote_file)
         except Exception:
-            log.warning("Could not download file %r, opening a shell", remote)
+            log.warning("Could not download file %r, opening a shell", remote_file)
             s.interactive()
             return
 


Test patch:
Repository: Gallopsled/pwntools

Issue:
phd throws an exception when output pipe fails, as with e.g. `head`
We should silence the BrokenPipeError exception when `pwn phd` output closes.

```
$ phd < /dev/random | head -n 1
00000000  43 18 3f 38  0e 45 9c 5d  d9 b8 ed 44  7c 64 ee e3  │C·?8│·E·]│···D│|d··│
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
BrokenPipeError: [Errno 32] Broken pipe
```


Discussion:

Resolving patch:
diff --git a/pwnlib/commandline/phd.py b/pwnlib/commandline/phd.py
--- a/pwnlib/commandline/phd.py
+++ b/pwnlib/commandline/phd.py
@@ -4,6 +4,7 @@
 
 import argparse
 import os
+import signal
 import sys
 import io
 
@@ -100,6 +101,8 @@ def main(args):
             for h in hs.split(','):
                 hl.append(asint(h))
 
+    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
     try:
         for line in hexdump_iter(infile, width, highlight = hl, begin = offset + skip):
             print(line)


Test patch:
Repository: Gallopsled/pwntools

Issue:
'pwn cyclic -o afca' throws a BytesWarning

```
$ pwn cyclic -o afca
/Users/heapcrash/pwntools/pwnlib/commandline/cyclic.py:74: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  pat = flat(pat, bytes=args.length)
506
```


Discussion:

Resolving patch:
diff --git a/pwnlib/commandline/cyclic.py b/pwnlib/commandline/cyclic.py
--- a/pwnlib/commandline/cyclic.py
+++ b/pwnlib/commandline/cyclic.py
@@ -67,6 +67,9 @@ def main(args):
     if args.lookup:
         pat = args.lookup
 
+        if six.PY3:
+            pat = bytes(pat, encoding='utf-8')
+
         try:
             pat = int(pat, 0)
         except ValueError:


Test patch:
Repository: Gallopsled/pwntools

Issue:
Implement RISC V architecture
* What the feature does
It will allow, e.g. `pwn.asm` output risc v instructions
* Why the feature should exit
It's an architecture here to stay ;) Should I elaborate this further?
* What tests should be included
Oh boy. Yes.

---

I'd like to write this

```python
import pwn
pwn.asm('add a0, a1, a0', arch='riscv')
```

and get `\x33\x85\xa5\x00`. Would be awesome (:



Discussion:
The best way to help is to submit some pull request.
There are several places where architecture-dependent stuff is:
* `pwnlib/context/__init__.py` so that the arch is recognized in the first place,
* `pwnlib/asm.py` so that you can do that stuff,

... and the best would be to add it to the following files as well so that it can go full featured:
* `pwnlib/abi.py`
* `pwnlib/data/syscalls/generate.py`
* `pwnlib/shellcraft/templates/<arch>/`
* `pwnlib/shellcraft/registers.py`
* `docs/source/shellcraft/<arch>.py`

You can do a quick `git grep aarch64` for an example of a well supported architecture and `git grep s390` for an architecture that is minimally supported. Have fun!

Resolving patch:
diff --git a/pwnlib/asm.py b/pwnlib/asm.py
--- a/pwnlib/asm.py
+++ b/pwnlib/asm.py
@@ -198,6 +198,7 @@ def which_binutils(util):
             # e.g. aarch64-linux-gnu-objdump, avr-objdump
             else:
                 patterns = ['%s*linux*-%s' % (arch, gutil),
+                            '%s*-elf-%s' % (arch, gutil),
                             '%s-%s' % (arch, gutil)]
 
             for pattern in patterns:
@@ -338,6 +339,7 @@ def _bfdname():
         'msp430'  : 'elf32-msp430',
         'powerpc' : 'elf32-powerpc',
         'powerpc64' : 'elf64-powerpc',
+        'riscv'   : 'elf%d-%sriscv' % (context.bits, E),
         'vax'     : 'elf32-vax',
         's390'    : 'elf%d-s390' % context.bits,
         'sparc'   : 'elf32-sparc',
diff --git a/pwnlib/context/__init__.py b/pwnlib/context/__init__.py
--- a/pwnlib/context/__init__.py
+++ b/pwnlib/context/__init__.py
@@ -397,6 +397,7 @@ class ContextType(object):
         'msp430':    little_16,
         'powerpc':   big_32,
         'powerpc64': big_64,
+        'riscv':     little_32,
         's390':      big_32,
         'sparc':     big_32,
         'sparc64':   big_64,


Test patch:
Repository: Gallopsled/pwntools

Issue:
context.terminal: existing code breaks
Hello :)

I generated a simple script with `pwn template ./a.out > xpl.py`. When running the script with `GDB` everything works just find. When I add the following line *as usual*: `context.terminal = "tmux splitw -h".split(" ")` and run the script `./xpl.py GDB` I get the following error:

```
Traceback (most recent call last):
  File "/io/exercise_bufferoverflow_shellcode/./xpl.py", line 43, in <module>
    io = start()
  File "/io/exercise_bufferoverflow_shellcode/./xpl.py", line 21, in start
    return gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw)
  File "/usr/local/lib/python3.9/dist-packages/pwnlib/context/__init__.py", line 1524, in setter
    return function(*a, **kw)
  File "/usr/local/lib/python3.9/dist-packages/pwnlib/gdb.py", line 576, in debug
    tmp = attach((host, port), exe=exe, gdbscript=gdbscript, ssh=ssh, sysroot=sysroot, api=api)
  File "/usr/local/lib/python3.9/dist-packages/pwnlib/context/__init__.py", line 1524, in setter
    return function(*a, **kw)
  File "/usr/local/lib/python3.9/dist-packages/pwnlib/gdb.py", line 1046, in attach
    gdb_pid = misc.run_in_new_terminal(cmd, preexec_fn = preexec_fn)
  File "/usr/local/lib/python3.9/dist-packages/pwnlib/util/misc.py", line 297, in run_in_new_terminal
    pid = int(out)
ValueError: invalid literal for int() with base 10: b''
```
Maybe this is related to recent changes in `pwnlib/util/misc.py` (https://github.com/Gallopsled/pwntools/commits/dev/pwnlib/util/misc.py)

```
$ pwn version
[*] Pwntools v4.7.0dev
```

Thanks!


Discussion:
Yes, this is a bug, but see #1874 #1878 for a workaround

DO NOT CLOSE THIS PLEASE, even if the workaround works

Resolving patch:
diff --git a/pwnlib/util/misc.py b/pwnlib/util/misc.py
--- a/pwnlib/util/misc.py
+++ b/pwnlib/util/misc.py
@@ -229,7 +229,7 @@ def run_in_new_terminal(command, terminal=None, args=None, kill_at_exit=True, pr
             args     = []
         elif 'TMUX' in os.environ and which('tmux'):
             terminal = 'tmux'
-            args     = ['splitw', '-F' '#{pane_pid}', '-P']
+            args     = ['splitw']
         elif 'STY' in os.environ and which('screen'):
             terminal = 'screen'
             args     = ['-t','pwntools-gdb','bash','-c']
@@ -256,6 +256,12 @@ def run_in_new_terminal(command, terminal=None, args=None, kill_at_exit=True, pr
     if isinstance(args, tuple):
         args = list(args)
 
+    # When not specifying context.terminal explicitly, we used to set these flags above.
+    # However, if specifying terminal=['tmux', 'splitw', '-h'], we would be lacking these flags.
+    # Instead, set them here and hope for the best.
+    if terminal == 'tmux':
+        args += ['-F' '#{pane_pid}', '-P']
+
     argv = [which(terminal)] + args
 
     if isinstance(command, six.string_types):


Test patch:
Repository: Gallopsled/pwntools

Issue:
Error while setting log level
```py
from pwn import *
context.log_level = 'silent'
```
```py
Traceback (most recent call last):
  File "/tmp/test.py", line 3, in <module>
    context.log_level = 'silent'
  File "/usr/local/lib/python3.9/dist-packages/pwnlib/context/__init__.py", line 173, in fset
    self._tls[name] = validator(self, val)
  File "/usr/local/lib/python3.9/dist-packages/pwnlib/context/__init__.py", line 974, in log_level
    level_names = filter(lambda x: isinstance(x,str), logging._levelNames)
AttributeError: module 'logging' has no attribute '_levelNames'
```
This appears to be left over from Python 2's logging module, which had `logging._levelNames`: 
`{0: 'NOTSET', 10: 'DEBUG', 'WARN': 30, 20: 'INFO', 'ERROR': 40, 'DEBUG': 10, 30: 'WARNING', 'INFO': 20, 'WARNING': 30, 40: 'ERROR', 50: 'CRITICAL', 'CRITICAL': 50, 'NOTSET': 0}`.

Python3 has `logging._levelToName`: `{50: 'CRITICAL', 40: 'ERROR', 30: 'WARNING', 20: 'INFO', 10: 'DEBUG', 0: 'NOTSET'}`

Ironically erroring 2 lines before throwing an error


Discussion:

Resolving patch:
diff --git a/pwnlib/context/__init__.py b/pwnlib/context/__init__.py
--- a/pwnlib/context/__init__.py
+++ b/pwnlib/context/__init__.py
@@ -972,7 +972,10 @@ def log_level(self, value):
         except AttributeError:  pass
 
         # Otherwise, fail
-        level_names = filter(lambda x: isinstance(x,str), logging._levelNames)
+        try:
+            level_names = logging._levelToName.values()
+        except AttributeError:
+            level_names = filter(lambda x: isinstance(x,str), logging._levelNames)
         permitted = sorted(level_names)
         raise AttributeError('log_level must be an integer or one of %r' % permitted)
 


Test patch:
Repository: Gallopsled/pwntools

Issue:
ret2csu seems broken
If I try your example for ret2libcsu I get a syntax error:

```
Traceback (most recent call last):
  File "/home/jonathan/Projekte/CTF/uiuctf/./exploit.py", line 38, in <module>
    main()
  File "/home/jonathan/Projekte/CTF/uiuctf/./exploit.py", line 28, in main
    r.ret2csu(1, 2, 3, 4, 5, call=0xdeadbeef)
  File "/home/jonathan/.local/lib/python3.9/site-packages/pwnlib/rop/rop.py", line 1458, in ret2csu
    if elf.pie:
UnboundLocalError: local variabe 'elf' referenced before assignment
```

The offending code in rop.py looks like this:

```
        exes = (elf for elf in self.elfs if not elf.library and elf.bits == 64)
        if not exes:
            log.error('No non-library binaries in [elfs]')

        nonpie = csu = None
        for elf in exes:
            if not elf.pie:
                if '__libc_csu_init' in elf.symbols:
                    break
                nonpie = elf
            elif '__libc_csu_init' in elf.symbols:
                csu = elf

        if elf.pie:
            if nonpie:
                elf = nonpie
            elif csu:
                elf = csu

        from .ret2csu import ret2csu
        ret2csu(self, elf, edi, rsi, rdx, rbx, rbp, r12, r13, r14, r15, call)
```

I dont think that this is right since elf is never referenced before the if condition (it is in the for loop but the if is not inside the for loop).


Discussion:

Resolving patch:
diff --git a/pwnlib/rop/rop.py b/pwnlib/rop/rop.py
--- a/pwnlib/rop/rop.py
+++ b/pwnlib/rop/rop.py
@@ -1477,8 +1477,6 @@ def ret2csu(self, edi=Padding('edi'), rsi=Padding('rsi'),
         # Find an appropriate, non-library ELF.
         # Prioritise non-PIE binaries so we can use _fini
         exes = (elf for elf in self.elfs if not elf.library and elf.bits == 64)
-        if not exes:
-            log.error('No non-library binaries in [elfs]')
 
         nonpie = csu = None
         for elf in exes:
@@ -1488,6 +1486,8 @@ def ret2csu(self, edi=Padding('edi'), rsi=Padding('rsi'),
                 nonpie = elf
             elif '__libc_csu_init' in elf.symbols:
                 csu = elf
+        else:
+            log.error('No non-library binaries in [elfs]')
 
         if elf.pie:
             if nonpie:


Test patch:
Repository: Gallopsled/pwntools

Issue:
Double decoding in util.packing._need_text
I noticed that if you send a bytestring to e.g. log.info(), you get an AttributeError:
`AttributeError: 'str' object has no attribute 'decode'`

This is because of the following line:
https://github.com/Gallopsled/pwntools/blob/ef698d4562024802be5cc3e2fa49333c70a96662/pwnlib/util/packing.py#L1051

If the param for _need_text is a bytestring and context.encoding = auto, then it will try to decode the string as seen in https://github.com/Gallopsled/pwntools/blob/ef698d4562024802be5cc3e2fa49333c70a96662/pwnlib/util/packing.py#L1043 
If this is successful it will then try to decode it one more time in the last return statement which will cause an exception. 

If encoding is auto it will iterate over 3 different encodings and try to decode. So the second decode will then use the last encoding that was tried above. However, if all encodings get a UnicodeDecodeError, it will still try to use that last encoding to decode it again in the return statement.


Discussion:

Resolving patch:
diff --git a/pwnlib/util/packing.py b/pwnlib/util/packing.py
--- a/pwnlib/util/packing.py
+++ b/pwnlib/util/packing.py
@@ -1040,7 +1040,7 @@ def _need_text(s, level=1):
     if encoding == 'auto':
         for encoding in 'ASCII', 'UTF-8', 'ISO-8859-1':
             try:
-                s = s.decode(encoding)
+                s.decode(encoding)
             except UnicodeDecodeError:
                 pass
             else:


Test patch:
Repository: Gallopsled/pwntools

Issue:
Building Docs Breaks on Python 3.10
Attempting to build the docs with Python 3.10, which is now the default in Kali Linux causes an error:
```
$ git clone https://github.com/Gallopsled/pwntools.git
$ cd pwntools/
$ cd docs
$ python3 -m venv ./venv
$ source ./venv/bin/activate
$ python3 -m pip install -q pwntools
$ python3 -m pip install -r requirements.txt 
...
$ make html
sphinx-build -b html -d build/doctrees   source build/html
Running Sphinx v4.5.0

Extension error:
Could not import extension sphinxcontrib.napoleon (exception: cannot import name 'Callable' from 'collections' (/usr/lib/python3.10/collections/__init__.py))
make: *** [Makefile:53: html] Error 2
```

Other info:
```
$ pip list | grep pwntools
pwntools                      4.8.0
```
```
$ python3 --version
Python 3.10.4
```
```
$ cat /etc/os-release
PRETTY_NAME="Kali GNU/Linux Rolling"
NAME="Kali GNU/Linux"
ID=kali
VERSION="2022.2"
VERSION_ID="2022.2"
VERSION_CODENAME="kali-rolling"
ID_LIKE=debian
```

Found this in the Sphinx repo: https://github.com/sphinx-doc/sphinx/issues/10378/. If I change in `source/conf.py`: 
```
'sphinxcontrib.napoleon'
```
to
```
'sphinx.ext.napoleon'
```
it works.


Discussion:

Resolving patch:
diff --git a/docs/source/conf.py b/docs/source/conf.py
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -42,8 +42,8 @@
     'sphinx.ext.coverage',
     'sphinx.ext.todo',
     'sphinx.ext.intersphinx',
+    'sphinx.ext.napoleon',
     'sphinxcontrib.autoprogram',
-    'sphinxcontrib.napoleon'
 ]
 
 # Disable "info" logging directly to stdout by Sphinx
diff --git a/pwnlib/util/safeeval.py b/pwnlib/util/safeeval.py
--- a/pwnlib/util/safeeval.py
+++ b/pwnlib/util/safeeval.py
@@ -6,6 +6,7 @@
     'BUILD_CONST_KEY_MAP', 'BUILD_STRING',
     'LOAD_CONST','RETURN_VALUE','STORE_SUBSCR', 'STORE_MAP',
     'LIST_TO_TUPLE', 'LIST_EXTEND', 'SET_UPDATE', 'DICT_UPDATE', 'DICT_MERGE',
+    'COPY', 'RESUME',
     ]
 
 _expr_codes = _const_codes + [
@@ -15,6 +16,7 @@
     'BINARY_MODULO','BINARY_ADD','BINARY_SUBTRACT',
     'BINARY_LSHIFT','BINARY_RSHIFT','BINARY_AND','BINARY_XOR',
     'BINARY_OR',
+    'BINARY_OP',
     ]
 
 _values_codes = _expr_codes + ['LOAD_NAME']


Test patch:
Repository: Gallopsled/pwntools

Issue:
Remote SSH debugging is broken due to missing qemu_port
When GDB is invoked on a remote host (via `gdb.debug(..., ssh=shell)`) the following error is thrown.  It's not particularly helpful -- perhaps we should double-check that `gdbserver` is available first?

This error only occurs when debugging a cross-arch binary on a remote host.

```
Traceback (most recent call last):
  File "exploit.py", line 66, in <module>
    io = start()
  File "exploit.py", line 46, in start
    return remote(argv, *a, **kw)
  File "exploit.py", line 37, in remote
    return gdb.debug([remote_path] + argv, gdbscript=gdbscript, ssh=shell, *a, **kw)
  File "/home/pwntools/pwntools/pwnlib/context/__init__.py", line 1449, in setter
    return function(*a, **kw)
  File "/home/pwntools/pwntools/pwnlib/gdb.py", line 454, in debug
    port = qemu_port
UnboundLocalError: local variable 'qemu_port' referenced before assignment
```

This error can be reproduced as follows:

```
$ pwn template --user level3 --pass c1aXb9E2OrgybHXE --path /levels/level03 --host ioarm.netgarage.org --port 2201 > exploit.py
$ python exploit.py GDB
```


Discussion:
It looks like the issue is:

```py
    # Find what port we need to connect to
    if context.native or (context.os == 'android'):
        port = _gdbserver_port(gdbserver, ssh)
    else:
        port = qemu_port
```

Does not properly handle the case where we are debugging over SSH and the remote host is native-arch.  There are likely other bugs along this front that don't have unit tests due to lack of arch-native hosts to run against in Travis CI and similar.
I have same issue on OS X for m1, however quick dirty fix is to change 

port= qemu_port to port = _gdbserver_port(gdbserver, ssh)

But then I have problems with context.terminal to be used. iTerm2 is not detected and tmux doesn't work

Resolving patch:
diff --git a/pwnlib/gdb.py b/pwnlib/gdb.py
--- a/pwnlib/gdb.py
+++ b/pwnlib/gdb.py
@@ -568,7 +568,7 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, api=
     gdbserver.executable = exe
 
     # Find what port we need to connect to
-    if context.native or (context.os == 'android'):
+    if ssh or context.native or (context.os == 'android'):
         port = _gdbserver_port(gdbserver, ssh)
     else:
         port = qemu_port


Test patch: