Compare commits

...
26 Commits
Author SHA1 Message Date
Ole André Vadla Ravnås ddab33010d subprojects: Prepare for release 2025-04-05 14:46:58 +02:00
Ole André Vadla Ravnås a2a77cdfa5 subprojects: Bump outdated 2025-04-05 11:14:07 +02:00
Ole André Vadla Ravnås 672bf55778 freebsd: Unseal Binjector to fix compilation
The C glue code depends on its fields for now.
2025-04-05 11:13:38 +02:00
Ole André Vadla Ravnås 722949d5fa subprojects: Prepare for release 2025-04-05 11:10:31 +02:00
Ole André Vadla Ravnås 5fed974dc5 subprojects: Bump outdated 2025-04-05 09:38:34 +02:00
Ole André Vadla Ravnås 7d2c0682e3 qnx: Unseal Qinjector to fix compilation
The C glue code depends on its fields for now.
2025-04-05 09:36:50 +02:00
Ole André Vadla Ravnås fcb66f61da subprojects: Prepare for release 2025-04-05 08:52:16 +02:00
Ole André Vadla Ravnås 23f1086bac subprojects: Bump outdated 2025-04-05 08:50:59 +02:00
Ole André Vadla Ravnås a0cf6a940b meson: Provide Gio-2.0.gir for convenience
So users won't need any GObject Introspection packages installed when
they're building language bindings and consuming us as a subproject.
2025-04-03 15:19:55 +02:00
Ole André Vadla Ravnås 0a4ee7acbb meson: Fix frida_girdir for the uninstalled case
It should point at the directory containing the refined .gir, not the
raw one from the Vala compiler.
2025-04-03 15:15:26 +02:00
Ole André Vadla Ravnås b8aeff0854 api: Seal classes not meant to be subclassed
Except for inner classes, as that results in C compiler warnings.
2025-04-03 12:23:57 +02:00
Ole André Vadla Ravnås 6a1f43f052 api: Fix vapi entries for sealed classes 2025-04-03 10:12:39 +02:00
Ole André Vadla Ravnås 87c293c831 api: Drop some accidentally exposed types 2025-04-02 18:40:57 +02:00
Ole André Vadla Ravnås 3e75fc9b84 subprojects: Prepare for release 2025-03-31 21:22:52 +02:00
Ole André Vadla Ravnås 1b6ca8fe46 subprojects: Bump outdated 2025-03-31 20:17:34 +02:00
Ole André Vadla Ravnås 9e35e245b1 host-session: Add support for remote services
So they are no longer exclusively an out-of-band local API. This means
that ControlService/frida-server can serve service sessions.
2025-03-31 20:10:49 +02:00
Ole André Vadla Ravnås 4a8c0bb13b api: Expose sealed classes 2025-03-31 20:10:49 +02:00
Ole André Vadla Ravnås 7c39f1783a stream: Factor out IOStream commonalities 2025-03-31 20:10:49 +02:00
Ole André Vadla Ravnås 194f025a98 host-session: Add support for remote channels
So they are no longer exclusively an out-of-band local API. This means
that ControlService/frida-server can serve channels.
2025-03-31 20:10:46 +02:00
Ole André Vadla Ravnås e6b2a6d6dd session: Remove unused ObjectPath constant 2025-03-30 16:26:58 +02:00
Ole André Vadla Ravnås e66b93b647 host-session: Factor out duplicated local logic 2025-03-28 17:18:35 +01:00
Ole André Vadla Ravnås 4a887eaed5 host-session: Rename BaseDBusHostSession to LocalHostSession
For clarity.
2025-03-28 17:18:17 +01:00
Ole André Vadla Ravnås 180075a7a0 control-service: Fix session logic for remote device 2025-03-28 15:29:14 +01:00
Ole André Vadla Ravnås 20ebf7fa15 host-session-provider: Add unlink_agent_session()
To support use-cases such as ControlService, where one specific client
gets disconnected and we need to tear down its agent sessions.
2025-03-28 15:29:11 +01:00
Ole André Vadla Ravnås 1018aca28d compiler: Bump frida-compile 2025-03-25 20:14:26 +01:00
Ole André Vadla Ravnås 93870b9f66 compiler: Bump @types/frida-gum 2025-03-24 17:33:23 +01:00
113 changed files with 143449 additions and 1864 deletions

No files matched your search

+2 -2
View File
@@ -147,7 +147,7 @@ namespace Frida.Inject {
public extern void init ();
}
public class Application : Object {
public sealed class Application : Object {
public string? device_id {
get;
construct;
@@ -426,7 +426,7 @@ namespace Frida.Inject {
#endif
}
private class ScriptRunner : Object, RpcPeer {
private sealed class ScriptRunner : Object, RpcPeer {
public TerminalMode terminal_mode {
get;
private set;
+2 -2
View File
@@ -11,7 +11,7 @@ namespace Frida.Agent {
PROCESS_TRANSITION
}
private class Runner : Object, ProcessInvader, AgentSessionProvider, ExitHandler, ForkHandler, SpawnHandler {
private sealed class Runner : Object, ProcessInvader, AgentSessionProvider, ExitHandler, ForkHandler, SpawnHandler {
public static Runner shared_instance = null;
public static Mutex shared_mutex;
private static string? cached_agent_path = null;
@@ -1621,7 +1621,7 @@ namespace Frida.Agent {
}
#endif
private class LiveAgentSession : BaseAgentSession {
private sealed class LiveAgentSession : BaseAgentSession {
public uint registration_id {
get;
set;
+3 -3
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class BufferBuilder : Object {
public sealed class BufferBuilder : Object {
public ByteOrder byte_order {
get;
construct;
@@ -307,7 +307,7 @@ namespace Frida {
NUL
}
public class Buffer : Object {
public sealed class Buffer : Object {
public Bytes bytes {
get;
construct;
@@ -466,7 +466,7 @@ namespace Frida {
}
}
public class BufferReader {
public sealed class BufferReader {
public size_t available {
get {
return buffer.bytes.get_size () - offset;
+240
View File
@@ -0,0 +1,240 @@
namespace Frida {
public sealed class ChannelRegistry : Object {
public signal void channel_closed (ChannelId id);
private Gee.Map<ChannelId?, weak IOStream> channels =
new Gee.HashMap<ChannelId?, weak IOStream> (ChannelId.hash, ChannelId.equal);
~ChannelRegistry () {
clear ();
}
public void clear () {
foreach (IOStream stream in channels.values.to_array ()) {
var channel_stream = stream as ChannelStream;
if (channel_stream != null)
channel_stream.abandon ();
}
channels.clear ();
}
public void register (ChannelId id, IOStream stream) {
stream.set_data ("channel-registry-entry", new Entry (this, id));
lock (channels)
channels[id] = stream;
}
public IOStream link (ChannelId id) throws Error {
IOStream? stream;
lock (channels)
stream = channels[id];
if (stream == null)
throw new Error.INVALID_ARGUMENT ("Invalid channel ID");
return stream;
}
public void unlink (ChannelId id) {
lock (channels) {
if (!channels.unset (id))
return;
}
channel_closed (id);
}
private class Entry {
public ChannelRegistry parent;
public ChannelId id;
public Entry (ChannelRegistry parent, ChannelId id) {
this.parent = parent;
this.id = id;
}
~Entry () {
parent.unlink (id);
}
}
}
public sealed class ChannelEndpoint : Object, Channel {
private IOStream? stream;
private ByteArray write_queue = new ByteArray ();
private bool writing = false;
private Cancellable io_cancellable = new Cancellable ();
public ChannelEndpoint (IOStream stream) {
this.stream = stream;
read_loop.begin ();
}
public async void close (Cancellable? cancellable) throws Error, IOError {
io_cancellable.cancel ();
}
public async void input (uint8[] data, Cancellable? cancellable) throws Error, IOError {
if (io_cancellable.is_cancelled ())
throw new Error.INVALID_OPERATION ("Channel is closed");
write_queue.append (data);
if (!writing) {
writing = true;
var source = new IdleSource ();
source.set_callback (() => {
process_write_queue.begin ();
return false;
});
source.attach (MainContext.get_thread_default ());
}
}
private async void read_loop () {
var input = stream.get_input_stream ();
var buffer = new uint8[64 * 1024];
while (true) {
ssize_t n;
try {
n = yield input.read_async (buffer, Priority.DEFAULT, io_cancellable);
} catch (GLib.Error e) {
break;
}
output (buffer[:n]);
}
stream.close_async.begin ();
stream = null;
}
private async void process_write_queue () {
if (stream != null) {
var output = stream.get_output_stream ();
while (write_queue.len > 0) {
uint8[] batch = write_queue.steal ();
size_t bytes_written;
try {
yield output.write_all_async (batch, Priority.DEFAULT, io_cancellable, out bytes_written);
} catch (GLib.Error e) {
break;
}
}
}
writing = false;
}
}
public sealed class ChannelStream : VirtualStream {
public Channel channel {
get;
construct;
}
private ByteArray recv_queue = new ByteArray ();
private ByteArray send_queue = new ByteArray ();
public ChannelStream (Channel channel) {
Object (channel: channel);
}
construct {
channel.output.connect (on_output);
}
public void abandon () {
with_state_lock (() => {
state = CLOSED;
update_pending_io ();
});
}
protected override IOCondition query_events () {
IOCondition new_events = 0;
if (recv_queue.len != 0 || state == CLOSED)
new_events |= IN;
if (state == OPEN)
new_events |= OUT;
return new_events;
}
protected override void handle_close () {
channel.close.begin (null);
}
public override ssize_t read (uint8[] buffer) throws IOError {
ssize_t n = 0;
with_state_lock (() => {
n = ssize_t.min (recv_queue.len, buffer.length);
if (n > 0) {
Memory.copy (buffer, recv_queue.data, n);
recv_queue.remove_range (0, (uint) n);
update_pending_io ();
} else {
if (state == OPEN)
n = -1;
}
});
if (n == -1)
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
return n;
}
public override ssize_t write (uint8[] buffer) throws IOError {
with_state_lock (() => {
send_queue.append (buffer);
});
if (main_context.is_owner ()) {
process_send_queue ();
} else {
var source = new IdleSource ();
source.set_callback (() => {
process_send_queue ();
return Source.REMOVE;
});
source.attach (main_context);
}
return buffer.length;
}
private void process_send_queue () {
uint8[]? chunk = null;
with_state_lock (() => {
size_t n = send_queue.len;
if (n == 0)
return;
chunk = send_queue.data[0:n];
send_queue.remove_range (0, (uint) n);
});
if (chunk == null)
return;
channel.input.begin (chunk, io_cancellable);
}
private void on_output (uint8[] data) {
with_state_lock (() => {
if (data.length != 0)
recv_queue.append (data);
else
state = CLOSED;
update_pending_io ();
});
}
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class CFArray<T> {
public sealed class CFArray<T> {
private CoreFoundation.Array handle;
public static CFArray<T> wrap<T> (void * handle) {
+1 -1
View File
@@ -60,7 +60,7 @@ namespace Frida {
return yield connection.get_proxy (null, ObjectPath.HOST_SESSION, DBusProxyFlags.NONE, cancellable);
}
private class DummyInputStream : InputStream {
private sealed class DummyInputStream : InputStream {
private bool done = false;
private Mutex mutex;
private Cond cond;
+3
View File
@@ -1,6 +1,9 @@
base_sources = [
'session.vala',
'session-glue.c',
'channel.vala',
'service.vala',
'stream.vala',
'rpc.vala',
'p2p.vala',
'p2p-glue.c',
+35 -233
View File
@@ -169,7 +169,7 @@ namespace Frida {
}
}
public class PeerSocket : Object, DatagramBased {
public sealed class PeerSocket : Object, DatagramBased {
public Nice.Agent agent {
get;
construct;
@@ -452,6 +452,8 @@ namespace Frida {
if ((_pending_io & c) != 0)
source.set_ready_time (0);
}
notify_property ("pending-io");
}
private void prepare_for_io (int64 timeout, Cancellable? cancellable, out int64 deadline) throws IOError {
@@ -563,7 +565,7 @@ namespace Frida {
}
}
public class SctpConnection : IOStream {
public sealed class SctpConnection : VirtualStream {
public DatagramBased transport_socket {
get;
construct;
@@ -584,55 +586,14 @@ namespace Frida {
construct;
}
public State state {
get {
return _state;
}
}
public override InputStream input_stream {
get {
return _input_stream;
}
}
public override OutputStream output_stream {
get {
return _output_stream;
}
}
public IOCondition pending_io {
get {
lock (state)
return sctp_events;
}
}
private State _state = CREATED;
private SctpInputStream _input_stream;
private SctpOutputStream _output_stream;
private DatagramBasedSource transport_source;
private uint8[] transport_buffer = new uint8[65536];
private void * sctp_socket;
private IOCondition sctp_events = 0;
private SctpTimerSource sctp_source;
private uint16 stream_id;
private ByteArray dcep_message = new ByteArray ();
private Gee.Map<unowned Source, IOCondition> sources = new Gee.HashMap<unowned Source, IOCondition> ();
private Cancellable io_cancellable = new Cancellable ();
public enum State {
CREATED,
OPENING,
OPENED,
CLOSED
}
public SctpConnection (DatagramBased transport_socket, PeerSetup setup, uint16 port, size_t max_message_size) {
Object (
transport_socket: transport_socket,
@@ -649,14 +610,9 @@ namespace Frida {
protected extern static void _initialize_sctp_backend ();
construct {
_input_stream = new SctpInputStream (this);
_output_stream = new SctpOutputStream (this);
sctp_socket = _create_sctp_socket ();
_connect_sctp_socket (sctp_socket, port);
var main_context = MainContext.get_thread_default ();
transport_source = transport_socket.create_source (IOCondition.IN, io_cancellable);
transport_source.set_callback (on_transport_socket_readable);
transport_source.attach (main_context);
@@ -669,17 +625,22 @@ namespace Frida {
protected extern void _connect_sctp_socket (void * sock, uint16 port);
public override bool close (GLib.Cancellable? cancellable) throws IOError {
do_close ();
return true;
protected override VirtualStream.State query_initial_state () {
return CREATED;
}
public override async bool close_async (int io_priority, GLib.Cancellable? cancellable) throws IOError {
do_close ();
return true;
protected override IOCondition query_events () {
return _query_sctp_socket_events (sctp_socket);
}
private void do_close () {
protected override void update_pending_io () {
base.update_pending_io ();
sctp_source.invalidate ();
}
protected extern static IOCondition _query_sctp_socket_events (void * sock);
protected override void handle_close () {
sctp_source.destroy ();
transport_source.destroy ();
@@ -689,13 +650,17 @@ namespace Frida {
public extern static void _close (void * sock);
public void shutdown (SctpShutdownType type) throws IOError {
_shutdown (sctp_socket, type);
public override void shutdown_read () throws IOError {
_shutdown (sctp_socket, READ);
}
public override void shutdown_write () throws IOError {
_shutdown (sctp_socket, WRITE);
}
public extern static void _shutdown (void * sock, SctpShutdownType type) throws IOError;
public ssize_t recv (uint8[] buffer) throws IOError {
public override ssize_t read (uint8[] buffer) throws IOError {
ssize_t n = -1;
try {
@@ -711,18 +676,18 @@ namespace Frida {
handle_dcep_message (stream_id, dcep_message.steal ());
}
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
} else if (protocol_id == NONE || _state != OPENED) {
} else if (protocol_id == NONE || state != OPEN) {
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
}
} finally {
update_sctp_events ();
update_pending_io ();
}
return n;
}
public ssize_t send (uint8[] buffer) throws IOError {
if (_state != OPENED)
public override ssize_t write (uint8[] buffer) throws IOError {
if (state != OPEN)
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
ssize_t n = ssize_t.min (buffer.length, (ssize_t) max_message_size);
@@ -730,20 +695,10 @@ namespace Frida {
try {
return _send (sctp_socket, stream_id, WEBRTC_BINARY, buffer[0:n]);
} finally {
update_sctp_events ();
update_pending_io ();
}
}
public void register_source (Source source, IOCondition condition) {
lock (state)
sources[source] = condition | IOCondition.ERR | IOCondition.HUP;
}
public void unregister_source (Source source) {
lock (state)
sources.unset (source);
}
private bool on_transport_socket_readable (DatagramBased datagram_based, IOCondition condition) {
var v = InputVector ();
v.buffer = transport_buffer;
@@ -783,9 +738,9 @@ namespace Frida {
}
protected void _on_sctp_socket_events_changed () {
update_sctp_events ();
update_pending_io ();
if (_state == CREATED && setup == ACTIVE && (sctp_events & IOCondition.OUT) != 0) {
if (state == CREATED && setup == ACTIVE && (pending_io & IOCondition.OUT) != 0) {
stream_id = 1;
uint8[] open_message = {
@@ -799,31 +754,12 @@ namespace Frida {
};
try {
_send (sctp_socket, stream_id, WEBRTC_DCEP, open_message);
_state = OPENING;
state = OPENING;
} catch (IOError e) {
}
}
}
private void update_sctp_events () {
IOCondition new_events = _query_sctp_socket_events (sctp_socket);
lock (state) {
sctp_events = new_events;
foreach (var entry in sources.entries) {
unowned Source source = entry.key;
IOCondition c = entry.value;
if ((new_events & c) != 0)
source.set_ready_time (0);
}
sctp_source.invalidate ();
}
}
protected extern static IOCondition _query_sctp_socket_events (void * sock);
protected extern static ssize_t _recv (void * sock, uint8[] buffer, out uint16 stream_id,
out PayloadProtocolId protocol_id, out SctpMessageFlags message_flags) throws IOError;
@@ -835,7 +771,7 @@ namespace Frida {
switch (type) {
case DATA_CHANNEL_OPEN: {
if (_state != CREATED || setup == ACTIVE)
if (state != CREATED || setup == ACTIVE)
return;
this.stream_id = stream_id;
@@ -843,15 +779,15 @@ namespace Frida {
uint8[] reply = { DcepMessageType.DATA_CHANNEL_ACK };
_send (sctp_socket, stream_id, WEBRTC_DCEP, reply);
_state = OPENED;
state = OPEN;
break;
}
case DATA_CHANNEL_ACK:
if (_state != OPENING)
if (state != OPENING)
return;
_state = OPENED;
state = OPEN;
break;
}
@@ -886,140 +822,6 @@ namespace Frida {
DATA_CHANNEL_ACK = 0x02
}
private class SctpInputStream : InputStream, PollableInputStream {
public weak SctpConnection connection {
get;
construct;
}
public SctpInputStream (SctpConnection connection) {
Object (connection: connection);
}
public override bool close (Cancellable? cancellable) throws IOError {
connection.shutdown (READ);
return true;
}
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
return close (cancellable);
}
public override ssize_t read (uint8[] buffer, Cancellable? cancellable) throws IOError {
assert_not_reached ();
}
public bool can_poll () {
return true;
}
public bool is_readable () {
return (connection.pending_io & IOCondition.IN) != 0;
}
public PollableSource create_source (Cancellable? cancellable) {
return new PollableSource.full (this, new SctpIOSource (connection, IOCondition.IN), cancellable);
}
public ssize_t read_nonblocking_fn (uint8[] buffer) throws GLib.Error {
return connection.recv (buffer);
}
}
private class SctpOutputStream : OutputStream, PollableOutputStream {
public weak SctpConnection connection {
get;
construct;
}
public SctpOutputStream (SctpConnection connection) {
Object (connection: connection);
}
public override bool close (Cancellable? cancellable) throws IOError {
connection.shutdown (WRITE);
return true;
}
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
return close (cancellable);
}
public override bool flush (GLib.Cancellable? cancellable) throws GLib.Error {
return true;
}
public override async bool flush_async (int io_priority, GLib.Cancellable? cancellable) throws GLib.Error {
return true;
}
public override ssize_t write (uint8[] buffer, Cancellable? cancellable) throws IOError {
assert_not_reached ();
}
public bool can_poll () {
return true;
}
public bool is_writable () {
return (connection.pending_io & IOCondition.OUT) != 0;
}
public PollableSource create_source (Cancellable? cancellable) {
return new PollableSource.full (this, new SctpIOSource (connection, IOCondition.OUT), cancellable);
}
public ssize_t write_nonblocking_fn (uint8[]? buffer) throws GLib.Error {
return connection.send (buffer);
}
public PollableReturn writev_nonblocking_fn (OutputVector[] vectors, out size_t bytes_written) throws GLib.Error {
assert_not_reached ();
}
}
private class SctpIOSource : Source {
public SctpConnection connection;
public IOCondition condition;
public SctpIOSource (SctpConnection connection, IOCondition condition) {
this.connection = connection;
this.condition = condition;
connection.register_source (this, condition);
}
~SctpIOSource () {
connection.unregister_source (this);
}
protected override bool prepare (out int timeout) {
timeout = -1;
return (connection.pending_io & condition) != 0;
}
protected override bool check () {
return (connection.pending_io & condition) != 0;
}
protected override bool dispatch (SourceFunc? callback) {
set_ready_time (-1);
if (callback == null)
return Source.REMOVE;
return callback ();
}
protected static bool closure_callback (Closure closure) {
var return_value = Value (typeof (bool));
closure.invoke (ref return_value, {});
return return_value.get_boolean ();
}
}
private class SctpTimerSource : Source {
private static int64 last_process_time = -1;
+1 -1
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class Promise<T> {
public sealed class Promise<T> {
private Impl<T> impl;
public Future<T> future {
+1 -1
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class RpcClient : Object {
public sealed class RpcClient : Object {
public weak RpcPeer peer {
get;
construct;
+48
View File
@@ -0,0 +1,48 @@
namespace Frida {
public sealed class ServiceSessionRegistry : Object {
public signal void session_closed (ServiceSessionId id);
private Gee.Map<ServiceSessionId?, ServiceSession> sessions =
new Gee.HashMap<ServiceSessionId?, ServiceSession> (ServiceSessionId.hash, ServiceSessionId.equal);
~ServiceSessionRegistry () {
clear ();
}
public void clear () {
foreach (var session in sessions.values.to_array ())
session.close ();
sessions.clear ();
}
public void register (ServiceSessionId id, ServiceSession session) {
sessions[id] = session;
ServiceSessionId? boxed_id = id;
session.set_data ("service-session-id", boxed_id);
session.close.connect (on_session_close);
}
public ServiceSession link (ServiceSessionId id) throws Error {
var session = sessions[id];
if (session == null)
throw new Error.INVALID_ARGUMENT ("Invalid session ID");
return session;
}
public void unlink (ServiceSessionId id) {
ServiceSession? session;
if (sessions.unset (id, out session)) {
session.close.disconnect (on_session_close);
session_closed (id);
}
}
private void on_session_close (ServiceSession session) {
ServiceSessionId? id = session.get_data ("service-session-id");
unlink (id);
}
}
}
+96 -16
View File
@@ -27,6 +27,10 @@ namespace Frida {
public abstract async InjectorPayloadId inject_library_blob (uint pid, uint8[] blob, string entrypoint, string data,
Cancellable? cancellable) throws GLib.Error;
public abstract async ChannelId open_channel (string address, Cancellable? cancellable) throws GLib.Error;
public abstract async ServiceSessionId open_service (string address, Cancellable? cancellable) throws GLib.Error;
public signal void spawn_added (HostSpawnInfo info);
public signal void spawn_removed (HostSpawnInfo info);
public signal void child_added (HostChildInfo info);
@@ -34,6 +38,8 @@ namespace Frida {
public signal void process_crashed (CrashInfo crash);
public signal void output (uint pid, int fd, uint8[] data);
public signal void agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash);
public signal void channel_closed (ChannelId id);
public signal void service_session_closed (ServiceSessionId id);
public signal void uninjected (InjectorPayloadId id);
}
@@ -145,7 +151,7 @@ namespace Frida {
DEBUGGER
}
public class AgentMessageTransmitter : Object {
public sealed class AgentMessageTransmitter : Object {
public signal void closed ();
public signal void new_candidates (string[] candidate_sdps);
public signal void candidate_gathering_done ();
@@ -743,6 +749,23 @@ namespace Frida {
}
}
[DBus (name = "re.frida.Channel16")]
public interface Channel : Object {
public abstract async void close (Cancellable? cancellable) throws GLib.Error;
public abstract async void input (uint8[] data, Cancellable? cancellable) throws GLib.Error;
public signal void output (uint8[] data);
}
[DBus (name = "re.frida.ServiceSession16")]
public interface ServiceSession : Object {
public signal void close ();
public signal void message (Variant message);
public abstract async void activate (Cancellable? cancellable) throws GLib.Error;
public abstract async void cancel (Cancellable? cancellable) throws GLib.Error;
public abstract async Variant request (Variant parameters, Cancellable? cancellable) throws GLib.Error;
}
[DBus (name = "re.frida.TransportBroker16")]
public interface TransportBroker : Object {
public abstract async void open_tcp_transport (AgentSessionId id, Cancellable? cancellable, out uint16 port,
@@ -770,7 +793,7 @@ namespace Frida {
public abstract async string authenticate (string token, Cancellable? cancellable) throws GLib.Error;
}
public class StaticAuthenticationService : Object, AuthenticationService {
public sealed class StaticAuthenticationService : Object, AuthenticationService {
public string token_hash {
get;
construct;
@@ -795,13 +818,13 @@ namespace Frida {
}
}
public class NullAuthenticationService : Object, AuthenticationService {
public sealed class NullAuthenticationService : Object, AuthenticationService {
public async string authenticate (string token, Cancellable? cancellable) throws Error, IOError {
throw new Error.INVALID_OPERATION ("Authentication not expected");
}
}
public class UnauthorizedHostSession : Object, HostSession {
public sealed class UnauthorizedHostSession : Object, HostSession {
public async void ping (uint interval_seconds, Cancellable? cancellable) throws Error, IOError {
throw_not_authorized ();
}
@@ -875,9 +898,17 @@ namespace Frida {
Cancellable? cancellable) throws Error, IOError {
throw_not_authorized ();
}
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
throw_not_authorized ();
}
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
throw_not_authorized ();
}
}
public class UnauthorizedPortalSession : Object, PortalSession {
public sealed class UnauthorizedPortalSession : Object, PortalSession {
public async void join (HostApplicationInfo app, SpawnStartState current_state,
AgentSessionId[] interrupted_sessions, HashTable<string, Variant> options,
Cancellable? cancellable, out SpawnStartState next_state) throws Error, IOError {
@@ -885,7 +916,7 @@ namespace Frida {
}
}
public class UnauthorizedBusSession : Object, BusSession {
public sealed class UnauthorizedBusSession : Object, BusSession {
public async void attach (Cancellable? cancellable) throws Error, IOError {
throw_not_authorized ();
}
@@ -1083,7 +1114,7 @@ namespace Frida {
}
}
public class FrontmostQueryOptions : Object {
public sealed class FrontmostQueryOptions : Object {
public Scope scope {
get;
set;
@@ -1113,7 +1144,7 @@ namespace Frida {
}
}
public class ApplicationQueryOptions : Object {
public sealed class ApplicationQueryOptions : Object {
public Scope scope {
get;
set;
@@ -1171,7 +1202,7 @@ namespace Frida {
}
}
public class ProcessQueryOptions : Object {
public sealed class ProcessQueryOptions : Object {
public Scope scope {
get;
set;
@@ -1313,7 +1344,7 @@ namespace Frida {
}
}
public class SessionOptions : Object {
public sealed class SessionOptions : Object {
public Realm realm {
get;
set;
@@ -1502,6 +1533,46 @@ namespace Frida {
}
}
public struct ChannelId {
public string handle;
public ChannelId (string handle) {
this.handle = handle;
}
public ChannelId.generate () {
this.handle = Uuid.string_random ().replace ("-", "");
}
public static uint hash (ChannelId? id) {
return id.handle.hash ();
}
public static bool equal (ChannelId? a, ChannelId? b) {
return a.handle == b.handle;
}
}
public struct ServiceSessionId {
public string handle;
public ServiceSessionId (string handle) {
this.handle = handle;
}
public ServiceSessionId.generate () {
this.handle = Uuid.string_random ().replace ("-", "");
}
public static uint hash (ServiceSessionId? id) {
return id.handle.hash ();
}
public static bool equal (ServiceSessionId? a, ServiceSessionId? b) {
return a.handle == b.handle;
}
}
public struct AgentScriptId {
public uint handle;
@@ -1518,7 +1589,7 @@ namespace Frida {
}
}
public class ScriptOptions : Object {
public sealed class ScriptOptions : Object {
public string? name {
get;
set;
@@ -1608,7 +1679,7 @@ namespace Frida {
SHARED_MEMORY
}
public class SnapshotOptions : Object {
public sealed class SnapshotOptions : Object {
public string? warmup_script {
get;
set;
@@ -1683,7 +1754,7 @@ namespace Frida {
}
}
public class PortalOptions : Object {
public sealed class PortalOptions : Object {
public TlsCertificate? certificate {
get;
set;
@@ -1746,7 +1817,7 @@ namespace Frida {
}
}
public class PeerOptions : Object {
public sealed class PeerOptions : Object {
public string? stun_server {
get;
set;
@@ -1807,7 +1878,7 @@ namespace Frida {
}
}
public class Relay : Object {
public sealed class Relay : Object {
public string address {
get;
construct;
@@ -2048,7 +2119,8 @@ namespace Frida {
public const string AGENT_SESSION = "/re/frida/AgentSession";
public const string AGENT_CONTROLLER = "/re/frida/AgentController";
public const string AGENT_MESSAGE_SINK = "/re/frida/AgentMessageSink";
public const string CHILD_SESSION = "/re/frida/ChildSession";
public const string CHANNEL = "/re/frida/Channel";
public const string SERVICE = "/re/frida/Service";
public const string TRANSPORT_BROKER = "/re/frida/TransportBroker";
public const string PORTAL_SESSION = "/re/frida/PortalSession";
public const string BUS_SESSION = "/re/frida/BusSession";
@@ -2061,6 +2133,14 @@ namespace Frida {
public static string for_agent_message_sink (AgentSessionId id) {
return AGENT_MESSAGE_SINK + "/" + id.handle;
}
public static string for_channel (ChannelId id) {
return CHANNEL + "/" + id.handle;
}
public static string for_service_session (ServiceSessionId id) {
return SERVICE + "/" + id.handle;
}
}
namespace Marshal {
+44 -236
View File
@@ -97,7 +97,7 @@ namespace Frida {
}
}
public class EndpointParameters : Object {
public sealed class EndpointParameters : Object {
public string? address {
get;
construct;
@@ -234,7 +234,7 @@ namespace Frida {
return (inet_addr.get_family () == IPV6) ? @"[$host]" : host;
}
public class WebService : Object {
public sealed class WebService : Object {
public signal void incoming (IOStream connection, SocketAddress remote_address, DynamicInterface? dynamic_iface);
public EndpointParameters endpoint_params {
@@ -852,7 +852,7 @@ namespace Frida {
public abstract void start ();
}
public class DynamicInterface : Object {
public sealed class DynamicInterface : Object {
public string name {
get;
construct;
@@ -870,7 +870,7 @@ namespace Frida {
public extern static unowned string _version_string ();
private class WebConnection : IOStream {
private sealed class WebConnection : VirtualStream {
public signal void websocket_closed ();
public Soup.WebsocketConnection websocket {
@@ -878,37 +878,9 @@ namespace Frida {
construct;
}
public override InputStream input_stream {
get {
return _input_stream;
}
}
public override OutputStream output_stream {
get {
return _output_stream;
}
}
public IOCondition pending_io {
get {
lock (state)
return _pending_io;
}
}
private WebInputStream _input_stream;
private WebOutputStream _output_stream;
private Soup.WebsocketState state;
private IOCondition _pending_io;
private ByteArray recv_queue = new ByteArray ();
private ByteArray send_queue = new ByteArray ();
private Gee.Map<unowned Source, IOCondition> sources = new Gee.HashMap<unowned Source, IOCondition> ();
private MainContext main_context;
public WebConnection (Soup.WebsocketConnection websocket) {
Object (websocket: websocket);
}
@@ -916,14 +888,6 @@ namespace Frida {
construct {
websocket.max_incoming_payload_size = (256 * 1024) + 1; // XXX: There's an off-by-one error in libsoup
_input_stream = new WebInputStream (this);
_output_stream = new WebOutputStream (this);
state = websocket.state;
_pending_io = (state == OPEN) ? IOCondition.OUT : IOCondition.IN;
main_context = MainContext.ref_thread_default ();
websocket.closed.connect (on_closed);
websocket.message.connect (on_message);
}
@@ -933,51 +897,50 @@ namespace Frida {
websocket.closed.disconnect (on_closed);
}
public override bool close (GLib.Cancellable? cancellable) throws IOError {
_close ();
return true;
}
public override async bool close_async (int io_priority, GLib.Cancellable? cancellable) throws IOError {
_close ();
return true;
}
private void _close () {
if (main_context.is_owner ()) {
do_close ();
} else {
var source = new IdleSource ();
source.set_callback (() => {
do_close ();
return Source.REMOVE;
});
source.attach (main_context);
protected override VirtualStream.State query_initial_state () {
switch (websocket.state) {
case OPEN:
case CLOSING:
return OPEN;
case CLOSED:
return CLOSED;
}
assert_not_reached ();
}
private void do_close () {
protected override IOCondition query_events () {
IOCondition new_events = 0;
if (recv_queue.len > 0 || state != OPEN)
new_events |= IN;
if (state == OPEN)
new_events |= OUT;
return new_events;
}
protected override void handle_close () {
if (websocket.state != OPEN)
return;
websocket.close (1000, "Closing");
}
public ssize_t recv (uint8[] buffer) throws IOError {
ssize_t n;
lock (state) {
public override ssize_t read (uint8[] buffer) throws IOError {
ssize_t n = 0;
with_state_lock (() => {
n = ssize_t.min (recv_queue.len, buffer.length);
if (n > 0) {
Memory.copy (buffer, recv_queue.data, n);
recv_queue.remove_range (0, (uint) n);
recompute_pending_io_unlocked ();
update_pending_io ();
} else {
if (state == OPEN)
n = -1;
}
}
});
if (n == -1)
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
@@ -985,9 +948,10 @@ namespace Frida {
return n;
}
public ssize_t send (uint8[] buffer) {
lock (state)
public override ssize_t write (uint8[] buffer) {
with_state_lock (() => {
send_queue.append (buffer);
});
if (main_context.is_owner ()) {
process_send_queue ();
@@ -1011,190 +975,34 @@ namespace Frida {
while (true) {
uint8[]? chunk = null;
lock (state) {
with_state_lock (() => {
size_t n = size_t.min (send_queue.len, max_message_size);
if (n == 0)
return;
chunk = send_queue.data[0:n];
send_queue.remove_range (0, (uint) n);
}
});
if (chunk == null)
return;
websocket.send_binary (chunk);
}
}
public void register_source (Source source, IOCondition condition) {
lock (state)
sources[source] = condition;
}
public void unregister_source (Source source) {
lock (state)
sources.unset (source);
}
private void on_closed () {
lock (state) {
state = websocket.state;
recompute_pending_io_unlocked ();
}
with_state_lock (() => {
state = CLOSED;
update_pending_io ();
});
websocket_closed ();
}
private void on_message (int type, Bytes message) {
lock (state) {
with_state_lock (() => {
recv_queue.append (message.get_data ());
recompute_pending_io_unlocked ();
}
}
private void recompute_pending_io_unlocked () {
IOCondition new_io = 0;
if (recv_queue.len > 0 || state != OPEN)
new_io |= IN;
if (state == OPEN)
new_io |= OUT;
_pending_io = new_io;
foreach (var entry in sources.entries) {
unowned Source source = entry.key;
IOCondition c = entry.value;
if ((new_io & c) != 0)
source.set_ready_time (0);
}
}
}
private class WebInputStream : InputStream, PollableInputStream {
public weak WebConnection connection {
get;
construct;
}
public WebInputStream (WebConnection connection) {
Object (connection: connection);
}
public override bool close (Cancellable? cancellable) throws IOError {
return true;
}
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
return close (cancellable);
}
public override ssize_t read (uint8[] buffer, Cancellable? cancellable) throws IOError {
assert_not_reached ();
}
public bool can_poll () {
return true;
}
public bool is_readable () {
return (connection.pending_io & IOCondition.IN) != 0;
}
public PollableSource create_source (Cancellable? cancellable) {
return new PollableSource.full (this, new WebIOSource (connection, IOCondition.IN), cancellable);
}
public ssize_t read_nonblocking_fn (uint8[] buffer) throws GLib.Error {
return connection.recv (buffer);
}
}
private class WebOutputStream : OutputStream, PollableOutputStream {
public weak WebConnection connection {
get;
construct;
}
public WebOutputStream (WebConnection connection) {
Object (connection: connection);
}
public override bool close (Cancellable? cancellable) throws IOError {
return true;
}
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
return close (cancellable);
}
public override bool flush (GLib.Cancellable? cancellable) throws GLib.Error {
return true;
}
public override async bool flush_async (int io_priority, GLib.Cancellable? cancellable) throws GLib.Error {
return true;
}
public override ssize_t write (uint8[] buffer, Cancellable? cancellable) throws IOError {
assert_not_reached ();
}
public bool can_poll () {
return true;
}
public bool is_writable () {
return (connection.pending_io & IOCondition.OUT) != 0;
}
public PollableSource create_source (Cancellable? cancellable) {
return new PollableSource.full (this, new WebIOSource (connection, IOCondition.OUT), cancellable);
}
public ssize_t write_nonblocking_fn (uint8[]? buffer) throws GLib.Error {
return connection.send (buffer);
}
public PollableReturn writev_nonblocking_fn (OutputVector[] vectors, out size_t bytes_written) throws GLib.Error {
assert_not_reached ();
}
}
private class WebIOSource : Source {
public WebConnection connection;
public IOCondition condition;
public WebIOSource (WebConnection connection, IOCondition condition) {
this.connection = connection;
this.condition = condition;
connection.register_source (this, condition);
}
~WebIOSource () {
connection.unregister_source (this);
}
protected override bool prepare (out int timeout) {
timeout = -1;
return (connection.pending_io & condition) != 0;
}
protected override bool check () {
return (connection.pending_io & condition) != 0;
}
protected override bool dispatch (SourceFunc? callback) {
set_ready_time (-1);
if (callback == null)
return Source.REMOVE;
return callback ();
}
protected static bool closure_callback (Closure closure) {
var return_value = Value (typeof (bool));
closure.invoke (ref return_value, {});
return return_value.get_boolean ();
update_pending_io ();
});
}
}
}
+334
View File
@@ -0,0 +1,334 @@
namespace Frida {
public abstract class VirtualStream : IOStream {
public override InputStream input_stream {
get {
return _input_stream;
}
}
public override OutputStream output_stream {
get {
return _output_stream;
}
}
public IOCondition pending_io {
get {
lock (state)
return _pending_io;
}
}
protected State state = OPEN;
private VirtualInputStream _input_stream;
private VirtualOutputStream _output_stream;
private IOCondition _pending_io;
private Gee.Map<unowned Source, IOCondition> sources = new Gee.HashMap<unowned Source, IOCondition> ();
protected Cancellable io_cancellable = new Cancellable ();
protected MainContext main_context;
protected enum State {
CREATED,
OPENING,
OPEN,
CLOSED
}
protected delegate void WorkFunc ();
construct {
_input_stream = new VirtualInputStream (this);
_output_stream = new VirtualOutputStream (this);
main_context = MainContext.ref_thread_default ();
state = query_initial_state ();
_pending_io = query_events ();
}
public override void dispose () {
_output_stream.detach ();
_input_stream.detach ();
io_cancellable.cancel ();
base.dispose ();
}
protected virtual State query_initial_state () {
return OPEN;
}
protected abstract IOCondition query_events ();
public override bool close (GLib.Cancellable? cancellable) throws IOError {
_close ();
return true;
}
public override async bool close_async (int io_priority, GLib.Cancellable? cancellable) throws IOError {
_close ();
return true;
}
private void _close () {
if (main_context.is_owner ()) {
do_close ();
} else {
var source = new IdleSource ();
source.set_callback (() => {
do_close ();
return Source.REMOVE;
});
source.attach (main_context);
}
}
private void do_close () {
if (state == CLOSED)
return;
handle_close ();
}
protected abstract void handle_close ();
public virtual void shutdown_read () throws IOError {
}
public virtual void shutdown_write () throws IOError {
}
public abstract ssize_t read (uint8[] buffer) throws IOError;
public abstract ssize_t write (uint8[] buffer) throws IOError;
protected void with_state_lock (WorkFunc func) {
lock (state)
func ();
}
public void register_source (Source source, IOCondition condition) {
lock (state)
sources[source] = condition | IOCondition.ERR | IOCondition.HUP;
}
public void unregister_source (Source source) {
lock (state)
sources.unset (source);
}
protected virtual void update_pending_io () {
_pending_io = query_events ();
foreach (var entry in sources.entries) {
unowned Source source = entry.key;
IOCondition c = entry.value;
if ((_pending_io & c) != 0)
source.set_ready_time (0);
}
notify_property ("pending-io");
}
}
private sealed class VirtualInputStream : InputStream, PollableInputStream {
private weak VirtualStream stream;
public VirtualInputStream (VirtualStream stream) {
Object ();
this.stream = stream;
}
internal void detach () {
stream = null;
}
public override bool close (Cancellable? cancellable) throws IOError {
if (stream != null)
stream.shutdown_read ();
return true;
}
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
return close (cancellable);
}
public override ssize_t read (uint8[] buffer, Cancellable? cancellable) throws IOError {
if (stream == null)
return 0;
if (!is_readable ()) {
bool done = false;
var mutex = Mutex ();
var cond = Cond ();
ulong io_handler = stream.notify["pending-io"].connect ((obj, pspec) => {
if (is_readable ()) {
mutex.lock ();
done = true;
cond.signal ();
mutex.unlock ();
}
});
ulong cancellation_handler = 0;
if (cancellable != null) {
cancellation_handler = cancellable.connect (() => {
mutex.lock ();
done = true;
cond.signal ();
mutex.unlock ();
});
}
if (!is_readable ()) {
mutex.lock ();
while (!done)
cond.wait (mutex);
mutex.unlock ();
}
if (cancellation_handler != 0)
cancellable.disconnect (cancellation_handler);
stream.disconnect (io_handler);
cancellable.set_error_if_cancelled ();
}
return stream.read (buffer);
}
public bool can_poll () {
return true;
}
public bool is_readable () {
if (stream == null)
return true;
return (stream.pending_io & IOCondition.IN) != 0;
}
public PollableSource create_source (Cancellable? cancellable) {
return new PollableSource.full (this, new VirtualIOSource (stream, IOCondition.IN), cancellable);
}
public ssize_t read_nonblocking_fn (uint8[] buffer) throws GLib.Error {
if (stream == null)
return 0;
return stream.read (buffer);
}
}
private sealed class VirtualOutputStream : OutputStream, PollableOutputStream {
private weak VirtualStream? stream;
public VirtualOutputStream (VirtualStream stream) {
Object ();
this.stream = stream;
}
internal void detach () {
stream = null;
}
public override bool close (Cancellable? cancellable) throws IOError {
if (stream != null)
stream.shutdown_write ();
return true;
}
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
return close (cancellable);
}
public override bool flush (GLib.Cancellable? cancellable) throws GLib.Error {
return true;
}
public override async bool flush_async (int io_priority, GLib.Cancellable? cancellable) throws GLib.Error {
return true;
}
public override ssize_t write (uint8[] buffer, Cancellable? cancellable) throws IOError {
return stream.write (buffer);
}
public bool can_poll () {
return true;
}
public bool is_writable () {
if (stream == null)
return false;
return (stream.pending_io & IOCondition.OUT) != 0;
}
public PollableSource create_source (Cancellable? cancellable) {
return new PollableSource.full (this, new VirtualIOSource (stream, IOCondition.OUT), cancellable);
}
public ssize_t write_nonblocking_fn (uint8[]? buffer) throws GLib.Error {
if (stream == null)
throw new IOError.CLOSED ("Virtual is closed");
return stream.write (buffer);
}
public PollableReturn writev_nonblocking_fn (OutputVector[] vectors, out size_t bytes_written) throws GLib.Error {
assert_not_reached ();
}
}
private class VirtualIOSource : Source {
public VirtualStream? stream;
public IOCondition condition;
public VirtualIOSource (VirtualStream stream, IOCondition condition) {
this.stream = stream;
this.condition = condition;
if (stream != null)
stream.register_source (this, condition);
}
~VirtualIOSource () {
if (stream != null)
stream.unregister_source (this);
}
protected override bool prepare (out int timeout) {
timeout = -1;
return is_ready ();
}
protected override bool check () {
return is_ready ();
}
private bool is_ready () {
IOCondition pending_io = (stream != null) ? stream.pending_io : IOCondition.IN;
return (pending_io & condition) != 0;
}
protected override bool dispatch (SourceFunc? callback) {
set_ready_time (-1);
if (callback == null)
return Source.REMOVE;
return callback ();
}
protected static bool closure_callback (Closure closure) {
var return_value = Value (typeof (bool));
closure.invoke (ref return_value, {});
return return_value.get_boolean ();
}
}
}
+3 -3
View File
@@ -38,7 +38,7 @@ namespace Frida {
public abstract unowned string get_uuid_value () throws Error;
}
public class VariantReader : Object, ObjectReader {
public sealed class VariantReader : Object, ObjectReader {
public Variant root_object {
get {
return scopes.peek_head ().val;
@@ -180,7 +180,7 @@ namespace Frida {
}
}
public class JsonObjectBuilder : Object, ObjectBuilder {
public sealed class JsonObjectBuilder : Object, ObjectBuilder {
private Json.Builder builder = new Json.Builder ();
private Gee.Map<string, Bytes> raw_values = new Gee.HashMap<string, Bytes> ();
@@ -267,7 +267,7 @@ namespace Frida {
}
}
public class JsonObjectReader : Object, ObjectReader {
public sealed class JsonObjectReader : Object, ObjectReader {
private Json.Reader reader;
public JsonObjectReader (string json) throws Error {
+2 -2
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class XpcClient : Object {
public sealed class XpcClient : Object {
public signal void message (Darwin.Xpc.Object obj);
public State state {
@@ -123,7 +123,7 @@ namespace Frida {
}
}
public class XpcObjectReader {
public sealed class XpcObjectReader {
public Darwin.Xpc.Object root_object {
get {
return scopes.peek_head ().object;
+24 -16
View File
@@ -1,5 +1,5 @@
namespace Frida.Gadget {
private class Config : Object, Json.Serializable {
private sealed class Config : Object, Json.Serializable {
public Object interaction {
get;
set;
@@ -93,7 +93,7 @@ namespace Frida.Gadget {
}
}
private class ScriptInteraction : Object, Json.Serializable {
private sealed class ScriptInteraction : Object, Json.Serializable {
public string path {
get;
set;
@@ -145,7 +145,7 @@ namespace Frida.Gadget {
}
}
private class ScriptDirectoryInteraction : Object {
private sealed class ScriptDirectoryInteraction : Object {
public string path {
get;
set;
@@ -164,7 +164,7 @@ namespace Frida.Gadget {
}
}
private class ScriptConfig : Object, Json.Serializable {
private sealed class ScriptConfig : Object, Json.Serializable {
public ProcessFilter? filter {
get;
set;
@@ -216,7 +216,7 @@ namespace Frida.Gadget {
}
}
private class ProcessFilter : Object {
private sealed class ProcessFilter : Object {
public string[] executables {
get;
set;
@@ -258,7 +258,7 @@ namespace Frida.Gadget {
}
}
private class ListenInteraction : SocketInteraction {
private sealed class ListenInteraction : SocketInteraction {
public PortConflictBehavior on_port_conflict {
get;
set;
@@ -287,7 +287,7 @@ namespace Frida.Gadget {
}
}
private class ConnectInteraction : SocketInteraction, Json.Serializable {
private sealed class ConnectInteraction : SocketInteraction, Json.Serializable {
public string[]? acl {
get;
set;
@@ -328,7 +328,7 @@ namespace Frida.Gadget {
}
}
private class Location : Object {
private sealed class Location : Object {
public string executable_name {
get;
construct;
@@ -988,7 +988,7 @@ namespace Frida.Gadget {
}
}
private class ScriptRunner : BaseController {
private sealed class ScriptRunner : BaseController {
private ScriptEngine engine;
private Script script;
@@ -1036,7 +1036,7 @@ namespace Frida.Gadget {
}
}
private class ScriptDirectoryRunner : BaseController {
private sealed class ScriptDirectoryRunner : BaseController {
public string directory_path {
get;
construct;
@@ -1241,7 +1241,7 @@ namespace Frida.Gadget {
}
}
private class Script : Object, RpcPeer {
private sealed class Script : Object, RpcPeer {
private const uint8 QUICKJS_BYTECODE_MAGIC = 0x02;
public enum ChangeBehavior {
@@ -1453,7 +1453,7 @@ namespace Frida.Gadget {
}
}
private class ControlServer : BaseController {
private sealed class ControlServer : BaseController {
public EndpointParameters endpoint_params {
get;
construct;
@@ -1694,7 +1694,7 @@ namespace Frida.Gadget {
public abstract async void close (Cancellable? cancellable = null) throws IOError;
}
private class AuthenticationChannel : Object, Peer, AuthenticationService {
private sealed class AuthenticationChannel : Object, Peer, AuthenticationService {
public weak ControlServer parent {
get;
construct;
@@ -1742,7 +1742,7 @@ namespace Frida.Gadget {
}
}
private class ControlChannel : Object, Peer, HostSession {
private sealed class ControlChannel : Object, Peer, HostSession {
public weak ControlServer parent {
get;
construct;
@@ -1927,13 +1927,21 @@ namespace Frida.Gadget {
throw new Error.NOT_SUPPORTED ("Unable to inject libraries when embedded");
}
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Unable to open channels when embedded");
}
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Unable to open services when embedded");
}
private void validate_pid (uint pid) throws Error {
if (pid != this_process.pid)
throw new Error.NOT_SUPPORTED ("Unable to act on other processes when embedded");
}
}
private class LiveAgentSession : BaseAgentSession {
private sealed class LiveAgentSession : BaseAgentSession {
public ControlChannel? controller {
get;
set;
@@ -1958,7 +1966,7 @@ namespace Frida.Gadget {
}
}
private class ClusterClient : BaseController {
private sealed class ClusterClient : BaseController {
public SocketConnectable connectable {
get;
construct;
+1 -1
View File
@@ -1,4 +1,4 @@
public class Frida.TunnelInterfaceObserver : Object, DynamicInterfaceObserver {
public sealed class Frida.TunnelInterfaceObserver : Object, DynamicInterfaceObserver {
#if IOS || TVOS
private Gee.Map<string, DynamicInterface> interfaces = new Gee.HashMap<string, DynamicInterface> ();
+8 -8
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class ThreadIgnoreScope {
public sealed class ThreadIgnoreScope {
public enum Kind {
APPLICATION_THREAD,
FRIDA_THREAD
@@ -43,7 +43,7 @@ namespace Frida {
}
#if ANDROID
public class ThreadCountCloaker : Object {
public sealed class ThreadCountCloaker : Object {
private ReadFunc * read_slot;
private static ReadFunc old_read_impl;
@@ -156,12 +156,12 @@ namespace Frida {
}
}
#else
public class ThreadCountCloaker : Object {
public sealed class ThreadCountCloaker : Object {
}
#endif
#if LINUX
public class ThreadListCloaker : Object, DirListFilter {
public sealed class ThreadListCloaker : Object, DirListFilter {
private string our_dir_by_pid;
private DirListCloaker cloaker;
@@ -180,7 +180,7 @@ namespace Frida {
}
}
public class FDListCloaker : Object, DirListFilter {
public sealed class FDListCloaker : Object, DirListFilter {
private string our_dir_by_pid;
private DirListCloaker cloaker;
@@ -199,7 +199,7 @@ namespace Frida {
}
}
private class DirListCloaker : Object {
private sealed class DirListCloaker : Object {
public weak DirListFilter filter {
get;
construct;
@@ -467,10 +467,10 @@ namespace Frida {
public abstract bool matches_file (string name);
}
#else
public class ThreadListCloaker : Object {
public sealed class ThreadListCloaker : Object {
}
public class FDListCloaker : Object {
public sealed class FDListCloaker : Object {
}
#endif
}
+1 -1
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class ExitMonitor : Object, Gum.InvocationListener {
public sealed class ExitMonitor : Object, Gum.InvocationListener {
public weak ExitHandler handler {
get;
construct;
+2 -2
View File
@@ -1,6 +1,6 @@
namespace Frida {
#if WINDOWS
public class FileDescriptorGuard : Object {
public sealed class FileDescriptorGuard : Object {
public Gum.MemoryRange agent_range {
get;
construct;
@@ -11,7 +11,7 @@ namespace Frida {
}
}
#else
public class FileDescriptorGuard : Object {
public sealed class FileDescriptorGuard : Object {
public Gum.MemoryRange agent_range {
get;
construct;
+2 -2
View File
@@ -1,6 +1,6 @@
namespace Frida {
#if WINDOWS
public class FileDescriptorTablePadder {
public sealed class FileDescriptorTablePadder {
public static FileDescriptorTablePadder obtain () {
return new FileDescriptorTablePadder ();
}
@@ -9,7 +9,7 @@ namespace Frida {
}
}
#else
public class FileDescriptorTablePadder {
public sealed class FileDescriptorTablePadder {
private const int MIN_TABLE_SIZE = 32;
private static unowned FileDescriptorTablePadder shared_instance = null;
+2 -2
View File
@@ -1,6 +1,6 @@
namespace Frida {
#if WINDOWS
public class ForkMonitor : Object {
public sealed class ForkMonitor : Object {
public weak ForkHandler handler {
get;
construct;
@@ -11,7 +11,7 @@ namespace Frida {
}
}
#else
public class ForkMonitor : Object, Gum.InvocationListener {
public sealed class ForkMonitor : Object, Gum.InvocationListener {
public weak ForkHandler handler {
get;
construct;
+1 -1
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class PortalClient : Object, AgentSessionProvider {
public sealed class PortalClient : Object, AgentSessionProvider {
public signal void resume ();
public signal void kill ();
+2 -2
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class ScriptEngine : Object {
public sealed class ScriptEngine : Object {
public signal void message_from_script (AgentScriptId script_id, string json, Bytes? data);
public signal void message_from_debugger (AgentScriptId script_id, string message);
@@ -223,7 +223,7 @@ namespace Frida {
source.attach (Gum.ScriptBackend.get_scheduler ().get_js_context ());
}
public class ScriptInstance : Object, RpcPeer {
public sealed class ScriptInstance : Object, RpcPeer {
public signal void closed ();
public signal void message (string json, Bytes? data);
public signal void debug_message (string message);
+1 -1
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class SpawnMonitor : Object, Gum.InvocationListener {
public sealed class SpawnMonitor : Object, Gum.InvocationListener {
public weak SpawnHandler handler {
get;
construct;
+2 -2
View File
@@ -1,6 +1,6 @@
namespace Frida {
#if DARWIN
public class ThreadSuspendMonitor : Object {
public sealed class ThreadSuspendMonitor : Object {
public weak ProcessInvader invader {
get;
construct;
@@ -131,7 +131,7 @@ namespace Frida {
}
}
#else
public class ThreadSuspendMonitor : Object {
public sealed class ThreadSuspendMonitor : Object {
public weak ProcessInvader invader {
get;
construct;
+2 -2
View File
@@ -1,6 +1,6 @@
namespace Frida {
#if DARWIN
public class UnwindSitter : Object {
public sealed class UnwindSitter : Object {
public weak ProcessInvader invader {
get;
construct;
@@ -62,7 +62,7 @@ namespace Frida {
public extern static void _unhook_libunwind ();
}
#else
public class UnwindSitter : Object {
public sealed class UnwindSitter : Object {
public weak ProcessInvader invader {
get;
construct;
+2 -2
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class PipeTransport : Object {
public sealed class PipeTransport : Object {
public string local_address {
get;
construct;
@@ -42,7 +42,7 @@ namespace Frida {
}
#if WINDOWS
public class WindowsPipe : IOStream {
public sealed class WindowsPipe : IOStream {
public string address {
get;
construct;
-1
View File
@@ -431,7 +431,6 @@ if gi_dep.found()
else
girdir = get_option('prefix') / get_option('datadir') / 'gir-1.0'
endif
uninstalled_girdir = meson.current_build_dir() / 'src'
vapidir = get_option('prefix') / get_option('datadir') / 'vala' / 'vapi'
+1 -1
View File
@@ -142,7 +142,7 @@ namespace Frida.Portal {
return application.run ();
}
private class Application : Object {
private sealed class Application : Object {
public signal void ready (bool success);
public PortalService service {
+1 -1
View File
@@ -235,7 +235,7 @@ namespace Frida.Server {
}
#endif
private class Application : Object {
private sealed class Application : Object {
public signal void ready (bool success);
public string? device_id {
+1 -1
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class AgentContainer : Object, AgentSessionProvider {
public sealed class AgentContainer : Object, AgentSessionProvider {
public DBusConnection connection {
get;
private set;
+141198
View File
File diff suppressed because it is too large. Load diff
+11 -3
View File
@@ -20,6 +20,8 @@ CORE_TAG_FIELD = f"{{{CORE_NAMESPACE}}}field"
CORE_TAG_CONSTRUCTOR = f"{{{CORE_NAMESPACE}}}constructor"
CORE_TAG_METHOD = f"{{{CORE_NAMESPACE}}}method"
OBJECT_TYPE_PATTERN = re.compile(r"\bpublic\s+(sealed )?(class|interface)\s+(\w+)\b")
def main():
parser = argparse.ArgumentParser(description="Generate refined Frida API definitions")
parser.add_argument('--output', dest='output_type', choices=['bundle', 'header', 'gir', 'vapi', 'vapi-stamp'], default='bundle')
@@ -288,12 +290,18 @@ def parse_api(api_version, toplevel_code, core_header, core_vapi, base_header, b
"StaticAuthenticationService": "AuthenticationService",
}
internal_type_prefixes = [
"AgentMessageKind",
"Fruity",
"HostSession",
"MessageType",
"PeerSetup",
"PortConflictBehavior",
"ResultCode",
"SpawnStartState",
"State",
"StringTerminator",
"UnloadPolicy",
"WebService",
"Winjector"
]
seen_enum_names = set()
@@ -412,8 +420,8 @@ def parse_api(api_version, toplevel_code, core_header, core_vapi, base_header, b
current_enum.vapi_declaration = stripped_line
else:
ignoring = True
elif stripped_line.startswith("public class") or stripped_line.startswith("public interface"):
name = re.match(r"^public (class|interface) (\w+) ", stripped_line).group(2)
elif (match := OBJECT_TYPE_PATTERN.match(stripped_line)) is not None:
name = match.group(3)
if name not in object_type_by_name:
ignoring = True
else:
@@ -470,7 +478,7 @@ def function_is_public(name):
]
def parse_vala_object_types(source) -> List[ApiObjectType]:
return [ApiObjectType(m.group(2), m.group(1)) for m in re.finditer(r"^\t+public\s+(class|interface)\s+(\w+)\s+", source, re.MULTILINE)]
return [ApiObjectType(m.group(3), m.group(2)) for m in OBJECT_TYPE_PATTERN.finditer(source, re.MULTILINE)]
def parse_vapi_functions(vapi) -> List[ApiFunction]:
return [ApiFunction(m.group(1), m.group(0)) for m in re.finditer(r"^\tpublic static .+ (\w+) \(.+;", vapi, re.MULTILINE)]
+6 -3
View File
@@ -1,3 +1,5 @@
fs = import('fs')
generate_api = [python, files('generate.py')]
generate_api_args = [
@@ -32,6 +34,8 @@ core_public_h = core_api[0]
core_public_gir = core_api[1]
core_public_vapi = [core_api[2], core_api[3]]
gio_gir = fs.copyfile('Gio-2.0.gir')
core_public_vapi_stamp = custom_target('frida-core-vapi-stamp',
input: core_public_vapi,
output: f'frida-core-@[email protected]',
@@ -59,8 +63,6 @@ core_public_lib = custom_target('frida-core-library',
install_dir: get_option('libdir'),
)
fs = import('fs')
core_public_extra_headers = []
if host_os == 'android'
core_public_extra_headers += fs.copyfile(frida_selinux_h)
@@ -71,6 +73,7 @@ if build_machine.system() == 'windows'
else
uninstalled_incdir = meson.current_build_dir()
endif
uninstalled_girdir = uninstalled_incdir
uninstalled_vapidir = uninstalled_incdir
uninstalled_variables = {
@@ -86,7 +89,7 @@ installed_variables = {
}
core_public_dep = declare_dependency(
sources: [core_public_h, core_public_gir, core_public_vapi_stamp, core_public_extra_headers],
sources: [core_public_h, core_public_gir, gio_gir, core_public_vapi_stamp, core_public_extra_headers],
include_directories: include_directories('.'),
link_args: backend_libs_private,
link_with: core_public_lib,
+1 -1
View File
@@ -17,7 +17,7 @@ namespace Frida.Barebone {
public abstract async void deallocate (Cancellable? cancellable) throws Error, IOError;
}
public class SimpleAllocator : Object, Allocator {
public sealed class SimpleAllocator : Object, Allocator {
public size_t page_size {
get { return _page_size; }
}
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
namespace Frida.Barebone {
public class ArmMachine : Object, Machine {
public sealed class ArmMachine : Object, Machine {
public override GDB.Client gdb {
get;
set;
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
namespace Frida.Barebone {
public class Arm64Machine : Object, Machine {
public sealed class Arm64Machine : Object, Machine {
public override GDB.Client gdb {
get;
set;
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
namespace Frida.Barebone {
public class UnknownMachine : Object, Machine {
public sealed class UnknownMachine : Object, Machine {
public GDB.Client gdb {
get;
set;
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
namespace Frida.Barebone {
public class IA32Machine : Object, Machine {
public sealed class IA32Machine : Object, Machine {
public override GDB.Client gdb {
get;
set;
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
namespace Frida.Barebone {
public class X64Machine : Object, Machine {
public sealed class X64Machine : Object, Machine {
public override GDB.Client gdb {
get;
set;
+44 -5
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class BareboneHostSessionBackend : Object, HostSessionBackend {
public sealed class BareboneHostSessionBackend : Object, HostSessionBackend {
private BareboneHostSessionProvider? provider;
private const uint16 DEFAULT_PORT = 3333;
@@ -30,7 +30,7 @@ namespace Frida {
}
}
public class BareboneHostSessionProvider : Object, HostSessionProvider {
public sealed class BareboneHostSessionProvider : Object, HostSessionProvider {
public string id {
get { return "barebone"; }
}
@@ -141,12 +141,35 @@ namespace Frida {
return yield this.host_session.link_agent_session (id, sink, cancellable);
}
public void unlink_agent_session (HostSession host_session, AgentSessionId id) {
if (host_session != this.host_session)
return;
this.host_session.unlink_agent_session (id);
}
public async IOStream link_channel (HostSession host_session, ChannelId id, Cancellable? cancellable)
throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Channels are not supported by this backend");
}
public void unlink_channel (HostSession host_session, ChannelId id) {
}
public async ServiceSession link_service_session (HostSession host_session, ServiceSessionId id, Cancellable? cancellable)
throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
}
public void unlink_service_session (HostSession host_session, ServiceSessionId id) {
}
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
agent_session_detached (id, reason, crash);
}
}
public class BareboneHostSession : Object, HostSession {
public sealed class BareboneHostSession : Object, HostSession {
public Barebone.Services services {
get;
construct;
@@ -260,6 +283,14 @@ namespace Frida {
return session;
}
public void unlink_agent_session (AgentSessionId id) {
BareboneAgentSession? session = agent_sessions[id];
if (session == null)
return;
session.message_sink = null;
}
public async InjectorPayloadId inject_library_file (uint pid, string path, string entrypoint, string data,
Cancellable? cancellable) throws Error, IOError {
throw_not_supported ();
@@ -270,6 +301,14 @@ namespace Frida {
throw_not_supported ();
}
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Channels are not supported by this backend");
}
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
}
private void on_agent_session_closed (BareboneAgentSession session) {
AgentSessionId id = session.id;
@@ -282,7 +321,7 @@ namespace Frida {
}
}
private class BareboneAgentSession : Object, AgentSession {
private sealed class BareboneAgentSession : Object, AgentSession {
public signal void closed ();
public AgentSessionId id {
@@ -525,7 +564,7 @@ namespace Frida {
}
namespace Barebone {
public class Services : Object {
public sealed class Services : Object {
public Machine machine {
get;
construct;
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
namespace Frida.Barebone {
public class Callback : Object {
public sealed class Callback : Object {
private uint64 code;
private CallbackHandler handler;
private Machine machine;
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
namespace Frida.Barebone {
public class Interceptor : Object {
public sealed class Interceptor : Object {
public Machine machine {
get;
construct;
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaBarebone", gir_version = "1.0")]
namespace Frida.Barebone {
private class RustModule : Object {
private sealed class RustModule : Object {
public signal void console_output (string message);
public Gee.List<Export> exports {
+1 -1
View File
@@ -1,5 +1,5 @@
namespace Frida {
private class BareboneScript : Object {
private sealed class BareboneScript : Object {
public signal void message (string json, Bytes? data);
public AgentScriptId id {
+5 -5
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class Compiler : Object {
public sealed class Compiler : Object {
public signal void starting ();
public signal void finished ();
public signal void output (string bundle);
@@ -199,7 +199,7 @@ namespace Frida {
try {
var device = yield manager.get_device_by_type (LOCAL, 0, io_cancellable);
var session = yield device.get_host_session (io_cancellable);
var agent = new Agent (this, (BaseDBusHostSession) session);
var agent = new Agent (this, (LocalHostSession) session);
load_request.resolve (agent);
} catch (GLib.Error e) {
@@ -238,7 +238,7 @@ namespace Frida {
private Promise<string> source_request = new Promise<string> ();
private Promise<Bytes?> snapshot_request = new Promise<Bytes?> ();
public Agent (Compiler parent, BaseDBusHostSession host_session) {
public Agent (Compiler parent, LocalHostSession host_session) {
Object (
parent: parent,
host_session: host_session,
@@ -465,10 +465,10 @@ namespace Frida {
}
}
public class BuildOptions : CompilerOptions {
public sealed class BuildOptions : CompilerOptions {
}
public class WatchOptions : CompilerOptions {
public sealed class WatchOptions : CompilerOptions {
}
public enum SourceMaps {
+14 -14
View File
@@ -9,7 +9,7 @@
"version": "1.0.0",
"dependencies": {
"@frida/crosspath": "3.0.0",
"frida-compile": "16.4.1",
"frida-compile": "16.4.2",
"frida-fs": "5.2.5"
},
"devDependencies": {
@@ -17,7 +17,7 @@
"@rollup/plugin-node-resolve": "^14.1.0",
"@rollup/plugin-replace": "^4.0.0",
"@rollup/plugin-typescript": "^8.3.4",
"@types/frida-gum": "18.8.1",
"@types/frida-gum": "18.8.2",
"@types/glob": "^8.0.0",
"@types/node": "18.7.23",
"glob": "^8.0.3",
@@ -468,9 +468,9 @@
"dev": true
},
"node_modules/@types/frida-gum": {
"version": "18.8.1",
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.8.1.tgz",
"integrity": "sha512-FhlHORjaw43QbNYIyj5Ji7iYSvk7t5nPiC+GuYDVndqc1bFheeAs88b1odp8HhmpQUrrYVU90wapapKVLlmJHg==",
"version": "18.8.2",
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.8.2.tgz",
"integrity": "sha512-5KH6ITrKJQe1UWrNnbXXx3KXRe/Lx9I1EwkBdC+AMmlo9F5UC0PxdC959aGxhfjXBRIHWxXwXPi3JmeWIbeqeg==",
"dev": true,
"license": "MIT"
},
@@ -641,9 +641,9 @@
"dev": true
},
"node_modules/frida-compile": {
"version": "16.4.1",
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-16.4.1.tgz",
"integrity": "sha512-xI9HNtUFpHxuKBGXaL6XJAYH1zWTvNJDrHRnz1hp0oS24iPHt6c01Jmm3qljZek3oQWn8HhvfNvrzfgbsKzoBQ==",
"version": "16.4.2",
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-16.4.2.tgz",
"integrity": "sha512-wNiFk37JVpCoEsuJF9AHZtccM9Z3KGj3yu0Amsb/DKzKnHCxvl8AlAU5qSfYXfAJtzbNuCKGqNBM8u96KvP28A==",
"dependencies": {
"@frida/assert": "^3.0.1",
"@frida/base64-js": "^2.0.3",
@@ -1466,9 +1466,9 @@
"dev": true
},
"@types/frida-gum": {
"version": "18.8.1",
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.8.1.tgz",
"integrity": "sha512-FhlHORjaw43QbNYIyj5Ji7iYSvk7t5nPiC+GuYDVndqc1bFheeAs88b1odp8HhmpQUrrYVU90wapapKVLlmJHg==",
"version": "18.8.2",
"resolved": "https://registry.npmjs.org/@types/frida-gum/-/frida-gum-18.8.2.tgz",
"integrity": "sha512-5KH6ITrKJQe1UWrNnbXXx3KXRe/Lx9I1EwkBdC+AMmlo9F5UC0PxdC959aGxhfjXBRIHWxXwXPi3JmeWIbeqeg==",
"dev": true
},
"@types/glob": {
@@ -1597,9 +1597,9 @@
"dev": true
},
"frida-compile": {
"version": "16.4.1",
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-16.4.1.tgz",
"integrity": "sha512-xI9HNtUFpHxuKBGXaL6XJAYH1zWTvNJDrHRnz1hp0oS24iPHt6c01Jmm3qljZek3oQWn8HhvfNvrzfgbsKzoBQ==",
"version": "16.4.2",
"resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-16.4.2.tgz",
"integrity": "sha512-wNiFk37JVpCoEsuJF9AHZtccM9Z3KGj3yu0Amsb/DKzKnHCxvl8AlAU5qSfYXfAJtzbNuCKGqNBM8u96KvP28A==",
"requires": {
"@frida/assert": "^3.0.1",
"@frida/base64-js": "^2.0.3",
+2 -2
View File
@@ -9,7 +9,7 @@
},
"dependencies": {
"@frida/crosspath": "3.0.0",
"frida-compile": "16.4.1",
"frida-compile": "16.4.2",
"frida-fs": "5.2.5"
},
"devDependencies": {
@@ -17,7 +17,7 @@
"@rollup/plugin-node-resolve": "^14.1.0",
"@rollup/plugin-replace": "^4.0.0",
"@rollup/plugin-typescript": "^8.3.4",
"@types/frida-gum": "18.8.1",
"@types/frida-gum": "18.8.2",
"@types/glob": "^8.0.0",
"@types/node": "18.7.23",
"glob": "^8.0.3",
+230 -150
View File
@@ -1,6 +1,5 @@
namespace Frida {
#if HAVE_LOCAL_BACKEND
public class ControlService : Object {
public sealed class ControlService : Object {
public EndpointParameters endpoint_params {
get;
construct;
@@ -12,6 +11,7 @@ namespace Frida {
}
private HostSession host_session;
private HostSessionProvider provider;
private State state = STOPPED;
@@ -21,8 +21,12 @@ namespace Frida {
private Gee.Set<ControlChannel> spawn_gaters = new Gee.HashSet<ControlChannel> ();
private Gee.Map<uint, PendingSpawn> pending_spawn = new Gee.HashMap<uint, PendingSpawn> ();
private Gee.Map<AgentSessionId?, AgentSessionEntry> sessions =
private Gee.Map<AgentSessionId?, AgentSessionEntry> agent_sessions =
new Gee.HashMap<AgentSessionId?, AgentSessionEntry> (AgentSessionId.hash, AgentSessionId.equal);
private Gee.Map<ChannelId?, ChannelEntry> channels =
new Gee.HashMap<ChannelId?, ChannelEntry> (ChannelId.hash, ChannelId.equal);
private Gee.Map<ServiceSessionId?, ServiceSessionEntry> service_sessions =
new Gee.HashMap<ServiceSessionId?, ServiceSessionEntry> (ServiceSessionId.hash, ServiceSessionId.equal);
private Cancellable io_cancellable = new Cancellable ();
@@ -35,7 +39,8 @@ namespace Frida {
STOPPING
}
public ControlService (EndpointParameters endpoint_params, ControlServiceOptions? options = null) {
public ControlService (EndpointParameters endpoint_params, ControlServiceOptions? options = null) throws Error {
#if HAVE_LOCAL_BACKEND
ControlServiceOptions opts = (options != null) ? options : new ControlServiceOptions ();
HostSession session;
@@ -63,7 +68,10 @@ namespace Frida {
options: opts
);
assign_session (session);
assign_session (session, new PrecreatedLocalHostSessionProvider ((LocalHostSession) session));
#else
throw new Error.NOT_SUPPORTED ("Local backend not available");
#endif
}
public async ControlService.with_device (Device device, EndpointParameters endpoint_params,
@@ -77,17 +85,7 @@ namespace Frida {
options: opts
);
assign_session (session);
}
internal ControlService.with_host_session (HostSession host_session, EndpointParameters endpoint_params,
ControlServiceOptions? options = null) {
Object (
endpoint_params: endpoint_params,
options: (options != null) ? options : new ControlServiceOptions ()
);
assign_session (host_session);
assign_session (session, device.provider);
}
construct {
@@ -99,7 +97,7 @@ namespace Frida {
main_handler = new ConnectionHandler (this, null);
}
private void assign_session (HostSession session) {
private void assign_session (HostSession session, HostSessionProvider provider) {
host_session = session;
host_session.spawn_added.connect (notify_spawn_added);
host_session.child_added.connect (notify_child_added);
@@ -107,7 +105,11 @@ namespace Frida {
host_session.process_crashed.connect (notify_process_crashed);
host_session.output.connect (notify_output);
host_session.agent_session_detached.connect (on_agent_session_detached);
host_session.channel_closed.connect (on_channel_closed);
host_session.service_session_closed.connect (on_service_session_closed);
host_session.uninjected.connect (notify_uninjected);
this.provider = provider;
}
public async void start (Cancellable? cancellable = null) throws Error, IOError {
@@ -123,7 +125,7 @@ namespace Frida {
yield service.start (cancellable);
if (options.enable_preload) {
var base_host_session = host_session as BaseDBusHostSession;
var base_host_session = host_session as LocalHostSession;
if (base_host_session != null)
base_host_session.preload.begin (io_cancellable);
}
@@ -162,9 +164,8 @@ namespace Frida {
yield main_handler.close (cancellable);
var base_host_session = host_session as BaseDBusHostSession;
if (base_host_session != null)
yield base_host_session.close (cancellable);
if (provider is PrecreatedLocalHostSessionProvider)
yield provider.destroy (host_session, cancellable);
state = STOPPED;
}
@@ -226,17 +227,15 @@ namespace Frida {
}
private async void teardown_control_channel (ControlChannel channel) {
foreach (AgentSessionId id in channel.sessions) {
AgentSessionEntry entry = sessions[id];
foreach (AgentSessionId id in channel.agent_sessions) {
AgentSessionEntry entry = agent_sessions[id];
var base_host_session = host_session as BaseDBusHostSession;
if (base_host_session != null)
base_host_session.unlink_agent_session (id);
provider.unlink_agent_session (host_session, id);
AgentSession? session = entry.session;
if (entry.persist_timeout == 0 || session == null) {
sessions.unset (id);
agent_sessions.unset (id);
if (session != null)
session.close.begin (io_cancellable);
} else {
@@ -245,6 +244,24 @@ namespace Frida {
}
}
foreach (ChannelId id in channel.channels.to_array ()) {
ChannelEntry entry = channels[id];
provider.unlink_channel (host_session, id);
channels.unset (id);
Channel? ch = entry.channel;
if (ch != null)
ch.close.begin (null);
}
foreach (ServiceSessionId id in channel.service_sessions.to_array ()) {
provider.unlink_service_session (host_session, id);
service_sessions.unset (id);
}
try {
yield disable_spawn_gating (channel);
} catch (GLib.Error e) {
@@ -379,12 +396,22 @@ namespace Frida {
yield parent.reattach (id, requester, cancellable);
}
public async ChannelId open_channel (string address, ControlChannel requester, Cancellable? cancellable)
throws Error, IOError {
return yield parent.open_channel (address, requester, cancellable);
}
public async ServiceSessionId open_service (string address, ControlChannel requester, Cancellable? cancellable)
throws Error, IOError {
return yield parent.open_service (address, requester, cancellable);
}
public void open_tcp_transport (AgentSessionId id, Cancellable? cancellable, out uint16 port, out string token)
throws Error {
#if WINDOWS
throw new Error.NOT_SUPPORTED ("Not yet supported on Windows");
#else
var base_host_session = host_session as BaseDBusHostSession;
var base_host_session = host_session as LocalHostSession;
if (base_host_session == null)
throw new Error.NOT_SUPPORTED ("Not supported for remote host sessions");
if (!base_host_session.can_pass_file_descriptors_to_agent_session (id))
@@ -454,7 +481,7 @@ namespace Frida {
#if !WINDOWS
AgentSessionId session_id = transport.session_id;
var base_host_session = host_session as BaseDBusHostSession;
var base_host_session = host_session as LocalHostSession;
if (base_host_session == null)
throw new Error.NOT_SUPPORTED ("Not supported for remote host sessions");
@@ -537,12 +564,12 @@ namespace Frida {
throw_dbus_error (e);
}
requester.sessions.add (id);
requester.agent_sessions.add (id);
var opts = SessionOptions._deserialize (options);
var entry = new AgentSessionEntry (requester, id, opts.persist_timeout, io_cancellable);
sessions[id] = entry;
var entry = new AgentSessionEntry (requester, id, opts.persist_timeout);
agent_sessions[id] = entry;
entry.expired.connect (on_agent_session_expired);
yield link_session (id, entry, requester, cancellable);
@@ -551,11 +578,11 @@ namespace Frida {
}
private async void reattach (AgentSessionId id, ControlChannel requester, Cancellable? cancellable) throws Error, IOError {
AgentSessionEntry? entry = sessions[id];
AgentSessionEntry? entry = agent_sessions[id];
if (entry == null || entry.controller != null)
throw new Error.INVALID_OPERATION ("Invalid session ID");
requester.sessions.add (id);
requester.agent_sessions.add (id);
entry.attach_controller (requester);
@@ -574,28 +601,7 @@ namespace Frida {
throw_dbus_error (e);
}
AgentSession session;
var base_host_session = host_session as BaseDBusHostSession;
if (base_host_session != null) {
session = yield base_host_session.link_agent_session (id, sink, cancellable);
} else {
DBusConnection internal_connection = ((DBusProxy) host_session).g_connection;
try {
session = yield internal_connection.get_proxy (null, ObjectPath.for_agent_session (id),
DO_NOT_LOAD_PROPERTIES, cancellable);
} catch (IOError e) {
throw_dbus_error (e);
}
entry.internal_connection = internal_connection;
try {
entry.take_internal_registration (
internal_connection.register_object (ObjectPath.for_agent_message_sink (id), sink));
} catch (IOError e) {
assert_not_reached ();
}
}
var session = yield provider.link_agent_session (host_session, id, sink, cancellable);
entry.session = session;
try {
@@ -606,6 +612,52 @@ namespace Frida {
}
}
private async ChannelId open_channel (string address, ControlChannel requester, Cancellable? cancellable)
throws Error, IOError {
ChannelId id;
try {
id = yield host_session.open_channel (address, cancellable);
} catch (GLib.Error e) {
throw_dbus_error (e);
}
requester.channels.add (id);
var entry = new ChannelEntry (requester, id);
channels[id] = entry;
var stream = yield provider.link_channel (host_session, id, cancellable);
Channel channel = new ChannelEndpoint (stream);
entry.channel = channel;
entry.take_controller_registration (requester.connection.register_object (ObjectPath.for_channel (id), channel));
return id;
}
private async ServiceSessionId open_service (string address, ControlChannel requester, Cancellable? cancellable)
throws Error, IOError {
ServiceSessionId id;
try {
id = yield host_session.open_service (address, cancellable);
} catch (GLib.Error e) {
throw_dbus_error (e);
}
requester.service_sessions.add (id);
var entry = new ServiceSessionEntry (requester, id);
service_sessions[id] = entry;
var session = yield provider.link_service_session (host_session, id, cancellable);
entry.session = session;
entry.take_controller_registration (
requester.connection.register_object (ObjectPath.for_service_session (id), session));
return id;
}
private void notify_spawn_added (HostSpawnInfo info) {
foreach (ControlChannel channel in spawn_gaters)
channel.spawn_added (info);
@@ -646,15 +698,33 @@ namespace Frida {
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
AgentSessionEntry entry;
if (sessions.unset (id, out entry)) {
if (agent_sessions.unset (id, out entry)) {
ControlChannel? controller = entry.controller;
if (controller != null) {
controller.sessions.remove (id);
controller.agent_sessions.remove (id);
controller.agent_session_detached (id, reason, crash);
}
}
}
private void on_channel_closed (ChannelId id) {
ChannelEntry entry;
if (channels.unset (id, out entry)) {
ControlChannel controller = entry.controller;
controller.channels.remove (id);
controller.channel_closed (id);
}
}
private void on_service_session_closed (ServiceSessionId id) {
ServiceSessionEntry entry;
if (service_sessions.unset (id, out entry)) {
ControlChannel controller = entry.controller;
controller.service_sessions.remove (id);
controller.service_session_closed (id);
}
}
private void notify_uninjected (InjectorPayloadId id) {
all_control_channels ().foreach (channel => {
channel.uninjected (id);
@@ -663,7 +733,7 @@ namespace Frida {
}
private void on_agent_session_expired (AgentSessionEntry entry) {
sessions.unset (entry.id);
agent_sessions.unset (entry.id);
}
private interface Peer : Object {
@@ -738,11 +808,21 @@ namespace Frida {
construct;
}
public Gee.Set<AgentSessionId?> sessions {
public Gee.Set<AgentSessionId?> agent_sessions {
get;
default = new Gee.HashSet<AgentSessionId?> (AgentSessionId.hash, AgentSessionId.equal);
}
public Gee.Set<ChannelId?> channels {
get;
default = new Gee.HashSet<ChannelId?> (ChannelId.hash, ChannelId.equal);
}
public Gee.Set<ServiceSessionId?> service_sessions {
get;
default = new Gee.HashSet<ServiceSessionId?> (ServiceSessionId.hash, ServiceSessionId.equal);
}
private Gee.Set<uint> registrations = new Gee.HashSet<uint> ();
private TimeoutSource? ping_timer;
@@ -867,6 +947,14 @@ namespace Frida {
return yield parent.host_session.inject_library_blob (pid, blob, entrypoint, data, cancellable);
}
public async ChannelId open_channel (string address, Cancellable? cancellable) throws GLib.Error {
return yield parent.open_channel (address, this, cancellable);
}
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws GLib.Error {
return yield parent.open_service (address, this, cancellable);
}
private async void open_tcp_transport (AgentSessionId id, Cancellable? cancellable, out uint16 port,
out string token) throws Error {
parent.open_tcp_transport (id, cancellable, out port, out token);
@@ -890,14 +978,45 @@ namespace Frida {
}
}
private class AgentSessionEntry {
public signal void expired ();
private abstract class Entry {
public ControlChannel? controller {
get;
private set;
get {
return _controller;
}
protected set {
unregister_all ();
_controller = value;
}
}
private ControlChannel? _controller;
private Gee.Collection<uint> registrations = new Gee.ArrayList<uint> ();
protected Entry (ControlChannel? controller) {
this.controller = controller;
}
~Entry () {
unregister_all ();
}
public void take_controller_registration (uint id) {
registrations.add (id);
}
private void unregister_all () {
if (_controller == null)
return;
var connection = _controller.connection;
foreach (uint id in registrations)
connection.unregister_object (id);
registrations.clear ();
}
}
private class AgentSessionEntry : Entry {
public signal void expired ();
public AgentSessionId id {
get;
private set;
@@ -913,36 +1032,20 @@ namespace Frida {
private set;
}
public DBusConnection? internal_connection {
get;
set;
}
public Cancellable io_cancellable {
get;
private set;
}
private Gee.Collection<uint> internal_registrations = new Gee.ArrayList<uint> ();
private Gee.Collection<uint> controller_registrations = new Gee.ArrayList<uint> ();
private TimeoutSource? expiry_timer;
public AgentSessionEntry (ControlChannel controller, AgentSessionId id, uint persist_timeout,
Cancellable io_cancellable) {
this.controller = controller;
public AgentSessionEntry (ControlChannel? controller, AgentSessionId id, uint persist_timeout) {
base (controller);
this.id = id;
this.persist_timeout = persist_timeout;
this.io_cancellable = io_cancellable;
}
~AgentSessionEntry () {
stop_expiry_timer ();
unregister_all ();
}
public void detach_controller () {
unregister_all ();
controller = null;
session = null;
@@ -956,27 +1059,6 @@ namespace Frida {
controller = c;
}
public void take_internal_registration (uint id) {
internal_registrations.add (id);
}
public void take_controller_registration (uint id) {
controller_registrations.add (id);
}
private void unregister_all () {
if (controller != null)
unregister_all_in (controller_registrations, controller.connection);
if (internal_connection != null)
unregister_all_in (internal_registrations, internal_connection);
}
private void unregister_all_in (Gee.Collection<uint> ids, DBusConnection connection) {
foreach (uint id in ids)
connection.unregister_object (id);
ids.clear ();
}
private void start_expiry_timer () {
if (expiry_timer != null)
return;
@@ -995,57 +1077,55 @@ namespace Frida {
expiry_timer = null;
}
}
}
#else
public class ControlService : Object {
public ControlService (EndpointParameters endpoint_params, ControlServiceOptions? options = null) {
}
public ControlService.with_host_session (HostSession host_session, EndpointParameters endpoint_params,
ControlServiceOptions? options = null) {
}
public async void start (Cancellable? cancellable = null) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Local backend not available");
}
public void start_sync (Cancellable? cancellable = null) throws Error, IOError {
create<StartTask> ().execute (cancellable);
}
private class StartTask : ControlServiceTask<void> {
protected override async void perform_operation () throws Error, IOError {
yield parent.start (cancellable);
}
}
public async void stop (Cancellable? cancellable = null) throws Error, IOError {
}
public void stop_sync (Cancellable? cancellable = null) throws Error, IOError {
create<StopTask> ().execute (cancellable);
}
private class StopTask : ControlServiceTask<void> {
protected override async void perform_operation () throws Error, IOError {
yield parent.stop (cancellable);
}
}
private T create<T> () {
return Object.new (typeof (T), parent: this);
}
private abstract class ControlServiceTask<T> : AsyncTask<T> {
public weak ControlService parent {
private class ChannelEntry : Entry {
public ChannelId id {
get;
construct;
private set;
}
public Channel? channel {
get;
set;
}
public ChannelEntry (ControlChannel controller, ChannelId id) {
base (controller);
this.id = id;
}
}
private class ServiceSessionEntry : Entry {
public ServiceSessionId id {
get;
private set;
}
public ServiceSession? session {
get;
set;
}
public ServiceSessionEntry (ControlChannel controller, ServiceSessionId id) {
base (controller);
this.id = id;
}
}
}
#endif
public class ControlServiceOptions : Object {
private sealed class PrecreatedLocalHostSessionProvider : LocalHostSessionProvider {
public PrecreatedLocalHostSessionProvider (LocalHostSession session) {
take_host_session (session);
}
protected override LocalHostSession make_host_session (HostSessionOptions? options) throws Error {
throw new Error.NOT_SUPPORTED ("Not supported");
}
}
public sealed class ControlServiceOptions : Object {
public string? sysroot {
get;
set;
+16 -90
View File
@@ -1,98 +1,24 @@
namespace Frida {
public class DarwinHostSessionBackend : Object, HostSessionBackend {
private DarwinHostSessionProvider local_provider;
public async void start (Cancellable? cancellable) throws IOError {
assert (local_provider == null);
local_provider = new DarwinHostSessionProvider ();
provider_available (local_provider);
}
public async void stop (Cancellable? cancellable) throws IOError {
assert (local_provider != null);
provider_unavailable (local_provider);
yield local_provider.close (cancellable);
local_provider = null;
public sealed class DarwinHostSessionBackend : LocalHostSessionBackend {
protected override LocalHostSessionProvider make_provider () {
return new DarwinHostSessionProvider ();
}
}
public class DarwinHostSessionProvider : Object, HostSessionProvider {
public string id {
get { return "local"; }
}
public string name {
get { return "Local System"; }
}
public Variant? icon {
get { return _icon; }
}
private Variant? _icon;
public HostSessionProviderKind kind {
get { return HostSessionProviderKind.LOCAL; }
}
private DarwinHostSession host_session;
construct {
_icon = _try_extract_icon ();
}
public async void close (Cancellable? cancellable) throws IOError {
if (host_session == null)
return;
host_session.agent_session_detached.disconnect (on_agent_session_detached);
yield host_session.close (cancellable);
host_session = null;
}
public async HostSession create (HostSessionOptions? options, Cancellable? cancellable) throws Error, IOError {
if (host_session != null)
throw new Error.INVALID_OPERATION ("Already created");
public sealed class DarwinHostSessionProvider : LocalHostSessionProvider {
protected override LocalHostSession make_host_session (HostSessionOptions? options) throws Error {
var tempdir = new TemporaryDirectory ();
host_session = new DarwinHostSession (new DarwinHelperProcess (tempdir), tempdir);
host_session.agent_session_detached.connect (on_agent_session_detached);
return host_session;
return new DarwinHostSession (new DarwinHelperProcess (tempdir), tempdir);
}
public async void destroy (HostSession session, Cancellable? cancellable) throws Error, IOError {
if (session != host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
host_session.agent_session_detached.disconnect (on_agent_session_detached);
yield host_session.close (cancellable);
host_session = null;
}
public async AgentSession link_agent_session (HostSession host_session, AgentSessionId id, AgentMessageSink sink,
Cancellable? cancellable) throws Error, IOError {
if (host_session != this.host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
return yield this.host_session.link_agent_session (id, sink, cancellable);
}
public void unlink_agent_session (HostSession host_session, AgentSessionId id) {
if (host_session != this.host_session)
return;
this.host_session.unlink_agent_session (id);
}
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
agent_session_detached (id, reason, crash);
protected override Variant? load_icon () {
return _try_extract_icon ();
}
public extern static Variant? _try_extract_icon ();
}
public class DarwinHostSession : BaseDBusHostSession {
public sealed class DarwinHostSession : LocalHostSession {
public DarwinHelper helper {
get;
construct;
@@ -410,7 +336,7 @@ namespace Frida {
}
#if IOS || TVOS
private class FruitController : Object, MappedAgentContainer {
private sealed class FruitController : Object, MappedAgentContainer {
public signal void spawn_added (HostSpawnInfo info);
public signal void spawn_removed (HostSpawnInfo info);
public signal void process_crashed (CrashInfo crash);
@@ -815,7 +741,7 @@ namespace Frida {
crash_deliveries.unset (delivery.pid);
}
private class CrashDelivery : Object {
private sealed class CrashDelivery : Object {
public signal void expired ();
public uint pid {
@@ -882,7 +808,7 @@ namespace Frida {
private delegate void FoundMappedAgentFunc (MappedAgent agent);
private class MappedAgent {
private sealed class MappedAgent {
public uint id {
get;
private set;
@@ -905,7 +831,7 @@ namespace Frida {
}
}
private class LaunchdAgent : InternalAgent {
private sealed class LaunchdAgent : InternalAgent {
public signal void app_launch_started (string identifier, uint pid);
public signal void app_launch_completed (string identifier, uint pid, GLib.Error? error);
public signal void spawn_preparation_started (HostSpawnInfo info);
@@ -1015,7 +941,7 @@ namespace Frida {
}
}
private class XpcProxyAgent : InternalAgent {
private sealed class XpcProxyAgent : InternalAgent {
public string identifier {
get;
construct;
@@ -1057,7 +983,7 @@ namespace Frida {
}
}
private class ReportCrashAgent : InternalAgent {
private sealed class ReportCrashAgent : InternalAgent {
public signal void crash_detected (uint pid);
public signal void crash_received (CrashInfo crash);
@@ -1289,7 +1215,7 @@ namespace Frida {
}
}
private class OSAnalyticsAgent : InternalAgent {
private sealed class OSAnalyticsAgent : InternalAgent {
public uint pid {
get;
construct;
+3 -3
View File
@@ -686,7 +686,7 @@ namespace Frida {
protected extern void _close_inject_instance (void * instance);
}
public class DTraceAgent : Object {
public sealed class DTraceAgent : Object {
public signal void spawn_added (HostSpawnInfo info);
public signal void spawn_removed (HostSpawnInfo info);
@@ -845,7 +845,7 @@ namespace Frida {
}
}
private class PendingLaunch : Object {
private sealed class PendingLaunch : Object {
public signal void completed ();
public string identifier {
@@ -889,7 +889,7 @@ namespace Frida {
}
}
public class StdioPipes : Object {
public sealed class StdioPipes : Object {
public int input {
get;
construct;
+1 -1
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class DarwinHelperBackend : Object, DarwinHelper {
public sealed class DarwinHelperBackend : Object, DarwinHelper {
public signal void idle ();
public signal void child_dead (uint pid);
public signal void spawn_instance_ready (uint pid);
+2 -2
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class DarwinHelperProcess : Object, DarwinHelper {
public sealed class DarwinHelperProcess : Object, DarwinHelper {
public uint pid {
get {
return (uint) process_pid;
@@ -473,7 +473,7 @@ namespace Frida {
}
}
private class ResourceStore {
private sealed class ResourceStore {
public HelperFile helper {
get;
private set;
+1 -1
View File
@@ -22,7 +22,7 @@ namespace Frida {
public extern void _start_run_loop ();
public extern void _stop_run_loop ();
public class DarwinHelperService : Object, DarwinRemoteHelper {
public sealed class DarwinHelperService : Object, DarwinRemoteHelper {
public string parent_address {
get;
construct;
+2 -2
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class Fruitjector : Object, Injector {
public sealed class Fruitjector : Object, Injector {
public signal void injected (uint id, uint pid, bool has_mapped_module, DarwinModuleDetails mapped_module);
public DarwinHelper helper {
@@ -117,7 +117,7 @@ namespace Frida {
}
}
public class AgentResource : Object {
public sealed class AgentResource : Object {
public string name {
get;
construct;
+4 -4
View File
@@ -6,7 +6,7 @@ namespace Frida {
public abstract void forget (uint pid);
}
public class NullPolicySoftener : Object, PolicySoftener {
public sealed class NullPolicySoftener : Object, PolicySoftener {
public void soften (uint pid) throws Error {
}
@@ -164,7 +164,7 @@ namespace Frida {
}
}
public class InternalIOSTVOSPolicySoftener : IOSTVOSPolicySoftener {
public sealed class InternalIOSTVOSPolicySoftener : IOSTVOSPolicySoftener {
private static bool enabled = false;
public static void enable () {
@@ -184,7 +184,7 @@ namespace Frida {
private extern static void _soften (uint pid) throws Error;
}
public class ElectraPolicySoftener : IOSTVOSPolicySoftener {
public sealed class ElectraPolicySoftener : IOSTVOSPolicySoftener {
private const string LIBJAILBREAK_PATH = "/usr/lib/libjailbreak.dylib";
private Module libjailbreak;
@@ -237,7 +237,7 @@ namespace Frida {
private extern static int _internal_jb_entitle_now (void * jbd_call, uint connection, uint pid);
}
public class Unc0verPolicySoftener : IOSTVOSPolicySoftener {
public sealed class Unc0verPolicySoftener : IOSTVOSPolicySoftener {
private const string SUBSTITUTED_PATH = "/usr/libexec/substituted";
private uint connection;
+5 -5
View File
@@ -69,7 +69,7 @@ namespace Frida.AXML {
}
}
public class ElementTree : Object {
public sealed class ElementTree : Object {
public string name {
get;
set;
@@ -135,7 +135,7 @@ namespace Frida.AXML {
}
}
public class ResourceValue : Object {
public sealed class ResourceValue : Object {
private uint16 size;
private uint8 unused;
private ResourceType type;
@@ -173,7 +173,7 @@ namespace Frida.AXML {
}
}
public class Attribute : Object {
public sealed class Attribute : Object {
private uint32 namespace;
private uint32 name;
private uint32 unused;
@@ -238,7 +238,7 @@ namespace Frida.AXML {
}
}
private class ResourceMap {
private sealed class ResourceMap {
private Gee.ArrayList<uint32> resources = new Gee.ArrayList<uint32> ();
public ResourceMap.with_stream (DataInputStream input, uint32 size) throws IOError {
@@ -247,7 +247,7 @@ namespace Frida.AXML {
}
}
private class StringPool {
private sealed class StringPool {
private uint32 flags;
private Gee.ArrayList<string> strings = new Gee.ArrayList<string> ();
+8 -8
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaDroidy", gir_version = "1.0")]
namespace Frida.Droidy {
public class DeviceTracker : Object {
public sealed class DeviceTracker : Object {
public signal void device_attached (DeviceDetails details);
public signal void device_detached (string serial);
@@ -149,7 +149,7 @@ namespace Frida.Droidy {
}
}
public class DeviceDetails : Object {
public sealed class DeviceDetails : Object {
public string serial {
get;
construct;
@@ -205,7 +205,7 @@ namespace Frida.Droidy {
}
}
public class ShellSession : Object {
public sealed class ShellSession : Object {
public signal void output (StdioPipe pipe, Bytes bytes);
public signal void closed ();
@@ -594,7 +594,7 @@ namespace Frida.Droidy {
STDERR
}
public class ShellCommandResult : Object {
public sealed class ShellCommandResult : Object {
public uint8 status {
get;
construct;
@@ -686,7 +686,7 @@ namespace Frida.Droidy {
}
}
public class FileMetadata : Object {
public sealed class FileMetadata : Object {
public uint32 mode {
get;
set;
@@ -700,7 +700,7 @@ namespace Frida.Droidy {
}
}
public class JDWPTracker : Object {
public sealed class JDWPTracker : Object {
public signal void debugger_attached (uint pid);
public signal void debugger_detached (uint pid);
@@ -768,7 +768,7 @@ namespace Frida.Droidy {
}
}
public class Client : Object {
public sealed class Client : Object {
public signal void closed ();
public signal void message (string payload);
@@ -1154,7 +1154,7 @@ namespace Frida.Droidy {
}
}
public class SyncSession : Object {
public sealed class SyncSession : Object {
public Client client {
get;
construct;
+74 -4
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class DroidyHostSessionBackend : Object, HostSessionBackend {
public sealed class DroidyHostSessionBackend : Object, HostSessionBackend {
private Droidy.DeviceTracker tracker;
private Gee.HashMap<string, DroidyHostSessionProvider> providers = new Gee.HashMap<string, DroidyHostSessionProvider> ();
@@ -86,7 +86,7 @@ namespace Frida {
}
}
public class DroidyHostSessionProvider : Object, HostSessionProvider, HostChannelProvider {
public sealed class DroidyHostSessionProvider : Object, HostSessionProvider, HostChannelProvider {
public string id {
get { return device_details.serial; }
}
@@ -158,6 +158,36 @@ namespace Frida {
return yield this.host_session.link_agent_session (id, sink, cancellable);
}
public void unlink_agent_session (HostSession host_session, AgentSessionId id) {
if (host_session != this.host_session)
return;
this.host_session.unlink_agent_session (id);
}
public async IOStream link_channel (HostSession host_session, ChannelId id, Cancellable? cancellable)
throws Error, IOError {
if (host_session != this.host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
return this.host_session.link_channel (id);
}
public void unlink_channel (HostSession host_session, ChannelId id) {
if (host_session != this.host_session)
return;
this.host_session.unlink_channel (id);
}
public async ServiceSession link_service_session (HostSession host_session, ServiceSessionId id, Cancellable? cancellable)
throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
}
public void unlink_service_session (HostSession host_session, ServiceSessionId id) {
}
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
agent_session_detached (id, reason, crash);
}
@@ -182,7 +212,7 @@ namespace Frida {
}
}
public class DroidyHostSession : Object, HostSession {
public sealed class DroidyHostSession : Object, HostSession {
public Droidy.DeviceDetails device_details {
get;
construct;
@@ -211,6 +241,8 @@ namespace Frida {
private Gee.HashMap<AgentSessionId?, AgentSessionEntry> agent_sessions =
new Gee.HashMap<AgentSessionId?, AgentSessionEntry> (AgentSessionId.hash, AgentSessionId.equal);
private ChannelRegistry channel_registry = new ChannelRegistry ();
private Cancellable io_cancellable = new Cancellable ();
private const double MIN_SERVER_CHECK_INTERVAL = 5.0;
@@ -223,6 +255,10 @@ namespace Frida {
);
}
construct {
channel_registry.channel_closed.connect (on_channel_closed);
}
public async void close (Cancellable? cancellable) throws IOError {
if (remote_server_request != null) {
var server = yield try_get_remote_server (cancellable);
@@ -832,6 +868,15 @@ namespace Frida {
return session;
}
public void unlink_agent_session (AgentSessionId id) {
AgentSessionEntry? entry = agent_sessions[id];
if (entry == null || entry.sink_registration_id == 0)
return;
entry.connection.unregister_object (entry.sink_registration_id);
entry.sink_registration_id = 0;
}
public async InjectorPayloadId inject_library_file (uint pid, string path, string entrypoint, string data,
Cancellable? cancellable) throws Error, IOError {
var server = yield get_remote_server (cancellable);
@@ -852,6 +897,31 @@ namespace Frida {
}
}
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
var stream = yield channel_provider.open_channel (address, cancellable);
var id = ChannelId.generate ();
channel_registry.register (id, stream);
return id;
}
public IOStream link_channel (ChannelId id) throws Error {
return channel_registry.link (id);
}
public void unlink_channel (ChannelId id) {
channel_registry.unlink (id);
}
private void on_channel_closed (ChannelId id) {
channel_closed (id);
}
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
}
private void on_gadget_entry_detached (GadgetEntry entry, SessionDetachReason reason) {
AgentSessionId id = entry.local_session_id;
var no_crash = CrashInfo.empty ();
@@ -1217,7 +1287,7 @@ namespace Frida {
}
}
public class HelperClient : Object, AsyncInitable {
public sealed class HelperClient : Object, AsyncInitable {
public signal void closed ();
public string device_serial {
+2 -2
View File
@@ -6,7 +6,7 @@ namespace Frida.Droidy.Injector {
return yield session.run (cancellable);
}
public class GadgetDetails : Object {
public sealed class GadgetDetails : Object {
public uint pid {
get;
construct;
@@ -31,7 +31,7 @@ namespace Frida.Droidy.Injector {
}
}
private class Session : Object {
private sealed class Session : Object {
public InputStream gadget {
get;
construct;
+57 -57
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaJDWP", gir_version = "1.0")]
namespace Frida.JDWP {
public class Client : GLib.Object, AsyncInitable {
public sealed class Client : GLib.Object, AsyncInitable {
public signal void closed ();
public signal void events_received (Events events);
@@ -593,7 +593,7 @@ namespace Frida.JDWP {
public abstract string to_string ();
}
public class Byte : Value {
public sealed class Byte : Value {
public uint8 val {
get;
construct;
@@ -608,7 +608,7 @@ namespace Frida.JDWP {
}
}
public class Char : Value {
public sealed class Char : Value {
public string val {
get;
construct;
@@ -623,7 +623,7 @@ namespace Frida.JDWP {
}
}
public class Double : Value {
public sealed class Double : Value {
public double val {
get;
construct;
@@ -638,7 +638,7 @@ namespace Frida.JDWP {
}
}
public class Float : Value {
public sealed class Float : Value {
public float val {
get;
construct;
@@ -653,7 +653,7 @@ namespace Frida.JDWP {
}
}
public class Int : Value {
public sealed class Int : Value {
public int32 val {
get;
construct;
@@ -668,7 +668,7 @@ namespace Frida.JDWP {
}
}
public class Long : Value {
public sealed class Long : Value {
public int64 val {
get;
construct;
@@ -698,7 +698,7 @@ namespace Frida.JDWP {
}
}
public class Short : Value {
public sealed class Short : Value {
public int16 val {
get;
construct;
@@ -713,7 +713,7 @@ namespace Frida.JDWP {
}
}
public class Void : Value {
public sealed class Void : Value {
public Void () {
GLib.Object (tag: ValueTag.VOID);
}
@@ -723,7 +723,7 @@ namespace Frida.JDWP {
}
}
public class Boolean : Value {
public sealed class Boolean : Value {
public bool val {
get;
construct;
@@ -738,43 +738,43 @@ namespace Frida.JDWP {
}
}
public class Array : Object {
public sealed class Array : Object {
public Array (ObjectID val) {
GLib.Object (tag: ValueTag.ARRAY, val: val);
}
}
public class ClassObject : Object {
public sealed class ClassObject : Object {
public ClassObject (ObjectID val) {
GLib.Object (tag: ValueTag.CLASS_OBJECT, val: val);
}
}
public class ThreadGroup : Object {
public sealed class ThreadGroup : Object {
public ThreadGroup (ObjectID val) {
GLib.Object (tag: ValueTag.THREAD_GROUP, val: val);
}
}
public class ClassLoader : Object {
public sealed class ClassLoader : Object {
public ClassLoader (ObjectID val) {
GLib.Object (tag: ValueTag.CLASS_LOADER, val: val);
}
}
public class String : Object {
public sealed class String : Object {
public String (ObjectID val) {
GLib.Object (tag: ValueTag.STRING, val: val);
}
}
public class Thread : Object {
public sealed class Thread : Object {
public Thread (ObjectID val) {
GLib.Object (tag: ValueTag.THREAD, val: val);
}
}
public class ClassInfo : GLib.Object {
public sealed class ClassInfo : GLib.Object {
public TaggedReferenceTypeID ref_type {
get;
construct;
@@ -815,7 +815,7 @@ namespace Frida.JDWP {
}
}
public class MethodInfo : GLib.Object {
public sealed class MethodInfo : GLib.Object {
public MethodID id {
get;
construct;
@@ -992,7 +992,7 @@ namespace Frida.JDWP {
}
}
public class Location : GLib.Object {
public sealed class Location : GLib.Object {
public TaggedReferenceTypeID declaring {
get;
construct;
@@ -1071,7 +1071,7 @@ namespace Frida.JDWP {
ALL = 2,
}
public class Events : GLib.Object {
public sealed class Events : GLib.Object {
public SuspendPolicy suspend_policy {
get;
construct;
@@ -1119,7 +1119,7 @@ namespace Frida.JDWP {
public abstract string to_string ();
}
public class SingleStepEvent : Event {
public sealed class SingleStepEvent : Event {
public ThreadID thread {
get;
construct;
@@ -1155,7 +1155,7 @@ namespace Frida.JDWP {
}
}
public class BreakpointEvent : Event {
public sealed class BreakpointEvent : Event {
public ThreadID thread {
get;
construct;
@@ -1191,7 +1191,7 @@ namespace Frida.JDWP {
}
}
public class FramePopEvent : Event {
public sealed class FramePopEvent : Event {
public override string to_string () {
return "FramePopEvent()";
}
@@ -1201,7 +1201,7 @@ namespace Frida.JDWP {
}
}
public class ExceptionEvent : Event {
public sealed class ExceptionEvent : Event {
public ThreadID thread {
get;
construct;
@@ -1254,7 +1254,7 @@ namespace Frida.JDWP {
}
}
public class UserDefinedEvent : Event {
public sealed class UserDefinedEvent : Event {
public override string to_string () {
return "UserDefinedEvent()";
}
@@ -1264,7 +1264,7 @@ namespace Frida.JDWP {
}
}
public class ThreadStartEvent : Event {
public sealed class ThreadStartEvent : Event {
public ThreadID thread {
get;
construct;
@@ -1292,7 +1292,7 @@ namespace Frida.JDWP {
}
}
public class ThreadDeathEvent : Event {
public sealed class ThreadDeathEvent : Event {
public ThreadID thread {
get;
construct;
@@ -1320,7 +1320,7 @@ namespace Frida.JDWP {
}
}
public class ClassPrepareEvent : Event {
public sealed class ClassPrepareEvent : Event {
public ThreadID thread {
get;
construct;
@@ -1373,7 +1373,7 @@ namespace Frida.JDWP {
}
}
public class ClassUnloadEvent : Event {
public sealed class ClassUnloadEvent : Event {
public string signature {
get;
construct;
@@ -1398,7 +1398,7 @@ namespace Frida.JDWP {
}
}
public class ClassLoadEvent : Event {
public sealed class ClassLoadEvent : Event {
public override string to_string () {
return "ClassLoadEvent()";
}
@@ -1435,7 +1435,7 @@ namespace Frida.JDWP {
}
}
public class FieldAccessEvent : FieldEvent {
public sealed class FieldAccessEvent : FieldEvent {
public FieldAccessEvent (EventRequestID request, ThreadID thread, Location location, TaggedReferenceTypeID ref_type,
FieldID field, TaggedObjectID object) {
GLib.Object (
@@ -1471,7 +1471,7 @@ namespace Frida.JDWP {
}
}
public class FieldModificationEvent : FieldEvent {
public sealed class FieldModificationEvent : FieldEvent {
public Value value_to_be {
get;
construct;
@@ -1516,7 +1516,7 @@ namespace Frida.JDWP {
}
}
public class ExceptionCatchEvent : Event {
public sealed class ExceptionCatchEvent : Event {
public override string to_string () {
return "ExceptionCatchEvent()";
}
@@ -1538,7 +1538,7 @@ namespace Frida.JDWP {
}
}
public class MethodEntryEvent : MethodEvent {
public sealed class MethodEntryEvent : MethodEvent {
public MethodEntryEvent (EventRequestID request, ThreadID thread, Location location) {
GLib.Object (
kind: EventKind.METHOD_ENTRY,
@@ -1564,7 +1564,7 @@ namespace Frida.JDWP {
}
}
public class MethodExitEvent : MethodEvent {
public sealed class MethodExitEvent : MethodEvent {
public MethodExitEvent (EventRequestID request, ThreadID thread, Location location) {
GLib.Object (
kind: EventKind.METHOD_EXIT,
@@ -1590,7 +1590,7 @@ namespace Frida.JDWP {
}
}
public class MethodExitWithReturnValueEvent : MethodEvent {
public sealed class MethodExitWithReturnValueEvent : MethodEvent {
public Value retval {
get;
construct;
@@ -1641,7 +1641,7 @@ namespace Frida.JDWP {
}
}
public class MonitorContendedEnterEvent : MonitorEvent {
public sealed class MonitorContendedEnterEvent : MonitorEvent {
public MonitorContendedEnterEvent (EventRequestID request, ThreadID thread, TaggedObjectID object, Location location) {
GLib.Object (
kind: EventKind.MONITOR_CONTENDED_ENTER,
@@ -1670,7 +1670,7 @@ namespace Frida.JDWP {
}
}
public class MonitorContendedEnteredEvent : MonitorEvent {
public sealed class MonitorContendedEnteredEvent : MonitorEvent {
public MonitorContendedEnteredEvent (EventRequestID request, ThreadID thread, TaggedObjectID object, Location location) {
GLib.Object (
kind: EventKind.MONITOR_CONTENDED_ENTERED,
@@ -1699,7 +1699,7 @@ namespace Frida.JDWP {
}
}
public class MonitorWaitEvent : MonitorEvent {
public sealed class MonitorWaitEvent : MonitorEvent {
public int64 timeout {
get;
construct;
@@ -1736,7 +1736,7 @@ namespace Frida.JDWP {
}
}
public class MonitorWaitedEvent : MonitorEvent {
public sealed class MonitorWaitedEvent : MonitorEvent {
public bool timed_out {
get;
construct;
@@ -1774,7 +1774,7 @@ namespace Frida.JDWP {
}
}
public class VMStartEvent : Event {
public sealed class VMStartEvent : Event {
public ThreadID thread {
get;
construct;
@@ -1799,7 +1799,7 @@ namespace Frida.JDWP {
}
}
public class VMDeathEvent : Event {
public sealed class VMDeathEvent : Event {
public VMDeathEvent (EventRequestID request) {
GLib.Object (kind: EventKind.VM_DEATH, request: request);
}
@@ -1814,7 +1814,7 @@ namespace Frida.JDWP {
}
}
public class VMDisconnectedEvent : Event {
public sealed class VMDisconnectedEvent : Event {
public override string to_string () {
return "VMDisconnectedEvent()";
}
@@ -1828,7 +1828,7 @@ namespace Frida.JDWP {
internal abstract void serialize (PacketBuilder builder);
}
public class CountModifier : EventModifier {
public sealed class CountModifier : EventModifier {
public int32 count {
get;
construct;
@@ -1845,7 +1845,7 @@ namespace Frida.JDWP {
}
}
public class ThreadOnlyModifier : EventModifier {
public sealed class ThreadOnlyModifier : EventModifier {
public ThreadID thread {
get;
construct;
@@ -1862,7 +1862,7 @@ namespace Frida.JDWP {
}
}
public class ClassOnlyModifier : EventModifier {
public sealed class ClassOnlyModifier : EventModifier {
public ReferenceTypeID clazz {
get;
construct;
@@ -1879,7 +1879,7 @@ namespace Frida.JDWP {
}
}
public class ClassMatchModifier : EventModifier {
public sealed class ClassMatchModifier : EventModifier {
public string class_pattern {
get;
construct;
@@ -1896,7 +1896,7 @@ namespace Frida.JDWP {
}
}
public class ClassExcludeModifier : EventModifier {
public sealed class ClassExcludeModifier : EventModifier {
public string class_pattern {
get;
construct;
@@ -1913,7 +1913,7 @@ namespace Frida.JDWP {
}
}
public class LocationOnlyModifier : EventModifier {
public sealed class LocationOnlyModifier : EventModifier {
public Location location {
get;
construct;
@@ -1929,7 +1929,7 @@ namespace Frida.JDWP {
}
}
public class ExceptionOnlyModifier : EventModifier {
public sealed class ExceptionOnlyModifier : EventModifier {
public ReferenceTypeID exception_or_null {
get;
construct;
@@ -1962,7 +1962,7 @@ namespace Frida.JDWP {
}
}
public class FieldOnlyModifier : EventModifier {
public sealed class FieldOnlyModifier : EventModifier {
public ReferenceTypeID declaring {
get;
construct;
@@ -1988,7 +1988,7 @@ namespace Frida.JDWP {
}
}
public class StepModifier : EventModifier {
public sealed class StepModifier : EventModifier {
public ThreadID thread {
get;
construct;
@@ -2032,7 +2032,7 @@ namespace Frida.JDWP {
OUT = 2,
}
public class InstanceOnlyModifier : EventModifier {
public sealed class InstanceOnlyModifier : EventModifier {
public ObjectID instance {
get;
construct;
@@ -2049,7 +2049,7 @@ namespace Frida.JDWP {
}
}
public class SourceNameMatchModifier : EventModifier {
public sealed class SourceNameMatchModifier : EventModifier {
public string source_name_pattern {
get;
construct;
@@ -2149,7 +2149,7 @@ namespace Frida.JDWP {
REPLY = (1 << 7),
}
private class CommandBuilder : PacketBuilder {
private sealed class CommandBuilder : PacketBuilder {
public CommandBuilder (uint32 id, CommandSet command_set, uint8 command, IDSizes id_sizes) {
base (id, 0, id_sizes);
@@ -2354,7 +2354,7 @@ namespace Frida.JDWP {
}
}
private class PacketReader {
private sealed class PacketReader {
public size_t available_bytes {
get {
return end - cursor;
@@ -2574,7 +2574,7 @@ namespace Frida.JDWP {
}
}
private class IDSizes {
private sealed class IDSizes {
private bool valid;
private int field_id_size = -1;
private int method_id_size = -1;
+1 -1
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class FileMonitor : Object {
public sealed class FileMonitor : Object {
public signal void change (string file_path, string? other_file_path, FileMonitorEvent event);
public string path {
+4 -4
View File
@@ -408,7 +408,7 @@ namespace Frida {
protected extern InputStream _get_fifo_for_inject_instance (void * instance);
protected extern void _free_inject_instance (void * instance, UnloadPolicy unload_policy);
public class ResourceStore {
public sealed class ResourceStore {
public TemporaryDirectory tempdir {
get;
private set;
@@ -439,7 +439,7 @@ namespace Frida {
}
}
public class AgentDescriptor : Object {
public sealed class AgentDescriptor : Object {
public string name {
get;
construct;
@@ -553,7 +553,7 @@ namespace Frida {
}
}
private class RemoteModule {
private sealed class RemoteModule {
private Gum.Address base_address;
private Gum.ElfModule module;
@@ -587,7 +587,7 @@ namespace Frida {
}
}
private class RemoteThreadSession : Object {
private sealed class RemoteThreadSession : Object {
public signal void ended (UnloadPolicy unload_policy);
public uint id {
+7 -72
View File
@@ -1,82 +1,17 @@
namespace Frida {
public class FreebsdHostSessionBackend : Object, HostSessionBackend {
private FreebsdHostSessionProvider local_provider;
public async void start (Cancellable? cancellable) throws IOError {
assert (local_provider == null);
local_provider = new FreebsdHostSessionProvider ();
provider_available (local_provider);
}
public async void stop (Cancellable? cancellable) throws IOError {
assert (local_provider != null);
provider_unavailable (local_provider);
yield local_provider.close (cancellable);
local_provider = null;
public sealed class FreebsdHostSessionBackend : LocalHostSessionBackend {
protected override LocalHostSessionProvider make_provider () {
return new FreebsdHostSessionProvider ();
}
}
public class FreebsdHostSessionProvider : Object, HostSessionProvider {
public string id {
get { return "local"; }
}
public string name {
get { return "Local System"; }
}
public Variant? icon {
get { return null; }
}
public HostSessionProviderKind kind {
get { return HostSessionProviderKind.LOCAL; }
}
private FreebsdHostSession host_session;
public async void close (Cancellable? cancellable) throws IOError {
if (host_session == null)
return;
host_session.agent_session_detached.disconnect (on_agent_session_detached);
yield host_session.close (cancellable);
host_session = null;
}
public async HostSession create (HostSessionOptions? options, Cancellable? cancellable) throws Error, IOError {
if (host_session != null)
throw new Error.INVALID_OPERATION ("Already created");
host_session = new FreebsdHostSession ();
host_session.agent_session_detached.connect (on_agent_session_detached);
return host_session;
}
public async void destroy (HostSession session, Cancellable? cancellable) throws Error, IOError {
if (session != host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
host_session.agent_session_detached.disconnect (on_agent_session_detached);
yield host_session.close (cancellable);
host_session = null;
}
public async AgentSession link_agent_session (HostSession host_session, AgentSessionId id, AgentMessageSink sink,
Cancellable? cancellable) throws Error, IOError {
if (host_session != this.host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
return yield this.host_session.link_agent_session (id, sink, cancellable);
}
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
agent_session_detached (id, reason, crash);
public sealed class FreebsdHostSessionProvider : LocalHostSessionProvider {
protected override LocalHostSession make_host_session (HostSessionOptions? options) throws Error {
return new FreebsdHostSession ();
}
}
public class FreebsdHostSession : BaseDBusHostSession {
public sealed class FreebsdHostSession : LocalHostSession {
private AgentContainer system_session_container;
private AgentDescriptor agent_desc;
+133 -44
View File
@@ -24,7 +24,7 @@ namespace Frida {
}
}
public class DeviceManager : Object {
public sealed class DeviceManager : Object {
public signal void added (Device device);
public signal void removed (Device device);
public signal void changed ();
@@ -468,7 +468,7 @@ namespace Frida {
}
}
public class DeviceList : Object {
public sealed class DeviceList : Object {
private Gee.List<Device> items;
internal DeviceList (Gee.List<Device> items) {
@@ -484,7 +484,7 @@ namespace Frida {
}
}
public class Device : Object {
public sealed class Device : Object {
public signal void spawn_added (Spawn spawn);
public signal void spawn_removed (Spawn spawn);
public signal void child_added (Child child);
@@ -551,7 +551,6 @@ namespace Frida {
private Gee.HashSet<Promise<Session>> pending_attach_requests = new Gee.HashSet<Promise<Session>> ();
private Gee.HashMap<AgentSessionId?, Promise<bool>> pending_detach_requests =
new Gee.HashMap<AgentSessionId?, Promise<bool>> (AgentSessionId.hash, AgentSessionId.equal);
private Gee.Set<Service> services = new Gee.HashSet<Service> ();
private Bus _bus;
public delegate bool ProcessPredicate (Process process);
@@ -1238,11 +1237,16 @@ namespace Frida {
public async IOStream open_channel (string address, Cancellable? cancellable = null) throws Error, IOError {
check_open ();
var channel_provider = provider as HostChannelProvider;
if (channel_provider == null)
throw new Error.NOT_SUPPORTED ("Channels are not supported by this device");
var host_session = yield get_host_session (cancellable);
return yield channel_provider.open_channel (address, cancellable);
ChannelId id;
try {
id = yield host_session.open_channel (address, cancellable);
} catch (GLib.Error e) {
throw_dbus_error (e);
}
return yield provider.link_channel (host_session, id, cancellable);
}
public IOStream open_channel_sync (string address, Cancellable? cancellable = null) throws Error, IOError {
@@ -1262,15 +1266,18 @@ namespace Frida {
public async Service open_service (string address, Cancellable? cancellable = null) throws Error, IOError {
check_open ();
var service_provider = provider as HostServiceProvider;
if (service_provider == null)
throw new Error.NOT_SUPPORTED ("Services are not supported by this device");
var host_session = yield get_host_session (cancellable);
var service = yield service_provider.open_service (address, cancellable);
service.close.connect (on_service_closed);
services.add (service);
ServiceSessionId id;
try {
id = yield host_session.open_service (address, cancellable);
} catch (GLib.Error e) {
throw_dbus_error (e);
}
return service;
var service_session = yield provider.link_service_session (host_session, id, cancellable);
return new Service (service_session);
}
public Service open_service_sync (string address, Cancellable? cancellable = null) throws Error, IOError {
@@ -1287,10 +1294,6 @@ namespace Frida {
}
}
private void on_service_closed (Service service) {
services.remove (service);
}
public async void unpair (Cancellable? cancellable = null) throws Error, IOError {
check_open ();
@@ -1389,10 +1392,6 @@ namespace Frida {
close_request = new Promise<bool> ();
try {
foreach (var service in services.to_array ())
yield service.cancel (cancellable);
services.clear ();
while (!pending_detach_requests.is_empty) {
var iterator = pending_detach_requests.entries.iterator ();
iterator.next ();
@@ -1546,7 +1545,7 @@ namespace Frida {
}
}
public class RemoteDeviceOptions : Object {
public sealed class RemoteDeviceOptions : Object {
public TlsCertificate? certificate {
get;
set;
@@ -1569,7 +1568,7 @@ namespace Frida {
}
}
public class ApplicationList : Object {
public sealed class ApplicationList : Object {
private Gee.List<Application> items;
internal ApplicationList (Gee.List<Application> items) {
@@ -1585,7 +1584,7 @@ namespace Frida {
}
}
public class Application : Object {
public sealed class Application : Object {
public string identifier {
get;
construct;
@@ -1611,7 +1610,7 @@ namespace Frida {
}
}
public class ProcessList : Object {
public sealed class ProcessList : Object {
private Gee.List<Process> items;
internal ProcessList (Gee.List<Process> items) {
@@ -1627,7 +1626,7 @@ namespace Frida {
}
}
public class Process : Object {
public sealed class Process : Object {
public uint pid {
get;
construct;
@@ -1648,7 +1647,7 @@ namespace Frida {
}
}
public class ProcessMatchOptions : Object {
public sealed class ProcessMatchOptions : Object {
public int timeout {
get;
set;
@@ -1662,7 +1661,7 @@ namespace Frida {
}
}
public class SpawnOptions : Object {
public sealed class SpawnOptions : Object {
public string[]? argv {
get;
set;
@@ -1696,7 +1695,7 @@ namespace Frida {
}
}
public class SpawnList : Object {
public sealed class SpawnList : Object {
private Gee.List<Spawn> items;
internal SpawnList (Gee.List<Spawn> items) {
@@ -1712,7 +1711,7 @@ namespace Frida {
}
}
public class Spawn : Object {
public sealed class Spawn : Object {
public uint pid {
get;
construct;
@@ -1736,7 +1735,7 @@ namespace Frida {
}
}
public class ChildList : Object {
public sealed class ChildList : Object {
private Gee.List<Child> items;
internal ChildList (Gee.List<Child> items) {
@@ -1752,7 +1751,7 @@ namespace Frida {
}
}
public class Child : Object {
public sealed class Child : Object {
public uint pid {
get;
construct;
@@ -1816,7 +1815,7 @@ namespace Frida {
}
}
public class Crash : Object {
public sealed class Crash : Object {
public uint pid {
get;
construct;
@@ -1865,7 +1864,7 @@ namespace Frida {
}
}
public class Bus : Object {
public sealed class Bus : Object {
public signal void detached ();
public signal void message (string json, Bytes? data);
@@ -2000,13 +1999,71 @@ namespace Frida {
}
}
public interface Service : Object {
public sealed class Service : Object {
public signal void close ();
public signal void message (Variant message);
public abstract bool is_closed ();
private ServiceSession? session;
private bool disposed = false;
public abstract async void activate (Cancellable? cancellable = null) throws Error, IOError;
internal Service (ServiceSession session) {
this.session = session;
session.close.connect (on_close);
session.message.connect (on_message);
}
public override void dispose () {
if (!disposed) {
disposed = true;
MainContext context = get_main_context ();
if (context.is_owner ()) {
abandon ();
} else {
var source = new IdleSource ();
source.set_callback (() => {
abandon ();
return false;
});
source.attach (context);
}
}
base.dispose ();
}
~Service () {
forget_session ();
}
private void abandon () {
var s = session;
if (s != null) {
forget_session ();
s.cancel.begin (null);
}
}
private void forget_session () {
session.close.disconnect (on_close);
session.message.disconnect (on_message);
session = null;
}
public bool is_closed () {
return session == null;
}
public async void activate (Cancellable? cancellable = null) throws Error, IOError {
check_open ();
try {
yield session.activate (cancellable);
} catch (GLib.Error e) {
throw_dbus_error (e);
}
}
public void activate_sync (Cancellable? cancellable = null) throws Error, IOError {
create<ActivateTask> ().execute (cancellable);
@@ -2018,7 +2075,17 @@ namespace Frida {
}
}
public abstract async void cancel (Cancellable? cancellable = null) throws IOError;
public async void cancel (Cancellable? cancellable = null) throws IOError {
if (session == null)
return;
try {
yield session.cancel (cancellable);
} catch (GLib.Error e) {
if (e is IOError.CANCELLED)
cancellable.set_error_if_cancelled ();
}
}
public void cancel_sync (Cancellable? cancellable = null) throws IOError {
try {
@@ -2034,7 +2101,15 @@ namespace Frida {
}
}
public abstract async Variant request (Variant parameters, Cancellable? cancellable = null) throws Error, IOError;
public async Variant request (Variant parameters, Cancellable? cancellable = null) throws Error, IOError {
check_open ();
try {
return yield session.request (parameters, cancellable);
} catch (GLib.Error e) {
throw_dbus_error (e);
}
}
public Variant request_sync (Variant parameters, Cancellable? cancellable = null) throws Error, IOError {
var task = create<RequestTask> () as RequestTask;
@@ -2050,6 +2125,20 @@ namespace Frida {
}
}
private void check_open () throws Error {
if (session == null)
throw new Error.INVALID_OPERATION ("Session is gone");
}
private void on_close () {
forget_session ();
close ();
}
private void on_message (Variant v) {
message (v);
}
private T create<T> () {
return Object.new (typeof (T), parent: this);
}
@@ -2062,7 +2151,7 @@ namespace Frida {
}
}
public class Session : Object, AgentMessageSink {
public sealed class Session : Object, AgentMessageSink {
public signal void detached (SessionDetachReason reason, Crash? crash);
public uint pid {
@@ -3030,7 +3119,7 @@ namespace Frida {
}
}
public class Script : Object {
public sealed class Script : Object {
public signal void destroyed ();
public signal void message (string json, Bytes? data);
@@ -3267,7 +3356,7 @@ namespace Frida {
}
}
public class PortalMembership : Object {
public sealed class PortalMembership : Object {
private uint id;
private Session session;
+2 -2
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class LinuxFruitFinder : Object, FruitFinder {
public sealed class LinuxFruitFinder : Object, FruitFinder {
public string? udid_from_iface (string ifname) throws Error {
var net = "/sys/class/net";
@@ -34,7 +34,7 @@ namespace Frida.Fruity {
}
}
public class LinuxPairingBrowser : Object, PairingBrowser {
public sealed class LinuxPairingBrowser : Object, PairingBrowser {
private Resolved.Manager? resolved;
private Source? timer;
+3 -3
View File
@@ -411,7 +411,7 @@ namespace Frida.Fruity {
return new PcbList (pcbs);
}
public class PcbList {
public sealed class PcbList {
private uint8[] pcbs;
internal PcbList (owned uint8[] pcbs) {
@@ -422,7 +422,7 @@ namespace Frida.Fruity {
return new Iterator (this);
}
public class Iterator {
public sealed class Iterator {
private PcbList list;
private InetItem * cursor;
@@ -461,7 +461,7 @@ namespace Frida.Fruity {
}
}
public class Item {
public sealed class Item {
public SocketFamily family {
get {
return ((pcb.version_flag & Darwin.XNU.InetVersionFlags.IPV6) != 0)
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class WindowsPairingBrowser : Object, PairingBrowser {
public sealed class WindowsPairingBrowser : Object, PairingBrowser {
private Gee.Map<string, Monitor> monitors = new Gee.HashMap<string, Monitor> ();
private MainContext main_context = MainContext.ref_thread_default ();
+2 -2
View File
@@ -1997,7 +1997,7 @@ namespace Frida.Fruity {
public abstract string? udid_from_iface (string ifname) throws Error;
}
public class NullFruitFinder : Object, FruitFinder {
public sealed class NullFruitFinder : Object, FruitFinder {
public string? udid_from_iface (string ifname) throws Error {
return null;
}
@@ -2022,7 +2022,7 @@ namespace Frida.Fruity {
public abstract async void stop (Cancellable? cancellable) throws IOError;
}
public class NullPairingBrowser : Object, PairingBrowser {
public sealed class NullPairingBrowser : Object, PairingBrowser {
public async void start (Cancellable? cancellable) throws IOError {
}
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class DnsPacketReader {
public sealed class DnsPacketReader {
private BufferReader reader;
public DnsPacketReader (Bytes packet) {
+10 -10
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class DeviceInfoService : Object, AsyncInitable {
public sealed class DeviceInfoService : Object, AsyncInitable {
public HostChannelProvider channel_provider {
get;
construct;
@@ -75,7 +75,7 @@ namespace Frida.Fruity {
return name;
}
public class ProcessInfo : Object {
public sealed class ProcessInfo : Object {
public uint pid {
get;
set;
@@ -108,7 +108,7 @@ namespace Frida.Fruity {
}
}
public class ApplicationListingService : Object, AsyncInitable {
public sealed class ApplicationListingService : Object, AsyncInitable {
public HostChannelProvider channel_provider {
get;
construct;
@@ -211,7 +211,7 @@ namespace Frida.Fruity {
return result;
}
public class ApplicationInfo : Object {
public sealed class ApplicationInfo : Object {
public ApplicationType app_type {
get;
set;
@@ -306,7 +306,7 @@ namespace Frida.Fruity {
}
}
public class ProcessControlService : Object, AsyncInitable {
public sealed class ProcessControlService : Object, AsyncInitable {
public HostChannelProvider channel_provider {
get;
construct;
@@ -346,7 +346,7 @@ namespace Frida.Fruity {
}
}
public class DTXConnection : Object, DTXTransport {
public sealed class DTXConnection : Object, DTXTransport {
public IOStream stream {
get;
construct;
@@ -847,7 +847,7 @@ namespace Frida.Fruity {
}
}
private class DTXControlChannel : DTXChannel {
private sealed class DTXControlChannel : DTXChannel {
public DTXControlChannel (DTXTransport transport) {
Object (code: 0, transport: transport);
}
@@ -1161,7 +1161,7 @@ namespace Frida.Fruity {
}
}
public class DTXArgumentListBuilder {
public sealed class DTXArgumentListBuilder {
private PrimitiveBuilder blob = new PrimitiveBuilder ();
public DTXArgumentListBuilder () {
@@ -1227,7 +1227,7 @@ namespace Frida.Fruity {
private const size_t PRIMITIVE_DICTIONARY_HEADER_SIZE = 16;
private class PrimitiveReader {
private sealed class PrimitiveReader {
public size_t available_bytes {
get {
return end - cursor;
@@ -1317,7 +1317,7 @@ namespace Frida.Fruity {
}
}
private class PrimitiveBuilder {
private sealed class PrimitiveBuilder {
public size_t offset {
get {
return cursor;
+168 -72
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class FruityHostSessionBackend : Object, HostSessionBackend {
public sealed class FruityHostSessionBackend : Object, HostSessionBackend {
private Fruity.DeviceMonitor device_monitor = new Fruity.DeviceMonitor ();
private Gee.Map<Fruity.Device, FruityHostSessionProvider> providers =
new Gee.HashMap<Fruity.Device, FruityHostSessionProvider> ();
@@ -42,7 +42,7 @@ namespace Frida {
}
}
public class FruityHostSessionProvider : Object, HostSessionProvider, HostChannelProvider, HostServiceProvider, Pairable {
public sealed class FruityHostSessionProvider : Object, HostSessionProvider, HostChannelProvider, Pairable {
public Fruity.Device device {
get;
construct;
@@ -108,6 +108,43 @@ namespace Frida {
return yield this.host_session.link_agent_session (id, sink, cancellable);
}
public void unlink_agent_session (HostSession host_session, AgentSessionId id) {
if (host_session != this.host_session)
return;
this.host_session.unlink_agent_session (id);
}
public async IOStream link_channel (HostSession host_session, ChannelId id, Cancellable? cancellable)
throws Error, IOError {
if (host_session != this.host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
return this.host_session.link_channel (id);
}
public void unlink_channel (HostSession host_session, ChannelId id) {
if (host_session != this.host_session)
return;
this.host_session.unlink_channel (id);
}
public async ServiceSession link_service_session (HostSession host_session, ServiceSessionId id, Cancellable? cancellable)
throws Error, IOError {
if (host_session != this.host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
return this.host_session.link_service_session (id);
}
public void unlink_service_session (HostSession host_session, ServiceSessionId id) {
if (host_session != this.host_session)
return;
this.host_session.unlink_service_session (id);
}
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
agent_session_detached (id, reason, crash);
}
@@ -116,37 +153,6 @@ namespace Frida {
return yield device.open_channel (address, cancellable);
}
public async Service open_service (string address, Cancellable? cancellable) throws Error, IOError {
string[] tokens = address.split (":", 2);
unowned string protocol = tokens[0];
unowned string service_name = tokens[1];
if (protocol == "plist") {
var stream = yield device.open_lockdown_service (service_name, cancellable);
return new PlistService (stream);
}
if (protocol == "dtx") {
var connection = yield Fruity.DTXConnection.obtain (device, cancellable);
return new DTXService (service_name, connection);
}
if (protocol == "xpc") {
var tunnel = yield device.find_tunnel (cancellable);
if (tunnel == null)
throw new Error.NOT_SUPPORTED ("RemoteXPC not supported by device");
var service_info = tunnel.discovery.get_service (service_name);
var stream = yield tunnel.open_tcp_connection (service_info.port, cancellable);
return new XpcService (new Fruity.XpcConnection (stream));
}
throw new Error.NOT_SUPPORTED ("Unsupported service address");
}
private async void unpair (Cancellable? cancellable) throws Error, IOError {
try {
var client = yield device.get_lockdown_client (cancellable);
@@ -159,7 +165,7 @@ namespace Frida {
}
}
public class FruityHostSession : Object, HostSession {
public sealed class FruityHostSession : Object, HostSession {
public Fruity.Device device {
get;
construct;
@@ -179,6 +185,10 @@ namespace Frida {
private Gee.HashMap<AgentSessionId?, AgentSessionEntry> agent_sessions =
new Gee.HashMap<AgentSessionId?, AgentSessionEntry> (AgentSessionId.hash, AgentSessionId.equal);
private ChannelRegistry channel_registry = new ChannelRegistry ();
private ServiceSessionRegistry service_session_registry = new ServiceSessionRegistry ();
private Cancellable io_cancellable = new Cancellable ();
private const double MIN_SERVER_CHECK_INTERVAL = 5.0;
@@ -196,6 +206,11 @@ namespace Frida {
Object (device: device);
}
construct {
channel_registry.channel_closed.connect (on_channel_closed);
service_session_registry.session_closed.connect (on_service_session_closed);
}
public async void close (Cancellable? cancellable) throws IOError {
if (remote_server_request != null) {
try {
@@ -999,6 +1014,15 @@ namespace Frida {
return session;
}
public void unlink_agent_session (AgentSessionId id) {
AgentSessionEntry? entry = agent_sessions[id];
if (entry == null || entry.sink_registration_id == 0)
return;
entry.connection.unregister_object (entry.sink_registration_id);
entry.sink_registration_id = 0;
}
public async InjectorPayloadId inject_library_file (uint pid, string path, string entrypoint, string data,
Cancellable? cancellable) throws Error, IOError {
var server = yield get_remote_server (cancellable);
@@ -1019,6 +1043,79 @@ namespace Frida {
}
}
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
var stream = yield device.open_channel (address, cancellable);
var id = ChannelId.generate ();
channel_registry.register (id, stream);
return id;
}
public IOStream link_channel (ChannelId id) throws Error {
return channel_registry.link (id);
}
public void unlink_channel (ChannelId id) {
channel_registry.unlink (id);
}
private void on_channel_closed (ChannelId id) {
channel_closed (id);
}
private void on_service_session_closed (ServiceSessionId id) {
service_session_closed (id);
}
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
var session = yield do_open_service (address, cancellable);
var id = ServiceSessionId.generate ();
service_session_registry.register (id, session);
return id;
}
private async ServiceSession do_open_service (string address, Cancellable? cancellable) throws Error, IOError {
string[] tokens = address.split (":", 2);
unowned string protocol = tokens[0];
unowned string service_name = tokens[1];
if (protocol == "plist") {
var stream = yield device.open_lockdown_service (service_name, cancellable);
return new PlistServiceSession (stream);
}
if (protocol == "dtx") {
var connection = yield Fruity.DTXConnection.obtain (device, cancellable);
return new DTXServiceSession (service_name, connection);
}
if (protocol == "xpc") {
var tunnel = yield device.find_tunnel (cancellable);
if (tunnel == null)
throw new Error.NOT_SUPPORTED ("RemoteXPC not supported by device");
var service_info = tunnel.discovery.get_service (service_name);
var stream = yield tunnel.open_tcp_connection (service_info.port, cancellable);
return new XpcServiceSession (new Fruity.XpcConnection (stream));
}
throw new Error.NOT_SUPPORTED ("Unsupported service address");
}
public ServiceSession link_service_session (ServiceSessionId id) throws Error {
return service_session_registry.link (id);
}
public void unlink_service_session (ServiceSessionId id) {
service_session_registry.unlink (id);
}
private void add_lldb_session (LLDBSession session) {
lldb_sessions[session.process.pid] = session;
@@ -1554,22 +1651,16 @@ namespace Frida {
}
}
private sealed class PlistService : Object, Service {
private sealed class PlistServiceSession : Object, ServiceSession {
public IOStream stream {
get;
construct;
}
private State state = INACTIVE;
private Fruity.PlistServiceClient client;
private bool client_closed = false;
private enum State {
INACTIVE,
ACTIVE,
}
public PlistService (IOStream stream) {
public PlistServiceSession (IOStream stream) {
Object (stream: stream);
}
@@ -1578,8 +1669,8 @@ namespace Frida {
client.closed.connect (on_client_closed);
}
public bool is_closed () {
return client_closed;
~PlistServiceSession () {
client.closed.disconnect (on_client_closed);
}
public async void activate (Cancellable? cancellable) throws Error, IOError {
@@ -1587,14 +1678,8 @@ namespace Frida {
}
private void ensure_active () throws Error {
if (state == INACTIVE) {
state = ACTIVE;
if (client_closed) {
close ();
throw new Error.INVALID_OPERATION ("Service is closed");
}
}
if (client_closed)
throw new Error.INVALID_OPERATION ("Service is closed");
}
public async void cancel (Cancellable? cancellable) throws IOError {
@@ -1603,6 +1688,8 @@ namespace Frida {
client_closed = true;
yield client.close (cancellable);
close ();
}
public async Variant request (Variant parameters, Cancellable? cancellable = null) throws Error, IOError {
@@ -1757,7 +1844,7 @@ namespace Frida {
}
}
private sealed class DTXService : Object, Service {
private sealed class DTXServiceSession : Object, ServiceSession {
public string identifier {
get;
construct;
@@ -1777,7 +1864,7 @@ namespace Frida {
ACTIVE,
}
public DTXService (string identifier, Fruity.DTXConnection connection) {
public DTXServiceSession (string identifier, Fruity.DTXConnection connection) {
Object (identifier: identifier, connection: connection);
}
@@ -1785,8 +1872,8 @@ namespace Frida {
connection.notify["state"].connect (on_connection_state_changed);
}
public bool is_closed () {
return connection_closed;
~DTXServiceSession () {
connection.notify["state"].disconnect (on_connection_state_changed);
}
public async void activate (Cancellable? cancellable) throws Error, IOError {
@@ -1794,14 +1881,12 @@ namespace Frida {
}
private void ensure_active () throws Error {
if (connection_closed)
throw new Error.INVALID_OPERATION ("Service is closed");
if (state == INACTIVE) {
state = ACTIVE;
if (connection_closed) {
close ();
throw new Error.INVALID_OPERATION ("Service is closed");
}
channel = connection.make_channel (identifier);
channel.invocation.connect (on_channel_invocation);
channel.notification.connect (on_channel_notification);
@@ -1812,7 +1897,13 @@ namespace Frida {
if (connection_closed)
return;
connection_closed = true;
channel = null;
if (channel != null) {
channel.invocation.disconnect (on_channel_invocation);
channel.notification.disconnect (on_channel_notification);
channel = null;
}
close ();
}
@@ -2026,7 +2117,7 @@ namespace Frida {
}
}
private sealed class XpcService : Object, Service {
private sealed class XpcServiceSession : Object, ServiceSession {
public Fruity.XpcConnection connection {
get;
construct;
@@ -2040,7 +2131,7 @@ namespace Frida {
ACTIVE,
}
public XpcService (Fruity.XpcConnection connection) {
public XpcServiceSession (Fruity.XpcConnection connection) {
Object (connection: connection);
}
@@ -2049,8 +2140,11 @@ namespace Frida {
connection.message.connect (on_message);
}
public bool is_closed () {
return connection_closed;
~XpcServiceSession () {
connection.close.disconnect (on_close);
connection.message.disconnect (on_message);
connection.cancel ();
}
public async void activate (Cancellable? cancellable) throws Error, IOError {
@@ -2058,20 +2152,21 @@ namespace Frida {
}
private void ensure_active () throws Error {
if (connection_closed)
throw new Error.INVALID_OPERATION ("Service is closed");
if (state == INACTIVE) {
state = ACTIVE;
if (connection_closed) {
close ();
throw new Error.INVALID_OPERATION ("Service is closed");
}
connection.activate ();
}
}
public async void cancel (Cancellable? cancellable) throws IOError {
connection.cancel ();
if (state == ACTIVE)
connection.cancel ();
else if (!connection_closed)
on_close (null);
}
public async Variant request (Variant parameters, Cancellable? cancellable = null) throws Error, IOError {
@@ -2095,6 +2190,7 @@ namespace Frida {
private void on_close (Error? error) {
connection_closed = true;
close ();
}
+2 -2
View File
@@ -6,7 +6,7 @@ namespace Frida.Fruity.Injector {
return yield session.run (cancellable);
}
public class GadgetDetails : Object {
public sealed class GadgetDetails : Object {
public uint16 port {
get;
construct;
@@ -21,7 +21,7 @@ namespace Frida.Fruity.Injector {
UNSUPPORTED
}
private class Session : Object {
private sealed class Session : Object {
public Gum.DarwinModule module {
get;
construct;
+2 -2
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class InstallationProxyClient : Object, AsyncInitable {
public sealed class InstallationProxyClient : Object, AsyncInitable {
public Device device {
get;
construct;
@@ -193,7 +193,7 @@ namespace Frida.Fruity {
}
}
public class ApplicationDetails : Object {
public sealed class ApplicationDetails : Object {
public string identifier {
get;
construct;
+11 -11
View File
@@ -22,7 +22,7 @@ namespace Frida.Fruity {
}
}
public class NSNumber : NSObject {
public sealed class NSNumber : NSObject {
public Kind kind {
get;
private set;
@@ -108,7 +108,7 @@ namespace Frida.Fruity {
}
}
public class NSString : NSObject {
public sealed class NSString : NSObject {
public string str {
get;
private set;
@@ -134,7 +134,7 @@ namespace Frida.Fruity {
}
}
public class NSData : NSObject {
public sealed class NSData : NSObject {
public Bytes bytes {
get;
private set;
@@ -160,7 +160,7 @@ namespace Frida.Fruity {
}
}
public class NSDictionary : NSObject {
public sealed class NSDictionary : NSObject {
public int size {
get {
return storage.size;
@@ -221,7 +221,7 @@ namespace Frida.Fruity {
}
}
public class NSDictionaryRaw : NSObject {
public sealed class NSDictionaryRaw : NSObject {
public int size {
get {
return storage.size;
@@ -255,7 +255,7 @@ namespace Frida.Fruity {
}
}
public class NSArray : NSObject {
public sealed class NSArray : NSObject {
public int length {
get {
return storage.size;
@@ -279,7 +279,7 @@ namespace Frida.Fruity {
}
}
public class NSDate : NSObject {
public sealed class NSDate : NSObject {
public double time {
get;
private set;
@@ -298,7 +298,7 @@ namespace Frida.Fruity {
}
}
public class NSError : NSObject {
public sealed class NSError : NSObject {
public NSString domain {
get;
private set;
@@ -321,7 +321,7 @@ namespace Frida.Fruity {
}
}
public class DTTapMessage : NSObject {
public sealed class DTTapMessage : NSObject {
public NSDictionary plist {
get;
private set;
@@ -658,7 +658,7 @@ namespace Frida.Fruity {
return new DTTapMessage ((NSDictionary) decode_value (instance.get_uid ("DTTapMessagePlist"), ctx));
}
private class EncodingContext {
private sealed class EncodingContext {
public PlistArray objects;
private Gee.HashMap<string, PlistUid> classes = new Gee.HashMap<string, PlistUid> ();
@@ -709,7 +709,7 @@ namespace Frida.Fruity {
}
}
private class DecodingContext {
private sealed class DecodingContext {
public PlistArray objects;
public DecodingContext (PlistArray objects) {
+10 -10
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaLLDB", gir_version = "1.0")]
namespace Frida.LLDB {
public class Client : GDB.Client {
public sealed class Client : GDB.Client {
public Process? process {
get {
return _process;
@@ -438,7 +438,7 @@ namespace Frida.LLDB {
}
}
public class LaunchOptions : Object {
public sealed class LaunchOptions : Object {
public string[] env {
get;
set;
@@ -457,7 +457,7 @@ namespace Frida.LLDB {
}
}
public class Process : Object {
public sealed class Process : Object {
public uint pid {
get;
set;
@@ -556,7 +556,7 @@ namespace Frida.LLDB {
ARM64E = 2,
}
public class Thread : GDB.Thread {
public sealed class Thread : GDB.Thread {
private const uint PAGE_SIZE = 16384U;
private const uint32 THREAD_MAGIC = 0x54485244U;
@@ -656,7 +656,7 @@ namespace Frida.LLDB {
return address & ~((uint64) (PAGE_SIZE - 1));
}
public class Snapshot {
public sealed class Snapshot {
public uint handle {
get;
private set;
@@ -667,7 +667,7 @@ namespace Frida.LLDB {
}
}
public class Frame {
public sealed class Frame {
public uint64 address {
get;
private set;
@@ -695,7 +695,7 @@ namespace Frida.LLDB {
}
}
public class Module : Object {
public sealed class Module : Object {
public uint64 load_address {
get;
construct;
@@ -719,7 +719,7 @@ namespace Frida.LLDB {
);
}
public class Segment {
public sealed class Segment {
public string name;
public uint64 vmaddr;
@@ -730,7 +730,7 @@ namespace Frida.LLDB {
}
}
public class Exception : GDB.Exception {
public sealed class Exception : GDB.Exception {
public MachExceptionType metype {
get;
construct;
@@ -896,7 +896,7 @@ namespace Frida.LLDB {
}
}
public class AppleDyldFields : Object {
public sealed class AppleDyldFields : Object {
public uint64 all_image_info {
get;
construct;
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class LockdownClient : Object {
public sealed class LockdownClient : Object {
public signal void closed ();
public PlistServiceClient service {
+1 -1
View File
@@ -411,7 +411,7 @@ namespace Frida.Fruity {
}
}
internal class UsbNcmConfig {
internal sealed class UsbNcmConfig {
public uint8 ctrl_iface;
public uint8 data_iface;
public int data_altsetting;
+70 -332
View File
@@ -196,7 +196,7 @@ namespace Frida.Fruity {
STOPPED
}
public class VirtualNetworkStack (Bytes? ethernet_address, InetAddress? ipv6_address, uint16 mtu) {
public VirtualNetworkStack (Bytes? ethernet_address, InetAddress? ipv6_address, uint16 mtu) {
Object (
ethernet_address: ethernet_address,
ipv6_address: ipv6_address,
@@ -394,7 +394,7 @@ namespace Frida.Fruity {
source.attach (main_context);
}
private class TcpConnection : IOStream, AsyncInitable {
private class TcpConnection : VirtualStream, AsyncInitable {
public VirtualNetworkStack netstack {
get;
construct;
@@ -405,53 +405,13 @@ namespace Frida.Fruity {
construct;
}
public State state {
get {
return _state;
}
}
public override InputStream input_stream {
get {
return _input_stream;
}
}
public override OutputStream output_stream {
get {
return _output_stream;
}
}
public IOCondition pending_io {
get {
lock (state)
return events;
}
}
private Promise<bool> established = new Promise<bool> ();
private State _state = OPENING;
private TcpInputStream _input_stream;
private TcpOutputStream _output_stream;
private unowned LWIP.TcpPcb? pcb;
private IOCondition events = 0;
private ByteArray rx_buf = new ByteArray.sized (64 * 1024);
private ByteArray tx_buf = new ByteArray.sized (64 * 1024);
private size_t tx_space_available = 0;
private Gee.Map<unowned Source, IOCondition> sources = new Gee.HashMap<unowned Source, IOCondition> ();
private MainContext main_context;
public enum State {
OPENING,
OPENED,
CLOSED
}
public static async TcpConnection open (VirtualNetworkStack netstack, InetSocketAddress address,
Cancellable? cancellable) throws Error, IOError {
var connection = new TcpConnection (netstack, address);
@@ -469,22 +429,28 @@ namespace Frida.Fruity {
Object (netstack: netstack, address: address);
}
construct {
_input_stream = new TcpInputStream (this);
_output_stream = new TcpOutputStream (this);
main_context = MainContext.ref_thread_default ();
}
public override void dispose () {
_output_stream.detach ();
_input_stream.detach ();
stop ();
base.dispose ();
}
protected override VirtualStream.State query_initial_state () {
return OPENING;
}
protected override IOCondition query_events () {
IOCondition new_events = 0;
if (rx_buf.len != 0 || state == CLOSED)
new_events |= IN;
if (tx_space_available != 0)
new_events |= OUT;
return new_events;
}
private async bool init_async (int io_priority, Cancellable? cancellable) throws Error, IOError {
LWIP.Runtime.schedule (do_start);
@@ -547,8 +513,8 @@ namespace Frida.Fruity {
return OK;
});
_state = CLOSED;
update_events ();
state = CLOSED;
update_pending_io ();
}
private void detach_from_pcb () {
@@ -557,12 +523,13 @@ namespace Frida.Fruity {
}
private void on_connect () {
lock (state)
with_state_lock (() => {
tx_space_available = pcb.query_available_send_buffer_space ();
update_events ();
});
update_pending_io ();
schedule_on_frida_thread (() => {
_state = OPENED;
state = OPEN;
if (!established.future.ready)
established.resolve (true);
@@ -575,8 +542,8 @@ namespace Frida.Fruity {
if (pbuf == null) {
detach_from_pcb ();
schedule_on_frida_thread (() => {
_state = CLOSED;
update_events ();
state = CLOSED;
update_pending_io ();
return Source.REMOVE;
});
return;
@@ -584,15 +551,17 @@ namespace Frida.Fruity {
var buffer = new uint8[pbuf.tot_len];
unowned uint8[] chunk = pbuf.get_contiguous (buffer, pbuf.tot_len);
lock (state)
with_state_lock (() => {
rx_buf.append (chunk[:pbuf.tot_len]);
update_events ();
});
update_pending_io ();
}
private void on_sent (uint16 len) {
lock (state)
with_state_lock (() => {
tx_space_available = pcb.query_available_send_buffer_space () - tx_buf.len;
update_events ();
});
update_pending_io ();
}
private void on_error (LWIP.ErrorCode err) {
@@ -602,8 +571,8 @@ namespace Frida.Fruity {
else
detach_from_pcb ();
schedule_on_frida_thread (() => {
_state = CLOSED;
update_events ();
state = CLOSED;
update_pending_io ();
if (!established.future.ready)
established.reject (parse_error (err));
@@ -612,17 +581,11 @@ namespace Frida.Fruity {
});
}
public override bool close (GLib.Cancellable? cancellable) throws IOError {
protected override void handle_close () {
stop ();
return true;
}
public override async bool close_async (int io_priority, GLib.Cancellable? cancellable) throws IOError {
stop ();
return true;
}
public void shutdown_rx () throws IOError {
public override void shutdown_read () throws IOError {
check_io (netstack.perform_on_lwip_thread (() => {
if (pcb == null)
return OK;
@@ -630,7 +593,7 @@ namespace Frida.Fruity {
}));
}
public void shutdown_tx () throws IOError {
public override void shutdown_write () throws IOError {
check_io (netstack.perform_on_lwip_thread (() => {
if (pcb == null)
return OK;
@@ -638,17 +601,19 @@ namespace Frida.Fruity {
}));
}
public ssize_t recv (uint8[] buffer) throws IOError {
public override ssize_t read (uint8[] buffer) throws IOError {
ssize_t n = 0;
netstack.perform_on_lwip_thread (() => {
lock (state) {
with_state_lock (() => {
n = ssize_t.min (buffer.length, rx_buf.len);
if (n == 0)
return OK;
return;
Memory.copy (buffer, rx_buf.data, n);
rx_buf.remove_range (0, (uint) n);
}
});
if (n == 0)
return OK;
if (pcb == null)
return OK;
@@ -664,41 +629,43 @@ namespace Frida.Fruity {
});
if (n == 0) {
if (_state == CLOSED)
if (state == CLOSED)
return 0;
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
}
update_events ();
update_pending_io ();
return n;
}
public ssize_t send (uint8[] buffer) throws IOError {
public override ssize_t write (uint8[] buffer) throws IOError {
ssize_t n = 0;
netstack.perform_on_lwip_thread (() => {
if (pcb == null)
return OK;
lock (state) {
with_state_lock (() => {
n = ssize_t.min (buffer.length, (ssize_t) tx_space_available);
if (n == 0)
return OK;
return;
tx_buf.append (buffer[:n]);
tx_space_available -= n;
}
});
if (n == 0)
return OK;
size_t available_space = pcb.query_available_send_buffer_space ();
uint8[]? data = null;
lock (state) {
with_state_lock (() => {
size_t num_bytes_to_write = size_t.min (tx_buf.len, available_space);
if (num_bytes_to_write != 0) {
data = tx_buf.data[:num_bytes_to_write];
tx_buf.remove_range (0, (uint) num_bytes_to_write);
}
}
});
if (data == null)
return OK;
@@ -706,8 +673,9 @@ namespace Frida.Fruity {
pcb.output ();
available_space = pcb.query_available_send_buffer_space ();
lock (state)
with_state_lock (() => {
tx_space_available = available_space - tx_buf.len;
});
return OK;
});
@@ -715,44 +683,11 @@ namespace Frida.Fruity {
if (n == 0)
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
update_events ();
update_pending_io ();
return n;
}
public void register_source (Source source, IOCondition condition) {
lock (state)
sources[source] = condition | IOCondition.ERR | IOCondition.HUP;
}
public void unregister_source (Source source) {
lock (state)
sources.unset (source);
}
private void update_events () {
lock (state) {
IOCondition new_events = 0;
if (rx_buf.len != 0 || _state == CLOSED)
new_events |= IN;
if (tx_space_available != 0)
new_events |= OUT;
events = new_events;
foreach (var entry in sources.entries) {
unowned Source source = entry.key;
IOCondition c = entry.value;
if ((new_events & c) != 0)
source.set_ready_time (0);
}
}
notify_property ("pending-io");
}
private void schedule_on_frida_thread (owned SourceFunc function) {
var source = new IdleSource ();
source.set_callback ((owned) function);
@@ -760,201 +695,6 @@ namespace Frida.Fruity {
}
}
private class TcpInputStream : InputStream, PollableInputStream {
private weak TcpConnection connection;
public TcpInputStream (TcpConnection connection) {
Object ();
this.connection = connection;
}
internal void detach () {
connection = null;
}
public override bool close (Cancellable? cancellable) throws IOError {
if (connection != null)
connection.shutdown_rx ();
return true;
}
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
return close (cancellable);
}
public override ssize_t read (uint8[] buffer, Cancellable? cancellable) throws IOError {
if (connection == null)
return 0;
if (!is_readable ()) {
bool done = false;
var mutex = Mutex ();
var cond = Cond ();
ulong io_handler = connection.notify["pending-io"].connect ((obj, pspec) => {
if (is_readable ()) {
mutex.lock ();
done = true;
cond.signal ();
mutex.unlock ();
}
});
ulong cancellation_handler = 0;
if (cancellable != null) {
cancellation_handler = cancellable.connect (() => {
mutex.lock ();
done = true;
cond.signal ();
mutex.unlock ();
});
}
if (!is_readable ()) {
mutex.lock ();
while (!done)
cond.wait (mutex);
mutex.unlock ();
}
if (cancellation_handler != 0)
cancellable.disconnect (cancellation_handler);
connection.disconnect (io_handler);
cancellable.set_error_if_cancelled ();
}
return connection.recv (buffer);
}
public bool can_poll () {
return true;
}
public bool is_readable () {
if (connection == null)
return true;
return (connection.pending_io & IOCondition.IN) != 0;
}
public PollableSource create_source (Cancellable? cancellable) {
return new PollableSource.full (this, new TcpIOSource (connection, IOCondition.IN), cancellable);
}
public ssize_t read_nonblocking_fn (uint8[] buffer) throws GLib.Error {
if (connection == null)
return 0;
return connection.recv (buffer);
}
}
private class TcpOutputStream : OutputStream, PollableOutputStream {
private weak TcpConnection? connection;
public TcpOutputStream (TcpConnection connection) {
Object ();
this.connection = connection;
}
internal void detach () {
connection = null;
}
public override bool close (Cancellable? cancellable) throws IOError {
if (connection != null)
connection.shutdown_tx ();
return true;
}
public override async bool close_async (int io_priority, Cancellable? cancellable) throws GLib.IOError {
return close (cancellable);
}
public override bool flush (GLib.Cancellable? cancellable) throws GLib.Error {
return true;
}
public override async bool flush_async (int io_priority, GLib.Cancellable? cancellable) throws GLib.Error {
return true;
}
public override ssize_t write (uint8[] buffer, Cancellable? cancellable) throws IOError {
assert_not_reached ();
}
public bool can_poll () {
return true;
}
public bool is_writable () {
if (connection == null)
return false;
return (connection.pending_io & IOCondition.OUT) != 0;
}
public PollableSource create_source (Cancellable? cancellable) {
return new PollableSource.full (this, new TcpIOSource (connection, IOCondition.OUT), cancellable);
}
public ssize_t write_nonblocking_fn (uint8[]? buffer) throws GLib.Error {
if (connection == null)
throw new IOError.CLOSED ("Connection is closed");
return connection.send (buffer);
}
public PollableReturn writev_nonblocking_fn (OutputVector[] vectors, out size_t bytes_written) throws GLib.Error {
assert_not_reached ();
}
}
private class TcpIOSource : Source {
public TcpConnection connection;
public IOCondition condition;
public TcpIOSource (TcpConnection? connection, IOCondition condition) {
this.connection = connection;
this.condition = condition;
if (connection != null)
connection.register_source (this, condition);
}
~TcpIOSource () {
if (connection != null)
connection.unregister_source (this);
}
protected override bool prepare (out int timeout) {
timeout = -1;
return is_ready ();
}
protected override bool check () {
return is_ready ();
}
private bool is_ready () {
IOCondition pending_io = (connection != null) ? connection.pending_io : IOCondition.IN;
return (pending_io & condition) != 0;
}
protected override bool dispatch (SourceFunc? callback) {
set_ready_time (-1);
if (callback == null)
return Source.REMOVE;
return callback ();
}
protected static bool closure_callback (Closure closure) {
var return_value = Value (typeof (bool));
closure.invoke (ref return_value, {});
return return_value.get_boolean ();
}
}
private class Ipv6UdpSocket : Object, UdpSocket, DatagramBased {
public VirtualNetworkStack netstack {
get;
@@ -969,13 +709,13 @@ namespace Frida.Fruity {
public IOCondition pending_io {
get {
lock (events)
return events;
lock (_pending_io)
return _pending_io;
}
}
private unowned LWIP.UdpPcb? pcb;
private IOCondition events = OUT;
private IOCondition _pending_io = OUT;
private Gee.Queue<Packet> rx_queue = new Gee.ArrayQueue<Packet> ();
private Gee.Map<unowned Source, IOCondition> sources = new Gee.HashMap<unowned Source, IOCondition> ();
@@ -1011,9 +751,9 @@ namespace Frida.Fruity {
var sender = ip6_address_to_inet_socket_address (addr, port);
var packet = new Packet (bytes, sender);
lock (events)
lock (pending_io)
rx_queue.offer (packet);
update_events ();
update_pending_io ();
}
public void bind (InetSocketAddress address) throws Error {
@@ -1047,14 +787,14 @@ namespace Frida.Fruity {
int received;
for (received = 0; received != messages.length; received++) {
Packet? packet;
lock (events)
lock (pending_io)
packet = rx_queue.poll ();
if (packet == null) {
if (received == 0)
throw new IOError.WOULD_BLOCK ("Resource temporarily unavailable");
break;
}
update_events ();
update_pending_io ();
if (messages[received].address != null)
*messages[received].address = packet.address.ref ();
@@ -1133,28 +873,26 @@ namespace Frida.Fruity {
}
public void register_source (Source source, IOCondition condition) {
lock (events)
lock (pending_io)
sources[source] = condition | IOCondition.ERR | IOCondition.HUP;
}
public void unregister_source (Source source) {
lock (events)
lock (pending_io)
sources.unset (source);
}
private void update_events () {
lock (events) {
IOCondition new_events = OUT;
private void update_pending_io () {
lock (pending_io) {
_pending_io = OUT;
if (!rx_queue.is_empty)
new_events |= IN;
events = new_events;
_pending_io |= IN;
foreach (var entry in sources.entries) {
unowned Source source = entry.key;
IOCondition c = entry.value;
if ((new_events & c) != 0)
if ((_pending_io & c) != 0)
source.set_ready_time (0);
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class OpackBuilder {
public sealed class OpackBuilder {
protected BufferBuilder builder = new BufferBuilder (LITTLE_ENDIAN);
private Gee.Deque<Scope> scopes = new Gee.ArrayQueue<Scope> ();
@@ -132,7 +132,7 @@ namespace Frida.Fruity {
}
}
public class OpackParser {
public sealed class OpackParser {
private BufferReader reader;
[Flags]
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class PlistServiceClient : Object {
public sealed class PlistServiceClient : Object {
public signal void closed ();
public IOStream stream {
+5 -5
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class Plist : PlistDict {
public sealed class Plist : PlistDict {
public enum Format {
AUTO,
BINARY,
@@ -1355,7 +1355,7 @@ namespace Frida.Fruity {
}
}
public class PlistArray : Object {
public sealed class PlistArray : Object {
public bool is_empty {
get {
return storage.is_empty;
@@ -1511,10 +1511,10 @@ namespace Frida.Fruity {
}
}
public class PlistNull : Object {
public sealed class PlistNull : Object {
}
public class PlistDate : Object {
public sealed class PlistDate : Object {
private DateTime time;
public PlistDate (DateTime time) {
@@ -1526,7 +1526,7 @@ namespace Frida.Fruity {
}
}
public class PlistUid : Object {
public sealed class PlistUid : Object {
public uint64 uid {
get;
construct;
+1 -1
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class SpringboardServicesClient : Object, AsyncInitable {
public sealed class SpringboardServicesClient : Object, AsyncInitable {
public Device device {
get;
construct;
+2 -2
View File
@@ -1,6 +1,6 @@
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
namespace Frida.Fruity {
public class UsbmuxClient : Object, AsyncInitable {
public sealed class UsbmuxClient : Object, AsyncInitable {
public signal void device_attached (UsbmuxDevice device);
public signal void device_detached (UsbmuxDevice device);
@@ -548,7 +548,7 @@ namespace Frida.Fruity {
PROTOCOL
}
public class UsbmuxDevice : Object {
public sealed class UsbmuxDevice : Object {
public ConnectionType connection_type {
get;
construct;
+23 -23
View File
@@ -3,7 +3,7 @@ namespace Frida.Fruity {
using OpenSSL;
using OpenSSL.Envelope;
public class DiscoveryService : Object, AsyncInitable {
public sealed class DiscoveryService : Object, AsyncInitable {
public IOStream stream {
get;
construct;
@@ -119,11 +119,11 @@ namespace Frida.Fruity {
}
}
public class ServiceInfo {
public sealed class ServiceInfo {
public uint16 port;
}
public class PairingService : Object, AsyncInitable {
public sealed class PairingService : Object, AsyncInitable {
public const string DNS_SD_NAME = "_remotepairing._tcp.local";
public PairingTransport transport {
@@ -1248,7 +1248,7 @@ namespace Frida.Fruity {
public abstract void post (Bytes message);
}
public class XpcPairingTransport : Object, PairingTransport {
public sealed class XpcPairingTransport : Object, PairingTransport {
public IOStream stream {
get;
construct;
@@ -1320,7 +1320,7 @@ namespace Frida.Fruity {
}
}
public class PlainPairingTransport : Object, PairingTransport {
public sealed class PlainPairingTransport : Object, PairingTransport {
public IOStream stream {
get;
construct;
@@ -1458,7 +1458,7 @@ namespace Frida.Fruity {
}
}
public class PairingStore {
public sealed class PairingStore {
public PairingIdentity self_identity {
get {
return _self_identity;
@@ -1664,7 +1664,7 @@ namespace Frida.Fruity {
}
}
public class PairingIdentity {
public sealed class PairingIdentity {
public string identifier;
public Key key;
public Bytes irk;
@@ -1681,7 +1681,7 @@ namespace Frida.Fruity {
}
}
public class PairingPeer {
public sealed class PairingPeer {
public string identifier;
public Bytes public_key;
public Bytes irk;
@@ -1692,7 +1692,7 @@ namespace Frida.Fruity {
public Bytes? remote_unlock_host_key;
}
public class PairingServiceMetadata {
public sealed class PairingServiceMetadata {
public string identifier;
public Bytes auth_tag;
@@ -1721,7 +1721,7 @@ namespace Frida.Fruity {
}
}
public class DeviceOptions {
public sealed class DeviceOptions {
public bool allows_pair_setup;
public bool allows_pinless_pairing;
public bool allows_promptless_automation_pairing_upgrade;
@@ -1729,7 +1729,7 @@ namespace Frida.Fruity {
public bool allows_incoming_tunnel_connections;
}
public class DeviceInfo {
public sealed class DeviceInfo {
public string name;
public string model;
public string udid;
@@ -1737,7 +1737,7 @@ namespace Frida.Fruity {
public Plist kvs;
}
private class PairingParamsBuilder {
private sealed class PairingParamsBuilder {
private BufferBuilder builder = new BufferBuilder (LITTLE_ENDIAN);
public unowned PairingParamsBuilder add_method (uint8 method) {
@@ -1810,7 +1810,7 @@ namespace Frida.Fruity {
}
}
private class PairingParamsParser {
private sealed class PairingParamsParser {
private BufferReader reader;
private EnumClass param_type_class;
@@ -1946,7 +1946,7 @@ namespace Frida.Fruity {
}
}
public class TunnelParameters {
public sealed class TunnelParameters {
public InetAddress address;
public uint16 mtu;
public InetAddress server_address;
@@ -2877,7 +2877,7 @@ namespace Frida.Fruity {
}
}
public class AppService : TrustedService {
public sealed class AppService : TrustedService {
public static async AppService open (IOStream stream, Cancellable? cancellable = null) throws Error, IOError {
var service = new AppService (stream);
@@ -3036,7 +3036,7 @@ namespace Frida.Fruity {
return processes;
}
public class ApplicationInfo {
public sealed class ApplicationInfo {
public string bundle_identifier;
public string? bundle_version;
public string name;
@@ -3050,7 +3050,7 @@ namespace Frida.Fruity {
public bool is_app_clip;
}
public class ProcessInfo {
public sealed class ProcessInfo {
public uint pid;
public string path;
}
@@ -3707,11 +3707,11 @@ namespace Frida.Fruity {
}
}
public class PeerInfo {
public sealed class PeerInfo {
public Variant? metadata;
}
public class XpcMessageBuilder : Object {
public sealed class XpcMessageBuilder : Object {
private MessageType message_type;
private MessageFlags message_flags = NONE;
private uint64 message_id = 0;
@@ -3752,7 +3752,7 @@ namespace Frida.Fruity {
}
}
public class XpcMessage {
public sealed class XpcMessage {
public MessageType type;
public MessageFlags flags;
public uint64 id;
@@ -3871,7 +3871,7 @@ namespace Frida.Fruity {
}
}
public class XpcBodyBuilder : XpcObjectBuilder {
public sealed class XpcBodyBuilder : XpcObjectBuilder {
public XpcBodyBuilder () {
base ();
@@ -4066,7 +4066,7 @@ namespace Frida.Fruity {
DICTIONARY = 0xf000,
}
private class XpcBodyParser {
private sealed class XpcBodyParser {
public static Variant parse (uint8[] data) throws Error {
if (data.length < 12)
throw new Error.INVALID_ARGUMENT ("Invalid xpc_object: truncated");
@@ -4086,7 +4086,7 @@ namespace Frida.Fruity {
}
}
private class XpcObjectParser {
private sealed class XpcObjectParser {
private Buffer buf;
private size_t cursor;
private EnumClass object_type_class;
+3 -3
View File
@@ -1087,7 +1087,7 @@ namespace Frida.GDB {
return sum;
}
public class Packet {
public sealed class Packet {
public const size_t OVERHEAD = 1 + 1 + 2;
public string payload {
@@ -1106,7 +1106,7 @@ namespace Frida.GDB {
}
}
public class PacketBuilder {
public sealed class PacketBuilder {
private StringBuilder? buffer;
private size_t initial_capacity;
private ChecksumType checksum_type;
@@ -1727,7 +1727,7 @@ namespace Frida.GDB {
}
}
public class Breakpoint : Object {
public sealed class Breakpoint : Object {
public signal void removed ();
public Kind kind {
+145 -10
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class HostSessionService : Object {
public sealed class HostSessionService : Object {
private Gee.ArrayList<HostSessionBackend> backends = new Gee.ArrayList<HostSessionBackend> ();
public signal void provider_available (HostSessionProvider provider);
@@ -168,7 +168,16 @@ namespace Frida {
public abstract async AgentSession link_agent_session (HostSession host_session, AgentSessionId id, AgentMessageSink sink,
Cancellable? cancellable = null) throws Error, IOError;
public abstract void unlink_agent_session (HostSession host_session, AgentSessionId id);
public signal void agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash);
public abstract async IOStream link_channel (HostSession host_session, ChannelId id, Cancellable? cancellable = null)
throws Error, IOError;
public abstract void unlink_channel (HostSession host_session, ChannelId id);
public abstract async ServiceSession link_service_session (HostSession host_session, ServiceSessionId id,
Cancellable? cancellable = null) throws Error, IOError;
public abstract void unlink_service_session (HostSession host_session, ServiceSessionId id);
}
public enum HostSessionProviderKind {
@@ -177,7 +186,7 @@ namespace Frida {
USB
}
public class HostSessionOptions : Object {
public sealed class HostSessionOptions : Object {
public Gee.Map<string, Value?> map {
get;
set;
@@ -189,10 +198,6 @@ namespace Frida {
public abstract async IOStream open_channel (string address, Cancellable? cancellable = null) throws Error, IOError;
}
public interface HostServiceProvider : Object {
public abstract async Service open_service (string address, Cancellable? cancellable = null) throws Error, IOError;
}
public interface Pairable : Object {
public abstract async void unpair (Cancellable? cancellable = null) throws Error, IOError;
}
@@ -205,7 +210,129 @@ namespace Frida {
public abstract async void stop (Cancellable? cancellable = null) throws IOError;
}
public abstract class BaseDBusHostSession : Object, HostSession, AgentController {
public abstract class LocalHostSessionBackend : Object, HostSessionBackend {
private LocalHostSessionProvider local_provider;
public async void start (Cancellable? cancellable) throws IOError {
assert (local_provider == null);
local_provider = make_provider ();
provider_available (local_provider);
}
public async void stop (Cancellable? cancellable) throws IOError {
assert (local_provider != null);
provider_unavailable (local_provider);
yield local_provider.close (cancellable);
local_provider = null;
}
protected abstract LocalHostSessionProvider make_provider ();
}
public abstract class LocalHostSessionProvider : Object, HostSessionProvider {
public string id {
get { return "local"; }
}
public string name {
get { return "Local System"; }
}
public Variant? icon {
get { return _icon; }
}
private Variant? _icon;
public HostSessionProviderKind kind {
get { return HostSessionProviderKind.LOCAL; }
}
private LocalHostSession host_session;
construct {
_icon = load_icon ();
}
protected abstract LocalHostSession make_host_session (HostSessionOptions? options) throws Error;
protected void take_host_session (LocalHostSession session) {
host_session = session;
host_session.agent_session_detached.connect (on_agent_session_detached);
}
protected virtual Variant? load_icon () {
return null;
}
public async void close (Cancellable? cancellable) throws IOError {
if (host_session == null)
return;
host_session.agent_session_detached.disconnect (on_agent_session_detached);
yield host_session.close (cancellable);
host_session = null;
}
public async HostSession create (HostSessionOptions? options, Cancellable? cancellable) throws Error, IOError {
if (host_session != null)
throw new Error.INVALID_OPERATION ("Already created");
take_host_session (make_host_session (options));
return host_session;
}
public async void destroy (HostSession session, Cancellable? cancellable) throws Error, IOError {
if (session != host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
host_session.agent_session_detached.disconnect (on_agent_session_detached);
yield host_session.close (cancellable);
host_session = null;
}
public async AgentSession link_agent_session (HostSession host_session, AgentSessionId id, AgentMessageSink sink,
Cancellable? cancellable) throws Error, IOError {
if (host_session != this.host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
return yield this.host_session.link_agent_session (id, sink, cancellable);
}
public void unlink_agent_session (HostSession host_session, AgentSessionId id) {
if (host_session != this.host_session)
return;
this.host_session.unlink_agent_session (id);
}
public async IOStream link_channel (HostSession host_session, ChannelId id, Cancellable? cancellable)
throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Channels are not supported by this backend");
}
public void unlink_channel (HostSession host_session, ChannelId id) {
}
public async ServiceSession link_service_session (HostSession host_session, ServiceSessionId id, Cancellable? cancellable)
throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
}
public void unlink_service_session (HostSession host_session, ServiceSessionId id) {
}
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
agent_session_detached (id, reason, crash);
}
}
public abstract class LocalHostSession : Object, HostSession, AgentController {
private Gee.HashMap<uint, Cancellable> pending_establish_ops = new Gee.HashMap<uint, Cancellable> ();
private Gee.HashMap<uint, Future<AgentEntry>> agent_entries = new Gee.HashMap<uint, Future<AgentEntry>> ();
@@ -770,6 +897,14 @@ namespace Frida {
return InjectorPayloadId (raw_id);
}
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Channels are not supported by this backend");
}
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
}
#if !WINDOWS
public async HostChildId prepare_to_fork (uint parent_pid, Cancellable? cancellable, out uint parent_injectee_id,
out uint child_injectee_id, out GLib.Socket child_socket) throws Error, IOError {
@@ -1251,7 +1386,7 @@ namespace Frida {
}
}
internal class InstalledHelperFile : Object, HelperFile {
internal sealed class InstalledHelperFile : Object, HelperFile {
public string path {
owned get {
return installed_path;
@@ -1268,7 +1403,7 @@ namespace Frida {
}
}
internal class TemporaryHelperFile : Object, HelperFile {
internal sealed class TemporaryHelperFile : Object, HelperFile {
public string path {
owned get {
return file.path;
@@ -1288,7 +1423,7 @@ namespace Frida {
public abstract class InternalAgent : Object, AgentMessageSink, RpcPeer {
public signal void unloaded ();
public weak BaseDBusHostSession host_session {
public weak LocalHostSession host_session {
get;
construct;
}
+18 -18
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class LinuxHelperBackend : Object, LinuxHelper {
public sealed class LinuxHelperBackend : Object, LinuxHelper {
public signal void idle ();
public bool is_idle {
@@ -597,7 +597,7 @@ namespace Frida {
}
}
private class SpawnedProcess : Object {
private sealed class SpawnedProcess : Object {
public signal void terminated ();
public signal void output (int fd, uint8[] data);
@@ -703,7 +703,7 @@ namespace Frida {
}
}
private class StdioPipes : Object {
private sealed class StdioPipes : Object {
public FileDescriptor input {
get;
construct;
@@ -734,7 +734,7 @@ namespace Frida {
}
}
private class ExecTransitionSession : SeizeSession {
private sealed class ExecTransitionSession : SeizeSession {
private ExecTransitionSession (uint pid) {
Object (pid: pid, on_init: SeizeSession.InitBehavior.CONTINUE);
}
@@ -758,7 +758,7 @@ namespace Frida {
}
}
private class PausedSyscallSession : SeizeSession {
private sealed class PausedSyscallSession : SeizeSession {
private State state = PENDING;
private enum State {
@@ -843,7 +843,7 @@ namespace Frida {
private const uint64 SOCK_CLOEXEC = 0x80000;
private class InjectSession : SeizeSession {
private sealed class InjectSession : SeizeSession {
private static ProcMapsSoEntry local_libc;
private static uint64 mmap_offset;
private static uint64 munmap_offset;
@@ -1353,7 +1353,7 @@ namespace Frida {
}
}
public class InjectSpec {
public sealed class InjectSpec {
public FileDescriptorBased library_so {
get;
private set;
@@ -1392,7 +1392,7 @@ namespace Frida {
}
}
private class CleanupSession : SeizeSession {
private sealed class CleanupSession : SeizeSession {
private CleanupSession (uint pid) {
Object (pid: pid);
}
@@ -1415,7 +1415,7 @@ namespace Frida {
}
}
private class ThreadSuspendSession : SeizeSession {
private sealed class ThreadSuspendSession : SeizeSession {
private ThreadSuspendSession (uint pid, uint tid) {
Object (pid: pid, tid: tid);
}
@@ -1445,7 +1445,7 @@ namespace Frida {
}
private class BootstrapResult {
private sealed class BootstrapResult {
public HelperBootstrapContext context;
public HelperLibcApi libc;
public AllocatedStack allocated_stack;
@@ -1464,7 +1464,7 @@ namespace Frida {
RELAUNCH
}
private class RemoteAgent : Object {
private sealed class RemoteAgent : Object {
public uint pid {
get;
construct;
@@ -2272,7 +2272,7 @@ namespace Frida {
ALREADY_ATTACHED,
}
private class ProcessCodeSwapScope {
private sealed class ProcessCodeSwapScope {
private State state = INACTIVE;
private SeizeSession session;
@@ -2329,7 +2329,7 @@ namespace Frida {
}
}
private class ThreadSuspendScope {
private sealed class ThreadSuspendScope {
private State state = INACTIVE;
private uint pid;
@@ -2427,7 +2427,7 @@ namespace Frida {
}
}
private class RemoteCallBuilder {
private sealed class RemoteCallBuilder {
private uint64 target;
private uint64[] args = {};
private GPRegs regs;
@@ -2478,7 +2478,7 @@ namespace Frida {
}
}
private class RemoteCall {
private sealed class RemoteCall {
private SeizeSession session;
private uint64 target;
private uint64[] args;
@@ -2660,7 +2660,7 @@ namespace Frida {
}
}
private class RemoteCallResult {
private sealed class RemoteCallResult {
public RemoteCallStatus status;
public int stop_signal;
public uint64 return_value;
@@ -3204,7 +3204,7 @@ namespace Frida {
}
}
public class PidFileDescriptor : FileDescriptor {
public sealed class PidFileDescriptor : FileDescriptor {
private uint pid;
private PidFileDescriptor (int fd, uint pid) {
@@ -3319,7 +3319,7 @@ namespace Frida {
}
#endif
private class ProcMapsSoEntry {
private sealed class ProcMapsSoEntry {
public uint64 base_address;
public string path;
public string identity;
+5 -5
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class LinuxHelperProcess : Object, LinuxHelper {
public sealed class LinuxHelperProcess : Object, LinuxHelper {
public TemporaryDirectory tempdir {
get;
construct;
@@ -246,7 +246,7 @@ namespace Frida {
}
}
private class HelperFactory {
private sealed class HelperFactory {
public signal void lost (LinuxHelper helper);
public signal void output (uint pid, int fd, uint8[] data);
public signal void uninjected (uint id);
@@ -457,7 +457,7 @@ namespace Frida {
}
}
private class HelperSession : Object, LinuxHelper {
private sealed class HelperSession : Object, LinuxHelper {
public LinuxRemoteHelper proxy {
get;
construct;
@@ -606,7 +606,7 @@ namespace Frida {
}
}
private class ResourceStore {
private sealed class ResourceStore {
public TemporaryDirectory tempdir {
get;
private set;
@@ -659,7 +659,7 @@ namespace Frida {
#endif
}
private class MemoryHelperFile : Object, HelperFile {
private sealed class MemoryHelperFile : Object, HelperFile {
public FileDescriptor fd {
get;
construct;
+1 -1
View File
@@ -9,7 +9,7 @@ namespace Frida {
return service.run ();
}
public class LinuxHelperService : Object, LinuxRemoteHelper {
public sealed class LinuxHelperService : Object, LinuxRemoteHelper {
public string parent_address {
get;
construct;
+3 -3
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class Linjector : Object, Injector {
public sealed class Linjector : Object, Injector {
public LinuxHelper helper {
get;
construct;
@@ -158,7 +158,7 @@ namespace Frida {
SINGLETON
}
public class AgentDescriptor : Object {
public sealed class AgentDescriptor : Object {
public PathTemplate name_template {
get;
construct;
@@ -219,7 +219,7 @@ namespace Frida {
internal extern static Bytes _clone_so (Bytes so);
}
public class AgentResource : Object {
public sealed class AgentResource : Object {
public string name {
get;
construct;
+15 -81
View File
@@ -1,84 +1,18 @@
namespace Frida {
public class LinuxHostSessionBackend : Object, HostSessionBackend {
private LinuxHostSessionProvider local_provider;
public async void start (Cancellable? cancellable) throws IOError {
assert (local_provider == null);
local_provider = new LinuxHostSessionProvider ();
provider_available (local_provider);
}
public async void stop (Cancellable? cancellable) throws IOError {
assert (local_provider != null);
provider_unavailable (local_provider);
yield local_provider.close (cancellable);
local_provider = null;
public sealed class LinuxHostSessionBackend : LocalHostSessionBackend {
protected override LocalHostSessionProvider make_provider () {
return new LinuxHostSessionProvider ();
}
}
public class LinuxHostSessionProvider : Object, HostSessionProvider {
public string id {
get { return "local"; }
}
public string name {
get { return "Local System"; }
}
public Variant? icon {
get { return null; }
}
public HostSessionProviderKind kind {
get { return HostSessionProviderKind.LOCAL; }
}
private LinuxHostSession host_session;
public async void close (Cancellable? cancellable) throws IOError {
if (host_session == null)
return;
host_session.agent_session_detached.disconnect (on_agent_session_detached);
yield host_session.close (cancellable);
host_session = null;
}
public async HostSession create (HostSessionOptions? options, Cancellable? cancellable) throws Error, IOError {
if (host_session != null)
throw new Error.INVALID_OPERATION ("Already created");
public sealed class LinuxHostSessionProvider : LocalHostSessionProvider {
protected override LocalHostSession make_host_session (HostSessionOptions? options) throws Error {
var tempdir = new TemporaryDirectory ();
host_session = new LinuxHostSession (new LinuxHelperProcess (tempdir), tempdir);
host_session.agent_session_detached.connect (on_agent_session_detached);
return host_session;
}
public async void destroy (HostSession session, Cancellable? cancellable) throws Error, IOError {
if (session != host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
host_session.agent_session_detached.disconnect (on_agent_session_detached);
yield host_session.close (cancellable);
host_session = null;
}
public async AgentSession link_agent_session (HostSession host_session, AgentSessionId id, AgentMessageSink sink,
Cancellable? cancellable) throws Error, IOError {
if (host_session != this.host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
return yield this.host_session.link_agent_session (id, sink, cancellable);
}
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
agent_session_detached (id, reason, crash);
return new LinuxHostSession (new LinuxHelperProcess (tempdir), tempdir);
}
}
public class LinuxHostSession : BaseDBusHostSession {
public sealed class LinuxHostSession : LocalHostSession {
public LinuxHelper helper {
get;
construct;
@@ -508,7 +442,7 @@ namespace Frida {
}
#if ANDROID
private class RoboLauncher : Object {
private sealed class RoboLauncher : Object {
public signal void spawn_added (HostSpawnInfo info);
public signal void spawn_removed (HostSpawnInfo info);
@@ -808,7 +742,7 @@ namespace Frida {
}
}
private class ZygoteAgent : InternalAgent {
private sealed class ZygoteAgent : InternalAgent {
public uint pid {
get;
construct;
@@ -861,7 +795,7 @@ namespace Frida {
}
}
private class SystemServerAgent : InternalAgent {
private sealed class SystemServerAgent : InternalAgent {
private delegate void CompletionNotify ();
public SystemServerAgent (LinuxHostSession host_session) {
@@ -1183,7 +1117,7 @@ namespace Frida {
}
}
private class CrashMonitor : Object {
private sealed class CrashMonitor : Object {
public signal void process_crashed (CrashInfo crash);
private Object logcat;
@@ -1613,7 +1547,7 @@ namespace Frida {
return result.str;
}
private class PackageEntrypoint : Object {
private abstract class PackageEntrypoint : Object {
public int uid {
get;
set;
@@ -1673,13 +1607,13 @@ namespace Frida {
}
}
private class DefaultActivityEntrypoint : PackageEntrypoint {
private sealed class DefaultActivityEntrypoint : PackageEntrypoint {
public DefaultActivityEntrypoint () {
Object ();
}
}
private class ActivityEntrypoint : PackageEntrypoint {
private sealed class ActivityEntrypoint : PackageEntrypoint {
public string activity {
get;
construct;
@@ -1690,7 +1624,7 @@ namespace Frida {
}
}
private class BroadcastReceiverEntrypoint : PackageEntrypoint {
private sealed class BroadcastReceiverEntrypoint : PackageEntrypoint {
public string receiver {
get;
construct;
+45 -2
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class PortalService : Object {
public sealed class PortalService : Object {
public signal void node_connected (uint connection_id, SocketAddress remote_address);
public signal void node_joined (uint connection_id, Application application);
public signal void node_left (uint connection_id, Application application);
@@ -986,7 +986,7 @@ namespace Frida {
if (host_session != channel)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
AgentSessionEntry entry = parent.sessions[id];
AgentSessionEntry? entry = parent.sessions[id];
if (entry == null)
throw new Error.INVALID_ARGUMENT ("Invalid session ID");
@@ -1000,6 +1000,33 @@ namespace Frida {
return entry.session;
}
public void unlink_agent_session (HostSession host_session, AgentSessionId id) {
if (host_session != channel)
return;
AgentSessionEntry? entry = parent.sessions[id];
if (entry == null)
return;
entry.clear_node_registrations ();
}
public async IOStream link_channel (HostSession host_session, ChannelId id, Cancellable? cancellable)
throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Channels are not supported by this backend");
}
public void unlink_channel (HostSession host_session, ChannelId id) {
}
public async ServiceSession link_service_session (HostSession host_session, ServiceSessionId id,
Cancellable? cancellable) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
}
public void unlink_service_session (HostSession host_session, ServiceSessionId id) {
}
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
agent_session_detached (id, reason, crash);
}
@@ -1278,6 +1305,14 @@ namespace Frida {
Cancellable? cancellable) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Not supported");
}
public async ChannelId open_channel (string address, Cancellable? cancellable) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Channels are not supported by this backend");
}
public async ServiceSessionId open_service (string address, Cancellable? cancellable) throws Error, IOError {
throw new Error.NOT_SUPPORTED ("Services are not supported by this backend");
}
}
private class BusService : Object, BusSession {
@@ -1516,8 +1551,16 @@ namespace Frida {
}
private void unregister_all () {
clear_controller_registrations ();
clear_node_registrations ();
}
private void clear_controller_registrations () {
if (controller != null)
unregister_all_in (controller_registrations, controller.connection);
}
public void clear_node_registrations () {
if (node != null)
unregister_all_in (node_registrations, node.connection);
}
+3 -3
View File
@@ -133,7 +133,7 @@ namespace Frida {
public extern void _free_instance (void * instance, UnloadPolicy unload_policy);
public extern uint _do_inject (uint pid, string path, string entrypoint, string data, string temp_path) throws Error;
public class ResourceStore {
public sealed class ResourceStore {
public TemporaryDirectory tempdir {
get;
private set;
@@ -164,7 +164,7 @@ namespace Frida {
}
}
public class AgentDescriptor : Object {
public sealed class AgentDescriptor : Object {
public string name {
get;
construct;
@@ -197,7 +197,7 @@ namespace Frida {
}
}
private class RemoteThreadSession : Object {
private sealed class RemoteThreadSession : Object {
public signal void ended (UnloadPolicy unload_policy);
public uint id {
+7 -72
View File
@@ -1,82 +1,17 @@
namespace Frida {
public class QnxHostSessionBackend : Object, HostSessionBackend {
private QnxHostSessionProvider local_provider;
public async void start (Cancellable? cancellable) throws IOError {
assert (local_provider == null);
local_provider = new QnxHostSessionProvider ();
provider_available (local_provider);
}
public async void stop (Cancellable? cancellable) throws IOError {
assert (local_provider != null);
provider_unavailable (local_provider);
yield local_provider.close (cancellable);
local_provider = null;
public sealed class QnxHostSessionBackend : LocalHostSessionBackend {
protected override LocalHostSessionProvider make_provider () {
return new QnxHostSessionProvider ();
}
}
public class QnxHostSessionProvider : Object, HostSessionProvider {
public string id {
get { return "local"; }
}
public string name {
get { return "Local System"; }
}
public Variant? icon {
get { return null; }
}
public HostSessionProviderKind kind {
get { return HostSessionProviderKind.LOCAL; }
}
private QnxHostSession host_session;
public async void close (Cancellable? cancellable) throws IOError {
if (host_session == null)
return;
host_session.agent_session_detached.disconnect (on_agent_session_detached);
yield host_session.close (cancellable);
host_session = null;
}
public async HostSession create (HostSessionOptions? options, Cancellable? cancellable) throws Error, IOError {
if (host_session != null)
throw new Error.INVALID_OPERATION ("Already created");
host_session = new QnxHostSession ();
host_session.agent_session_detached.connect (on_agent_session_detached);
return host_session;
}
public async void destroy (HostSession session, Cancellable? cancellable) throws Error, IOError {
if (session != host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
host_session.agent_session_detached.disconnect (on_agent_session_detached);
yield host_session.close (cancellable);
host_session = null;
}
public async AgentSession link_agent_session (HostSession host_session, AgentSessionId id, AgentMessageSink sink,
Cancellable? cancellable) throws Error, IOError {
if (host_session != this.host_session)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
return yield this.host_session.link_agent_session (id, sink, cancellable);
}
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
agent_session_detached (id, reason, crash);
public sealed class QnxHostSessionProvider : LocalHostSessionProvider {
protected override LocalHostSession make_host_session (HostSessionOptions? options) throws Error {
return new QnxHostSession ();
}
}
public class QnxHostSession : BaseDBusHostSession {
public sealed class QnxHostSession : LocalHostSession {
private AgentContainer system_session_container;
private AgentDescriptor agent_desc;
+90 -7
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class SocketHostSessionBackend : Object, HostSessionBackend {
public sealed class SocketHostSessionBackend : Object, HostSessionBackend {
private SocketHostSessionProvider provider;
public async void start (Cancellable? cancellable) throws IOError {
@@ -14,7 +14,7 @@ namespace Frida {
}
}
public class SocketHostSessionProvider : Object, HostSessionProvider {
public sealed class SocketHostSessionProvider : Object, HostSessionProvider {
public string id {
get { return "socket"; }
}
@@ -199,6 +199,21 @@ namespace Frida {
host_session_detached (entry.host_session);
}
private HostEntry get_host_entry_by_session (HostSession session) throws Error {
var entry = find_host_entry_by_session (session);
if (entry == null)
throw new Error.INVALID_ARGUMENT ("Invalid host session");
return entry;
}
private HostEntry? find_host_entry_by_session (HostSession session) {
foreach (var entry in hosts) {
if (entry.host_session == session)
return entry;
}
return null;
}
private void on_host_connection_closed (DBusConnection connection, bool remote_peer_vanished, GLib.Error? error) {
bool closed_by_us = (!remote_peer_vanished && error == null);
if (closed_by_us)
@@ -219,11 +234,38 @@ namespace Frida {
public async AgentSession link_agent_session (HostSession host_session, AgentSessionId id, AgentMessageSink sink,
Cancellable? cancellable) throws Error, IOError {
foreach (var entry in hosts) {
if (entry.host_session == host_session)
return yield entry.link_agent_session (id, sink, cancellable);
}
throw new Error.INVALID_ARGUMENT ("Invalid host session");
var entry = get_host_entry_by_session (host_session);
return yield entry.link_agent_session (id, sink, cancellable);
}
public void unlink_agent_session (HostSession host_session, AgentSessionId id) {
var entry = find_host_entry_by_session (host_session);
if (entry != null)
entry.unlink_agent_session (id);
}
public async IOStream link_channel (HostSession host_session, ChannelId id, Cancellable? cancellable)
throws Error, IOError {
var entry = get_host_entry_by_session (host_session);
return yield entry.link_channel (id, cancellable);
}
public void unlink_channel (HostSession host_session, ChannelId id) {
var entry = find_host_entry_by_session (host_session);
if (entry != null)
entry.unlink_channel (id);
}
public async ServiceSession link_service_session (HostSession host_session, ServiceSessionId id, Cancellable? cancellable)
throws Error, IOError {
var entry = get_host_entry_by_session (host_session);
return yield entry.link_service_session (id, cancellable);
}
public void unlink_service_session (HostSession host_session, ServiceSessionId id) {
var entry = find_host_entry_by_session (host_session);
if (entry != null)
entry.unlink_service_session (id);
}
private void on_agent_session_detached (AgentSessionId id, SessionDetachReason reason, CrashInfo crash) {
@@ -252,6 +294,8 @@ namespace Frida {
private Gee.HashMap<AgentSessionId?, AgentSessionEntry> agent_sessions =
new Gee.HashMap<AgentSessionId?, AgentSessionEntry> (AgentSessionId.hash, AgentSessionId.equal);
private ChannelRegistry channel_registry = new ChannelRegistry ();
private ServiceSessionRegistry service_session_registry = new ServiceSessionRegistry ();
private Cancellable io_cancellable = new Cancellable ();
@@ -291,6 +335,10 @@ namespace Frida {
agent_session_detached (id, reason, no_crash);
agent_sessions.clear ();
channel_registry.clear ();
service_session_registry.clear ();
if (reason != CONNECTION_TERMINATED) {
try {
yield connection.close (cancellable);
@@ -315,6 +363,41 @@ namespace Frida {
return session;
}
public void unlink_agent_session (AgentSessionId id) {
AgentSessionEntry? entry = agent_sessions[id];
if (entry == null || entry.sink_registration_id == 0)
return;
entry.connection.unregister_object (entry.sink_registration_id);
entry.sink_registration_id = 0;
}
public async IOStream link_channel (ChannelId id, Cancellable? cancellable) throws Error, IOError {
Channel channel = yield connection.get_proxy (null, ObjectPath.for_channel (id),
DO_NOT_LOAD_PROPERTIES, cancellable);
var stream = new ChannelStream (channel);
channel_registry.register (id, stream);
return stream;
}
public void unlink_channel (ChannelId id) {
channel_registry.unlink (id);
}
public async ServiceSession link_service_session (ServiceSessionId id, Cancellable? cancellable)
throws Error, IOError {
ServiceSession session = yield connection.get_proxy (null, ObjectPath.for_service_session (id),
DO_NOT_LOAD_PROPERTIES, cancellable);
service_session_registry.register (id, session);
return session;
}
public void unlink_service_session (ServiceSessionId id) {
service_session_registry.unlink (id);
}
private bool on_keepalive_tick () {
host_session.ping.begin (keepalive_interval, io_cancellable);
return true;
+4 -4
View File
@@ -6,7 +6,7 @@ namespace Frida {
public extern static void kill (uint pid);
}
public class ApplicationEnumerator : Object {
public sealed class ApplicationEnumerator : Object {
private ThreadPool<EnumerateRequest> pool;
private MainContext main_context;
@@ -68,7 +68,7 @@ namespace Frida {
}
}
public class ProcessEnumerator : Object {
public sealed class ProcessEnumerator : Object {
private ThreadPool<EnumerateRequest> pool;
private MainContext main_context;
@@ -130,7 +130,7 @@ namespace Frida {
}
}
public class TemporaryDirectory {
public sealed class TemporaryDirectory {
private string? name;
public string path {
@@ -247,7 +247,7 @@ namespace Frida {
private extern static string get_system_tmp ();
}
public class TemporaryFile {
public sealed class TemporaryFile {
public string path {
owned get {
return file.get_path ();
+3 -3
View File
@@ -1,5 +1,5 @@
namespace Frida {
public class WindowsHelperBackend : Object, WindowsHelper {
public sealed class WindowsHelperBackend : Object, WindowsHelper {
public PrivilegeLevel level {
get;
construct;
@@ -127,7 +127,7 @@ namespace Frida {
}
}
private class AssetDirectory {
private sealed class AssetDirectory {
public File file {
get;
private set;
@@ -170,7 +170,7 @@ namespace Frida {
}
}
private class AssetBundle {
private sealed class AssetBundle {
public Gee.List<File> files {
get;
private set;
Loaded 100 of 113 files, more files were not shown because too many files have changed in this diff. Show more