Conversation
getdents64 wrote linux_dirent64 records with d_reclen = header + name, without rounding up to the alignment of the leading u64 d_ino. The next record's d_ino then lands unaligned, and a strict-alignment guest (e.g. MIPS/MIPS64) faults with UC_ERR_READ_UNALIGNED when walking the buffer. x86 tolerates the unaligned load, which is why this was never caught. Round d_reclen up to the d_ino alignment, matching the kernel. The rounding is scoped to the getdents64 (is_64) branch only: getdents64 places d_type before d_name so the trailing pad bytes are inert, whereas the legacy getdents layout stores d_type at offset d_reclen-1 and would break if padded the same way -- that is what got the earlier blanket fix (PR #1419) reverted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Calls ql_syscall_getdents64 on a directory and walks the returned linux_dirent64 records, asserting every record (and thus its leading u64 d_ino) starts on an 8-byte boundary. Before the fix d_reclen was not rounded up, so records were misaligned and a strict-alignment guest (e.g. MIPS) faulted with an unaligned load. Self-contained; runs on stock unicorn. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Modern glibc (recent toolchains) issues clone3 from pthread_create rather than clone, so thread creation fails on any guest built against it: Qiling does not return -ENOSYS for unimplemented syscalls (it logs a warning and leaves the return register untouched), so glibc's clone3->clone fallback never fires. Add ql_syscall_clone3, which unpacks struct clone_args and delegates to the existing clone() handler. Translations: child_stack = stack + stack_size (clone3 passes the stack base plus a size; legacy clone wants the highest address), exit_signal folded into the flags' CSIGNAL byte, and an x8664 pre-swap that cancels ql_syscall_clone's arch-specific newtls<->child_tidptr swap. Add a self-contained regression test (test_clone3_translates_to_clone) that drives ql_syscall_clone3 directly and asserts the translation for both the generic path and the x8664 swap. Runs on stock unicorn; no clone3 binary needed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extend the record alignment to the legacy getdents path. The kernel rounds both getdents and getdents64 records up to the alignment of their leading d_ino (ALIGN(reclen, sizeof(long))); without it a strict-alignment guest (MIPS) faults walking the buffer, e.g. older glibc busybox 'ls' (which uses the legacy getdents syscall) crashes on directory listings. Legacy linux_dirent stores d_type in the record's last byte (offset d_reclen-1), so the alignment padding goes between d_name and d_type to keep d_type there -- padding without relocating d_type is what got the earlier blanket attempt (PR #1419) reverted. getdents64 (d_type before d_name) is unchanged. Add test_linux_getdents_alignment: walks legacy getdents records on a big-endian MIPS guest and asserts each is aligned, tiles the buffer, and keeps d_type (DT_DIR for '.'/'..'). Runs on stock unicorn. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
linux_mips_socket_options used generic/incorrect values. MIPS has its own SO_* numbering (arch/mips/include/uapi/asm/socket.h) with the buffer/timeout/ type options in the 0x1000 range. The table listed SO_SNDBUF=0x01, SO_RCVBUF=0x02 (should be 0x1001/0x1002), SO_SND/RCVLOWAT and SO_SND/RCVTIMEO_OLD all wrong, SO_RCVLOWAT=0x04 silently collided with SO_REUSEADDR (Enum alias), and SO_OOBINLINE/SO_REUSEPORT were 0x00. A guest setsockopt(SOL_SOCKET, SO_RCVBUF, ...) (e.g. busybox ping) therefore raised 'Could not convert emulated socket option 4098'. Correct all values to the MIPS uapi and add the missing SO_TYPE/SO_ERROR/SO_ACCEPTCONN/SO_PROTOCOL/ SO_DOMAIN. Add test_elf.ELFTest.test_setsockopt_mips_so_rcvbuf: opens a socket on a MIPS guest and asserts setsockopt(SOL_SOCKET, SO_RCVBUF) succeeds. Self-contained, runs on stock unicorn; fails on dev, passes with the fix. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add AGENT documentation.
call_dll_entrypoint() caught the DllMain UcError and restored registers but left ql._state at STARTED, since emu_start() only clears it on success. The 'emu_state is not STARTED' gate then silently skipped DllMain for every DLL loaded afterward. Reset the state to STOPPED on the exception path.
FiberManager.free/set/get set `self.last_error` on the FiberManager instance, but nothing ever reads that attribute. The Windows last-error that GetLastError returns lives on `ql.os.last_error`, so FlsFree, FlsSetValue and FlsGetValue never actually reported ERROR_INVALID_PARAMETER for an invalid FLS index. Route the three writes to `self.ql.os.last_error`, consistent with every other kernel32 hook. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Jvle <keke.oerv@isrc.iscas.ac.cn>
Signed-off-by: Jvle <keke.oerv@isrc.iscas.ac.cn>
Signed-off-by: Jvle <keke.oerv@isrc.iscas.ac.cn>
Signed-off-by: Jvle <keke.oerv@isrc.iscas.ac.cn>
The first line reads `from future import __annotations__`, with the module name and the imported symbol swapped. The intent was clearly the PEP 563 future statement `from __future__ import annotations`. As written, the line fails in both possible situations: - without the third-party `future` package installed (the common case), the import raises `ModuleNotFoundError`, so `QILING_IDA` is never defined; - with that package installed, the import silently succeeds but binds the module's empty `__annotations__` dict, so PEP 563 is *not* enabled — while the annotations in this file (`ql: Qiling`) rely on it, `Qiling` being imported under `TYPE_CHECKING` only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pru9dwqPVrDakERYZwzjUx
handle_s answered every single-step ('s') with a SIGTERM stop-reply
whenever ql.emu_state was QL_STATE.STOPPED. But emu_start always leaves
the state STOPPED after running the requested step count, so the guard
was true on every step and gdb clients saw a spurious termination signal,
disconnecting mid-debug (issues #1377, #1538).
Give handle_s the same exit-vs-trap discrimination handle_c already uses:
a step reports SIGTRAP unless it carried pc to the emulation exit point,
in which case the guest has actually terminated and we reply W{exit_code}.
Also wrap the step in the same UcError/KeyboardInterrupt handling as
handle_c so a fault while stepping maps to a signal instead of crashing
the stub, and hoist the shared uc-error->signal map to a module constant.
Add a regression test that single-steps over the gdb stub and asserts the
stop-reply is 'S05' (SIGTRAP), which fails as 'S0f' (SIGTERM) without the fix.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The stub drove continue by calling emu_start synchronously and only read the socket again once the target stopped on its own, so the bare \x03 break byte a client sends to pause a running target was never seen. A guest that free-runs (e.g. an idle/event loop) could not be interrupted at all -- gdb/Ghidra reported 'Cannot execute this command while the target is running'. Poll the client socket for the break byte from the per-instruction run hook (dbg_hook), which does run on the emulation thread during emu_start: - GdbSerialConn.poll_interrupt(): non-blocking select+recv, True on \x03. - QlGdbUtils.dbg_hook: throttled (every INTR_POLL_INTERVAL insns) check of an installed check_interrupt callback; on a break, stop emulation and record it. - handle_c: reply SIGINT when the stop was an interrupt rather than a breakpoint or normal exit. Add a regression test that lets an infinite-loop guest free-run, sends the bare break byte and asserts the stop-reply is 'S02' (SIGINT). Without the fix no reply ever arrives, so the test stops the guest itself and fails rather than hanging the run. Also verified against a free-running MIPS64 BE guest: \x03 -> S02 in <1ms. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A client that resumes while a signal is pending sends a vCont action of the form 'C<sig>' (continue and deliver) or 'S<sig>' (step and deliver), e.g. 'vCont;S0f:pa410.1996;c:pa410.-1' -- the exact packet reported in issue #1377. handle_v matched only 'c'/'C05' and 's'/'S05', so any other signal fell through to an empty reply and clients aborted the session with 'Invalid remote reply:'. We do not deliver host signals to the guest, so the signal value carries no meaning for us: accept any of them and carry the action out as a plain resume or step, which is what the client asked for. This matters more now that the stub can stop with SIGINT on an async interrupt, since a client may well resume from such a stop with 'C02'. Also stop assuming os.exit_code exists when reporting termination: bare-metal os layers (QlOsMcu) do not define it, which turns the exit path into an AttributeError (seen in issue #1276). The underlying MCU interrupt handling of #1276 is out of scope here. Add a regression test asserting the '#1377' packet is answered with a SIGTRAP stop-reply and that a signalled continue runs the guest to termination; both replies are empty without the fix. Fixes #1377 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gdb: fix stop-replies for step, signalled vCont resume, and ctrl-c interrupt
update new ARCHITECTURE docs
Fix broken __future__ import in IDA plugin custom_script
feat: add qdb riscv support
feat: add riscv debugger support
Fix FLS FiberManager writing last_error to a dead attribute
Implement the clone3 syscall
Align getdents and getdents64 records to fix unaligned access on MIPS
…state Reset emu state after a failing DllMain
Fix MIPS socket option (SO_*) values
implement FlsGetValue2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist
Which kind of PR do you create?
Coding convention?
Extra tests?
Changelog?
Target branch?
One last thing