From e658654b3ed1389fdfb1ce6097ebe7329e3bee27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Wed, 12 Mar 2025 08:22:29 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20Merge=20PR=20#72177=20Sync=20fri?= =?UTF-8?q?da-gum=20typings=20with=20Frida=2016.7.0=20by=20@oleavr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- types/frida-gum/frida-gum-tests.ts | 30 ++++++ types/frida-gum/index.d.ts | 155 +++++++++++++++++++++++++++++ types/frida-gum/package.json | 2 +- 3 files changed, 186 insertions(+), 1 deletion(-) diff --git a/types/frida-gum/frida-gum-tests.ts b/types/frida-gum/frida-gum-tests.ts index 2003325e4f9298..3bb9eb4d3dfe8e 100644 --- a/types/frida-gum/frida-gum-tests.ts +++ b/types/frida-gum/frida-gum-tests.ts @@ -424,3 +424,33 @@ Process.enumerateThreads().forEach(t => { Process.enumerateThreads().forEach(t => { t.unsetHardwareWatchpoint(0); }); + +const threadObserver = Process.attachThreadObserver({ + onAdded(thread) { + // $ExpectType StableThreadDetails + thread; + }, + onRemoved(thread) { + // $ExpectType StableThreadDetails + thread; + }, + onRenamed(thread, previousName) { + // $ExpectType StableThreadDetails + thread; + // $ExpectType string | null + previousName; + }, +}); +threadObserver.detach(); + +const moduleObserver = Process.attachModuleObserver({ + onAdded(module) { + // $ExpectType Module + module; + }, + onRemoved(module) { + // $ExpectType Module + module; + }, +}); +moduleObserver.detach(); diff --git a/types/frida-gum/index.d.ts b/types/frida-gum/index.d.ts index 5a41553a3456cf..f2fa7ad3d9a0ba 100644 --- a/types/frida-gum/index.d.ts +++ b/types/frida-gum/index.d.ts @@ -371,6 +371,15 @@ declare namespace Process { */ function enumerateThreads(): ThreadDetails[]; + /** + * Starts observing threads, calling the provided callbacks as threads are + * added, removed, and renamed. Calls `onAdded` with all existing threads + * right away, so the initial state vs. updates can be managed easily + * without worrying about race conditions. + * All callbacks are optional, but at least one of them must be provided. + */ + function attachThreadObserver(callbacks: ThreadObserverCallbacks): ThreadObserver; + /** * Looks up a module by address. Returns null if not found. */ @@ -396,6 +405,15 @@ declare namespace Process { */ function enumerateModules(): Module[]; + /** + * Starts observing modules, calling the provided callbacks as modules are + * added and removed. Calls `onAdded` with all existing modules right away, + * so the initial state vs. updates can be managed easily without worrying + * about race conditions. + * Both callbacks are optional, but at least one of them must be provided. + */ + function attachModuleObserver(callbacks: ModuleObserverCallbacks): ModuleObserver; + /** * Looks up a memory range by address. Returns null if not found. */ @@ -576,6 +594,51 @@ declare class Module { static getExportByName(moduleName: string | null, exportName: string): NativePointer; } +declare class ThreadObserver { + /** + * Detaches observer previously attached through `Process#attachThreadObserver()`. + */ + detach(): void; +} + +interface ThreadObserverCallbacks { + /** + * Called synchronously when a Thread has been added. + */ + onAdded?(thread: StableThreadDetails): void; + + /** + * Called synchronously when a Thread has been removed. + */ + onRemoved?(thread: StableThreadDetails): void; + + /** + * Called synchronously when a Thread has been renamed. + */ + onRenamed?(thread: StableThreadDetails, previousName: string | null): void; +} + +type StableThreadDetails = Omit; + +declare class ModuleObserver { + /** + * Detaches observer previously attached through `Process#attachModuleObserver()`. + */ + detach(): void; +} + +interface ModuleObserverCallbacks { + /** + * Called synchronously when a Module has been added. + */ + onAdded?(module: Module): void; + + /** + * Called synchronously when a Module has been removed. + */ + onRemoved?(module: Module): void; +} + declare class ModuleMap { /** * Creates a new module map optimized for determining which module a given memory address belongs to, if any. @@ -829,6 +892,11 @@ interface MemoryAccessCallbacks { } interface MemoryAccessDetails { + /** + * The ID of the thread performing the access. + */ + threadId: ThreadId; + /** * The kind of operation that triggered the access. */ @@ -865,6 +933,11 @@ interface MemoryAccessDetails { * Overall number of pages that were initially monitored. */ pagesTotal: number; + + /** + * CPU registers. You may also update register values by assigning to these keys. + */ + context: CpuContext; } declare namespace Thread { @@ -969,6 +1042,11 @@ interface ThreadDetails { */ context: CpuContext; + /** + * Where the thread started its execution, if applicable and available. + */ + entrypoint?: ThreadEntrypoint; + /** * Set a hardware breakpoint. * @@ -1007,6 +1085,18 @@ interface ThreadDetails { unsetHardwareWatchpoint(id: HardwareWatchpointId): void; } +interface ThreadEntrypoint { + /** + * The thread's start routine. + */ + routine: NativePointer; + + /** + * Parameter passed to `routine`, if available. + */ + parameter?: NativePointer; +} + interface KernelModuleDetails { /** * Canonical module name. @@ -1744,6 +1834,7 @@ declare class NativePointer { writeUtf8String(value: string): NativePointer; writeUtf16String(value: string): NativePointer; writeAnsiString(value: string): NativePointer; + writeVolatile(value: ArrayBuffer | number[]): NativePointer; } type PointerAuthenticationKey = "ia" | "ib" | "da" | "db"; @@ -4549,6 +4640,70 @@ declare namespace Cloak { function hasFileDescriptor(fd: number): boolean; } +declare class Profiler { + /** + * Starts instrumenting the specified function using the specified sampler. + */ + instrument(functionAddress: NativePointerValue, sampler: Sampler, callbacks: ProfilerInstrumentCallbacks): void; + + /** + * Generates an XML report from the live profiler state. May be called at + * any point, and as many times as desired. + */ + generateReport(): string; +} + +interface ProfilerInstrumentCallbacks { + /** + * Called synchronously when a new worst-case has been discovered, and a + * description should be captured from the argument list and/or other + * relevant state. + */ + describe?(this: InvocationContext, args: InvocationArguments): string; +} + +declare abstract class Sampler { + /** + * Retrieves a new sample. What it denotes depends on the specific sampler. + */ + sample(): bigint; +} + +/** + * Sampler that measures CPU cycles, e.g. using the RDTSC instruction on x86. + */ +declare class CycleSampler extends Sampler {} + +/** + * Sampler that measures CPU cycles only spent by the current thread, e.g. + * using QueryThreadCycleTime() on Windows. + */ +declare class BusyCycleSampler extends Sampler {} + +/** + * Sampler that measures passage of time. + */ +declare class WallClockSampler extends Sampler {} + +/** + * Sampler that measures time spent in user-space. + */ +declare class UserTimeSampler extends Sampler { + constructor(threadId?: ThreadId); +} + +/** + * Sampler that counts the number of calls to malloc(), calloc(), and realloc(). + */ +declare class MallocCountSampler extends Sampler {} + +/** + * Sampler that counts the number of calls to functions of your choosing. + */ +declare class CallCountSampler extends Sampler { + constructor(functions: NativePointerValue[]); +} + declare namespace ObjC { // tslint:disable:no-unnecessary-qualifier diff --git a/types/frida-gum/package.json b/types/frida-gum/package.json index 30176a05d36bcc..88dccab16bc89d 100644 --- a/types/frida-gum/package.json +++ b/types/frida-gum/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@types/frida-gum", - "version": "18.7.9999", + "version": "18.8.9999", "nonNpm": true, "nonNpmDescription": "frida-gum", "projects": [