frida-java-bridge 6.3.5 → 6.3.7
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/index.js +7 -13
- package/lib/android.js +100 -83
- package/lib/class-factory.js +11 -5
- package/lib/jvm.js +222 -173
- package/lib/mkdex.js +10 -9
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -214,29 +214,23 @@ class Runtime {
|
|
|
214
214
|
const { vm, api } = this;
|
|
215
215
|
const env = vm.getEnv();
|
|
216
216
|
|
|
217
|
-
const classHandles = [];
|
|
218
217
|
const addGlobalReference = api['art::JavaVMExt::AddGlobalRef'];
|
|
219
218
|
const { vm: vmHandle } = api;
|
|
220
219
|
withRunnableArtThread(vm, env, thread => {
|
|
221
220
|
const collectClassHandles = makeArtClassVisitor(klass => {
|
|
222
|
-
|
|
221
|
+
const handle = addGlobalReference(vmHandle, thread, klass);
|
|
222
|
+
try {
|
|
223
|
+
const className = env.getClassName(handle);
|
|
224
|
+
callbacks.onMatch(className, handle);
|
|
225
|
+
} finally {
|
|
226
|
+
env.deleteGlobalRef(handle);
|
|
227
|
+
}
|
|
223
228
|
return true;
|
|
224
229
|
});
|
|
225
230
|
|
|
226
231
|
api['art::ClassLinker::VisitClasses'](api.artClassLinker.address, collectClassHandles);
|
|
227
232
|
});
|
|
228
233
|
|
|
229
|
-
try {
|
|
230
|
-
classHandles.forEach(handle => {
|
|
231
|
-
const className = env.getClassName(handle);
|
|
232
|
-
callbacks.onMatch(className, handle);
|
|
233
|
-
});
|
|
234
|
-
} finally {
|
|
235
|
-
classHandles.forEach(handle => {
|
|
236
|
-
env.deleteGlobalRef(handle);
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
|
|
240
234
|
callbacks.onComplete();
|
|
241
235
|
}
|
|
242
236
|
|
package/lib/android.js
CHANGED
|
@@ -139,13 +139,20 @@ function _getApi () {
|
|
|
139
139
|
|
|
140
140
|
const temporaryApi = {
|
|
141
141
|
module: vmModule,
|
|
142
|
+
find (name) {
|
|
143
|
+
const { module } = this;
|
|
144
|
+
let address = module.findExportByName(name);
|
|
145
|
+
if (address === null) {
|
|
146
|
+
address = module.findSymbolByName(name);
|
|
147
|
+
}
|
|
148
|
+
return address;
|
|
149
|
+
},
|
|
142
150
|
flavor,
|
|
143
151
|
addLocalReference: null
|
|
144
152
|
};
|
|
145
153
|
|
|
146
154
|
const pending = isArt
|
|
147
|
-
?
|
|
148
|
-
module: vmModule.path,
|
|
155
|
+
? {
|
|
149
156
|
functions: {
|
|
150
157
|
JNI_GetCreatedJavaVMs: ['JNI_GetCreatedJavaVMs', 'int', ['pointer', 'int', 'pointer']],
|
|
151
158
|
|
|
@@ -312,7 +319,7 @@ function _getApi () {
|
|
|
312
319
|
this.isDebuggerActive = () => !!address.readU8();
|
|
313
320
|
}
|
|
314
321
|
},
|
|
315
|
-
optionals: [
|
|
322
|
+
optionals: new Set([
|
|
316
323
|
'artInterpreterToCompiledCodeBridge',
|
|
317
324
|
'_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadENS_6ObjPtrINS_6mirror6ObjectEEE',
|
|
318
325
|
'_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadEPNS_6mirror6ObjectE',
|
|
@@ -360,10 +367,9 @@ function _getApi () {
|
|
|
360
367
|
'_ZN3art3jni12JniIdManager14DecodeMethodIdEP10_jmethodID',
|
|
361
368
|
'_ZN3art11interpreter18GetNterpEntryPointEv',
|
|
362
369
|
'_ZN3art7Monitor17TranslateLocationEPNS_9ArtMethodEjPPKcPi'
|
|
363
|
-
]
|
|
364
|
-
}
|
|
365
|
-
:
|
|
366
|
-
module: vmModule.path,
|
|
370
|
+
])
|
|
371
|
+
}
|
|
372
|
+
: {
|
|
367
373
|
functions: {
|
|
368
374
|
_Z20dvmDecodeIndirectRefP6ThreadP8_jobject: ['dvmDecodeIndirectRef', 'pointer', ['pointer', 'pointer']],
|
|
369
375
|
_Z15dvmUseJNIBridgeP6MethodPv: ['dvmUseJNIBridge', 'void', ['pointer', 'pointer']],
|
|
@@ -380,52 +386,41 @@ function _getApi () {
|
|
|
380
386
|
this.gDvm = address;
|
|
381
387
|
}
|
|
382
388
|
}
|
|
383
|
-
}
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
const {
|
|
392
|
+
functions = {},
|
|
393
|
+
variables = {},
|
|
394
|
+
optionals = new Set()
|
|
395
|
+
} = pending;
|
|
384
396
|
|
|
385
397
|
const missing = [];
|
|
386
398
|
|
|
387
|
-
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
const exp = exportByName[name];
|
|
402
|
-
if (exp !== undefined && exp.type === 'function') {
|
|
403
|
-
const signature = functions[name];
|
|
404
|
-
if (typeof signature === 'function') {
|
|
405
|
-
signature.call(temporaryApi, exp.address);
|
|
406
|
-
} else {
|
|
407
|
-
temporaryApi[signature[0]] = new NativeFunction(exp.address, signature[1], signature[2], nativeFunctionOptions);
|
|
408
|
-
}
|
|
409
|
-
} else {
|
|
410
|
-
if (!optionals.has(name)) {
|
|
411
|
-
missing.push(name);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
});
|
|
399
|
+
for (const [name, signature] of Object.entries(functions)) {
|
|
400
|
+
const address = temporaryApi.find(name);
|
|
401
|
+
if (address !== null) {
|
|
402
|
+
if (typeof signature === 'function') {
|
|
403
|
+
signature.call(temporaryApi, address);
|
|
404
|
+
} else {
|
|
405
|
+
temporaryApi[signature[0]] = new NativeFunction(address, signature[1], signature[2], nativeFunctionOptions);
|
|
406
|
+
}
|
|
407
|
+
} else {
|
|
408
|
+
if (!optionals.has(name)) {
|
|
409
|
+
missing.push(name);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
415
413
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
});
|
|
428
|
-
});
|
|
414
|
+
for (const [name, handler] of Object.entries(variables)) {
|
|
415
|
+
const address = temporaryApi.find(name);
|
|
416
|
+
if (address !== null) {
|
|
417
|
+
handler.call(temporaryApi, address);
|
|
418
|
+
} else {
|
|
419
|
+
if (!optionals.has(name)) {
|
|
420
|
+
missing.push(name);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
429
424
|
|
|
430
425
|
if (missing.length > 0) {
|
|
431
426
|
throw new Error('Java API only partially available; please file a bug. Missing: ' + missing.join(', '));
|
|
@@ -501,9 +496,11 @@ function _getApi () {
|
|
|
501
496
|
}
|
|
502
497
|
if (temporaryApi['art::interpreter::GetNterpEntryPoint'] !== undefined) {
|
|
503
498
|
temporaryApi.artNterpEntryPoint = temporaryApi['art::interpreter::GetNterpEntryPoint']();
|
|
499
|
+
} else {
|
|
500
|
+
temporaryApi.artNterpEntryPoint = temporaryApi.find('ExecuteNterpImpl');
|
|
504
501
|
}
|
|
505
502
|
|
|
506
|
-
artController = makeArtController(vm);
|
|
503
|
+
artController = makeArtController(temporaryApi, vm);
|
|
507
504
|
|
|
508
505
|
fixupArtQuickDeliverExceptionBug(temporaryApi);
|
|
509
506
|
|
|
@@ -518,7 +515,7 @@ function _getApi () {
|
|
|
518
515
|
});
|
|
519
516
|
}
|
|
520
517
|
|
|
521
|
-
const cxxImports =
|
|
518
|
+
const cxxImports = vmModule.enumerateImports()
|
|
522
519
|
.filter(imp => imp.name.indexOf('_Z') === 0)
|
|
523
520
|
.reduce((result, imp) => {
|
|
524
521
|
result[imp.name] = imp.address;
|
|
@@ -536,8 +533,11 @@ function tryGetEnvJvmti (vm, runtime) {
|
|
|
536
533
|
let env = null;
|
|
537
534
|
|
|
538
535
|
vm.perform(() => {
|
|
539
|
-
const
|
|
540
|
-
|
|
536
|
+
const ensurePluginLoadedAddr = getApi().find('_ZN3art7Runtime18EnsurePluginLoadedEPKcPNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE');
|
|
537
|
+
if (ensurePluginLoadedAddr === null) {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
const ensurePluginLoaded = new NativeFunction(ensurePluginLoadedAddr,
|
|
541
541
|
'bool',
|
|
542
542
|
['pointer', 'pointer', 'pointer']);
|
|
543
543
|
const errorPtr = Memory.alloc(pointerSize);
|
|
@@ -623,7 +623,8 @@ function _getArtRuntimeSpec (api) {
|
|
|
623
623
|
|
|
624
624
|
const apiLevel = getAndroidApiLevel();
|
|
625
625
|
const codename = getAndroidCodename();
|
|
626
|
-
const isApiLevel34OrApexEquivalent =
|
|
626
|
+
const isApiLevel34OrApexEquivalent = api.find('_ZN3art7AppInfo29GetPrimaryApkReferenceProfileEv') !== null ||
|
|
627
|
+
api.find('_ZN3art6Thread15RunFlipFunctionEPS0_') !== null;
|
|
627
628
|
|
|
628
629
|
let spec = null;
|
|
629
630
|
|
|
@@ -685,7 +686,7 @@ function _getArtRuntimeSpec (api) {
|
|
|
685
686
|
}
|
|
686
687
|
|
|
687
688
|
spec.offset.instrumentation = tryDetectInstrumentationOffset(api);
|
|
688
|
-
spec.offset.jniIdsIndirection = tryDetectJniIdsIndirectionOffset();
|
|
689
|
+
spec.offset.jniIdsIndirection = tryDetectJniIdsIndirectionOffset(api);
|
|
689
690
|
|
|
690
691
|
return spec;
|
|
691
692
|
}
|
|
@@ -771,8 +772,8 @@ const jniIdsIndirectionOffsetParsers = {
|
|
|
771
772
|
arm64: parseArm64JniIdsIndirectionOffset
|
|
772
773
|
};
|
|
773
774
|
|
|
774
|
-
function tryDetectJniIdsIndirectionOffset () {
|
|
775
|
-
const impl =
|
|
775
|
+
function tryDetectJniIdsIndirectionOffset (api) {
|
|
776
|
+
const impl = api.find('_ZN3art7Runtime12SetJniIdTypeENS_9JniIdTypeE');
|
|
776
777
|
if (impl === null) {
|
|
777
778
|
return null;
|
|
778
779
|
}
|
|
@@ -1568,7 +1569,7 @@ function notifyArtMethodHooked (method, vm) {
|
|
|
1568
1569
|
ensureArtKnowsHowToHandleReplacementMethods(vm);
|
|
1569
1570
|
}
|
|
1570
1571
|
|
|
1571
|
-
function makeArtController (vm) {
|
|
1572
|
+
function makeArtController (api, vm) {
|
|
1572
1573
|
const threadOffsets = getArtThreadSpec(vm).offset;
|
|
1573
1574
|
const managedStackOffsets = getArtManagedStackSpec().offset;
|
|
1574
1575
|
|
|
@@ -1776,10 +1777,9 @@ on_leave_gc_concurrent_copying_copying_phase (GumInvocationContext * ic)
|
|
|
1776
1777
|
const replacements = methods.add(methodsSize);
|
|
1777
1778
|
const lastSeenArtMethod = replacements.add(replacementsSize);
|
|
1778
1779
|
|
|
1779
|
-
const getOatQuickMethodHeaderImpl =
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
: '_ZN3art9ArtMethod23GetOatQuickMethodHeaderEm');
|
|
1780
|
+
const getOatQuickMethodHeaderImpl = api.find((pointerSize === 4)
|
|
1781
|
+
? '_ZN3art9ArtMethod23GetOatQuickMethodHeaderEj'
|
|
1782
|
+
: '_ZN3art9ArtMethod23GetOatQuickMethodHeaderEm');
|
|
1783
1783
|
|
|
1784
1784
|
const cm = new CModule(code, {
|
|
1785
1785
|
lock,
|
|
@@ -1864,8 +1864,9 @@ function instrumentArtMethodInvocationFromInterpreter () {
|
|
|
1864
1864
|
artInterpreterDoCallExportRegex = /^_ZN3art11interpreter6DoCallILb[0-1]EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtbPNS_6JValueE$/;
|
|
1865
1865
|
}
|
|
1866
1866
|
|
|
1867
|
-
|
|
1868
|
-
|
|
1867
|
+
const art = getApi().module;
|
|
1868
|
+
for (const entry of [...art.enumerateExports(), ...art.enumerateSymbols()].filter(entry => artInterpreterDoCallExportRegex.test(entry.name))) {
|
|
1869
|
+
Interceptor.attach(entry.address, artController.hooks.Interpreter.doCall);
|
|
1869
1870
|
}
|
|
1870
1871
|
}
|
|
1871
1872
|
|
|
@@ -1893,23 +1894,24 @@ function ensureArtKnowsHowToHandleReplacementMethods (vm) {
|
|
|
1893
1894
|
|
|
1894
1895
|
const apiLevel = getAndroidApiLevel();
|
|
1895
1896
|
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1897
|
+
let copyingPhase = null;
|
|
1898
|
+
const api = getApi();
|
|
1899
|
+
if (apiLevel > 28) {
|
|
1900
|
+
copyingPhase = api.find('_ZN3art2gc9collector17ConcurrentCopying12CopyingPhaseEv');
|
|
1901
|
+
} else if (apiLevel > 22) {
|
|
1902
|
+
copyingPhase = api.find('_ZN3art2gc9collector17ConcurrentCopying12MarkingPhaseEv');
|
|
1903
|
+
}
|
|
1904
|
+
if (copyingPhase !== null) {
|
|
1905
|
+
Interceptor.attach(copyingPhase, artController.hooks.Gc.copyingPhase);
|
|
1906
|
+
}
|
|
1900
1907
|
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
exportName = '_ZN3art2gc9collector17ConcurrentCopying12MarkingPhaseEv';
|
|
1909
|
-
}
|
|
1910
|
-
if (exportName !== null) {
|
|
1911
|
-
Interceptor.attach(Module.getExportByName('libart.so', exportName), artController.hooks.Gc.copyingPhase);
|
|
1912
|
-
}
|
|
1908
|
+
let runFlip = null;
|
|
1909
|
+
runFlip = api.find('_ZN3art6Thread15RunFlipFunctionEPS0_');
|
|
1910
|
+
if (runFlip === null) {
|
|
1911
|
+
runFlip = api.find('_ZN3art6Thread15RunFlipFunctionEPS0_b');
|
|
1912
|
+
}
|
|
1913
|
+
if (runFlip !== null) {
|
|
1914
|
+
Interceptor.attach(runFlip, artController.hooks.Gc.runFlip);
|
|
1913
1915
|
}
|
|
1914
1916
|
}
|
|
1915
1917
|
|
|
@@ -3408,7 +3410,7 @@ class ArtMethodMangler {
|
|
|
3408
3410
|
|
|
3409
3411
|
// Replace Nterp quick entrypoints with art_quick_to_interpreter_bridge to force stepping out
|
|
3410
3412
|
// of ART's next-generation interpreter and use the quick stub instead.
|
|
3411
|
-
if (artNterpEntryPoint !==
|
|
3413
|
+
if (artNterpEntryPoint !== null && quickCode.equals(artNterpEntryPoint)) {
|
|
3412
3414
|
patchArtMethod(hookedMethodId, {
|
|
3413
3415
|
quickCode: api.artQuickToInterpreterBridge
|
|
3414
3416
|
}, vm);
|
|
@@ -3919,9 +3921,24 @@ const threadStateTransitionRecompilers = {
|
|
|
3919
3921
|
};
|
|
3920
3922
|
|
|
3921
3923
|
function makeArtThreadStateTransitionImpl (vm, env, callback) {
|
|
3924
|
+
const api = getApi();
|
|
3922
3925
|
const envVtable = env.handle.readPointer();
|
|
3923
|
-
|
|
3924
|
-
|
|
3926
|
+
|
|
3927
|
+
let exceptionClearImpl;
|
|
3928
|
+
const innerExceptionClearImpl = api.find('_ZN3art3JNIILb1EE14ExceptionClearEP7_JNIEnv');
|
|
3929
|
+
if (innerExceptionClearImpl !== null) {
|
|
3930
|
+
exceptionClearImpl = innerExceptionClearImpl;
|
|
3931
|
+
} else {
|
|
3932
|
+
exceptionClearImpl = envVtable.add(ENV_VTABLE_OFFSET_EXCEPTION_CLEAR).readPointer();
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
let nextFuncImpl;
|
|
3936
|
+
const innerNextFuncImpl = api.find('_ZN3art3JNIILb1EE10FatalErrorEP7_JNIEnvPKc');
|
|
3937
|
+
if (innerNextFuncImpl !== null) {
|
|
3938
|
+
nextFuncImpl = innerNextFuncImpl;
|
|
3939
|
+
} else {
|
|
3940
|
+
nextFuncImpl = envVtable.add(ENV_VTABLE_OFFSET_FATAL_ERROR).readPointer();
|
|
3941
|
+
}
|
|
3925
3942
|
|
|
3926
3943
|
const recompile = threadStateTransitionRecompilers[Process.arch];
|
|
3927
3944
|
if (recompile === undefined) {
|
package/lib/class-factory.js
CHANGED
|
@@ -16,6 +16,8 @@ const {
|
|
|
16
16
|
makeJniObjectTypeName
|
|
17
17
|
} = require('./types');
|
|
18
18
|
|
|
19
|
+
const kAccStatic = 0x0008;
|
|
20
|
+
|
|
19
21
|
const CONSTRUCTOR_METHOD = 1;
|
|
20
22
|
const STATIC_METHOD = 2;
|
|
21
23
|
const INSTANCE_METHOD = 3;
|
|
@@ -450,6 +452,9 @@ class ClassFactory {
|
|
|
450
452
|
impl = methodValue;
|
|
451
453
|
}
|
|
452
454
|
} else {
|
|
455
|
+
if (methodValue.isStatic) {
|
|
456
|
+
type = STATIC_METHOD;
|
|
457
|
+
}
|
|
453
458
|
returnType = this._getType(methodValue.returnType || 'void');
|
|
454
459
|
argumentTypes = (methodValue.argumentTypes || []).map(name => this._getType(name));
|
|
455
460
|
impl = methodValue.implementation;
|
|
@@ -479,7 +484,7 @@ class ClassFactory {
|
|
|
479
484
|
const argumentTypeNames = argumentTypes.map(t => t.name);
|
|
480
485
|
const signature = '(' + argumentTypeNames.join('') + ')' + returnTypeName;
|
|
481
486
|
|
|
482
|
-
dexMethods.push([name, returnTypeName, argumentTypeNames, thrownTypeNames]);
|
|
487
|
+
dexMethods.push([name, returnTypeName, argumentTypeNames, thrownTypeNames, (type === STATIC_METHOD) ? kAccStatic : 0]);
|
|
483
488
|
implMethods.push([name, signature, type, returnType, argumentTypes, impl]);
|
|
484
489
|
});
|
|
485
490
|
|
|
@@ -566,15 +571,16 @@ class ClassFactory {
|
|
|
566
571
|
const JVMTI_HEAP_OBJECT_EITHER = 3;
|
|
567
572
|
|
|
568
573
|
const h = classWrapper.$borrowClassHandle(env);
|
|
574
|
+
const tag = int64(h.value.toString());
|
|
569
575
|
try {
|
|
570
576
|
const heapObjectCallback = new NativeCallback((classTag, size, tagPtr, userData) => {
|
|
571
|
-
tagPtr.
|
|
577
|
+
tagPtr.writeS64(tag);
|
|
572
578
|
return JVMTI_ITERATION_CONTINUE;
|
|
573
|
-
}, 'int', ['
|
|
579
|
+
}, 'int', ['int64', 'int64', 'pointer', 'pointer']);
|
|
574
580
|
jvmti.iterateOverInstancesOfClass(h.value, JVMTI_HEAP_OBJECT_EITHER, heapObjectCallback, h.value);
|
|
575
581
|
|
|
576
|
-
const tagPtr = Memory.alloc(
|
|
577
|
-
tagPtr.
|
|
582
|
+
const tagPtr = Memory.alloc(8);
|
|
583
|
+
tagPtr.writeS64(tag);
|
|
578
584
|
const countPtr = Memory.alloc(jsizeSize);
|
|
579
585
|
const objectsPtr = Memory.alloc(pointerSize);
|
|
580
586
|
jvmti.getObjectsWithTags(1, tagPtr, countPtr, objectsPtr, NULL);
|
package/lib/jvm.js
CHANGED
|
@@ -51,184 +51,226 @@ function _getApi () {
|
|
|
51
51
|
flavor: 'jvm'
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
-
const pending =
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
:
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
54
|
+
const pending = Process.platform === 'windows'
|
|
55
|
+
? [{
|
|
56
|
+
module: vmModule.path,
|
|
57
|
+
functions: {
|
|
58
|
+
JNI_GetCreatedJavaVMs: ['JNI_GetCreatedJavaVMs', 'int', ['pointer', 'int', 'pointer']],
|
|
59
|
+
JVM_Sleep: ['JVM_Sleep', 'void', ['pointer', 'pointer', 'long']],
|
|
60
|
+
'VMThread::execute': ['VMThread::execute', 'void', ['pointer']],
|
|
61
|
+
'Method::size': ['Method::size', 'int', ['int']],
|
|
62
|
+
'Method::set_native_function': ['Method::set_native_function', 'void', ['pointer', 'pointer', 'int']],
|
|
63
|
+
'Method::clear_native_function': ['Method::clear_native_function', 'void', ['pointer']],
|
|
64
|
+
'Method::jmethod_id': ['Method::jmethod_id', 'pointer', ['pointer']],
|
|
65
|
+
'ClassLoaderDataGraph::classes_do': ['ClassLoaderDataGraph::classes_do', 'void', ['pointer']],
|
|
66
|
+
'NMethodSweeper::sweep_code_cache': ['NMethodSweeper::sweep_code_cache', 'void', []],
|
|
67
|
+
'OopMapCache::flush_obsolete_entries': ['OopMapCache::flush_obsolete_entries', 'void', ['pointer']]
|
|
68
|
+
},
|
|
69
|
+
variables: {
|
|
70
|
+
'VM_RedefineClasses::`vftable\'': function (address) {
|
|
71
|
+
this.vtableRedefineClasses = address;
|
|
72
|
+
},
|
|
73
|
+
'VM_RedefineClasses::doit': function (address) {
|
|
74
|
+
this.redefineClassesDoIt = address;
|
|
75
|
+
},
|
|
76
|
+
'VM_RedefineClasses::doit_prologue': function (address) {
|
|
77
|
+
this.redefineClassesDoItPrologue = address;
|
|
78
|
+
},
|
|
79
|
+
'VM_RedefineClasses::doit_epilogue': function (address) {
|
|
80
|
+
this.redefineClassesDoItEpilogue = address;
|
|
81
|
+
},
|
|
82
|
+
'VM_RedefineClasses::allow_nested_vm_operations': function (address) {
|
|
83
|
+
this.redefineClassesAllow = address;
|
|
84
|
+
},
|
|
85
|
+
'NMethodSweeper::_traversals': function (address) {
|
|
86
|
+
this.traversals = address;
|
|
87
|
+
},
|
|
88
|
+
'NMethodSweeper::_should_sweep': function (address) {
|
|
89
|
+
this.shouldSweep = address;
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
optionals: [
|
|
93
|
+
]
|
|
94
|
+
}]
|
|
95
|
+
// If platform is not Windows
|
|
96
|
+
: [{
|
|
97
|
+
module: vmModule.path,
|
|
98
|
+
functions: {
|
|
99
|
+
JNI_GetCreatedJavaVMs: ['JNI_GetCreatedJavaVMs', 'int', ['pointer', 'int', 'pointer']],
|
|
100
|
+
|
|
101
|
+
_ZN6Method4sizeEb: ['Method::size', 'int', ['int']],
|
|
102
|
+
_ZN6Method19set_native_functionEPhb: ['Method::set_native_function', 'void', ['pointer', 'pointer', 'int']],
|
|
103
|
+
_ZN6Method21clear_native_functionEv: ['Method::clear_native_function', 'void', ['pointer']],
|
|
104
|
+
// JDK >= 17
|
|
105
|
+
_ZN6Method24restore_unshareable_infoEP10JavaThread: ['Method::restore_unshareable_info', 'void', ['pointer', 'pointer']],
|
|
106
|
+
// JDK < 17
|
|
107
|
+
_ZN6Method24restore_unshareable_infoEP6Thread: ['Method::restore_unshareable_info', 'void', ['pointer', 'pointer']],
|
|
108
|
+
_ZN6Method10jmethod_idEv: ['Method::jmethod_id', 'pointer', ['pointer']],
|
|
109
|
+
_ZN6Method10clear_codeEv: function (address) {
|
|
110
|
+
const clearCode = new NativeFunction(address, 'void', ['pointer'], nativeFunctionOptions);
|
|
111
|
+
this['Method::clear_code'] = function (thisPtr) {
|
|
112
|
+
clearCode(thisPtr);
|
|
113
|
+
};
|
|
114
|
+
},
|
|
115
|
+
_ZN6Method10clear_codeEb: function (address) {
|
|
116
|
+
const clearCode = new NativeFunction(address, 'void', ['pointer', 'int'], nativeFunctionOptions);
|
|
117
|
+
const lock = 0;
|
|
118
|
+
this['Method::clear_code'] = function (thisPtr) {
|
|
119
|
+
clearCode(thisPtr, lock);
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
// JDK >= 13
|
|
124
|
+
_ZN18VM_RedefineClasses19mark_dependent_codeEP13InstanceKlass: ['VM_RedefineClasses::mark_dependent_code', 'void', ['pointer', 'pointer']],
|
|
125
|
+
_ZN18VM_RedefineClasses20flush_dependent_codeEv: ['VM_RedefineClasses::flush_dependent_code', 'void', []],
|
|
126
|
+
// JDK < 13
|
|
127
|
+
_ZN18VM_RedefineClasses20flush_dependent_codeEP13InstanceKlassP6Thread: ['VM_RedefineClasses::flush_dependent_code', 'void', ['pointer', 'pointer', 'pointer']],
|
|
128
|
+
// JDK < 10
|
|
129
|
+
_ZN18VM_RedefineClasses20flush_dependent_codeE19instanceKlassHandleP6Thread: ['VM_RedefineClasses::flush_dependent_code', 'void', ['pointer', 'pointer', 'pointer']],
|
|
130
|
+
|
|
131
|
+
_ZN19ResolvedMethodTable21adjust_method_entriesEPb: ['ResolvedMethodTable::adjust_method_entries', 'void', ['pointer']],
|
|
132
|
+
// JDK < 10
|
|
133
|
+
_ZN15MemberNameTable21adjust_method_entriesEP13InstanceKlassPb: ['MemberNameTable::adjust_method_entries', 'void', ['pointer', 'pointer', 'pointer']],
|
|
134
|
+
|
|
135
|
+
_ZN17ConstantPoolCache21adjust_method_entriesEPb: function (address) {
|
|
136
|
+
const adjustMethod = new NativeFunction(address, 'void', ['pointer', 'pointer'], nativeFunctionOptions);
|
|
137
|
+
this['ConstantPoolCache::adjust_method_entries'] = function (thisPtr, holderPtr, tracePtr) {
|
|
138
|
+
adjustMethod(thisPtr, tracePtr);
|
|
139
|
+
};
|
|
140
|
+
},
|
|
141
|
+
// JDK < 13
|
|
142
|
+
_ZN17ConstantPoolCache21adjust_method_entriesEP13InstanceKlassPb: function (address) {
|
|
143
|
+
const adjustMethod = new NativeFunction(address, 'void', ['pointer', 'pointer', 'pointer'], nativeFunctionOptions);
|
|
144
|
+
this['ConstantPoolCache::adjust_method_entries'] = function (thisPtr, holderPtr, tracePtr) {
|
|
145
|
+
adjustMethod(thisPtr, holderPtr, tracePtr);
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
_ZN20ClassLoaderDataGraph10classes_doEP12KlassClosure: ['ClassLoaderDataGraph::classes_do', 'void', ['pointer']],
|
|
150
|
+
_ZN20ClassLoaderDataGraph22clean_deallocate_listsEb: ['ClassLoaderDataGraph::clean_deallocate_lists', 'void', ['int']],
|
|
151
|
+
|
|
152
|
+
_ZN10JavaThread27thread_from_jni_environmentEP7JNIEnv_: ['JavaThread::thread_from_jni_environment', 'pointer', ['pointer']],
|
|
153
|
+
|
|
154
|
+
_ZN8VMThread7executeEP12VM_Operation: ['VMThread::execute', 'void', ['pointer']],
|
|
155
|
+
|
|
156
|
+
_ZN11OopMapCache22flush_obsolete_entriesEv: ['OopMapCache::flush_obsolete_entries', 'void', ['pointer']],
|
|
157
|
+
|
|
158
|
+
_ZN14NMethodSweeper11force_sweepEv: ['NMethodSweeper::force_sweep', 'void', []],
|
|
159
|
+
_ZN14NMethodSweeper16sweep_code_cacheEv: ['NMethodSweeper::sweep_code_cache', 'void', []],
|
|
160
|
+
_ZN14NMethodSweeper17sweep_in_progressEv: ['NMethodSweeper::sweep_in_progress', 'bool', []],
|
|
161
|
+
|
|
162
|
+
JVM_Sleep: ['JVM_Sleep', 'void', ['pointer', 'pointer', 'long']]
|
|
163
|
+
},
|
|
164
|
+
variables: {
|
|
165
|
+
// JDK <= 9
|
|
166
|
+
_ZN18VM_RedefineClasses14_the_class_oopE: function (address) {
|
|
167
|
+
this.redefineClass = address;
|
|
168
|
+
},
|
|
169
|
+
// 9 < JDK < 13
|
|
170
|
+
_ZN18VM_RedefineClasses10_the_classE: function (address) {
|
|
171
|
+
this.redefineClass = address;
|
|
172
|
+
},
|
|
173
|
+
// JDK < 13
|
|
174
|
+
_ZN18VM_RedefineClasses25AdjustCpoolCacheAndVtable8do_klassEP5Klass: function (address) {
|
|
175
|
+
this.doKlass = address;
|
|
176
|
+
},
|
|
177
|
+
// JDK >= 13
|
|
178
|
+
_ZN18VM_RedefineClasses22AdjustAndCleanMetadata8do_klassEP5Klass: function (address) {
|
|
179
|
+
this.doKlass = address;
|
|
180
|
+
},
|
|
181
|
+
_ZTV18VM_RedefineClasses: function (address) {
|
|
182
|
+
this.vtableRedefineClasses = address;
|
|
183
|
+
},
|
|
184
|
+
_ZN18VM_RedefineClasses4doitEv: function (address) {
|
|
185
|
+
this.redefineClassesDoIt = address;
|
|
186
|
+
},
|
|
187
|
+
_ZN18VM_RedefineClasses13doit_prologueEv: function (address) {
|
|
188
|
+
this.redefineClassesDoItPrologue = address;
|
|
189
|
+
},
|
|
190
|
+
_ZN18VM_RedefineClasses13doit_epilogueEv: function (address) {
|
|
191
|
+
this.redefineClassesDoItEpilogue = address;
|
|
192
|
+
},
|
|
193
|
+
_ZN18VM_RedefineClassesD0Ev: function (address) {
|
|
194
|
+
this.redefineClassesDispose0 = address;
|
|
195
|
+
},
|
|
196
|
+
_ZN18VM_RedefineClassesD1Ev: function (address) {
|
|
197
|
+
this.redefineClassesDispose1 = address;
|
|
198
|
+
},
|
|
199
|
+
_ZNK18VM_RedefineClasses26allow_nested_vm_operationsEv: function (address) {
|
|
200
|
+
this.redefineClassesAllow = address;
|
|
201
|
+
},
|
|
202
|
+
_ZNK18VM_RedefineClasses14print_on_errorEP12outputStream: function (address) {
|
|
203
|
+
this.redefineClassesOnError = address;
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
// JDK >= 17
|
|
207
|
+
_ZN13InstanceKlass33create_new_default_vtable_indicesEiP10JavaThread: function (address) {
|
|
208
|
+
this.createNewDefaultVtableIndices = address;
|
|
209
|
+
},
|
|
210
|
+
// JDK < 17
|
|
211
|
+
_ZN13InstanceKlass33create_new_default_vtable_indicesEiP6Thread: function (address) {
|
|
212
|
+
this.createNewDefaultVtableIndices = address;
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
_ZN19Abstract_VM_Version19jre_release_versionEv: function (address) {
|
|
216
|
+
const getVersion = new NativeFunction(address, 'pointer', [], nativeFunctionOptions);
|
|
217
|
+
const versionS = getVersion().readCString();
|
|
218
|
+
this.version = versionS.startsWith('1.8')
|
|
219
|
+
? 8
|
|
220
|
+
: versionS.startsWith('9.')
|
|
221
|
+
? 9
|
|
222
|
+
: parseInt(versionS.slice(0, 2), 10);
|
|
223
|
+
this.versionS = versionS;
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
_ZN14NMethodSweeper11_traversalsE: function (address) {
|
|
227
|
+
this.traversals = address;
|
|
228
|
+
},
|
|
229
|
+
_ZN14NMethodSweeper21_sweep_fractions_leftE: function (address) {
|
|
230
|
+
this.fractions = address;
|
|
231
|
+
},
|
|
232
|
+
_ZN14NMethodSweeper13_should_sweepE: function (address) {
|
|
233
|
+
this.shouldSweep = address;
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
optionals: [
|
|
237
|
+
'_ZN6Method24restore_unshareable_infoEP10JavaThread',
|
|
238
|
+
'_ZN6Method24restore_unshareable_infoEP6Thread',
|
|
239
|
+
'_ZN6Method10clear_codeEv',
|
|
240
|
+
'_ZN6Method10clear_codeEb',
|
|
199
241
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
242
|
+
'_ZN18VM_RedefineClasses19mark_dependent_codeEP13InstanceKlass',
|
|
243
|
+
'_ZN18VM_RedefineClasses20flush_dependent_codeEv',
|
|
244
|
+
'_ZN18VM_RedefineClasses20flush_dependent_codeEP13InstanceKlassP6Thread',
|
|
245
|
+
'_ZN18VM_RedefineClasses20flush_dependent_codeE19instanceKlassHandleP6Thread',
|
|
204
246
|
|
|
205
|
-
|
|
206
|
-
|
|
247
|
+
'_ZN19ResolvedMethodTable21adjust_method_entriesEPb',
|
|
248
|
+
'_ZN15MemberNameTable21adjust_method_entriesEP13InstanceKlassPb',
|
|
207
249
|
|
|
208
|
-
|
|
209
|
-
|
|
250
|
+
'_ZN17ConstantPoolCache21adjust_method_entriesEPb',
|
|
251
|
+
'_ZN17ConstantPoolCache21adjust_method_entriesEP13InstanceKlassPb',
|
|
210
252
|
|
|
211
|
-
|
|
253
|
+
'_ZN20ClassLoaderDataGraph22clean_deallocate_listsEb',
|
|
212
254
|
|
|
213
|
-
|
|
255
|
+
'_ZN10JavaThread27thread_from_jni_environmentEP7JNIEnv_',
|
|
214
256
|
|
|
215
|
-
|
|
216
|
-
|
|
257
|
+
'_ZN14NMethodSweeper11force_sweepEv',
|
|
258
|
+
'_ZN14NMethodSweeper17sweep_in_progressEv',
|
|
217
259
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
260
|
+
'_ZN18VM_RedefineClasses14_the_class_oopE',
|
|
261
|
+
'_ZN18VM_RedefineClasses10_the_classE',
|
|
262
|
+
'_ZN18VM_RedefineClasses25AdjustCpoolCacheAndVtable8do_klassEP5Klass',
|
|
263
|
+
'_ZN18VM_RedefineClasses22AdjustAndCleanMetadata8do_klassEP5Klass',
|
|
264
|
+
'_ZN18VM_RedefineClassesD0Ev',
|
|
265
|
+
'_ZN18VM_RedefineClassesD1Ev',
|
|
266
|
+
'_ZNK18VM_RedefineClasses14print_on_errorEP12outputStream',
|
|
225
267
|
|
|
226
|
-
|
|
227
|
-
|
|
268
|
+
'_ZN13InstanceKlass33create_new_default_vtable_indicesEiP10JavaThread',
|
|
269
|
+
'_ZN13InstanceKlass33create_new_default_vtable_indicesEiP6Thread',
|
|
228
270
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
271
|
+
'_ZN14NMethodSweeper21_sweep_fractions_leftE'
|
|
272
|
+
]
|
|
273
|
+
}];
|
|
232
274
|
|
|
233
275
|
const missing = [];
|
|
234
276
|
|
|
@@ -294,10 +336,17 @@ function _getApi () {
|
|
|
294
336
|
}
|
|
295
337
|
temporaryApi.vm = vms.readPointer();
|
|
296
338
|
|
|
297
|
-
const allocatorFunctions =
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
339
|
+
const allocatorFunctions = Process.platform === 'windows'
|
|
340
|
+
? {
|
|
341
|
+
$new: ['??2@YAPEAX_K@Z', 'pointer', ['ulong']],
|
|
342
|
+
$delete: ['??3@YAXPEAX@Z', 'void', ['pointer']]
|
|
343
|
+
}
|
|
344
|
+
// If platform is not Windows
|
|
345
|
+
: {
|
|
346
|
+
$new: ['_Znwm', 'pointer', ['ulong']],
|
|
347
|
+
$delete: ['_ZdlPv', 'void', ['pointer']]
|
|
348
|
+
};
|
|
349
|
+
|
|
301
350
|
for (const [name, [rawName, retType, argTypes]] of Object.entries(allocatorFunctions)) {
|
|
302
351
|
let address = Module.findExportByName(null, rawName);
|
|
303
352
|
if (address === null) {
|
package/lib/mkdex.js
CHANGED
|
@@ -530,7 +530,7 @@ function computeModel (classes) {
|
|
|
530
530
|
}
|
|
531
531
|
|
|
532
532
|
klass.methods.forEach(method => {
|
|
533
|
-
const [methodName, retType, argTypes, thrownTypes = []] = method;
|
|
533
|
+
const [methodName, retType, argTypes, thrownTypes = [], accessFlags] = method;
|
|
534
534
|
|
|
535
535
|
strings.add(methodName);
|
|
536
536
|
|
|
@@ -563,13 +563,13 @@ function computeModel (classes) {
|
|
|
563
563
|
strings.add('value');
|
|
564
564
|
}
|
|
565
565
|
|
|
566
|
-
methods.push([klass.name, protoId, methodName, throwsAnnotationId]);
|
|
566
|
+
methods.push([klass.name, protoId, methodName, throwsAnnotationId, accessFlags]);
|
|
567
567
|
|
|
568
568
|
if (methodName === '<init>') {
|
|
569
569
|
superConstructors.add(name + '|' + protoId);
|
|
570
570
|
const superConstructorId = superClass + '|' + protoId;
|
|
571
571
|
if (javaConstructors.has(name) && !superConstructors.has(superConstructorId)) {
|
|
572
|
-
methods.push([superClass, protoId, methodName, null]);
|
|
572
|
+
methods.push([superClass, protoId, methodName, null, 0]);
|
|
573
573
|
superConstructors.add(superConstructorId);
|
|
574
574
|
}
|
|
575
575
|
}
|
|
@@ -658,12 +658,13 @@ function computeModel (classes) {
|
|
|
658
658
|
fieldItems.sort(compareFieldItems);
|
|
659
659
|
|
|
660
660
|
const methodItems = methods.map(method => {
|
|
661
|
-
const [klass, protoId, name, annotationsId] = method;
|
|
661
|
+
const [klass, protoId, name, annotationsId, accessFlags] = method;
|
|
662
662
|
return [
|
|
663
663
|
typeToIndex[klass],
|
|
664
664
|
protoToIndex[protoId],
|
|
665
665
|
stringToIndex[name],
|
|
666
|
-
annotationsId
|
|
666
|
+
annotationsId,
|
|
667
|
+
accessFlags
|
|
667
668
|
];
|
|
668
669
|
});
|
|
669
670
|
methodItems.sort(compareMethodItems);
|
|
@@ -719,9 +720,9 @@ function computeModel (classes) {
|
|
|
719
720
|
const sourceFileIndex = stringToIndex[klass.sourceFileName];
|
|
720
721
|
|
|
721
722
|
const classMethods = methodItems.reduce((result, method, index) => {
|
|
722
|
-
const [holder, protoIndex, name, annotationsId] = method;
|
|
723
|
+
const [holder, protoIndex, name, annotationsId, accessFlags] = method;
|
|
723
724
|
if (holder === classIndex) {
|
|
724
|
-
result.push([index, name, annotationsId, protoIndex]);
|
|
725
|
+
result.push([index, name, annotationsId, protoIndex, accessFlags]);
|
|
725
726
|
}
|
|
726
727
|
return result;
|
|
727
728
|
}, []);
|
|
@@ -771,8 +772,8 @@ function computeModel (classes) {
|
|
|
771
772
|
});
|
|
772
773
|
const virtualMethods = compressClassMethodIndexes(classMethods
|
|
773
774
|
.filter(([, name]) => name !== constructorNameIndex)
|
|
774
|
-
.map(([index]) => {
|
|
775
|
-
return [index, kAccPublic | kAccNative];
|
|
775
|
+
.map(([index, , , , accessFlags]) => {
|
|
776
|
+
return [index, accessFlags | kAccPublic | kAccNative];
|
|
776
777
|
}));
|
|
777
778
|
|
|
778
779
|
const classData = {
|