frida 16.7.13 → 16.7.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -10
- package/build/BSDmakefile +6 -0
- package/build/Makefile +10 -0
- package/build/src/frida.d.ts +364 -0
- package/build/src/frida.js +962 -0
- package/build/src/frida_binding.d.ts +938 -0
- package/meson.build +34 -67
- package/package.json +30 -20
- package/scripts/fetch-abi-bits.py +15 -65
- package/scripts/install.js +5 -4
- package/src/addon.def +3 -0
- package/src/addon.symbols +2 -1
- package/src/addon.version +4 -0
- package/src/frida_bindgen/__init__.py +0 -0
- package/src/frida_bindgen/__main__.py +4 -0
- package/src/frida_bindgen/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/frida_bindgen/__pycache__/__main__.cpython-312.pyc +0 -0
- package/src/frida_bindgen/__pycache__/cli.cpython-312.pyc +0 -0
- package/src/frida_bindgen/__pycache__/codegen.cpython-312.pyc +0 -0
- package/src/frida_bindgen/__pycache__/customization.cpython-312.pyc +0 -0
- package/src/frida_bindgen/__pycache__/loader.cpython-312.pyc +0 -0
- package/src/frida_bindgen/__pycache__/model.cpython-312.pyc +0 -0
- package/src/frida_bindgen/assets/codegen_helpers.c +1970 -0
- package/src/frida_bindgen/assets/codegen_helpers.ts +100 -0
- package/src/frida_bindgen/assets/codegen_prototypes.h +78 -0
- package/src/frida_bindgen/assets/codegen_types.h +57 -0
- package/src/frida_bindgen/assets/customization_facade.exports +13 -0
- package/src/frida_bindgen/assets/customization_facade.ts +157 -0
- package/src/frida_bindgen/assets/customization_helpers.imports +2 -0
- package/src/frida_bindgen/assets/customization_helpers.ts +396 -0
- package/src/frida_bindgen/cli.py +96 -0
- package/src/frida_bindgen/codegen.py +2233 -0
- package/src/frida_bindgen/customization.py +924 -0
- package/src/frida_bindgen/loader.py +60 -0
- package/src/frida_bindgen/model.py +1357 -0
- package/src/meson.build +92 -27
- package/{lib/build.py → src/tsc.py} +12 -12
- package/src/win_delay_load_hook.c +56 -0
- package/subprojects/frida-core.wrap +1 -1
- package/test/data/index.ts +2 -2
- package/test/device.ts +1 -2
- package/test/device_manager.ts +1 -2
- package/test/labrat.ts +2 -2
- package/test/script.ts +12 -12
- package/test/session.ts +3 -3
- package/tsconfig.json +6 -11
- package/dist/application.d.ts +0 -81
- package/dist/application.js +0 -2
- package/dist/authentication.d.ts +0 -3
- package/dist/authentication.js +0 -2
- package/dist/bus.d.ts +0 -16
- package/dist/bus.js +0 -23
- package/dist/cancellable.d.ts +0 -15
- package/dist/cancellable.js +0 -41
- package/dist/child.d.ts +0 -16
- package/dist/child.js +0 -9
- package/dist/crash.d.ts +0 -10
- package/dist/crash.js +0 -2
- package/dist/device.d.ts +0 -156
- package/dist/device.js +0 -188
- package/dist/device_manager.d.ts +0 -25
- package/dist/device_manager.js +0 -42
- package/dist/endpoint_parameters.d.ts +0 -26
- package/dist/endpoint_parameters.js +0 -24
- package/dist/icon.d.ts +0 -14
- package/dist/icon.js +0 -2
- package/dist/index.d.ts +0 -161
- package/dist/index.js +0 -170
- package/dist/iostream.d.ts +0 -13
- package/dist/iostream.js +0 -73
- package/dist/native.d.ts +0 -1
- package/dist/native.js +0 -11
- package/dist/portal_membership.d.ts +0 -6
- package/dist/portal_membership.js +0 -12
- package/dist/portal_service.d.ts +0 -48
- package/dist/portal_service.js +0 -52
- package/dist/process.d.ts +0 -47
- package/dist/process.js +0 -2
- package/dist/relay.d.ts +0 -22
- package/dist/relay.js +0 -32
- package/dist/script.d.ts +0 -70
- package/dist/script.js +0 -266
- package/dist/service.d.ts +0 -16
- package/dist/service.js +0 -26
- package/dist/session.d.ts +0 -45
- package/dist/session.js +0 -73
- package/dist/signals.d.ts +0 -20
- package/dist/signals.js +0 -40
- package/dist/socket_address.d.ts +0 -25
- package/dist/socket_address.js +0 -2
- package/dist/spawn.d.ts +0 -4
- package/dist/spawn.js +0 -2
- package/dist/system_parameters.d.ts +0 -84
- package/dist/system_parameters.js +0 -2
- package/lib/application.ts +0 -98
- package/lib/authentication.ts +0 -3
- package/lib/bus.ts +0 -30
- package/lib/cancellable.ts +0 -48
- package/lib/child.ts +0 -15
- package/lib/crash.ts +0 -11
- package/lib/device.ts +0 -331
- package/lib/device_manager.ts +0 -69
- package/lib/endpoint_parameters.ts +0 -56
- package/lib/icon.ts +0 -15
- package/lib/index.ts +0 -316
- package/lib/iostream.ts +0 -78
- package/lib/meson.build +0 -53
- package/lib/native.ts +0 -9
- package/lib/portal_membership.ts +0 -10
- package/lib/portal_service.ts +0 -105
- package/lib/process.ts +0 -57
- package/lib/relay.ts +0 -44
- package/lib/script.ts +0 -361
- package/lib/service.ts +0 -34
- package/lib/session.ts +0 -113
- package/lib/signals.ts +0 -45
- package/lib/socket_address.ts +0 -35
- package/lib/spawn.ts +0 -4
- package/lib/system_parameters.ts +0 -103
- package/meson.options +0 -11
- package/src/addon.cc +0 -78
- package/src/application.cc +0 -148
- package/src/application.h +0 -31
- package/src/authentication.cc +0 -174
- package/src/authentication.h +0 -24
- package/src/bus.cc +0 -167
- package/src/bus.h +0 -33
- package/src/cancellable.cc +0 -117
- package/src/cancellable.h +0 -31
- package/src/child.cc +0 -150
- package/src/child.h +0 -32
- package/src/crash.cc +0 -122
- package/src/crash.h +0 -30
- package/src/device.cc +0 -1350
- package/src/device.h +0 -56
- package/src/device_manager.cc +0 -362
- package/src/device_manager.h +0 -35
- package/src/endpoint_parameters.cc +0 -171
- package/src/endpoint_parameters.h +0 -28
- package/src/glib_context.cc +0 -62
- package/src/glib_context.h +0 -29
- package/src/glib_object.cc +0 -25
- package/src/glib_object.h +0 -37
- package/src/iostream.cc +0 -243
- package/src/iostream.h +0 -30
- package/src/operation.h +0 -94
- package/src/portal_membership.cc +0 -100
- package/src/portal_membership.h +0 -26
- package/src/portal_service.cc +0 -401
- package/src/portal_service.h +0 -40
- package/src/process.cc +0 -135
- package/src/process.h +0 -30
- package/src/relay.cc +0 -139
- package/src/relay.h +0 -31
- package/src/runtime.cc +0 -568
- package/src/runtime.h +0 -69
- package/src/script.cc +0 -301
- package/src/script.h +0 -36
- package/src/service.cc +0 -224
- package/src/service.h +0 -36
- package/src/session.cc +0 -860
- package/src/session.h +0 -42
- package/src/signals.cc +0 -334
- package/src/signals.h +0 -47
- package/src/spawn.cc +0 -95
- package/src/spawn.h +0 -27
- package/src/usage_monitor.h +0 -117
- package/src/uv_context.cc +0 -118
- package/src/uv_context.h +0 -40
- package/src/win_delay_load_hook.cc +0 -63
- package/subprojects/nan.wrap +0 -9
- package/subprojects/packagefiles/nan.patch +0 -13
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
const STANDARD_SPAWN_OPTION_NAMES = new Set<keyof SpawnOptions>([
|
|
2
|
+
"argv",
|
|
3
|
+
"envp",
|
|
4
|
+
"env",
|
|
5
|
+
"cwd",
|
|
6
|
+
"stdio",
|
|
7
|
+
]);
|
|
8
|
+
|
|
9
|
+
interface LogMessage {
|
|
10
|
+
type: "log";
|
|
11
|
+
level: LogLevel;
|
|
12
|
+
payload: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
class ScriptServices implements RpcController {
|
|
16
|
+
exportsProxy = new ScriptExportsProxy(this);
|
|
17
|
+
|
|
18
|
+
#script: Script;
|
|
19
|
+
#pendingRequests = new Map<number, (error: Error | null, result?: any) => void>();
|
|
20
|
+
#nextRequestId = 1;
|
|
21
|
+
|
|
22
|
+
constructor(script: Script) {
|
|
23
|
+
this.#script = script;
|
|
24
|
+
process.nextTick(() => {
|
|
25
|
+
script.message.connect(() => {});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
handleMessageIntercept = (message: Message, data: Buffer | null): boolean => {
|
|
30
|
+
if (message.type === MessageType.Send && isRpcSendMessage(message)) {
|
|
31
|
+
const [ , id, operation, ...params ] = message.payload;
|
|
32
|
+
this.#onRpcMessage(id, operation, params, data);
|
|
33
|
+
return false;
|
|
34
|
+
} else if (isLogMessage(message)) {
|
|
35
|
+
const opaqueMessage: any = message;
|
|
36
|
+
const logMessage: LogMessage = opaqueMessage;
|
|
37
|
+
this.#script.logHandler(logMessage.level, logMessage.payload);
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return true;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
request(operation: string, params: any[], data: Buffer | null, cancellable: Cancellable | null = null): Promise<any> {
|
|
45
|
+
return new Promise((resolve, reject) => {
|
|
46
|
+
const id = this.#nextRequestId++;
|
|
47
|
+
|
|
48
|
+
const complete = (error: Error | null, result?: any): void => {
|
|
49
|
+
if (cancellable !== null) {
|
|
50
|
+
cancellable.cancelled.disconnect(onOperationCancelled);
|
|
51
|
+
}
|
|
52
|
+
this.#script.destroyed.disconnect(onScriptDestroyed);
|
|
53
|
+
|
|
54
|
+
this.#pendingRequests.delete(id);
|
|
55
|
+
|
|
56
|
+
if (error === null) {
|
|
57
|
+
resolve(result);
|
|
58
|
+
} else {
|
|
59
|
+
reject(error);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
function onScriptDestroyed(): void {
|
|
64
|
+
complete(new Error("Script is destroyed"));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function onOperationCancelled(): void {
|
|
68
|
+
complete(new Error("Operation was cancelled"));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
this.#pendingRequests.set(id, complete);
|
|
72
|
+
|
|
73
|
+
this.#script.post(["frida:rpc", id, operation, ...params], data);
|
|
74
|
+
this.#script.destroyed.connect(onScriptDestroyed);
|
|
75
|
+
if (cancellable !== null) {
|
|
76
|
+
cancellable.cancelled.connect(onOperationCancelled);
|
|
77
|
+
if (cancellable.isCancelled) {
|
|
78
|
+
onOperationCancelled();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (this.#script.isDestroyed) {
|
|
83
|
+
onScriptDestroyed();
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
#onRpcMessage(id: number, operation: RpcOperation, params: any[], data: Buffer | null) {
|
|
89
|
+
if (operation === RpcOperation.Ok || operation === RpcOperation.Error) {
|
|
90
|
+
const callback = this.#pendingRequests.get(id);
|
|
91
|
+
if (callback === undefined) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let value = null;
|
|
96
|
+
let error = null;
|
|
97
|
+
if (operation === RpcOperation.Ok) {
|
|
98
|
+
if (data !== null) {
|
|
99
|
+
value = (params.length > 1) ? [params[1], data] : data;
|
|
100
|
+
} else {
|
|
101
|
+
value = params[0];
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
const [message, name, stack, rawErr] = params;
|
|
105
|
+
error = new Error(message);
|
|
106
|
+
error.name = name;
|
|
107
|
+
error.stack = stack;
|
|
108
|
+
Object.assign(error, rawErr);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
callback(error, value);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
class ScriptExportsProxy implements ScriptExports {
|
|
117
|
+
[name: string]: (...args: any[]) => Promise<any>;
|
|
118
|
+
|
|
119
|
+
constructor(rpcController: RpcController) {
|
|
120
|
+
return new Proxy(this, {
|
|
121
|
+
has(target, property) {
|
|
122
|
+
return !isReservedMethodName(property);
|
|
123
|
+
},
|
|
124
|
+
get(target, property, receiver) {
|
|
125
|
+
if (typeof property === "symbol") {
|
|
126
|
+
if (property === inspect.custom) {
|
|
127
|
+
return inspectProxy;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (property in target) {
|
|
134
|
+
return target[property];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (isReservedMethodName(property)) {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return (...args: any[]): Promise<any> => {
|
|
142
|
+
let cancellable: Cancellable | null = null;
|
|
143
|
+
if (args[args.length - 1] instanceof Cancellable) {
|
|
144
|
+
cancellable = args.pop();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let data: Buffer | null = null;
|
|
148
|
+
if (Buffer.isBuffer(args[args.length - 1])) {
|
|
149
|
+
data = args.pop();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return rpcController.request("call", [property, args], data, cancellable);
|
|
153
|
+
};
|
|
154
|
+
},
|
|
155
|
+
set(target, property, value, receiver) {
|
|
156
|
+
if (typeof property === "symbol") {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
target[property] = value;
|
|
160
|
+
return true;
|
|
161
|
+
},
|
|
162
|
+
ownKeys(target) {
|
|
163
|
+
return Object.getOwnPropertyNames(target);
|
|
164
|
+
},
|
|
165
|
+
getOwnPropertyDescriptor(target, property) {
|
|
166
|
+
if (property in target) {
|
|
167
|
+
return Object.getOwnPropertyDescriptor(target, property);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (isReservedMethodName(property)) {
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
writable: true,
|
|
176
|
+
configurable: true,
|
|
177
|
+
enumerable: true
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function inspectProxy() {
|
|
185
|
+
return "ScriptExportsProxy {}";
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
interface RpcController {
|
|
189
|
+
request(operation: string, params: any[], data: ArrayBuffer | null, cancellable: Cancellable | null): Promise<any>;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
enum RpcOperation {
|
|
193
|
+
Ok = "ok",
|
|
194
|
+
Error = "error"
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function isInternalMessage(message: Message): boolean {
|
|
198
|
+
return isRpcMessage(message) || isLogMessage(message);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function isRpcMessage(message: Message): boolean {
|
|
202
|
+
return message.type === MessageType.Send && isRpcSendMessage(message);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function isRpcSendMessage(message: SendMessage): boolean {
|
|
206
|
+
const payload = message.payload;
|
|
207
|
+
if (!Array.isArray(payload)) {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return payload[0] === "frida:rpc";
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function isLogMessage(message: Message): boolean {
|
|
215
|
+
return message.type as string === "log";
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function log(level: LogLevel, text: string): void {
|
|
219
|
+
switch (level) {
|
|
220
|
+
case LogLevel.Info:
|
|
221
|
+
console.log(text);
|
|
222
|
+
break;
|
|
223
|
+
case LogLevel.Warning:
|
|
224
|
+
console.warn(text);
|
|
225
|
+
break;
|
|
226
|
+
case LogLevel.Error:
|
|
227
|
+
console.error(text);
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const reservedMethodNames = new Set<string>([
|
|
233
|
+
"then",
|
|
234
|
+
"catch",
|
|
235
|
+
"finally",
|
|
236
|
+
]);
|
|
237
|
+
|
|
238
|
+
function isReservedMethodName(name: string | number | symbol): boolean {
|
|
239
|
+
return reservedMethodNames.has(name.toString());
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const IO_PRIORITY_DEFAULT = 0;
|
|
243
|
+
|
|
244
|
+
class IOStreamAdapter extends Duplex {
|
|
245
|
+
#impl: IOStream;
|
|
246
|
+
#input: InputStream;
|
|
247
|
+
#output: OutputStream;
|
|
248
|
+
#pending = new Set<Promise<void>>();
|
|
249
|
+
|
|
250
|
+
#cancellable = new Cancellable();
|
|
251
|
+
|
|
252
|
+
constructor(impl: IOStream) {
|
|
253
|
+
super({});
|
|
254
|
+
|
|
255
|
+
this.#impl = impl;
|
|
256
|
+
this.#input = impl.inputStream;
|
|
257
|
+
this.#output = impl.outputStream;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async _destroy(error: Error | null, callback: (error: Error | null) => void): Promise<void> {
|
|
261
|
+
this.#cancellable.cancel();
|
|
262
|
+
|
|
263
|
+
for (const operation of this.#pending) {
|
|
264
|
+
try {
|
|
265
|
+
await operation;
|
|
266
|
+
} catch (e) {
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
try {
|
|
271
|
+
await this.#impl.close(IO_PRIORITY_DEFAULT);
|
|
272
|
+
} catch (e) {
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
callback(error);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
_read(size: number): void {
|
|
279
|
+
const operation = this.#input.read(size, IO_PRIORITY_DEFAULT, this.#cancellable)
|
|
280
|
+
.then((data: Buffer): void => {
|
|
281
|
+
const isEof = data.length === 0;
|
|
282
|
+
if (isEof) {
|
|
283
|
+
this.push(null);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
this.push(data);
|
|
288
|
+
})
|
|
289
|
+
.catch((error: Error): void => {
|
|
290
|
+
if (this.#impl.closed) {
|
|
291
|
+
this.push(null);
|
|
292
|
+
}
|
|
293
|
+
this.emit("error", error);
|
|
294
|
+
});
|
|
295
|
+
this.#track(operation);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
_write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void {
|
|
299
|
+
let data: Buffer;
|
|
300
|
+
if (Buffer.isBuffer(chunk)) {
|
|
301
|
+
data = chunk;
|
|
302
|
+
} else {
|
|
303
|
+
data = Buffer.from(chunk, encoding);
|
|
304
|
+
}
|
|
305
|
+
const operation = this.#writeAll(data)
|
|
306
|
+
.then((): void => {
|
|
307
|
+
callback(null);
|
|
308
|
+
})
|
|
309
|
+
.catch((error: Error): void => {
|
|
310
|
+
callback(error);
|
|
311
|
+
});
|
|
312
|
+
this.#track(operation);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
async #writeAll(data: Buffer): Promise<void> {
|
|
316
|
+
let offset = 0;
|
|
317
|
+
do {
|
|
318
|
+
const n = await this.#output.write(data.slice(offset), IO_PRIORITY_DEFAULT, this.#cancellable);
|
|
319
|
+
offset += n;
|
|
320
|
+
} while (offset !== data.length);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
#track(operation: Promise<void>): void {
|
|
324
|
+
this.#pending.add(operation);
|
|
325
|
+
operation
|
|
326
|
+
.catch(_ => {})
|
|
327
|
+
.finally(() => {
|
|
328
|
+
this.#pending.delete(operation);
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
class CallbackAuthenticationService extends binding.AbstractAuthenticationService {
|
|
334
|
+
#callback: AuthenticationCallback;
|
|
335
|
+
|
|
336
|
+
constructor(callback: AuthenticationCallback) {
|
|
337
|
+
super();
|
|
338
|
+
this.#callback = callback;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
async authenticate(token: string, cancellable: Cancellable | null): Promise<string> {
|
|
342
|
+
const info = await this.#callback(token);
|
|
343
|
+
return JSON.stringify(info);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function parseSocketAddress(address: BaseSocketAddress): SocketAddress {
|
|
348
|
+
const family = address.family;
|
|
349
|
+
switch (family) {
|
|
350
|
+
case SocketFamily.Unix: {
|
|
351
|
+
const addr = address as UnixSocketAddress;
|
|
352
|
+
switch (addr.addressType) {
|
|
353
|
+
case UnixSocketAddressType.Anonymous:
|
|
354
|
+
return {
|
|
355
|
+
family: "unix:anonymous",
|
|
356
|
+
};
|
|
357
|
+
case UnixSocketAddressType.Path:
|
|
358
|
+
return {
|
|
359
|
+
family: "unix:path",
|
|
360
|
+
path: addr.path.toString(),
|
|
361
|
+
};
|
|
362
|
+
case UnixSocketAddressType.Abstract:
|
|
363
|
+
case UnixSocketAddressType.AbstractPadded:
|
|
364
|
+
return {
|
|
365
|
+
family: "unix:abstract",
|
|
366
|
+
path: addr.path,
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
case SocketFamily.Ipv4: {
|
|
372
|
+
const addr = address as InetSocketAddress;
|
|
373
|
+
return {
|
|
374
|
+
family: "ipv4",
|
|
375
|
+
address: addr.address.toString(),
|
|
376
|
+
port: addr.port,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
case SocketFamily.Ipv6: {
|
|
380
|
+
const addr = address as InetSocketAddress;
|
|
381
|
+
return {
|
|
382
|
+
family: "ipv6",
|
|
383
|
+
address: addr.address.toString(),
|
|
384
|
+
port: addr.port,
|
|
385
|
+
flowlabel: addr.flowinfo,
|
|
386
|
+
scopeid: addr.scopeId,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
throw new Error("invalid BaseSocketAddress");
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function objectToStrv(object: { [name: string]: string }): string[] {
|
|
395
|
+
return Object.entries(object).map(([k, v]) => `${k}=${v}`);
|
|
396
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from io import StringIO
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from . import codegen
|
|
8
|
+
from .customization import load_customizations
|
|
9
|
+
from .loader import compute_model
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def main():
|
|
13
|
+
run(build_arguments())
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def build_arguments() -> argparse.Namespace:
|
|
17
|
+
p = argparse.ArgumentParser(
|
|
18
|
+
description="Generate TypeScript and Node-API bindings for Frida."
|
|
19
|
+
)
|
|
20
|
+
p.add_argument(
|
|
21
|
+
"--frida-gir",
|
|
22
|
+
required=True,
|
|
23
|
+
type=Path,
|
|
24
|
+
help="Path to the Frida .gir file.",
|
|
25
|
+
)
|
|
26
|
+
p.add_argument(
|
|
27
|
+
"--glib-gir",
|
|
28
|
+
required=True,
|
|
29
|
+
type=Path,
|
|
30
|
+
help="Path to the GLib .gir file.",
|
|
31
|
+
)
|
|
32
|
+
p.add_argument(
|
|
33
|
+
"--gobject-gir",
|
|
34
|
+
required=True,
|
|
35
|
+
type=Path,
|
|
36
|
+
help="Path to the GObject .gir file.",
|
|
37
|
+
)
|
|
38
|
+
p.add_argument(
|
|
39
|
+
"--gio-gir",
|
|
40
|
+
required=True,
|
|
41
|
+
type=Path,
|
|
42
|
+
help="Path to the GIO .gir file.",
|
|
43
|
+
)
|
|
44
|
+
p.add_argument(
|
|
45
|
+
"--output-ts",
|
|
46
|
+
required=True,
|
|
47
|
+
type=Path,
|
|
48
|
+
help="Path to the output TypeScript file.",
|
|
49
|
+
)
|
|
50
|
+
p.add_argument(
|
|
51
|
+
"--output-dts",
|
|
52
|
+
required=True,
|
|
53
|
+
type=Path,
|
|
54
|
+
help="Path to the output TypeScript declaration file.",
|
|
55
|
+
)
|
|
56
|
+
p.add_argument(
|
|
57
|
+
"--output-c",
|
|
58
|
+
required=True,
|
|
59
|
+
type=Path,
|
|
60
|
+
help="Path to the output C file for N-API bindings.",
|
|
61
|
+
)
|
|
62
|
+
return p.parse_args()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def run(args: argparse.Namespace) -> None:
|
|
66
|
+
customizations = load_customizations()
|
|
67
|
+
model = compute_model(
|
|
68
|
+
args.frida_gir, args.glib_gir, args.gobject_gir, args.gio_gir, customizations
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
artefacts = codegen.generate_all(model)
|
|
72
|
+
|
|
73
|
+
with OutputFile(args.output_ts) as f:
|
|
74
|
+
f.write(artefacts["ts"])
|
|
75
|
+
with OutputFile(args.output_dts) as f:
|
|
76
|
+
f.write(artefacts["dts"])
|
|
77
|
+
with OutputFile(args.output_c) as f:
|
|
78
|
+
f.write(artefacts["c"])
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class OutputFile:
|
|
82
|
+
def __init__(self, output_path):
|
|
83
|
+
self._output_path = output_path
|
|
84
|
+
self._io = StringIO()
|
|
85
|
+
|
|
86
|
+
def __enter__(self):
|
|
87
|
+
return self._io
|
|
88
|
+
|
|
89
|
+
def __exit__(self, *exc):
|
|
90
|
+
result = self._io.getvalue()
|
|
91
|
+
if self._output_path.exists():
|
|
92
|
+
existing_contents = self._output_path.read_text(encoding="utf-8")
|
|
93
|
+
if existing_contents == result:
|
|
94
|
+
return False
|
|
95
|
+
self._output_path.write_text(result, encoding="utf-8")
|
|
96
|
+
return False
|