const std = @import("std"); pub fn gum_stalker(b: *std.Build, opts: struct { target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, }) *std.Build.Step.Compile { const dep = b.dependency("frida-gum", .{}); const capstone_dep = b.dependency("capstone", .{}); // stub gumenumtypes.h — normally generated by gnome.mkenums const wf = b.addWriteFiles(); _ = wf.add("gum/gumenumtypes.h", \\#ifndef __GUM_ENUM_TYPES_H__ \\#define __GUM_ENUM_TYPES_H__ \\#include \\G_BEGIN_DECLS \\GType gum_elf_type_get_type (void) G_GNUC_CONST; \\#define GUM_TYPE_ELF_TYPE (gum_elf_type_get_type ()) \\GType gum_elf_osabi_get_type (void) G_GNUC_CONST; \\#define GUM_TYPE_ELF_OSABI (gum_elf_osabi_get_type ()) \\GType gum_elf_machine_get_type (void) G_GNUC_CONST; \\#define GUM_TYPE_ELF_MACHINE (gum_elf_machine_get_type ()) \\GType gum_elf_source_mode_get_type (void) G_GNUC_CONST; \\#define GUM_TYPE_ELF_SOURCE_MODE (gum_elf_source_mode_get_type ()) \\G_END_DECLS \\#endif ); // C-only module (translate-c can't handle GLib's _Pragma macros) const c_mod = b.createModule(.{ .target = opts.target, // .optimize = opts.optimize, .optimize = .Debug, .link_libc = true, }); // include paths for C source compilation c_mod.addIncludePath(dep.path("")); c_mod.addIncludePath(dep.path("gum")); c_mod.addIncludePath(dep.path("gum/arch-x86")); c_mod.addIncludePath(dep.path("gum/arch-arm")); c_mod.addIncludePath(dep.path("gum/arch-arm64")); c_mod.addIncludePath(dep.path("gum/arch-mips")); c_mod.addIncludePath(dep.path("gum/backend-linux/include")); c_mod.addIncludePath(dep.path("gum/backend-elf")); c_mod.addIncludePath(dep.path("gum/backend-posix")); c_mod.addIncludePath(dep.path("libs")); c_mod.addIncludePath(dep.path("libs/gum/heap")); c_mod.addIncludePath(dep.path("libs/gum/prof")); c_mod.addIncludePath(capstone_dep.path("include/capstone")); c_mod.addIncludePath(capstone_dep.path("include")); c_mod.addIncludePath(wf.getDirectory()); // system libraries c_mod.linkSystemLibrary("glib-2.0", .{}); c_mod.linkSystemLibrary("gobject-2.0", .{}); // config defines — replaces meson's config.h + add_project_arguments // platform / arch c_mod.addCMacro("HAVE_LINUX", "1"); c_mod.addCMacro("HAVE_I386", "1"); c_mod.addCMacro("HAVE_ELF", "1"); c_mod.addCMacro("HAVE_GLIBC", "1"); // frida-gum options c_mod.addCMacro("GUM_STATIC", "1"); c_mod.addCMacro("GUM_USE_SYSTEM_ALLOC", "1"); c_mod.addCMacro("FRIDA_VERSION", "\"16.x\""); // compiler feature detection c_mod.addCMacro("HAVE_SYNC_LOCK", "1"); c_mod.addCMacro("HAVE_CLEAR_CACHE", "1"); c_mod.addCMacro("HAVE_CLTZ", "1"); c_mod.addCMacro("HAVE_POPCOUNT", "1"); c_mod.addCMacro("HAVE_PACK_PRAGMA", "1"); // system headers c_mod.addCMacro("HAVE_ELF_H", "1"); c_mod.addCMacro("HAVE_LINK_H", "1"); c_mod.addCMacro("HAVE_STDINT_H", "1"); c_mod.addCMacro("HAVE_SYS_AUXV_H", "1"); c_mod.addCMacro("HAVE_ASM_PRCTL_H", "1"); c_mod.addCMacro("HAVE_SYS_USER_H", "1"); // system functions / types c_mod.addCMacro("HAVE_MADVISE", "1"); c_mod.addCMacro("HAVE_LONG_DOUBLE", "1"); c_mod.addCMacro("HAVE_LONG_LONG_INT", "1"); c_mod.addCMacro("HAVE_UNSIGNED_LONG_LONG_INT", "1"); c_mod.addCMacro("HAVE_PTHREAD_ATTR_GETSTACK", "1"); c_mod.addCMacro("HAVE_PTHREAD_SETNAME_NP", "1"); // NOTE: HAVE_FRIDA_GLIB omitted — system GLib lacks frida's patches // capstone compat (frida-gum uses capstone 5 type names) c_mod.addCMacro("CAPSTONE_ARM_COMPAT_HEADER", "1"); c_mod.addCMacro("CAPSTONE_AARCH64_COMPAT_HEADER", "1"); c_mod.addCMacro("CAPSTONE_SYSTEMZ_COMPAT_HEADER", "1"); // GLib / compiler flags c_mod.addCMacro("_GNU_SOURCE", "1"); c_mod.addCMacro("G_LOG_DOMAIN", "\"Frida\""); c_mod.addCMacro("GLIB_VERSION_MIN_REQUIRED", "GLIB_VERSION_2_56"); c_mod.addCMacro("G_DISABLE_DEPRECATED", ""); // core + arch writers (unconditional in upstream meson) c_mod.addCSourceFiles(.{ .root = dep.path("gum"), .files = &.{ "gum.c", "gumapiresolver.c", "gumbacktracer.c", "gumcloak.c", "gumcodeallocator.c", "gumcodesegment.c", // gumdarwingrafter.c and gumdarwinmodule.c omitted (darwin only) "gumelfmodule.c", "gumeventsink.c", "gumexceptor.c", "gumheapapi.c", "guminterceptor.c", "guminvocationcontext.c", "guminvocationlistener.c", "gumkernel.c", "gumleb.c", "gumlibc.c", "gummemory.c", "gummemorymap.c", "gummetalarray.c", "gummetalhash.c", "gummoduleapiresolver.c", "gummodulemap.c", "gumprintf.c", "gumprocess.c", "gumthreadregistry.c", "gummodule.c", "gummodulefacade.c", "gummoduleregistry.c", "gumreturnaddress.c", "gumspinlock.c", "gumstalker.c", "gumswiftapiresolver.c", // arch writers (x86 only — arm/arm64/mips need frida's capstone fork) "arch-x86/gumx86writer.c", "arch-x86/gumx86relocator.c", "arch-x86/gumx86reader.c", // x86 backend "arch-x86/gumx86backtracer.c", "backend-x86/gumcpucontext-x86.c", "backend-x86/gumprocess-x86.c", "backend-x86/guminterceptor-x86.c", "backend-x86/gumstalker-x86.c", // linux + posix backend "backend-linux/gummemory-linux.c", "backend-posix/gummemory-posix.c", "backend-linux/gumprocess-linux.c", "backend-linux/gumthreadregistry-linux.c", "backend-linux/gummoduleregistry-linux.c", "backend-linux/gummodule-linux.c", "backend-posix/gumtls-posix.c", "backend-posix/gumexceptor-posix.c", "backend-posix/gummemoryaccessmonitor-posix.c", // elf backend "backend-elf/gummodule-elf.c", "backend-elf/gummoduleregistry-elf.c", }, }); // x86 assembly glue c_mod.addAssemblyFile(dep.path("gum/backend-x86/gumstalker-x86-glue.S")); const stalker_lib = b.addLibrary(.{ .name = "gumstalker", .linkage = .static, .root_module = c_mod, }); stalker_lib.installHeadersDirectory(capstone_dep.path("include/capstone"), "capstone", .{}); stalker_lib.installHeader(capstone_dep.path("include/platform.h"), "capstone/platform.h"); return stalker_lib; }