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 b→bne "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).
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_VIRTUALfor MIPS64unicorn's MIPS64 CPU-MMU only executes in the low ~2 GB (
useg); at/above0x80000000it raises an address exception. But real n64 ELFs link at0x120000000(~4.8 GB) and PIE binaries load at0x555555…, and Qiling's 64-bit profile places stack/mmap above 4 GB. The fix (inqiling/arch/mips64.py) is to switch the MIPS64 engine intoUC_TLB_VIRTUALmode with an identity-mappingUC_HOOK_TLB_FILLcallback, 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_RIafter a delay-slot TLB fill — unicorn issue #2272, fix PR #2347.glibc's
__libc_setup_tlsscans the program headers forPT_TLSusing ab→bne"branch-onto-branch" (back-to-back delay slots). UnderUC_TLB_VIRTUAL,unicorn_fill_tlb()unconditionally calledcpu_restore_state(); on a successful fill this re-injected the branch-delayhflags(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 withUC_ERR_FETCH_UNMAPPED. The fix removes the unconditional restore (the exception path still restores viacpu_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
AdELonll/lldfrom high addresses — unicorn issue #2345, fix PR #2346.Right after TLS setup, glibc takes an
ll/scspinlock.ll/lldare emitted as helpers that perform the load through the soft-TLB (works), but also calldo_translate_addresspurely to setCP0_LLAddr— and that walks the MIPS segments (xuseg,UXunset 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 intoCP0_LLAddrinstead (alignment check preserved, so a genuinely misalignedllstill faults correctly).Both are contained to the
UC_TLB_VIRTUALpath (not present in upstream QEMU, which has no such mode) and are in the same family.Impact / CI gating
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).