Repository: pwndbg/pwndbg

Issue:
Fix Arch Linux tests
The Arch Linux tests are failing due to new versions of pip needing to use the `--break-system-packages` flag to install packages globally. We should update the CI to use a virtualenv here.
CI: try to bring back Arch Linux CI
Let's see if this works now with virtualenv setup

<!-- Please make sure to read the testing and linting instructions at https://github.com/pwndbg/pwndbg/blob/dev/DEVELOPING.md before creating a PR -->



Discussion:
https://github.com/pwndbg/pwndbg/pull/1776 removed arch from CI for now. 

In the future, #1634 should allow for bringing back Arch on CI (or not bothering about it at all?).

Going to close this for now.
This was actually intended to be the tracking issue for re-enabling the test, so going to reopen :)
Interestingly, we are failing on some bogus GH actions error: https://gitlab.archlinux.org/archlinux/archlinux-docker/-/issues/76

Resolving patch:
diff --git a/gdbinit.py b/gdbinit.py
--- a/gdbinit.py
+++ b/gdbinit.py
@@ -2,6 +2,7 @@
 import glob
 import locale
 import os
+import site
 import sys
 import time
 from glob import glob
@@ -30,6 +31,14 @@
 
 site_pkgs_path = glob(os.path.join(venv_path, "lib/*/site-packages"))[0]
 
+# add virtualenv's site-packages to sys.path and run .pth files
+site.addsitedir(site_pkgs_path)
+
+# remove existing, system-level site-packages from sys.path
+for site_packages in site.getsitepackages():
+    if site_packages in sys.path:
+        sys.path.remove(site_packages)
+
 # Set virtualenv's bin path (needed for utility tools like ropper, pwntools etc)
 bin_path = os.path.join(venv_path, "bin")
 os.environ["PATH"] = bin_path + os.pathsep + os.environ.get("PATH")
@@ -37,7 +46,6 @@
 # Add gdb-pt-dump directory to sys.path so it can be imported
 gdbpt = path.join(directory, "gdb-pt-dump")
 sys.path.append(directory)
-sys.path.append(site_pkgs_path)
 sys.path.append(gdbpt)
 
 # warn if the user has different encoding than utf-8
diff --git a/pwndbg/wrappers/readelf.py b/pwndbg/wrappers/readelf.py
--- a/pwndbg/wrappers/readelf.py
+++ b/pwndbg/wrappers/readelf.py
@@ -23,7 +23,7 @@ def get_got_entry(local_path: str) -> Dict[RelocationType, List[str]]:
 
     entries: Dict[RelocationType, List[str]] = {category: [] for category in RelocationType}
     for line in readelf_out.splitlines():
-        if not line or not line[0].isdigit():
+        if not line or not line[0].isdigit() or " " not in line:
             continue
         category = line.split()[2]
         # TODO/FIXME: There's a bug here, somehow the IRELATIVE relocation might point to somewhere in .data.rel.ro, which is not in .got or .got.plt


Test patch:
diff --git a/tests/gdb-tests/tests/test_commands_elf.py b/tests/gdb-tests/tests/test_commands_elf.py
--- a/tests/gdb-tests/tests/test_commands_elf.py
+++ b/tests/gdb-tests/tests/test_commands_elf.py
@@ -131,7 +131,8 @@ def test_command_got_for_target_binary_and_loaded_library():
     assert out[2] == ""
     assert re.match(r"State of the GOT of .*/libc.so.6:", out[3])
     m = re.match(
-        r"GOT protection: Partial RELRO \| Found (\d+) GOT entries passing the filter", out[4]
+        r"GOT protection: (?:Partial|Full) RELRO \| Found (\d+) GOT entries passing the filter",
+        out[4],
     )
     got_entries_count = int(m.group(1))
     assert got_entries_count > 0
@@ -145,7 +146,8 @@ def test_command_got_for_target_binary_and_loaded_library():
     assert out[1] == ""
     assert re.match(r"State of the GOT of .*/libc.so.6:", out[2])
     m = re.match(
-        r"GOT protection: Partial RELRO \| Found (\d+) GOT entries passing the filter", out[3]
+        r"GOT protection: (?:Partial|Full) RELRO \| Found (\d+) GOT entries passing the filter",
+        out[3],
     )
     assert int(m.group(1)) > got_entries_count  # We should have more entries now
     got_entries_count = int(m.group(1))
@@ -161,7 +163,8 @@ def test_command_got_for_target_binary_and_loaded_library():
     assert out[3] == ""
     assert re.match(r"State of the GOT of .*/libc.so.6:", out[4])
     m = re.match(
-        r"GOT protection: Partial RELRO \| Found (\d+) GOT entries passing the filter", out[5]
+        r"GOT protection: (?:Partial|Full) RELRO \| Found (\d+) GOT entries passing the filter",
+        out[5],
     )
     got_entries_count = int(m.group(1))
     assert len(out) == (6 + got_entries_count)
@@ -176,18 +179,20 @@ def test_command_got_for_target_binary_and_loaded_library():
     assert out[2] == ""
     assert re.match(r"State of the GOT of .*/ld-linux-x86-64.so.2:", out[3])
     m = re.match(
-        r"GOT protection: Partial RELRO \| Found (\d+) GOT entries passing the filter", out[4]
+        r"GOT protection: (?:Partial|Full) RELRO \| Found (\d+) GOT entries passing the filter",
+        out[4],
     )
     got_entries_count = int(m.group(1))
     for i in range(got_entries_count):
         assert re.match(r"\[0x[0-9a-f]+\] .* -> .*", out[5 + i])
-    assert out[5 + i + 1] == ""
+    assert out[5 + got_entries_count] == ""
 
     # Second should be libc.so.6
-    out = out[5 + i + 2 :]
+    out = out[5 + got_entries_count + 1 :]
     assert re.match(r"State of the GOT of .*/libc.so.6:", out[0])
     m = re.match(
-        r"GOT protection: Partial RELRO \| Found (\d+) GOT entries passing the filter", out[1]
+        r"GOT protection: (?:Partial|Full) RELRO \| Found (\d+) GOT entries passing the filter",
+        out[1],
     )
     got_entries_count = int(m.group(1))
     assert len(out) == (2 + got_entries_count)
@@ -207,18 +212,20 @@ def test_command_got_for_target_binary_and_loaded_library():
     # Second should be ld-linux-x86-64.so.2
     assert re.match(r"State of the GOT of .*/ld-linux-x86-64.so.2:", out[0])
     m = re.match(
-        r"GOT protection: Partial RELRO \| Found (\d+) GOT entries passing the filter", out[1]
+        r"GOT protection: (?:Partial|Full) RELRO \| Found (\d+) GOT entries passing the filter",
+        out[1],
     )
     got_entries_count = int(m.group(1))
     for i in range(got_entries_count):
         assert re.match(r"\[0x[0-9a-f]+\] .* -> .*", out[2 + i])
-    assert out[2 + i + 1] == ""
-    out = out[2 + i + 2 :]
+    assert out[2 + got_entries_count] == ""
+    out = out[2 + got_entries_count + 1 :]
 
     # Third should be libc.so.6
     assert re.match(r"State of the GOT of .*/libc.so.6:", out[0])
     m = re.match(
-        r"GOT protection: Partial RELRO \| Found (\d+) GOT entries passing the filter", out[1]
+        r"GOT protection: (?:Partial|Full) RELRO \| Found (\d+) GOT entries passing the filter",
+        out[1],
     )
     got_entries_count = int(m.group(1))
     assert len(out) == (2 + got_entries_count)
@@ -234,8 +241,12 @@ def test_command_got_for_target_binary_and_loaded_library():
     assert re.match(r"\[0x[0-9a-f]+\] puts@GLIBC_[0-9.]+ -> .*", out[4])
     assert out[5] == ""
     assert re.match(r"State of the GOT of .*/ld-linux-x86-64.so.2:", out[6])
-    assert out[7] == "GOT protection: Partial RELRO | Found 0 GOT entries passing the filter"
+    assert re.match(
+        r"GOT protection: (?:Partial|Full) RELRO \| Found 0 GOT entries passing the filter", out[7]
+    )
     assert out[8] == ""
     assert re.match(r"State of the GOT of .*/libc.so.6:", out[9])
-    assert out[10] == "GOT protection: Partial RELRO | Found 0 GOT entries passing the filter"
+    assert re.match(
+        r"GOT protection: (?:Partial|Full) RELRO \| Found 0 GOT entries passing the filter", out[10]
+    )
     assert len(out) == 11