Commit Graph
187 Commits
Author SHA1 Message Date
Ole André Vadla Ravnås 3d20980966 ui: Read more memory when a decode runs out 2026-10-01 20:49:11 +02:00
Ole André Vadla Ravnås a3cdd5df5f core: Derive the approval-gated tool list 2026-10-01 20:49:11 +02:00
Ole André Vadla Ravnås f96764edf7 ui: Move insight refreshes to the sidebar menu 2026-10-01 20:49:11 +02:00
Ole André Vadla Ravnås 3f70d259d3 core: Persist pattern placements
Store them with the REPL cell and the address insight, as a JSON
column each, and bind the decode view to them. Older rows and wire
cells without the field decode as none.
2026-10-01 20:49:11 +02:00
Ole André Vadla Ravnås f2883eb24c core: Add a pattern library and decoder
Scan the data directory's Patterns folder for .hexpat and .pat files,
and describe and decode them through Frida.PatternCompiler.
2026-10-01 20:49:11 +02:00
Ole André Vadla Ravnås 8d12aa4d7f core: Carry the app icon on a spawn target 2026-09-28 17:35:15 +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 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 8d8ca30a76 core: Track how connecting to a device is going
A device connects on the first call that reaches it, and on the
Barebone backend that can take a while. Follow every discovered
device's connecting and connected events into a ConnectionActivityCenter
keyed by device id, holding the current stage, its fraction, and how
long the stage is expected to take. StageDurationMemory learns the
duration of each stage from what it observes, so a frontend can pace a
progress bar over the expected time rather than jumping between stages.
2026-09-16 13:00:08 +02:00
Ole André Vadla Ravnås b092b17bc2 core: Fix disassembling what the map misses
Open through the r2 command so what it opens is mapped: the
disassembler skips whatever falls outside a map, and reading is not
enough. Drop the bin load, which only sniffed formats at address zero.

Let a failed read say so instead of returning null, remember the pages
that have none, and resolve an anchor live or not at all -- a stale
address lands on whatever occupies it now.
2026-09-10 16:30:19 +02:00
Ole André Vadla Ravnås 21121accb1 disassembler: Ask the agent for functions only
Analysis pulled every export, import and symbol across the wire
and then kept the handful that name code -- 87k rows for a
kernel, each carrying a type and an address as text.

Ask for what it uses instead: the offset, name and source of each
function the module knows about, chosen where the rows already
are.
2026-09-09 23:27:01 +02:00
Ole André Vadla Ravnås b88a9be290 Replace SwiftyMonaco with native editors
Drop the Monaco webview. Edit in a GtkSourceView on GTK and in a
native text view on Apple, both speaking to Frida.Compiler's
in-process language server for completions, signature help,
hovers and diagnostics.

Color, complete and indent code natively, matching the GitHub
theme in light and dark.
2026-09-08 19:52:31 +02:00
Ole André Vadla Ravnås 9bf7783159 Boot virtual machines on Windows too
QEMU's D-Bus display is there, and so is a Windows path through it
that never passes a descriptor: the console socket goes over QMP as
protocol info, the listener socket the same way through
RegisterListener, and a scanout arrives as a section handle QEMU has
already duplicated into us. The frame is still the guest's own
memory, mapped read-only, so nothing is copied to reach the screen.

The executable was looked for by splitting PATH on a colon, which on
Windows is what a drive letter ends with.
2026-09-08 18:54:43 +02:00
Ole André Vadla Ravnås 0e933206fb Boot virtual machines from the target picker
Add a machine abstraction to LumaCore, with QEMU as its first
backend: templates mirroring frida-core's test guests, a QMP client,
and a display that maps QEMU's surface over D-Bus rather than
copying frames.

Leave readiness to the user: drive the guest, mark it ready, and come
back to that snapshot later. Keep the machine in the project, so
booting it again resumes where it was marked. Hand the stub to
addBareboneDevice, so it joins the picker beside the other devices.

Show the display while booting, and afterwards in a Machines panel,
which the side panel now models as an enum to share its slot.
2026-08-20 14:52:52 +02:00
Ole André Vadla Ravnås f8d25015ae Drop the comments that only restate the code
A comment is a last resort, and these were not one: section banners,
doc headers naming what the declaration below already names, and
notes saying in prose what the next line says in code.

What is left is what the code cannot show -- an ordering that matters,
a platform quirk, why the obvious way fails.
2026-08-13 13:09:18 +02:00
Ole André Vadla Ravnås 4f7f06e57d Follow frida-swift's regenerated API
Take the regenerated bindings on both frontends.
2026-08-13 12:46:09 +02:00
Ole André Vadla Ravnås b6ee7d7187 Put the whole surface on iOS too
The playground, the notebook cells, the source editor with its
marks, the inspector columns and the canvas are written once for
both Apple platforms, with a file naming what the two frameworks
call differently. The editor is where they really part company.

The engine owns the image and its start-up, so a mission reaches
the whole of Pharo.
2026-08-13 12:46:09 +02:00
Ole André Vadla Ravnås ad7ffcdabc Add a synthesiser that sounds arriving events
Eight channels, each with its own patch and pattern on its own step
clock, mixed on the audio device's thread: storage allocated once,
reached through unsafe pointers, and a lock-free ring for control,
so nothing under the callback allocates, retains or locks.

The image performs a tune, names it, and sounds chords.
2026-08-13 12:46:09 +02:00
Ole André Vadla Ravnås 2528c8fed2 Keep a snippet and its result in the notebook
A notebook cell holds a Pharo snippet and what it produced, updated
field by field and synced back when it is re-run. Trace blobs move
to a store of their own, read through one loader.

The method mark's editor keeps its own keys and clicks, so editing
inside an opened body works like editing anywhere else.
2026-08-13 12:46:09 +02:00
Ole André Vadla Ravnås cd4e350dbf core: Fix crash stripping CRLF from process output
"\r\n" is a single Character, so removeLast(2) overran a lone-CRLF
string and also clipped a real character otherwise. Drop the one
trailing newline grapheme.
2026-07-10 18:40:22 +02:00
Ole André Vadla Ravnås 86b6040585 core: Share one itrace drain script per device
Hoist the system-session drain script out of ProcessNode into a
per-device SystemDrainService owned by Engine. Multiple targets on
a device now drain their ringbuffers through a single PID 0 script
instead of one attach and script each. Retire the service when its
last node goes away.
2026-07-10 16:29:36 +02:00
Ole André Vadla Ravnås 2e1b2c3d92 core: Create itrace drain script lazily
Attach to the system session and load the drain script on the
first trace, not at every process attach. Most sessions never
use itrace and need not touch PID 0.
2026-07-10 16:29:32 +02:00
Ole André Vadla Ravnås 5d1ed175fe core: Prepare attaching sessions in the engine
Frontends built the session record, set its phase and surfaced it,
briefly showing the detached banner at the idle phase before attach
began. Move construction, phase and surfacing into prepareSpawnSession
and prepareAttachSession so the session appears already attaching.
2026-07-09 17:31:45 +02:00
Ole André Vadla Ravnås 922a1e2cab Declare tracer hook globals for type checking
Feed the defineHandler ambient declarations to the hook compiler
so type checking resolves them. Wrap them in a declare-global
module imported by the entry, keeping them out of package and
custom-instrument compiles that share the workspace root.
2026-07-06 17:55:02 +02:00
Sunwoo Moon 03b5fb8791 Add a second OpenAI-compatible mission provider
Fold the local and URL providers into one configurable
OpenAICompatibleProvider and register both, so a remote
endpoint can be set alongside the local one. Accept optional
API keys for compatible providers in the mission sheet, and
collapse duplicate /v1 segments when building request URLs.
2026-07-06 17:31:43 +02:00
Sunwoo Moon a6d6ec439e Keep mission reply visible until it is persisted
Clear the live assistant text on an explicit liveTextCleared
event emitted once the turn is saved, not on messageStop or
finalMessage. Navigating away and back no longer drops the
latest streamed reply.
2026-07-06 17:31:43 +02:00
necpition205 7411c3c9a4 Optimize mission context reads 2026-06-28 02:02:14 +02:00
necpition205 83769a5e8e Harden custom instrument handling 2026-06-28 02:02:14 +02:00
Ole André Vadla Ravnås eb16b31f83 Drop empty r2 log entries from REPL results
r2 returns an empty error entry beside the real one, and joining
them prepended a newline to the message. Filter empty messages and
revert the leading-output trim that only masked it.
2026-06-27 23:55:55 +02:00
Ole André Vadla Ravnås d69ffed36f Seek the main module when the REPL opens
Seed the r2 seek to the main module base once it is known at
attach, so a fresh REPL starts on the program instead of address
zero. Restoring a persisted seek anchor still takes precedence.
2026-06-27 19:15:10 +02:00
Ole André Vadla Ravnås 38e5198209 Move modules and threads into the sidebar
Drop the modules/threads tabs; show both as collapsible sidebar
groups mirroring the hooks UX: a handful of top picks plus a
browse popover for the rest. Default threads to collapsed.

Revert the eager re-analysis of persisted modules on attach; keep
disassembly analysis lazy and add a per-module Analyze action and
status indicator instead.

Share one sidebar-row and one browser-popover component across
hooks, modules, and threads in both the SwiftUI and GTK frontends.
2026-06-27 14:53:01 +02:00
Ole André Vadla Ravnås 1fd6c25426 Trim leading newlines from r2 output
Drop newline characters from both ends of command output while
leaving spaces and tabs intact, so a failure like "pdf" no longer
renders with an awkward blank first line.
2026-06-27 04:14:51 +02:00
Ole André Vadla Ravnås e711f772e3 Render r2 hexdumps in the hex view widget
Detect the plain px and x commands and fetch their bytes via
pxj, rendering them in our interactive hex view rather than as
text. Resolve the target address so the offset column shows the
real addresses, carrying it on the binary result's metadata.
2026-06-26 19:13:57 +02:00
Ole André Vadla Ravnås 7d38ac2f7f Persist the r2 REPL seek as an address anchor
Snapshot the r2 seek after each r2 eval, storing it on
SessionUIState as an AddressAnchor so it re-bases across runs.
Resolve and restore it during the session warm-up, which now
also runs when only a seek (no analysis) was saved.
2026-06-26 18:49:13 +02:00
Ole André Vadla Ravnås ce32477080 Adopt unified SwiftyR2 cmd API
Move to the single cmd that returns an R2CommandResult with an
optional output, and handle the nil that r2 yields for commands
with no string result (e.g. an invalid command from completion).
Bump the SwiftyR2 pin to the revision with that fix.
2026-06-26 18:33:16 +02:00
Ole André Vadla Ravnås d759062291 Warm up persisted module analysis on attach
Replay every module that has a persisted analysis row into the
fresh r2 core once modules are enumerated, restoring last
session's warm state without blocking attach. Replays are cheap
re-basing; modules lacking persisted analysis stay lazy.
2026-06-26 17:49:55 +02:00
Ole André Vadla Ravnås 0285de051a Enrich r2 REPL completion and persist input state
Carry a display/insert split through completion so command
suggestions show r2's help text via the native secondary title,
and complete command arguments against eval vars and flagspaces
in addition to flags. Recall the language alongside the code when
cycling history, and keep r2 output's leading whitespace intact.

Persist the REPL draft and active language per session in
SessionUIState so they survive reopening the project. Defer the
input field's first-responder change out of the view update.
2026-06-26 17:46:01 +02:00
Ole André Vadla Ravnås f6e012ae5c Add r2 autocompletion to the REPL
Complete the command token via r2's own help tree ("<prefix>?")
and argument tokens against flag and symbol names ("fq~"). Route
completion by language and replace the whole token in r2 mode
rather than splitting on dots as the JavaScript path does.
2026-06-26 16:52:27 +02:00
Ole André Vadla Ravnås b84bfa0a2b Add r2 as a first-class REPL language
Make the REPL prompt a clickable mode toggle between JavaScript
and r2; ":", ":r2" and ":js" switch from the keyboard. Carry the
language on REPLCell and REPLResult, route r2 input through the
session disassembler, and render output as a JSInspectValue tree
for JSON commands or ANSI-parsed styled text otherwise.
2026-06-26 16:45:21 +02:00
Ole André Vadla Ravnås 9606ec4930 Drop the driver concept; await host-claim ack
The driver seat became fully redundant with the host once session
interaction moved to owner gating: it was always equal to the host and
nothing read it for authorization. Remove it wholesale — the
claim-driver op, driverBySession, localUserIsDriver, Session.driver,
and the REPL "Driving" indicator.

Gate REPL submission on ownership (solo always). Claim hosting through
an acknowledged request and attach only once the server accepts,
instead of optimistically attaching before the claim is even sent.
2026-06-26 15:34:02 +02:00
Ole André Vadla Ravnås 2a281a133d Gate hosting on the driver seat when collaborative
Claim the driver seat when hosting a session, both on a fresh
spawn/attach and on re-host, wiring the previously unused claim-driver
op so the driver tracks the actual host.

Gate every spawn/attach/re-attach control on canTakeHosting: owner,
joined to the lab, and the seat free (not actively hosted by another).
Re-attach is now disabled while offline, since you can't hold the seat
then. Apply across both frontends — sidebar menus and detached
banners.
2026-06-26 15:34:02 +02:00
Ole André Vadla Ravnås 79e273c78e Fix collaborative session UI before reconnect
Add Engine.localUserID, falling back to the GitHub identity, so
host-ownership checks resolve before the collaboration bus connects.
Route the banner, REPL, and host-badge comparisons through it across
both frontends.

Hide the REPL "Driving" label when the local user is the driver.
2026-06-26 12:55:53 +02:00
Ole André Vadla Ravnås 05544eb6cc Keep Notes & AI chat open during approvals
Approving a tool call popped the global action-queue popover,
which evicted the Notes & AI chat. Show approve/reject inline in
the address-note chat, with the tool's code preview, and skip the
global auto-present for ambient note-reply actions.

On GTK host the chat in an Adw.Dialog; a GtkPopover dismisses
itself during layout passes, so it can't stay open while the
reply streams. Render the code preview with a native monospace
view rather than the embedded web editor.

Track the in-flight reply text on the engine so it survives the
chat closing and restores on reopen.
2026-06-25 13:17:53 +02:00
Ole André Vadla Ravnås 141400f6ec Dedup tracer hooks by resolved address
An imported symbol anchors to the linked library path (e.g.
libSystem.B.dylib) while a search anchors to the defining module
(libsystem_c.dylib), so anchor-string equality never matched and
the search offered Add instead of Go to Hook. Match by the
agent-resolved address instead, in both the macOS and GTK config
views. Relax resolve() to accept a module identified by path, not
just leaf name; without it path-form anchors fail to resolve at
all.
2026-06-25 01:44:57 +02:00
Ole André Vadla Ravnås 686cea8173 core: Route tracer errors to hook status
Intercept tracer-error events, map them to the failing hook,
and set a per-hook loadFailed status the sidebar indicator
shows; suppress them from the raw event log. Cleared on the
next config apply.
2026-06-24 13:23:19 +02:00
Ole André Vadla Ravnås b001d409af Keep facts resolution off the selection path
Mark the address-facts caches @ObservationIgnored so resolving
a cell's facts no longer invalidates the view tree and rebuilds
tables mid-click. Drop the per-cell session-identity read from
the facts task key, which churned on every module update.
2026-06-24 13:23:19 +02:00
Ole André Vadla Ravnås b6d7d656ac core: Reuse an insight at the same address
Match an existing insight by resolved address when its anchor
differs, so navigating to a function start lands on the named
insight instead of minting a sub_<offset> duplicate.
2026-06-24 13:23:19 +02:00
Ole André Vadla Ravnås bcac18515a core: Resolve address facts and gate actions
Resolve whether an address is executable, a function start,
data, or unmapped — from page protection and the disassembler,
cached per process identity. Gate the tracer hook actions on
it. Skip resolution while detached; invalidate the cache when
re-attaching to a different process.
2026-06-23 10:51:48 +02:00
Ole André Vadla Ravnås c6d07ca32a Derive hook and insight names from symbol
Modules-view actions built names via anchor.displayString,
yielding module!symbol for hooks and module+offset for
disassembly/memory insights. Route both through the symbol the
tracer search already uses.

Add AddressAnchor.symbolName; default tracer hook names to it.
Thread the context anchor hint into getOrCreateInsight so
insights opened on exports and imports inherit the symbol name.
Drop the unused title parameter from ModuleDetailView.
2026-06-22 22:26:27 +02:00
Ole André Vadla Ravnås b37db281dc core: Share a single app-wide DeviceManager 2026-06-12 21:35:28 +02:00