Skip to content

MIPS64 real-ELF (glibc) support depends on upstream unicorn vtlb fixes (unicorn #2272/#2347, #2345/#2346) #1645

Description

@retrocpugeek

Summary

Real-world (glibc / PIE) MIPS64 ELF support in Qiling depends on two upstream unicorn fixes that are not yet in a released unicorn. This issue tracks that cross-repo dependency so the MIPS64 work can rely on it once unicorn ships the fixes.

The MIPS64 shellcode and freestanding (syscall-only) static ELF paths already work on stock pip unicorn. The glibc-ELF paths (dynamic + PIE binaries, TLS setup, pthreads) do not — they trip two bugs in unicorn's virtual-TLB (UC_TLB_VIRTUAL) code path.

Background: why Qiling needs UC_TLB_VIRTUAL for MIPS64

unicorn's MIPS64 CPU-MMU only executes in the low ~2 GB (useg); at/above 0x80000000 it raises an address exception. But real n64 ELFs link at 0x120000000 (~4.8 GB) and PIE binaries load at 0x555555…, and Qiling's 64-bit profile places stack/mmap above 4 GB. The fix (in qiling/arch/mips64.py) is to switch the MIPS64 engine into UC_TLB_VIRTUAL mode with an identity-mapping UC_HOOK_TLB_FILL callback, which bypasses the CPU-MMU segment checks while keeping virtual == physical, so Qiling's flat memory model works unchanged.

Enabling that soft-TLB path is what exposed the two unicorn bugs below.

Blocking unicorn bugs

1. Spurious EXCP_RI after a delay-slot TLB fill — unicorn issue #2272, fix PR #2347.

glibc's __libc_setup_tls scans the program headers for PT_TLS using a bbne "branch-onto-branch" (back-to-back delay slots). Under UC_TLB_VIRTUAL, unicorn_fill_tlb() unconditionally called cpu_restore_state(); on a successful fill this re-injected the branch-delay hflags (MIPS_HFLAG_B|BDS32) into the live env, so the next translation block (the branch target) was generated with BMASK set → spurious Reserved-Instruction exception (intno 20). The RI vectors PC→0 and Qiling dies with UC_ERR_FETCH_UNMAPPED. The fix removes the unconditional restore (the exception path still restores via cpu_loop_exit_restore). (unicorn's own PR #2273 attempted #2272 but only covered the no-hook fallback path; #2347 fixes both the hooked and unhooked cases.)

2. Spurious AdEL on ll/lld from high addresses — unicorn issue #2345, fix PR #2346.

Right after TLS setup, glibc takes an ll/sc spinlock. ll/lld are emitted as helpers that perform the load through the soft-TLB (works), but also call do_translate_address purely to set CP0_LLAddr — and that walks the MIPS segments (xuseg, UX unset for a >2 GB address) → TLBRET_BADADDR → spurious address error (intno 12). The fix skips the segment-walking translate in vtlb mode and records the hook-mapped physical address into CP0_LLAddr instead (alignment check preserved, so a genuinely misaligned ll still faults correctly).

Both are contained to the UC_TLB_VIRTUAL path (not present in upstream QEMU, which has no such mode) and are in the same family.

Impact / CI gating

  • ✅ MIPS64 shellcode and freestanding static ELF tests pass on stock pip unicorn 2.1.3 and are safe for CI today.
  • ⛔ MIPS64 glibc-ELF tests (dynamic + PIE binaries, statx/stat64 end-to-end, multithreading) require the two unicorn fixes above and will fail on stock unicorn / CI until unicorn ships them in a release.

The eventual (reopened) MIPS64 arch PR should keep the glibc-ELF tests gated/held until a unicorn release includes both fixes, then flip them on and reference this issue.

Related Qiling fixes (independent — run on stock unicorn)

These were found while bringing MIPS64 up but are standalone and do not depend on the unicorn fixes: #1633 (statx big-endian), #1635 (getdents alignment), #1638 (clone3), #1640 (MIPS socket options).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions