diff --git a/pwndbg/commands/cymbol.py b/pwndbg/commands/cymbol.py index 2599a6439..fb7c454b4 100644 --- a/pwndbg/commands/cymbol.py +++ b/pwndbg/commands/cymbol.py @@ -31,8 +31,8 @@ import pwndbg import pwndbg.aglib.arch import pwndbg.commands import pwndbg.lib.config -import pwndbg.lib.gcc import pwndbg.lib.tempfile +import pwndbg.lib.zig from pwndbg.color import message from pwndbg.commands import CommandCategory @@ -108,17 +108,16 @@ def generate_debug_symbols( pwndbg_debug_symbols_output_file, ] - # TODO: implement remote debugging support. - try: - gcc_flags = pwndbg.lib.gcc.which(pwndbg.aglib.arch) - except ValueError as _: - # The error message is already printed by pwntools. - return None - if gcc_compiler_path != "": - gcc_flags[0] = gcc_compiler_path # type: ignore[call-overload] + compiler_flags = [gcc_compiler_path] + else: + try: + compiler_flags = pwndbg.lib.zig.flags(pwndbg.aglib.arch) + except ValueError as exception: + print(message.error(exception)) + return None - gcc_cmd = gcc_flags + gcc_extra_flags + gcc_cmd = compiler_flags + gcc_extra_flags try: subprocess.run(gcc_cmd, check=True, text=True) diff --git a/pwndbg/lib/gcc.py b/pwndbg/lib/gcc.py deleted file mode 100644 index 9c6546e37..000000000 --- a/pwndbg/lib/gcc.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -Functions for determining the architecture-dependent path to -GCC and any flags it should be executed with. -""" - -from __future__ import annotations - -import glob -import os -import platform -from typing import Any -from typing import List - -import pwnlib - -from pwndbg.lib.arch import ArchDefinition - -printed_message = False - - -def which(arch: ArchDefinition) -> List[str]: - try: - gcc = pwnlib.asm.which_binutils("g++") - except pwnlib.exception.PwnlibException as _: - raise ValueError("Couldn't find g++ for the current architecture.") - - return [gcc] + _flags(arch.name) - - -def _flags(arch_name: str) -> List[str]: - if arch_name == "i386": - return ["-m32"] - if arch_name.endswith("x86-64"): - return ["-m64"] - - return [] diff --git a/pwndbg/lib/zig.py b/pwndbg/lib/zig.py new file mode 100644 index 000000000..30c585a50 --- /dev/null +++ b/pwndbg/lib/zig.py @@ -0,0 +1,72 @@ +from __future__ import annotations + +import os.path +from typing import Dict +from typing import List +from typing import Literal +from typing import Tuple + +from pwndbg.lib.arch import PWNDBG_SUPPORTED_ARCHITECTURES_TYPE +from pwndbg.lib.arch import ArchDefinition +from pwndbg.lib.arch import Platform + +# Supported architectures can be obtained using the command: `zig targets` +_arch_mapping: Dict[Tuple[PWNDBG_SUPPORTED_ARCHITECTURES_TYPE, Literal["little", "big"], int], str] = { + ("x86-64", "little", 8): "x86_64", + ("i386", "little", 4): "x86", + ("mips", "big", 4): "mips", + ("mips", "little", 4): "mipsel", + ("mips", "big", 8): "mips64", + ("mips", "little", 8): "mips64el", + ("aarch64", "little", 8): "aarch64", + ("aarch64", "big", 8): "aarch64_be", + ("arm", "little", 4): "arm", + ("arm", "big", 4): "armeb", + ("armcm", "little", 4): "thumb", + ("armcm", "big", 4): "thumbeb", + ("rv32", "little", 4): "riscv32", + ("rv64", "little", 8): "riscv64", + ("sparc", "big", 4): "sparc", + ("sparc", "big", 8): "sparc64", + ("powerpc", "big", 4): "powerpc", + ("powerpc", "little", 4): "powerpcle", + ("powerpc", "big", 8): "powerpc64", + ("powerpc", "little", 8): "powerpc64le", + ("loongarch64", "little", 8): "loongarch64", + ("s390x", "big", 8): "s390x", +} + +def _get_zig_target(arch: ArchDefinition) -> str | None: + if arch.platform == Platform.LINUX: + # "gnu", "gnuabin32", "gnuabi64", "gnueabi", "gnueabihf", + # "gnuf32","gnusf", "gnux32", "gnuilp32", + # TODO: support soft/hard float abi? + osabi = "linux-gnu" + elif arch.platform == Platform.DARWIN: + osabi = "macos-none" + else: + return None + + arch_mapping = _arch_mapping.get((arch.name, arch.endian, arch.ptrsize), None) + if arch_mapping is None: + return None + + return f"{arch_mapping}-{osabi}" + + +def flags(arch: ArchDefinition) -> List[str] | None: + try: + import ziglang # type: ignore[import-untyped] + except ImportError: + raise ValueError("Can't import ziglang") + + zig_target = _get_zig_target(arch) + if zig_target is None: + raise ValueError(f"Can't find ziglang target for ({(arch.name, arch.endian, arch.ptrsize)})") + + return [ + os.path.join(os.path.dirname(ziglang.__file__), "zig"), + "cc", + "-target", + zig_target, + ]