Compare commits

...
17 Commits
Author SHA1 Message Date
Ole André Vadla Ravnås 20d5d121b7 subprojects: Prepare for release 2025-06-20 01:13:54 +02:00
Ole André Vadla Ravnås dc71534220 subprojects: Bump outdated 2025-06-20 01:12:26 +02:00
Ole André Vadla Ravnås 35afee9b4a package-manager: Handle tarballs with root entries
Like if there's a directory entry for "package/", or somehow any files
at the root level.
2025-06-20 01:11:39 +02:00
Ole André Vadla Ravnås 7b130e6eba package-manager: Fix handling of scoped specs 2025-06-20 01:11:39 +02:00
Ole André Vadla Ravnås d28c46c332 package-manager: Fix a stylistic inconsistency 2025-06-20 01:11:39 +02:00
Ole André Vadla Ravnås ab103a73ca package-manager: Simplify substring logic 2025-06-20 01:11:39 +02:00
Ole André Vadla Ravnås 7b7d9acf8c subprojects: Prepare for release 2025-06-19 23:25:44 +02:00
Ole André Vadla Ravnås 215076a0fa subprojects: Bump outdated 2025-06-19 23:23:46 +02:00
Ole André Vadla Ravnås 3d47bf73b4 package-manager: Only report installed packages
The toplevel packages that were left untouched should not be included.

Also simplify the install() logic while at it.
2025-06-19 23:22:22 +02:00
Ole André Vadla Ravnås 7d84a44c7f package-manager: Fix the lockfile up-to-date path 2025-06-19 22:55:19 +02:00
Ole André Vadla Ravnås ef7e0a88e0 package-manager: Fix two stylistic inconsistencies 2025-06-19 22:53:09 +02:00
Ole André Vadla Ravnås 1f95416a77 subprojects: Prepare for release 2025-06-19 21:03:42 +02:00
Ole André Vadla Ravnås 80c7ec2dce meson: Fix build when libsoup is a subproject 2025-06-19 20:23:30 +02:00
Ole André Vadla Ravnås 69c68fdf7f subprojects: Bump outdated 2025-06-19 20:18:51 +02:00
Ole André Vadla Ravnås 7070042128 compiler: Make backend a shared library on Android
To avoid dynamic linking issues due to thread-local storage. This was
caused by our previous hack where we pretended Android was GOOS=linux
to work around the Go toolchain refusing `-buildmode=c-archive` for
GOOS=android.
2025-06-19 20:17:06 +02:00
Ole André Vadla Ravnås 9a4ce30be5 post-process: Support skipping ELF-cleaner step
It seems to corrupt shared library ELFs generated by the Go toolchain.
2025-06-19 20:08:47 +02:00
Ole André Vadla Ravnås 7731aea6f7 linux: Split out useful primitives into base
- check_kernel_version()
- FileDescriptor
- PidFileDescriptor
- MemoryFileDescriptor
2025-06-19 20:08:47 +02:00
19 changed files with 376 additions and 249 deletions

No files matched your search

@@ -1,5 +1,5 @@
#ifndef __FRIDA_SYSCALL_H__
#define __FRIDA_SYSCALL_H__
#ifndef __FRIDA_LINUX_SYSCALL_H__
#define __FRIDA_LINUX_SYSCALL_H__
#include <linux/unistd.h>
#include <sys/syscall.h>
@@ -14,7 +14,7 @@ namespace Frida {
[CCode (cheader_filename = "sys/mman.h", cname = "MAP_ANONYMOUS")]
public const int MAP_ANONYMOUS;
[CCode (cheader_filename = "linux/frida-syscall.h", cprefix = "SYS_", has_type_id = false)]
[CCode (cheader_filename = "linux-syscall.h", cprefix = "SYS_", has_type_id = false)]
public enum SysCall {
memfd_create,
pidfd_getfd,
+107
View File
@@ -0,0 +1,107 @@
namespace Frida {
private uint linux_major = 0;
private uint linux_minor = 0;
public bool check_kernel_version (uint major, uint minor) {
if (linux_major == 0) {
var name = Posix.utsname ();
name.release.scanf ("%u.%u", out linux_major, out linux_minor);
}
return (linux_major == major && linux_minor >= minor) || linux_major > major;
}
public class FileDescriptor : Object, FileDescriptorBased {
public int handle;
public FileDescriptor (int handle) {
this.handle = handle;
}
~FileDescriptor () {
if (handle != -1)
Posix.close (handle);
}
public int steal () {
int result = handle;
handle = -1;
return result;
}
public int get_fd () {
return handle;
}
}
public sealed class PidFileDescriptor : FileDescriptor {
private uint pid;
private PidFileDescriptor (int fd, uint pid) {
base (fd);
this.pid = pid;
}
public static bool is_supported () {
return check_kernel_version (5, 3);
}
public static bool getfd_is_supported () {
return check_kernel_version (5, 6);
}
public static PidFileDescriptor from_pid (uint pid) throws Error {
int fd = pidfd_open (pid, 0);
if (fd == -1)
throw_pidfd_error (pid, errno);
return new PidFileDescriptor (fd, pid);
}
public FileDescriptor getfd (int targetfd) throws Error {
int fd = pidfd_getfd (handle, targetfd, 0);
if (fd == -1)
throw_pidfd_error (pid, errno);
return new FileDescriptor (fd);
}
private static int pidfd_open (uint pid, uint flags) {
return Linux.syscall (SysCall.pidfd_open, pid, flags);
}
private static int pidfd_getfd (int pidfd, int targetfd, uint flags) {
return Linux.syscall (SysCall.pidfd_getfd, pidfd, targetfd, flags);
}
[NoReturn]
private static void throw_pidfd_error (uint pid, int err) throws Error {
switch (err) {
case Posix.ESRCH:
throw new Error.PROCESS_NOT_FOUND ("Process not found");
case Posix.EPERM:
throw new Error.PERMISSION_DENIED ("Unable to use pidfd for pid %u: %s", pid, strerror (err));
default:
throw new Error.NOT_SUPPORTED ("Unable to use pidfd for pid %u: %s", pid, strerror (err));
}
}
}
namespace MemoryFileDescriptor {
public bool is_supported () {
return check_kernel_version (3, 17);
}
public static FileDescriptor from_bytes (string name, Bytes bytes) {
assert (is_supported ());
var fd = new FileDescriptor (memfd_create (name, 0));
unowned uint8[] data = bytes.get_data ();
ssize_t n = Posix.write (fd.handle, data, data.length);
assert (n == data.length);
return fd;
}
private int memfd_create (string name, uint flags) {
return Linux.syscall (SysCall.memfd_create, name, flags);
}
}
}
+16 -1
View File
@@ -29,6 +29,15 @@ if host_os_family == 'darwin'
base_sources += 'corefoundation.vala'
endif
if host_os_family == 'linux'
base_sources += 'linux.vala'
extra_vala_args += [
'--pkg=linux',
'--pkg=linux-system',
'--pkg=posix',
]
endif
extra_deps = []
if host_os_family != 'windows'
extra_vala_args += '--pkg=gio-unix-2.0'
@@ -46,6 +55,12 @@ if host_os_family == 'darwin'
'--pkg=darwin-xpc',
]
endif
if host_os_family == 'linux'
base_vala_args += [
'--vapidir=' + meson.current_source_dir(),
'--pkg=gio-unix-2.0',
]
endif
base_gir_name = f'FridaBase-@[email protected]'
@@ -63,7 +78,7 @@ base = static_library('frida-base-' + api_version, base_sources,
base_dep = declare_dependency(
include_directories: include_directories('.'),
link_with: base,
dependencies: [nice_dep, json_glib_dep, gum_dep],
dependencies: [nice_dep, json_glib_dep, gum_dep] + extra_deps,
)
base_build_dir = meson.current_build_dir()
+8 -1
View File
@@ -423,6 +423,7 @@ if compiler_backend_opt.allowed()
go,
host_os,
host_abi,
shlib_suffix,
cc.get_id(),
'>>>', cc.cmd_array(), '<<<',
'>>>', ar, '<<<',
@@ -436,7 +437,13 @@ if compiler_backend_opt.allowed()
status = lines[0]
if status == 'ok'
have_compiler_backend = true
go_config = lines[1]
tokens = lines[1].split(' ')
go_mode = tokens[0]
go_config = tokens[1]
compiler_backend_static_compilation = go_mode == 'c-archive'
if compiler_backend_static_compilation
vala_flags += '--define=COMPILER_BACKEND_STATIC_COMPILATION'
endif
else
error_message = lines[1]
if compiler_backend_opt.enabled()
+2 -1
View File
@@ -510,7 +510,8 @@ def function_is_public(name):
"parse_control_address",
"parse_cluster_address",
"parse_socket_address",
"negotiate_connection"
"negotiate_connection",
"check_kernel_version",
]
def parse_vala_object_types(source) -> List[ApiObjectType]:
+2 -2
View File
@@ -13,7 +13,7 @@
extern void FRIDA_CGO_INIT_FUNC ();
void
frida_compiler_backend_init (void)
_frida_compiler_backend_init_go_runtime (void)
{
FRIDA_CGO_INIT_FUNC ();
}
@@ -21,7 +21,7 @@ frida_compiler_backend_init (void)
#else
void
frida_compiler_backend_init (void)
_frida_compiler_backend_init_go_runtime (void)
{
}
+6 -6
View File
@@ -144,8 +144,8 @@ type BuildEndCallback func()
type BuildOutputCallback func(bundle string)
type BuildDiagnosticCallback func(d Diagnostic)
//export frida_compiler_backend_build
func frida_compiler_backend_build(cProjectRoot, cEntrypoint *C.char, outputFormat C.FridaOutputFormat, bundleFormat C.FridaBundleFormat,
//export _frida_compiler_backend_build
func _frida_compiler_backend_build(cProjectRoot, cEntrypoint *C.char, outputFormat C.FridaOutputFormat, bundleFormat C.FridaBundleFormat,
disableTypeCheck, sourceMap, compress uintptr,
onCompleteFn C.FridaBuildCompleteFunc, onCompleteData unsafe.Pointer, onCompleteDataDestroy C.FridaDestroyFunc,
onDiagnosticFn C.FridaDiagnosticFunc, onDiagnosticData unsafe.Pointer) {
@@ -179,8 +179,8 @@ func frida_compiler_backend_build(cProjectRoot, cEntrypoint *C.char, outputForma
}()
}
//export frida_compiler_backend_watch
func frida_compiler_backend_watch(cProjectRoot, cEntrypoint *C.char, outputFormat C.FridaOutputFormat, bundleFormat C.FridaBundleFormat,
//export _frida_compiler_backend_watch
func _frida_compiler_backend_watch(cProjectRoot, cEntrypoint *C.char, outputFormat C.FridaOutputFormat, bundleFormat C.FridaBundleFormat,
disableTypeCheck, sourceMap, compress uintptr,
onReadyFn C.FridaWatchReadyFunc, onReadyData unsafe.Pointer, onReadyDataDestroy C.FridaDestroyFunc,
onStartingFn C.FridaStartingFunc, onStartingData unsafe.Pointer,
@@ -238,8 +238,8 @@ func frida_compiler_backend_watch(cProjectRoot, cEntrypoint *C.char, outputForma
}()
}
//export frida_compiler_backend_watch_session_dispose
func frida_compiler_backend_watch_session_dispose(h uintptr) {
//export _frida_compiler_backend_watch_session_dispose
func _frida_compiler_backend_watch_session_dispose(h uintptr) {
handle := cgo.Handle(h)
session := handle.Value().(*WatchSession)
session.Dispose()
+7
View File
@@ -0,0 +1,7 @@
{
global:
_frida_compiler_backend_*;
local:
*;
};
+57 -40
View File
@@ -57,62 +57,79 @@ def build_backend(
run(npm, "install")
# run(npm, "link", "/home/oleavr/src/frida-fs")
backend_a = priv_dir / "frida-compiler-backend.a"
backend_h = priv_dir / "frida-compiler-backend.h"
mode = config["mode"]
backend_stem = "frida-compiler-backend"
if mode == "c-shared":
backend_stem += "-raw"
backend_a = priv_dir / f"{backend_stem}.a"
backend_shlib = priv_dir / (f"{backend_stem}" + config["shlib_suffix"])
backend_h = priv_dir / f"{backend_stem}.h"
extra_go_args = config["extra_go_args"].copy()
if mode == "c-shared":
version_script = priv_dir / "backend.version"
extra_go_args.append(f"-ldflags=-linkmode=external -extldflags=-Wl,--version-script={version_script}")
run(
go,
"build",
"-buildmode=c-archive",
f"-buildmode={mode}",
"-o",
backend_a.name,
backend_a.name if mode == "c-archive" else backend_shlib.name,
"-buildvcs=false",
*config["extra_go_args"],
*extra_go_args,
*go_sources,
)
symbols_to_scramble = detect_conflictful_symbols_in_archive(backend_a, config["nm"])
scramble_symbols_in_archive(backend_a, symbols_to_scramble, config["ranlib"])
if mode == "c-archive":
symbols_to_scramble = detect_conflictful_symbols_in_archive(backend_a, config["nm"])
scramble_symbols_in_archive(backend_a, symbols_to_scramble, config["ranlib"])
if (mingw := config.get("mingw")) is not None and (abi := config["abi"]) in {
"x86",
"x86_64",
}:
prefix = Path(mingw["prefix"])
ar = config["ar"]
if (mingw := config.get("mingw")) is not None and (abi := config["abi"]) in {
"x86",
"x86_64",
}:
prefix = Path(mingw["prefix"])
ar = config["ar"]
libmingwex_a = prefix / "lib" / "libmingwex.a"
if not libmingwex_a.exists():
libmingwex_a = prefix / mingw["triplet"] / "lib" / "libmingwex.a"
libmingwex_a = prefix / "lib" / "libmingwex.a"
if not libmingwex_a.exists():
libmingwex_a = prefix / mingw["triplet"] / "lib" / "libmingwex.a"
libgcc_objects = [
"_chkstk_ms.o",
]
run(*ar, "x", mingw["libcc"], *libgcc_objects)
gwex_objflavor = "64" if abi == "x86_64" else "32"
gwex_objects = [
f"lib{gwex_objflavor}_libmingwex_a-{name}.o"
for name in [
"dmisc",
"gdtoa",
"gmisc",
"mingw_fprintf",
"mingw_pformat",
"misc",
libgcc_objects = [
"_chkstk_ms.o",
]
]
run(*ar, "x", libmingwex_a, *gwex_objects)
run(*ar, "x", mingw["libcc"], *libgcc_objects)
extra_objects = []
if abi == "x86_64":
run(*ar, "x", backend_a.name, "go.o")
sort_pdata_in_object(Path(priv_dir) / "go.o")
extra_objects.append("go.o")
gwex_objflavor = "64" if abi == "x86_64" else "32"
gwex_objects = [
f"lib{gwex_objflavor}_libmingwex_a-{name}.o"
for name in [
"dmisc",
"gdtoa",
"gmisc",
"mingw_fprintf",
"mingw_pformat",
"misc",
]
]
run(*ar, "x", libmingwex_a, *gwex_objects)
run(*ar, "rs", backend_a.name, *libgcc_objects, *gwex_objects, *extra_objects)
extra_objects = []
if abi == "x86_64":
run(*ar, "x", backend_a.name, "go.o")
sort_pdata_in_object(Path(priv_dir) / "go.o")
extra_objects.append("go.o")
run(*ar, "rs", backend_a.name, *libgcc_objects, *gwex_objects, *extra_objects)
shutil.copy(priv_dir / backend_a.name, output_dir / backend_a.name)
else:
shutil.copy(priv_dir / backend_shlib.name, output_dir / backend_shlib.name)
shutil.copy(priv_dir / backend_a.name, output_dir / backend_a.name)
shutil.copy(priv_dir / backend_h.name, output_dir / backend_h.name)
+2
View File
@@ -0,0 +1,2 @@
[resource-compiler]
namespace = Frida.Data.Compiler
+81 -26
View File
@@ -29,6 +29,8 @@ namespace Frida {
public async string build (string entrypoint, BuildOptions? options = null, Cancellable? cancellable = null)
throws Error, IOError {
CompilerBackend.check_available ();
BuildOptions opts = (options != null) ? options : new BuildOptions ();
string project_root = compute_project_root (entrypoint, opts);
@@ -77,6 +79,8 @@ namespace Frida {
public async void watch (string entrypoint, WatchOptions? options = null, Cancellable? cancellable = null)
throws Error, IOError {
CompilerBackend.check_available ();
WatchOptions opts = (options != null) ? options : new WatchOptions ();
string project_root = compute_project_root (entrypoint, opts);
@@ -227,40 +231,82 @@ namespace Frida {
}
namespace CompilerBackend {
private extern void init ();
private void init () {
#if HAVE_COMPILER_BACKEND
private extern void build (string project_root, string entrypoint, OutputFormat output_format, BundleFormat bundle_format,
size_t disable_type_check, size_t source_map, size_t compress, owned BuildCompleteFunc on_complete,
DiagnosticFunc on_diagnostic);
private extern void watch (string project_root, string entrypoint, OutputFormat output_format, BundleFormat bundle_format,
size_t disable_type_check, size_t source_map, size_t compress, owned WatchReadyFunc on_ready,
StartingFunc on_starting, FinishedFunc on_finished, OutputFunc on_output, DiagnosticFunc on_diagnostic);
namespace WatchSession {
private extern void dispose (size_t handle);
}
#if COMPILER_BACKEND_STATIC_COMPILATION
_init_go_runtime ();
build = (BuildFunc) _build;
watch = (WatchFunc) _watch;
WatchSession.dispose = (WatchSession.DisposeFunc) WatchSession._dispose;
#else
private const string DISABLED_MESSAGE = "Compiler backend disabled at build-time";
unowned uint8[] backend_so = Frida.Data.Compiler.get_frida_compiler_backend_so_blob ().data;
private void build (string project_root, string entrypoint, OutputFormat output_format, BundleFormat bundle_format,
size_t disable_type_check, size_t source_map, size_t compress, owned BuildCompleteFunc on_complete,
DiagnosticFunc on_diagnostic) {
on_complete (null, DISABLED_MESSAGE);
}
FileDescriptor fd;
if (MemoryFileDescriptor.is_supported ()) {
fd = MemoryFileDescriptor.from_bytes ("frida-compiler-backend.so", new Bytes.static (backend_so));
} else {
string name_used;
try {
fd = new FileDescriptor (FileUtils.open_tmp ("frida-compiler-backend-XXXXXX.so", out name_used));
FileUtils.unlink (name_used);
private void watch (string project_root, string entrypoint, OutputFormat output_format, BundleFormat bundle_format,
size_t disable_type_check, size_t source_map, size_t compress, owned WatchReadyFunc on_ready,
StartingFunc on_starting, FinishedFunc on_finished, OutputFunc on_output, DiagnosticFunc on_diagnostic) {
on_ready (0, DISABLED_MESSAGE);
}
var output = new UnixOutputStream (fd.handle, false);
output.write_all (backend_so, null);
namespace WatchSession {
private void dispose (size_t handle) {
Posix.lseek (fd.handle, 0, Posix.SEEK_SET);
} catch (GLib.Error e) {
assert_not_reached ();
}
}
Module backend;
try {
backend = new Module ("/proc/self/fd/%d".printf (fd.handle), LOCAL);
} catch (ModuleError e) {
assert_not_reached ();
}
}
build = resolve_symbol (backend, "_frida_compiler_backend_build");
watch = resolve_symbol (backend, "_frida_compiler_backend_watch");
WatchSession.dispose = resolve_symbol (backend, "_frida_compiler_backend_watch_session_dispose");
#endif
#endif
}
private void check_available () throws Error {
if (build == null)
throw new Error.NOT_SUPPORTED ("Compiler backend disabled at build-time");
}
private BuildFunc? build;
private WatchFunc? watch;
[CCode (has_target = false)]
private delegate void BuildFunc (string project_root, string entrypoint, OutputFormat output_format,
BundleFormat bundle_format, size_t disable_type_check, size_t source_map, size_t compress,
owned BuildCompleteFunc on_complete, DiagnosticFunc on_diagnostic);
[CCode (has_target = false)]
private delegate void WatchFunc (string project_root, string entrypoint, OutputFormat output_format,
BundleFormat bundle_format, size_t disable_type_check, size_t source_map, size_t compress,
owned WatchReadyFunc on_ready, StartingFunc on_starting, FinishedFunc on_finished, OutputFunc on_output,
DiagnosticFunc on_diagnostic);
#if COMPILER_BACKEND_STATIC_COMPILATION
private extern void _init_go_runtime ();
private extern void _build ();
private extern void _watch ();
#endif
namespace WatchSession {
[CCode (has_target = false)]
private delegate void DisposeFunc (size_t handle);
private DisposeFunc? dispose;
#if COMPILER_BACKEND_STATIC_COMPILATION
private extern void _dispose ();
#endif
}
private delegate void BuildCompleteFunc (owned string? bundle, owned string? error_message);
private delegate void WatchReadyFunc (size_t session_handle, owned string? error_message);
@@ -269,6 +315,15 @@ namespace Frida {
private delegate void OutputFunc (owned string bundle);
private delegate void DiagnosticFunc (owned string category, int code, owned string? path, int line, int character,
owned string text);
#if HAVE_COMPILER_BACKEND && !COMPILER_BACKEND_STATIC_COMPILATION
private static T resolve_symbol<T> (Module m, string name) {
void * address;
if (!m.symbol (name, out address))
assert_not_reached ();
return (T) address;
}
#endif
}
private string compute_project_root (string entrypoint, CompilerOptions options) {
+33 -2
View File
@@ -9,6 +9,7 @@ if have_compiler_backend
'go.mod',
'go.sum',
'backend.go',
'backend.version',
'tscompiler.go',
'tsconfig.go',
'shims.go',
@@ -16,7 +17,7 @@ if have_compiler_backend
'package-lock.json',
],
output: [
'frida-compiler-backend.a',
'frida-compiler-backend' + (compiler_backend_static_compilation ? '.a' : ('-raw' + shlib_suffix)),
'frida-compiler-backend.h',
],
command: [
@@ -30,5 +31,35 @@ if have_compiler_backend
'@INPUT@',
],
)
backend_libs += compiler_backend[0]
if compiler_backend_static_compilation
backend_libs += compiler_backend[0]
else
filename = 'frida-compiler-backend' + shlib_suffix
identity = (host_os_family == 'darwin') ? 'FridaCompilerBackend' : filename
compiler_backend_shlib = custom_target('frida-compiler-backend-shlib',
input: compiler_backend[0],
output: filename,
command: post_process + ['shared-library', identity, 'elf-cleaner:off'],
)
compiler_data = custom_target('frida-data-compiler',
input: [
'compiler.resources',
compiler_backend_shlib,
],
output: [
'frida-data-compiler.vapi',
'frida-data-compiler.h',
'frida-data-compiler.c',
'frida-data-compiler-blob' + resource_blob_extension,
],
command: [
resource_compiler_cmd_array,
'-c', '@INPUT0@',
'-o', meson.current_build_dir() / 'frida-data-compiler',
'@INPUT1@',
],
)
backend_sources += compiler_data
endif
endif
-105
View File
@@ -3167,114 +3167,9 @@ namespace Frida {
return Linux.syscall (SysCall.tgkill, tgid, tid, sig);
}
private uint linux_major = 0;
private uint linux_minor = 0;
public bool check_kernel_version (uint major, uint minor) {
if (linux_major == 0) {
var name = Posix.utsname ();
name.release.scanf ("%u.%u", out linux_major, out linux_minor);
}
return (linux_major == major && linux_minor >= minor) || linux_major > major;
}
public extern bool _syscall_satisfies (int syscall_id, LinuxSyscall mask);
public class FileDescriptor : Object, FileDescriptorBased {
public int handle;
public FileDescriptor (int handle) {
this.handle = handle;
}
~FileDescriptor () {
if (handle != -1)
Posix.close (handle);
}
public int steal () {
int result = handle;
handle = -1;
return result;
}
public int get_fd () {
return handle;
}
}
public sealed class PidFileDescriptor : FileDescriptor {
private uint pid;
private PidFileDescriptor (int fd, uint pid) {
base (fd);
this.pid = pid;
}
public static bool is_supported () {
return check_kernel_version (5, 3);
}
public static bool getfd_is_supported () {
return check_kernel_version (5, 6);
}
public static PidFileDescriptor from_pid (uint pid) throws Error {
int fd = pidfd_open (pid, 0);
if (fd == -1)
throw_pidfd_error (pid, errno);
return new PidFileDescriptor (fd, pid);
}
public FileDescriptor getfd (int targetfd) throws Error {
int fd = pidfd_getfd (handle, targetfd, 0);
if (fd == -1)
throw_pidfd_error (pid, errno);
return new FileDescriptor (fd);
}
private static int pidfd_open (uint pid, uint flags) {
return Linux.syscall (SysCall.pidfd_open, pid, flags);
}
private static int pidfd_getfd (int pidfd, int targetfd, uint flags) {
return Linux.syscall (SysCall.pidfd_getfd, pidfd, targetfd, flags);
}
[NoReturn]
private static void throw_pidfd_error (uint pid, int err) throws Error {
switch (err) {
case Posix.ESRCH:
throw new Error.PROCESS_NOT_FOUND ("Process not found");
case Posix.EPERM:
throw new Error.PERMISSION_DENIED ("Unable to use pidfd for pid %u: %s", pid, strerror (err));
default:
throw new Error.NOT_SUPPORTED ("Unable to use pidfd for pid %u: %s", pid, strerror (err));
}
}
}
namespace MemoryFileDescriptor {
public bool is_supported () {
return check_kernel_version (3, 17);
}
public static FileDescriptor from_bytes (string name, Bytes bytes) {
assert (is_supported ());
var fd = new FileDescriptor (memfd_create (name, 0));
unowned uint8[] data = bytes.get_data ();
ssize_t n = Posix.write (fd.handle, data, data.length);
assert (n == data.length);
return fd;
}
private int memfd_create (string name, uint flags) {
return Linux.syscall (SysCall.memfd_create, name, flags);
}
}
private void make_pty (out FileDescriptor read, out FileDescriptor write) throws Error {
#if HAVE_OPENPTY
int rfd = -1, wfd = -1;
+2 -3
View File
@@ -365,16 +365,14 @@ if have_local_backend
helper_backend_vala_args = [
base_vala_args,
gum_vala_args,
'--pkg=gio-unix-2.0',
'--pkg=posix',
]
helper_backend = static_library('frida-helper-backend', helper_backend_sources,
c_args: frida_component_cflags,
vala_args: [
helper_backend_vala_args,
'--vapidir=' + meson.current_source_dir() / 'linux',
'--pkg=frida-sysapi',
'--pkg=linux',
'--pkg=linux-system',
'--pkg=frida-gum-linux-1.0',
],
dependencies: [gio_dep, gio_unix_dep, gee_dep, gum_dep, base_dep] + helper_backend_extra_deps,
@@ -635,6 +633,7 @@ core = library('frida-core', core_sources,
base_vala_args,
gumjs_inspector_vala_args,
'--pkg=gmodule-2.0',
'--pkg=libsoup-3.0',
],
vala_gir: core_gir_name,
link_args: backend_libs_private,
+38 -50
View File
@@ -108,9 +108,9 @@ namespace Frida {
foreach (string spec_str in opts.specs) {
string name, version_spec_val;
int at = spec_str.last_index_of ("@");
if (at != -1) {
name = spec_str.substring (0, at);
version_spec_val = spec_str.substring (at + 1);
if (at > 0) {
name = spec_str[:at];
version_spec_val = spec_str[at + 1:];
} else {
name = spec_str;
version_spec_val = "latest";
@@ -120,9 +120,8 @@ namespace Frida {
install_progress (PREPARING_DEPENDENCIES, 0.05);
var wanted_deps_list = new Gee.ArrayList<PackageDependency> ();
foreach (var dep_entry in manifest.dependencies.all.values) {
foreach (var dep_entry in manifest.dependencies.all.values)
wanted_deps_list.add (dep_entry);
}
foreach (var e in specs.entries) {
string name = e.key;
string version_spec_val = e.value;
@@ -192,55 +191,36 @@ namespace Frida {
double physical_completion_start_fraction = dep_processing_start_fraction + dep_processing_span;
double physical_completion_span = 0.05;
install_progress (AWAITING_COMPLETION, physical_completion_start_fraction);
foreach (var promise in all_physical_installs.values)
yield promise.future.wait_async (cancellable);
install_progress (DEPENDENCIES_PROCESSED, physical_completion_start_fraction + physical_completion_span);
var finished_installs = new Gee.HashMap<string, PackageLockEntry> ();
install_progress (AWAITING_COMPLETION, physical_completion_start_fraction);
foreach (var entry in all_physical_installs.entries)
finished_installs[entry.key] = yield entry.value.future.wait_async (cancellable);
install_progress (DEPENDENCIES_PROCESSED, physical_completion_start_fraction + physical_completion_span);
var pkgs = new Gee.ArrayList<Package> ();
var new_manifest_dependencies = new PackageDependencies ();
foreach (var future_ple in initial_dep_link_futures) {
PackageLockEntry ple = yield future_ple.wait_async (cancellable);
PackageDependency? original_wanted_dep = null;
foreach (var wd in wanted_deps_list) {
if (wd == ple.toplevel_dep) {
original_wanted_dep = wd;
break;
}
}
if (original_wanted_dep != null) {
new_manifest_dependencies.add (new PackageDependency () {
name = ple.name,
version = original_wanted_dep.derive_version (ple.version),
role = original_wanted_dep.role,
});
}
if (ple.newly_installed)
pkgs.add (new Package (ple.name, ple.version, ple.description));
var original_dep = ple.toplevel_dep;
new_manifest_dependencies.add (new PackageDependency () {
name = ple.name,
version = original_dep.derive_version (ple.version),
role = original_dep.role,
});
}
manifest.dependencies = new_manifest_dependencies;
double finalizing_manifests_start_fraction = physical_completion_start_fraction + physical_completion_span;
install_progress (FINALIZING_MANIFESTS, finalizing_manifests_start_fraction);
yield write_back_manifests (manifest, finished_installs, pkg_json_file, lock_file, cancellable);
install_progress (FINALIZING_MANIFESTS, 0.95);
var pkgs = new Gee.ArrayList<Package> ();
foreach (var future_ple in initial_dep_link_futures) {
PackageLockEntry e = yield future_ple.wait_async (cancellable);
bool already_added = false;
foreach (var p in pkgs) {
if (p.name == e.name && p.version == e.version) {
already_added = true;
break;
}
}
if (!already_added)
pkgs.add (new Package (e.name, e.version, e.description));
}
install_progress (COMPLETE, 1.0);
return new PackageInstallResult (new PackageList (pkgs));
}
@@ -346,6 +326,7 @@ namespace Frida {
public string? license;
public PackageDependencies dependencies;
public PackageDependency toplevel_dep;
public bool newly_installed;
}
private async Manifest load_manifest (File pkg_json_file, File lock_file, Cancellable? cancellable) throws Error, IOError {
@@ -390,6 +371,11 @@ namespace Frida {
lock_r.read_member ("name");
pli.name = lock_r.get_string_value ();
lock_r.end_member ();
} else {
int last_start = path_key.last_index_of ("/node_modules/");
pli.name = (last_start != -1)
? path_key[last_start + 14:]
: path_key[13:];
}
lock_r.read_member ("version");
@@ -645,7 +631,8 @@ namespace Frida {
rpd_promise.resolve (rpd);
break;
}
} catch (Error e) { }
} catch (Error e) {
}
}
}
}
@@ -693,7 +680,8 @@ namespace Frida {
description = existing_ple.description,
license = existing_ple.license,
dependencies = existing_ple.dependencies,
toplevel_dep = toplevel_dep
toplevel_dep = toplevel_dep,
newly_installed = existing_ple.newly_installed
});
return;
}
@@ -724,9 +712,8 @@ namespace Frida {
File sub_deps_parent_node_modules_dir = target_dir.get_child ("node_modules");
PackageDependencies dependencies_to_recurse = rpd.dependencies;
if (!dependencies_to_recurse.all.is_empty) {
if (!dependencies_to_recurse.all.is_empty)
FS.mkdirp (sub_deps_parent_node_modules_dir, cancellable);
}
foreach (PackageDependency d in dependencies_to_recurse.all.values) {
bool install_this_sub_dep = d.role == RUNTIME || d.role == OPTIONAL;
@@ -773,7 +760,8 @@ namespace Frida {
description = rpd.description,
license = rpd.license,
dependencies = rpd.dependencies,
toplevel_dep = toplevel_dep
toplevel_dep = toplevel_dep,
newly_installed = !already_correctly_installed
});
} catch (GLib.Error e) {
@@ -1628,10 +1616,10 @@ namespace Frida {
string core_part_of_spec = stripped_spec;
int plus_idx = core_part_of_spec.index_of_char ('+');
if (plus_idx != -1)
core_part_of_spec = core_part_of_spec.substring (0, plus_idx);
core_part_of_spec = core_part_of_spec[:plus_idx];
int dash_idx = core_part_of_spec.index_of_char ('-');
if (dash_idx != -1)
core_part_of_spec = core_part_of_spec.substring (0, dash_idx);
core_part_of_spec = core_part_of_spec[:dash_idx];
return count_char (core_part_of_spec, '.') == 2;
} catch (Error e) {
@@ -1953,11 +1941,11 @@ namespace Frida {
string size_field = header.read_fixed_string (124, 12).split (" ")[0];
uint64 file_size = 0;
if (!uint64.try_parse (size_field, out file_size, null, 8))
throw new Error.PROTOCOL ("Invalid tarball size (file '%s' corrupt)", safe_entry);
throw new Error.PROTOCOL ("Invalid tarball size (file '%s' corrupt)", name);
var typeflag = (char) header.read_uint8 (156);
if (typeflag == '0' || typeflag == '\0') {
if ((typeflag == '0' || typeflag == '\0') && safe_entry != "") {
current_file = root.get_child (safe_entry);
FS.mkdirp (current_file.get_parent (), cancellable);
try {
@@ -1983,9 +1971,9 @@ namespace Frida {
private static string sanitize_entry (string name, File root) throws Error {
int slash = name.index_of ("/");
string entry = (slash == -1) ? name : name[slash + 1:];
if (entry.length == 0)
throw new Error.PROTOCOL ("Empty tar entry name: %s", name);
string entry = (slash == -1) ? "" : name[slash + 1:];
if (entry == "")
return entry;
entry = entry.replace ("/", Path.DIR_SEPARATOR_S);
+1 -1
View File
@@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/frida/frida-gum.git
revision = 17.2.0
revision = 17.2.3
depth = 1
[provide]
+9 -7
View File
@@ -18,7 +18,6 @@ if platform.system() == "Windows":
FRIDA_OS_TO_GO_OS = {
"android": "linux", # XXX: Work around lack of support for -buildmode=c-archive
"macos": "darwin",
}
@@ -53,6 +52,7 @@ def main(argv: List[str]):
go = Path(args.pop(0))
host_os = args.pop(0)
host_abi = args.pop(0)
shlib_suffix = args.pop(0)
cc_id = args.pop(0)
cc_cmd_array = pop_cmd_array_arg(args)
ar_cmd_array = pop_cmd_array_arg(args)
@@ -64,6 +64,7 @@ def main(argv: List[str]):
go,
host_os,
host_abi,
shlib_suffix,
cc_id,
cc_cmd_array,
ar_cmd_array,
@@ -71,7 +72,7 @@ def main(argv: List[str]):
ranlib_cmd_array,
)
print("ok")
print(base64.b64encode(json.dumps(config).encode("utf-8")).decode("ascii"))
print(config["mode"], base64.b64encode(json.dumps(config).encode("utf-8")).decode("ascii"))
except Exception as e:
print("error")
print(str(e).replace("\n", "\\n"))
@@ -95,6 +96,7 @@ def detect_config(
go: Path,
host_os: str,
host_abi: str,
shlib_suffix: str,
cc_id: str,
cc_cmd_array: List[str],
ar_cmd_array: Optional[List[str]],
@@ -141,10 +143,6 @@ def detect_config(
extra_go_args.append("-ldflags=-extldflags=-mmacosx-version-min=11.0")
env["MACOSX_DEPLOYMENT_TARGET"] = "11.0"
if host_os == "android":
# XXX: Avoid socklen_t compatibility issue caused by us using GOOS=linux for Android
extra_go_args += ["-tags", "netgo"]
def run(*args):
return subprocess.run(
args,
@@ -165,14 +163,18 @@ def detect_config(
env["GOOS"] = goos
env["GOARCH"] = goarch
mode = "c-shared" if host_os == "android" else "c-archive"
try:
run(go, "build", "-buildmode=c-archive", "-o", "cgotest.a", "-buildvcs=false")
run(go, "build", f"-buildmode={mode}", "-o", "cgotest.a", "-buildvcs=false")
except subprocess.CalledProcessError as e:
raise BuildError(e.output.strip())
config = {
"mode": mode,
"os": host_os,
"abi": host_abi,
"shlib_suffix": shlib_suffix,
"extra_go_args": extra_go_args,
"env": env,
"ar": ar_cmd_array,
+2 -1
View File
@@ -23,6 +23,7 @@ def main(argv):
input_entitlements_path = args.pop(0) if args else None
else:
input_entitlements_path = None
flags = set(args.pop(0).split("|") if args else [])
is_apple_os = host_os in {"macos", "ios", "watchos", "tvos"}
@@ -62,7 +63,7 @@ def main(argv):
codesign_args += ["--entitlements", input_entitlements_path]
subprocess.run(codesign + codesign_args + [intermediate_path], **run_kwargs)
if host_os == "android":
if host_os == "android" and "elf-cleaner:off" not in flags:
api_level = 19 if host_abi in {"x86", "arm"} else 21
subprocess.run(termux_elf_cleaner + ["--api-level", str(api_level), "--quiet", intermediate_path],
**run_kwargs)