Commit Graph
71 Commits
Author SHA1 Message Date
Ole André Vadla Ravnås 0659f5f14e core: Expose virtual machines to LLMs 2026-10-01 20:49:11 +02:00
Ole André Vadla Ravnås 660946f2c0 Share VM keystroke events 2026-10-01 20:49:11 +02:00
Ole André Vadla Ravnås 78789032c2 emulator: Convert display frames off main actor
The per-frame RGBA-to-BGRA conversion ran on the main actor
and starved the async continuations that drive injection, so
attaching to a booted emulator stalled. Move it into
nonisolated helpers that adopt() awaits, and mark
SharedFrameBuffer Sendable so it can cross the actor hop.
2026-09-30 15:12:13 +02:00
Ole André Vadla Ravnås 6a4389b5cb core: Drop a stale single-core comment 2026-09-28 17:35:15 +02:00
Ole André Vadla Ravnås f599f7c785 core: Stream the emulator at its native size 2026-09-28 17:35:15 +02:00
Ole André Vadla Ravnås 7a4174a9a8 core: Detect guest vsock by a real symbol
hasSymbol("vsock") never matches; probe vsock_core_register
so a mined kernel is reached over vsock, not hostlink.
2026-09-28 00:39:25 +02:00
Ole André Vadla Ravnås 9b3f31d20b core: Stop the boot hanging on emulator exit
Race adb wait-for-device against the launcher exiting, so a
failed launch fails fast rather than blocking forever, and
reap the qemu by its gdb port when a boot dies before it
records the pid.
2026-09-28 00:39:19 +02:00
Ole André Vadla Ravnås 4aa17098b2 core: Speed up and simplify the VM picker
templates and availability spawned `emulator -list-avds` on every
render, so opening the boot sheet -- and clicking a template, which
re-queries them all -- stuttered for seconds. Cache the listing and
warm it off the main thread when the picker or sheet appears.

Collapse the two per-architecture Android entries into one; the
chosen AVD now decides the architecture, retiring the message that
wrongly claimed Frida could only instrument the other one.
2026-09-27 17:55:08 +02:00
Ole André Vadla Ravnås b6e2fff8a2 core: Fail when a machine's device can't be added
Shut the machine down again when booting, and record the ready snapshot
before re-adding the device when marking it ready.
2026-09-26 21:54:46 +02:00
Ole André Vadla Ravnås f6ae01c34f core: Tell a System.map from a kernel image
QEMU hands over a System.map, which LinuxKernelImage cannot read, so no
barebone device was added. Let each machine say which kind it has.
2026-09-26 21:54:46 +02:00
Ole André Vadla Ravnås 193dc6b13f core: Build the HTTP/2 config before capturing it 2026-09-26 21:10:18 +02:00
Ole André Vadla Ravnås 9d923db798 core: Keep the emulator display off iOS
Only its machine uses it, and that is desktop-only already. On iOS
there is no home directory to find the running AVDs in.
2026-09-25 19:12:26 +02:00
Ole André Vadla Ravnås 5dc3e1b823 core: Keep the frame mapped while it is read
Closing the display unmapped the shared frame at once, but cancelling a
task only asks it to stop: a screenshot already in flight goes on to read
through the base address, and the process dies on a page that is no
longer there.

Let the mapping go when the last reader does.
2026-09-21 12:36:20 +02:00
Ole André Vadla Ravnås a64f4ad36f core: Let x86_64 AVDs be instrumented
Injection works end to end on the emulator's x86_64 kernel now, over
the virtio-serial hostlink.
2026-09-19 16:45:15 +02:00
Ole André Vadla Ravnås 12726d5327 core: Skip the vsock probe on Windows
Inflating and scanning the kernel image to see whether it names vsock
takes some 28 seconds, and the launch waits for it. On Windows the
answer changes nothing: the transport is the virtio-serial hostlink
either way. A run of the emulator check goes from 66 to 39 seconds.
2026-09-19 16:45:15 +02:00
Ole André Vadla Ravnås 19d7ff0416 core: Let the emulator's kernel log be read
An agent that oopses inside the guest looks like one that hangs while
the emulator's output is thrown away. FRIDA_EMULATOR_KERNEL_LOG names
a file to collect it in.
2026-09-19 16:45:03 +02:00
Ole André Vadla Ravnås cce9f40a4f core: Take the kernel image as an object
frida-core now reads a kernel once and answers what it names, so the
image config carries that rather than a path, and the vsock probe asks
it for the symbol instead of searching the image for the word.

That probe was never a symbol lookup: kallsyms stores its names
compressed, so the match came from whatever else in the kernel happens
to spell vsock. It took an LZ4 inflater of its own to look, which goes
with it.
2026-09-17 19:41:59 +02:00
Ole André Vadla Ravnås d9d83fa3db core: Keep x86_64 AVDs out until injection lands
An x86_64 AVD boots and streams, and its kernel now gives up its
symbols, but the agent never reaches it: the backend parks on a
breakpoint at schedule() that is never reported hit. The gate was
widened while that was being chased and should not have been.
2026-09-17 15:28:01 +02:00
Ole André Vadla Ravnås f89d31aa9d core: Order OS checks Windows, macOS, Linux
The house order was not kept where these were first written.
2026-09-17 13:15:53 +02:00
Ole André Vadla Ravnås c0cca3c16d core: Carry the emulator's QMP over TCP
QEMU's named-pipe chardev on Windows delivers what it writes and never
reads what is sent back, so the QMP handshake cannot complete over one.
A loopback port works, and with `server,nowait` QEMU no longer holds
the machine still until something connects -- so the pipe is opened,
held and handed down no longer.
2026-09-17 13:13:47 +02:00
Ole André Vadla Ravnås 87485eb0e5 core: Reach the emulator's hostlink on Windows
The emulator bridges a guest's vsock to a host UNIX socket, which
Windows has none of, so the guest is reached over the virtio-serial
hostlink there whatever its kernel offers. That channel is opened
through QMP, which QEMU serves over a named pipe on Windows -- and it
holds the machine still until something connects to that pipe, then
gives the pipe up for good once the connection goes.

So the pipe is opened here, as soon as QEMU is spawned and before the
guest is waited on, and held for the barebone backend to adopt by
handle. Waiting for adb first would have deadlocked: the guest cannot
boot until the pipe is answered.

The transport carries the QMP address as a string now rather than a
socket URL, since each host spells it differently.

Also drops the single-core launch, which nothing turned out to need.
2026-09-17 13:13:47 +02:00
Ole André Vadla Ravnås b7b59e57b0 core: Drop a stale note on the ABI gate
frida-core now skips the emulator instrumentation off Darwin and
carries an i386-64bit feature document, so the aarch64 gdbstub shim
is no longer what keeps an x86_64 AVD out. Its kallsyms parser still
wants a raw or gzipped arm64 Image, which an LZ4-packed x86 bzImage
is not, so the gate stays as it is.
2026-09-17 13:13:47 +02:00
Ole André Vadla Ravnås 53813d1505 core: Take the AVD's own ABI, not arm64
An AVD's config names the ABI it boots, and the agent that gets
injected has to match it, so the ABI is read rather than assumed and
the flavor follows from it. Everything on a Windows host is x86_64,
where the old arm64 assumption would have asked for an agent that
does not fit.

Which is as far as it goes for now: Frida reaches the emulator's QEMU
through a gdbstub shim that resolves aarch64_cpu_gdb_write_register,
so an x86_64 guest boots, streams its display and reports its stub,
then fails inside instrumentation. The backend offers only what can
actually be injected into, and says which ABIs it did find when that
leaves nothing:

    Frida can only instrument arm64 AVDs, and the ones installed are
    x86-64. Create one in Android Studio.
2026-09-17 13:13:47 +02:00
Ole André Vadla Ravnås 761ee194fb core: Run the Android emulator on Windows
The emulator's control channel was the only thing pulling grpc-swift
in, and with it swift-nio-ssl, which does not build on Windows at all
-- it has no branch for the platform and its PosixPort reaches for
mlock, lstat and readlink. Nothing here wants TLS: the endpoint is
plaintext on the loopback, and only seven calls are ever made.

So the wire is spoken directly. GRPCConnection opens one HTTP/2
stream per call over swift-nio-http2 and frames length-prefixed
protobuf into it; EmulatorControlClient names the seven. That drops
grpc-swift-2, grpc-swift-nio-transport, grpc-swift-protobuf and
swift-nio-ssl from the graph, along with 7840 lines of generated
service stubs. The generated messages stay.

The rest is what running it on Windows turned up:

  - AVD discovery split on "\n" and trimmed only .whitespaces, so
    every name kept a trailing \r and every AVD was dropped.
  - An AVD config spells its paths with backslashes, which URL keeps
    as ordinary characters rather than separators.
  - emulator and adb want .exe, and the SDK sits under LOCALAPPDATA.
  - Port reservation and process lookup move into HostPort and
    HostProcessLookup, which QemuMachine's two copies also wanted.
  - The launcher re-execs into QEMU there, so the discovery ini is
    named after that process; the one naming this launch's debug port
    is taken when the launcher's own is absent.

Frames still arrive through a mapping rather than the socket:
CreateFileMapping backs the same file:// handle the emulator is
handed elsewhere.

A guest without vsock is refused outright on Windows, where the
virtio-serial fallback would ask QEMU for a QMP UNIX socket and be
told "unix sockets are not available on windows".

LUMA_EMULATOR_DISPLAY_ONLY drives launch, control and streaming
without a guest agent. Against a Pixel_2 AVD it reports a 1080x1920
first frame and nine more in three seconds.
2026-09-17 13:13:47 +02:00
Ole André Vadla Ravnås 27cf387cc6 core: Find symbols in an LZ4-packed kernel
Android builds its x86 kernels with CONFIG_KERNEL_LZ4, so the payload
is neither gzip nor a PE and the image the scan sees is the bare
bzImage, which names none of the kernel's symbols. Teach the scan the
LZ4 legacy frame and add names(_:in:) for asking whether a kernel has
a symbol at all.

The emulator's own android-30 x86_64 kernel-ranchu is such an image:
39MB of payload behind an LZ4 stream at offset 16106, with "vsock"
inside it and nothing to find outside.
2026-09-17 13:13:46 +02:00
Ole André Vadla Ravnås e749791229 Follow the versioned barebone asset names
The agents ship as frida-barebone-agent-<version>-<flavor>.xz now, and
winnt on arm64 joins the flavors.
2026-09-16 19:17:40 +02:00
Ole André Vadla Ravnås 190a442c79 core: Reap the emulator's QEMU on shutdown
The emulator launcher hands QEMU off to launchd, so terminating
the launcher leaves the VM and its injected helper running.
Kill the QEMU process directly.
2026-09-16 19:17:40 +02:00
Ole André Vadla Ravnås 93f668d144 core: Control the Android emulator over gRPC
Drive the emulator's gRPC control API: stream its screen into an
embedded display through a shared-memory frame transport sized from the
device's reported resolution, re-opened when a notification says it
changed; forward pointer and key input; and take ready snapshots with
the SnapshotService.
2026-09-16 19:17:40 +02:00
Ole André Vadla Ravnås 899a6e325d core: Inflate the AVD kernel off the main thread
kernelSupportsVsock spawns gzip and reads back the whole kernel; on the
main thread it froze the boot -- gzip's output filled the pipe before
the write finished, wedging both ends. Feed gzip off-thread while
draining it, and run the whole inspection off the main actor.
2026-09-16 19:17:40 +02:00
Ole André Vadla Ravnås 2a4b2dcdb3 core: Route old AVD kernels over virtio-serial
A guest kernel without vsock cannot use the pipe-vsock transport, so
inspect the AVD's kernel image and, when it names no vsock, launch the
emulator single-core and hand the agent a virtio-serial port it drives
over the guest's PCIe config space at the ranchu ECAM base.

Boot from FRIDA_EMULATOR_SNAPSHOT when set, for a fast iteration loop.
2026-09-16 19:17:40 +02:00
Ole André Vadla Ravnås 4975f53fa9 core: Add an Android emulator VM backend
Launch an AVD made in Android Studio with a GDB stub, find its QEMU by
the debug port on its command line, and report the stub, kernel image
and hostlink so Frida can attach. The user picks from the AVDs the
emulator lists; the kernel image is mined for symbols, so none is asked
for.
2026-09-16 19:17:40 +02:00
Ole André Vadla Ravnås eb5026309e core: Map the Android emulator debug stub
Add the androidEmulator debug stub and the pipe-over-vsock agent
transport, and map both onto their barebone config: the connection
carries the hosting QEMU's pid so the backend can instrument its
gdbstub, and the guest dials out to a host socket for the hostlink.
2026-09-16 19:17:40 +02:00
Ole André Vadla Ravnås 7e395a14bf Find PATH by the name Windows gives it
Windows calls it Path, so looking the variable up as PATH found
nothing and set a second one beside it holding only the installation
directory. Names are matched without regard to case, so the emulators
were handed whichever came first and could not see the libraries the
app had lined up for them.

Read and write the name that is already there, and lay the block out
the way CreateProcessW asks, so a pair that differs only in case
cannot change places.
2026-09-15 13:45:09 +02:00
Ole André Vadla Ravnås 24ef5a3ad6 Inflate gzip through zlib
Off Apple this ran /usr/bin/env gzip, which Windows answers the way
it answered xz: no such file. The Alpine arm64 kernel is gzipped, so
that starter image could not be unpacked at all.

Drop the gzip packaging with it -- no template asks for it, and the
kernels that are wrapped come through LinuxKernelImage.
2026-09-15 13:45:09 +02:00
Ole André Vadla Ravnås fa1416e3bc Spawn children without a console
Foundation calls CreateProcessW with CREATE_UNICODE_ENVIRONMENT and
nothing else, and offers no way to add to that. The app has no
console of its own, so every console child it started -- an
emulator, qemu-img, the agent CLI -- was given a fresh command
prompt to look at.

Spawn through ChildProcess instead, which asks for CREATE_NO_WINDOW
on Windows and is Process everywhere else.
2026-09-15 13:45:03 +02:00
Ole André Vadla Ravnås 4767b7ded0 ci: Build QEMU on Windows from source
The emulators were downloaded from a qemu-<build> release built in
MSYS2 against MinGW's GLib and pixman, so the installer carried
those beside the vcpkg ones the app links: two copies of GLib and
friends.

Build them in the Windows job instead, against the vcpkg prefix,
cached like the other dependencies on the QEMU version and the
build script. QEMU builds under MinGW and nowhere else on Windows,
but UCRT64 and CLANGARM64 sit on the same C runtime as the MSVC
DLLs they now link, so a descriptor means the same on both sides.
The x86_64 environment moves from MINGW64 for that reason.

The emulators live a directory below the app, where nothing looks
for its GLib on its own, so they are started with the installation
root on PATH.

Windows drops out of the QEMU workflow, which macOS still uses.
2026-09-15 13:45:03 +02:00
Ole André Vadla Ravnås 9a545579f7 Say why a download failed
A rejected response became a file-does-not-exist error, and both
libraries then threw the cause away and guessed at it: a refused
agent was reported as one nobody had published.

Name the status the server answered, and carry it through.
2026-09-15 13:45:03 +02:00
Ole André Vadla Ravnås c2164543a8 core: Fix the socket type on Linux
SOCK_STREAM is __socket_type there.
2026-09-10 21:41:04 +02:00
Ole André Vadla Ravnås cfc7a1d960 core: Build the macOS guest on arm64 only
Virtualization's macOS-guest API is not there on Intel.
2026-09-10 21:41:04 +02:00
Ole André Vadla Ravnås 7df308f30c core: Keep QEMU off iOS
Nothing there spawns a process, and the machine UI is AppKit's.
2026-09-10 16:29:56 +02:00
Ole André Vadla Ravnås 479f285daa core: Point a bundled QEMU at its firmware
Only Windows looks for it beside the executable, so a copy travelling
with the app comes up without its romfiles anywhere else. Pass -L when
a share directory sits next to the emulator.
2026-09-10 13:37:04 +02:00
Ole André Vadla Ravnås ecec162552 core: Give USB guests a keyboard
Machines without PS/2 got a tablet and nothing to type on. Plug in
usb-kbd beside usb-tablet, and rename the enum for what it decides.
2026-09-10 12:51:32 +02:00
Ole André Vadla Ravnås 960f619b7e Merge the Windows templates into one
Fold the 32- and 64-bit guests under one Windows NT template, the
way the Linux guests already group.
2026-09-08 18:54:43 +02:00
Ole André Vadla Ravnås ee2fbf0868 Reach the guest agent over its named fabric
Adopt the reworked Barebone config, where a guest names how its
hostlink is reached and the agent takes its image as bytes.
2026-09-08 18:54:43 +02:00
Ole André Vadla Ravnås bbc3baaf83 Drop the Linux kernel virtualization template
Retire the VZ arm64 template and its orphaned starter images.
2026-09-08 18:54:43 +02:00
Ole André Vadla Ravnås cca3d46b87 Find a kernel's version in its gzipped payload
Scan the gzip streams for the banner when the kernel hides it.
2026-09-08 18:54:43 +02:00
Ole André Vadla Ravnås b7bd64e79f Show the Linux guest on its own console
Add console=tty0 so the kernel paints the display, not only the
serial line left blinking a cursor.
2026-09-08 18:54:43 +02:00
Ole André Vadla Ravnås ceb1baf2dd Settle a machine while it is stopping
Keep a stopping machine listed until its shutdown returns, guard
against a second stop, and let the button say so and go quiet
instead of firing again.
2026-09-08 18:54:43 +02:00
Ole André Vadla Ravnås 7f2a39a6d5 Type the shifted characters into a machine
Map the shifted row so keys like ':' reach the guest, and hold
shift around a stroke that needs it. Send a character on its own
key-down, tapping down and up, rather than tracking its phases.
2026-09-08 18:54:43 +02:00
Ole André Vadla Ravnås 225e703595 Pick and update the barebone agent version
Read the version stamped into a fetched agent's note, and list the
last releases from GitHub to learn what each flavor has published.

Offer the latest to download, name it on the button, and show an
update once a newer one lands. Drop the pinned version constant.
2026-09-08 18:54:43 +02:00