Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ RUN set -eux; mkdir -p /sysroots; \
stage mipseb mipseb-linux-musl mipseb-linux-musl; \
stage mips64el mips64el-linux-musl-cross mips64el-linux-musl; \
stage mips64eb mips64-linux-musl-cross mips64-linux-musl; \
stage intel64 x86_64-linux-musl-cross x86_64-linux-musl; \
stage x86_64 x86_64-linux-musl-cross x86_64-linux-musl; \
du -sh /sysroots/* | sort -h; du -sh /sysroots

#### NMAP BUILDER: Build nmap ####
Expand Down Expand Up @@ -511,7 +511,7 @@ RUN set -eux; \
stage mipseb mips mipseb; \
stage mips64el mips64 mips64el; \
stage mips64eb mips64 mips64eb; \
stage intel64 x86_64 x86_64
stage x86_64 x86_64 x86_64
COPY guest-utils /igloo_static/guest-utils
COPY --from=rust_builder /root/vhost-device/target/x86_64-unknown-linux-gnu/release/vhost-device-vsock /usr/local/bin/vhost-device-vsock

Expand Down
13 changes: 7 additions & 6 deletions docs/schema_doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ Core configuration options for this rehosting

|||
|-|-|
|__Type__|`"armel"` or `"aarch64"` or `"mipsel"` or `"mipseb"` or `"mips64el"` or `"mips64eb"` or `"powerpc"` or `"powerpc64"` or `"powerpc64le"` or `"riscv64"` or `"loongarch64"` or `"intel64"` or null|
|__Type__|`"armel"` or `"arm"` or `"armle"` or `"aarch64"` or `"arm64"` or `"mipsel"` or `"mipseb"` or `"mipsbe"` or `"mips64el"` or `"mips64eb"` or `"mips64be"` or `"powerpc"` or `"ppc"` or `"powerpc64"` or `"ppc64"` or `"powerpc64le"` or `"ppc64le"` or `"powerpc64el"` or `"ppc64el"` or `"riscv64"` or `"riscv"` or `"rv64"` or `"loongarch64"` or `"loongarch"` or `"la64"` or `"x86_64"` or `"intel64"` or `"amd64"` or `"x86-64"` or `"x64"` or null|
|__Default__|`null`|

Canonical name or an accepted alias (normalized at load, e.g. intel64 -> x86_64).

```yaml
x86_64
```

```yaml
armel
Expand All @@ -35,11 +40,7 @@ mips64el
```

```yaml
mips64eb
```

```yaml
intel64
powerpc64le
```

### `core.kernel` Path to kernel image
Expand Down
6 changes: 4 additions & 2 deletions pyplugins/apis/kffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
from wrappers.ptregs_wrap import get_pt_regs_wrapper

from penguin import Plugin, getColoredLogger, plugins
from penguin.abi_info import ARCH_ABI_INFO
from penguin.abi_info import arch_abi_info


class KFFI(Plugin):
Expand All @@ -72,6 +72,8 @@ def __init__(self) -> None:
self.outdir = self.get_arg("outdir")
conf = self.get_arg("conf")
kernel = conf["core"]["kernel"]
# cosi files are named by the config arch, except x86_64 and arm64.
# (arch is already canonical post-load; the intel64 case is a safety net.)
arch = conf["core"]["arch"]
if arch == "intel64":
arch = "x86_64"
Expand Down Expand Up @@ -120,7 +122,7 @@ def cdef(self, source: str) -> None:
proj_dir = self.get_arg("proj_dir")

arch = conf["core"]["arch"]
arch_info = ARCH_ABI_INFO[arch]
arch_info = arch_abi_info(arch)
abi = arch_info.get("default_abi", list(arch_info.get("abis", {}).keys())[0])
abi_info = arch_info["abis"][abi]

Expand Down
11 changes: 8 additions & 3 deletions pyplugins/apis/unwind.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def __init__(self, name, ptr_size, endian, dwarf_map, cs_arch, cs_mode, call_off
RISCV_MAP = {"sp_reg": 2, "ra_reg": 1, "fp_reg": 8}

CONFIGS = {
"intel64": ArchInfo("x86_64", 8, "little", X86_64_MAP, CS_ARCH_X86, CS_MODE_64, 5),
"x86_64": ArchInfo("x86_64", 8, "little", X86_64_MAP, CS_ARCH_X86, CS_MODE_64, 5),
"armel": ArchInfo("arm", 4, "little", ARM_MAP, CS_ARCH_ARM, CS_MODE_ARM, 4),
"aarch64": ArchInfo("arm64", 8, "little", ARM64_MAP, CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, 4),
"mipsel": ArchInfo("mips", 4, "little", MIPS_MAP, CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_LITTLE_ENDIAN, 8),
Expand Down Expand Up @@ -100,9 +100,14 @@ def _get_arch_info(self) -> ArchInfo:
if self._arch_info:
return self._arch_info
conf = self.get_arg("conf")
arch_str = conf.get("core", {}).get("arch") if conf else "intel64"
arch_str = conf.get("core", {}).get("arch") if conf else "x86_64"
try:
from penguin.arch_registry import normalize_arch
arch_str = normalize_arch(arch_str)
except Exception:
pass
if arch_str not in CONFIGS:
arch_str = "intel64"
arch_str = "x86_64"
info = CONFIGS[arch_str]
self._init_capstone(info)
return info
Expand Down
8 changes: 5 additions & 3 deletions pyplugins/core/live_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def __init__(self) -> None:
self.patch_queue = []
self.config = self.get_arg("conf")
core_config = self.config.get("core", {})
self.arch = core_config.get("arch", "intel64")
self.arch = core_config.get("arch", "x86_64")
self.ensure_init = lambda *args: None
self._init_callbacks = []

Expand Down Expand Up @@ -509,9 +509,11 @@ def _gen_asm_patch_bytes(self, asm_code: str, user_mode: Optional[str]) -> Optio
return None

arch_map = {"armel": keystone.KS_ARCH_ARM, "aarch64": keystone.KS_ARCH_ARM64,
"mipsel": keystone.KS_ARCH_MIPS, "mipseb": keystone.KS_ARCH_MIPS, "intel64": keystone.KS_ARCH_X86}
"mipsel": keystone.KS_ARCH_MIPS, "mipseb": keystone.KS_ARCH_MIPS,
"x86_64": keystone.KS_ARCH_X86, "intel64": keystone.KS_ARCH_X86}
mode_map = {"aarch64": keystone.KS_MODE_LITTLE_ENDIAN, "mipsel": keystone.KS_MODE_MIPS32 | keystone.KS_MODE_LITTLE_ENDIAN,
"mipseb": keystone.KS_MODE_MIPS32 | keystone.KS_MODE_BIG_ENDIAN, "intel64": keystone.KS_MODE_64}
"mipseb": keystone.KS_MODE_MIPS32 | keystone.KS_MODE_BIG_ENDIAN,
"x86_64": keystone.KS_MODE_64, "intel64": keystone.KS_MODE_64}

ks_arch = arch_map.get(self.arch)
if self.arch == "armel":
Expand Down
18 changes: 5 additions & 13 deletions pyplugins/interventions/nvram2.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@

"""

from penguin import Plugin, plugins, PluginArgs
from penguin.abi_info import ARCH_ABI_INFO
from penguin import Plugin, plugins, PluginArgs, arch_registry
from penguin.abi_info import arch_abi_info
from pydantic import Field
import subprocess
import os
Expand Down Expand Up @@ -86,7 +86,7 @@ def add_lib_inject_for_abi(config, abi, cache_dir, proj_dir=None, build_log_path

arch = config["core"]["arch"]
lib_inject = config.get("lib_inject", dict())
arch_info = ARCH_ABI_INFO[arch]
arch_info = arch_abi_info(arch)
abi_info = arch_info["abis"][abi]
headers_dir = f"/igloo_static/musl-headers/{abi_info['musl_arch_name']}/include"
libnvram_arch_name = abi_info.get(
Expand Down Expand Up @@ -217,7 +217,7 @@ def add_lib_inject_all_abis(conf, cache_dir, proj_dir=None, build_log_path=None)
"""Add lib_inject for all supported ABIs to /igloo"""

arch = conf["core"]["arch"]
arch_info = ARCH_ABI_INFO[arch]
arch_info = arch_abi_info(arch)
for abi in arch_info["abis"].keys():
add_lib_inject_for_abi(conf, abi, cache_dir, proj_dir=proj_dir, build_log_path=build_log_path)

Expand Down Expand Up @@ -245,15 +245,7 @@ def add_lib_inject_all_abis(conf, cache_dir, proj_dir=None, build_log_path=None)
# than deriving it from musl_arch_name, because musl_arch_name reflects the
# headers directory (shared between endianness variants) not the loader
# filename (which encodes endianness: ld-musl-mipsel.so.1 ≠ ld-musl-mips.so.1).
_dylib_dir_overrides = {
"aarch64": "arm64",
"intel64": "x86_64",
"loongarch64": "loongarch",
"powerpc": "ppc",
"powerpc64": "ppc64",
"powerpc64le": "ppc64el",
}
dylib_dir = _dylib_dir_overrides.get(arch, arch)
dylib_dir = arch_registry.dylib_subdir(arch)
canonical_loader = f"ld-musl-{arch}.so.1"
actual_loaders = glob.glob(f"/igloo_static/dylibs/{dylib_dir}/ld-musl-*.so.1")
if actual_loaders:
Expand Down
13 changes: 12 additions & 1 deletion src/penguin/abi_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
),
),
),
intel64=dict(
x86_64=dict(
target_triple="x86_64-unknown-linux-musl",
libnvram_arch_name="x86_64",
default_abi="default",
Expand Down Expand Up @@ -192,3 +192,14 @@
),
)
)


def arch_abi_info(arch: str) -> dict:
"""
Look up ABI info for a config arch name or any accepted alias.

Normalizes via the arch registry so callers may pass e.g. ``intel64`` or
``x86_64`` (both resolve to the canonical ``x86_64`` entry).
"""
from penguin.arch_registry import spec
return ARCH_ABI_INFO[spec(arch).abi_key]
26 changes: 7 additions & 19 deletions src/penguin/arch.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,15 @@

def get_dylib_subdir(arch_name: str) -> str:
"""
Map a config arch name (e.g. "aarch64", "powerpc64le") to the subdirectory
under ``<static>/dylibs`` holding that arch's prebuilt dynamic libraries.
Map a config arch name (or alias) to the subdirectory under
``<static>/dylibs`` holding that arch's prebuilt dynamic libraries.

Dylibs are built/published under short, sometimes-distinct names that differ
from both the config arch name and the generic arch subdir, so this mapping
is the single source of truth for both patch generation and config templating
(the ``{{ dylib_dir }}`` template variable).
Thin wrapper over the arch registry (the single source of truth), kept for
backward compatibility with existing callers / the ``{{ dylib_dir }}``
template variable.
"""
if arch_name == "aarch64":
return "arm64"
if arch_name == "intel64":
return "x86_64"
if arch_name == "loongarch64":
return "loongarch"
if arch_name == "powerpc64le":
return "ppc64el"
if "powerpc" in arch_name:
return arch_name.replace("powerpc", "ppc") # dylibs use short names
# Fall back to the generic arch subdir (e.g. intel64 -> x86_64, mips* as-is).
from .utils import get_arch_subdir
return get_arch_subdir({"core": {"arch": arch_name}})
from .arch_registry import dylib_subdir
return dylib_subdir(arch_name)


@dataclasses.dataclass
Expand Down
Loading
Loading