frida-java-bridge 6.3.6 → 6.3.8
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 +123 -93
- package/lib/class-factory.js +11 -5
- 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,25 @@ 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
|
|
|
154
|
+
temporaryApi.isApiLevel34OrApexEquivalent = isArt && (
|
|
155
|
+
temporaryApi.find('_ZN3art7AppInfo29GetPrimaryApkReferenceProfileEv') !== null ||
|
|
156
|
+
temporaryApi.find('_ZN3art6Thread15RunFlipFunctionEPS0_') !== null
|
|
157
|
+
);
|
|
158
|
+
|
|
146
159
|
const pending = isArt
|
|
147
|
-
?
|
|
148
|
-
module: vmModule.path,
|
|
160
|
+
? {
|
|
149
161
|
functions: {
|
|
150
162
|
JNI_GetCreatedJavaVMs: ['JNI_GetCreatedJavaVMs', 'int', ['pointer', 'int', 'pointer']],
|
|
151
163
|
|
|
@@ -312,7 +324,7 @@ function _getApi () {
|
|
|
312
324
|
this.isDebuggerActive = () => !!address.readU8();
|
|
313
325
|
}
|
|
314
326
|
},
|
|
315
|
-
optionals: [
|
|
327
|
+
optionals: new Set([
|
|
316
328
|
'artInterpreterToCompiledCodeBridge',
|
|
317
329
|
'_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadENS_6ObjPtrINS_6mirror6ObjectEEE',
|
|
318
330
|
'_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadEPNS_6mirror6ObjectE',
|
|
@@ -360,10 +372,9 @@ function _getApi () {
|
|
|
360
372
|
'_ZN3art3jni12JniIdManager14DecodeMethodIdEP10_jmethodID',
|
|
361
373
|
'_ZN3art11interpreter18GetNterpEntryPointEv',
|
|
362
374
|
'_ZN3art7Monitor17TranslateLocationEPNS_9ArtMethodEjPPKcPi'
|
|
363
|
-
]
|
|
364
|
-
}
|
|
365
|
-
:
|
|
366
|
-
module: vmModule.path,
|
|
375
|
+
])
|
|
376
|
+
}
|
|
377
|
+
: {
|
|
367
378
|
functions: {
|
|
368
379
|
_Z20dvmDecodeIndirectRefP6ThreadP8_jobject: ['dvmDecodeIndirectRef', 'pointer', ['pointer', 'pointer']],
|
|
369
380
|
_Z15dvmUseJNIBridgeP6MethodPv: ['dvmUseJNIBridge', 'void', ['pointer', 'pointer']],
|
|
@@ -380,52 +391,41 @@ function _getApi () {
|
|
|
380
391
|
this.gDvm = address;
|
|
381
392
|
}
|
|
382
393
|
}
|
|
383
|
-
}
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const {
|
|
397
|
+
functions = {},
|
|
398
|
+
variables = {},
|
|
399
|
+
optionals = new Set()
|
|
400
|
+
} = pending;
|
|
384
401
|
|
|
385
402
|
const missing = [];
|
|
386
403
|
|
|
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
|
-
});
|
|
404
|
+
for (const [name, signature] of Object.entries(functions)) {
|
|
405
|
+
const address = temporaryApi.find(name);
|
|
406
|
+
if (address !== null) {
|
|
407
|
+
if (typeof signature === 'function') {
|
|
408
|
+
signature.call(temporaryApi, address);
|
|
409
|
+
} else {
|
|
410
|
+
temporaryApi[signature[0]] = new NativeFunction(address, signature[1], signature[2], nativeFunctionOptions);
|
|
411
|
+
}
|
|
412
|
+
} else {
|
|
413
|
+
if (!optionals.has(name)) {
|
|
414
|
+
missing.push(name);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
415
418
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
});
|
|
428
|
-
});
|
|
419
|
+
for (const [name, handler] of Object.entries(variables)) {
|
|
420
|
+
const address = temporaryApi.find(name);
|
|
421
|
+
if (address !== null) {
|
|
422
|
+
handler.call(temporaryApi, address);
|
|
423
|
+
} else {
|
|
424
|
+
if (!optionals.has(name)) {
|
|
425
|
+
missing.push(name);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
429
|
|
|
430
430
|
if (missing.length > 0) {
|
|
431
431
|
throw new Error('Java API only partially available; please file a bug. Missing: ' + missing.join(', '));
|
|
@@ -501,9 +501,11 @@ function _getApi () {
|
|
|
501
501
|
}
|
|
502
502
|
if (temporaryApi['art::interpreter::GetNterpEntryPoint'] !== undefined) {
|
|
503
503
|
temporaryApi.artNterpEntryPoint = temporaryApi['art::interpreter::GetNterpEntryPoint']();
|
|
504
|
+
} else {
|
|
505
|
+
temporaryApi.artNterpEntryPoint = temporaryApi.find('ExecuteNterpImpl');
|
|
504
506
|
}
|
|
505
507
|
|
|
506
|
-
artController = makeArtController(vm);
|
|
508
|
+
artController = makeArtController(temporaryApi, vm);
|
|
507
509
|
|
|
508
510
|
fixupArtQuickDeliverExceptionBug(temporaryApi);
|
|
509
511
|
|
|
@@ -518,7 +520,7 @@ function _getApi () {
|
|
|
518
520
|
});
|
|
519
521
|
}
|
|
520
522
|
|
|
521
|
-
const cxxImports =
|
|
523
|
+
const cxxImports = vmModule.enumerateImports()
|
|
522
524
|
.filter(imp => imp.name.indexOf('_Z') === 0)
|
|
523
525
|
.reduce((result, imp) => {
|
|
524
526
|
result[imp.name] = imp.address;
|
|
@@ -536,8 +538,11 @@ function tryGetEnvJvmti (vm, runtime) {
|
|
|
536
538
|
let env = null;
|
|
537
539
|
|
|
538
540
|
vm.perform(() => {
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
+
const ensurePluginLoadedAddr = getApi().find('_ZN3art7Runtime18EnsurePluginLoadedEPKcPNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE');
|
|
542
|
+
if (ensurePluginLoadedAddr === null) {
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
const ensurePluginLoaded = new NativeFunction(ensurePluginLoadedAddr,
|
|
541
546
|
'bool',
|
|
542
547
|
['pointer', 'pointer', 'pointer']);
|
|
543
548
|
const errorPtr = Memory.alloc(pointerSize);
|
|
@@ -623,7 +628,7 @@ function _getArtRuntimeSpec (api) {
|
|
|
623
628
|
|
|
624
629
|
const apiLevel = getAndroidApiLevel();
|
|
625
630
|
const codename = getAndroidCodename();
|
|
626
|
-
const isApiLevel34OrApexEquivalent =
|
|
631
|
+
const { isApiLevel34OrApexEquivalent } = api;
|
|
627
632
|
|
|
628
633
|
let spec = null;
|
|
629
634
|
|
|
@@ -632,7 +637,7 @@ function _getArtRuntimeSpec (api) {
|
|
|
632
637
|
if (value.equals(vm)) {
|
|
633
638
|
let classLinkerOffsets;
|
|
634
639
|
let jniIdManagerOffset = null;
|
|
635
|
-
if (apiLevel >= 33 || codename === 'Tiramisu') {
|
|
640
|
+
if (apiLevel >= 33 || codename === 'Tiramisu' || isApiLevel34OrApexEquivalent) {
|
|
636
641
|
classLinkerOffsets = [offset - (4 * pointerSize)];
|
|
637
642
|
jniIdManagerOffset = offset - pointerSize;
|
|
638
643
|
} else if (apiLevel >= 30 || codename === 'R') {
|
|
@@ -685,7 +690,7 @@ function _getArtRuntimeSpec (api) {
|
|
|
685
690
|
}
|
|
686
691
|
|
|
687
692
|
spec.offset.instrumentation = tryDetectInstrumentationOffset(api);
|
|
688
|
-
spec.offset.jniIdsIndirection = tryDetectJniIdsIndirectionOffset();
|
|
693
|
+
spec.offset.jniIdsIndirection = tryDetectJniIdsIndirectionOffset(api);
|
|
689
694
|
|
|
690
695
|
return spec;
|
|
691
696
|
}
|
|
@@ -771,8 +776,8 @@ const jniIdsIndirectionOffsetParsers = {
|
|
|
771
776
|
arm64: parseArm64JniIdsIndirectionOffset
|
|
772
777
|
};
|
|
773
778
|
|
|
774
|
-
function tryDetectJniIdsIndirectionOffset () {
|
|
775
|
-
const impl =
|
|
779
|
+
function tryDetectJniIdsIndirectionOffset (api) {
|
|
780
|
+
const impl = api.find('_ZN3art7Runtime12SetJniIdTypeENS_9JniIdTypeE');
|
|
776
781
|
if (impl === null) {
|
|
777
782
|
return null;
|
|
778
783
|
}
|
|
@@ -828,6 +833,7 @@ function _getArtInstrumentationSpec () {
|
|
|
828
833
|
'4-28': 212,
|
|
829
834
|
'4-29': 172,
|
|
830
835
|
'4-30': 180,
|
|
836
|
+
'4-31': 180,
|
|
831
837
|
'8-21': 224,
|
|
832
838
|
'8-22': 224,
|
|
833
839
|
'8-23': 296,
|
|
@@ -837,7 +843,8 @@ function _getArtInstrumentationSpec () {
|
|
|
837
843
|
'8-27': 352,
|
|
838
844
|
'8-28': 392,
|
|
839
845
|
'8-29': 328,
|
|
840
|
-
'8-30': 336
|
|
846
|
+
'8-30': 336,
|
|
847
|
+
'8-31': 336
|
|
841
848
|
};
|
|
842
849
|
|
|
843
850
|
const deoptEnabledOffset = deoptimizationEnabledOffsets[`${pointerSize}-${getAndroidApiLevel()}`];
|
|
@@ -943,6 +950,8 @@ function tryGetArtClassLinkerSpec (runtime, runtimeSpec) {
|
|
|
943
950
|
|
|
944
951
|
if (spec !== null) {
|
|
945
952
|
cachedArtClassLinkerSpec = spec;
|
|
953
|
+
} else {
|
|
954
|
+
throw new Error('Unable to determine ClassLinker field offsets');
|
|
946
955
|
}
|
|
947
956
|
|
|
948
957
|
return spec;
|
|
@@ -1568,7 +1577,7 @@ function notifyArtMethodHooked (method, vm) {
|
|
|
1568
1577
|
ensureArtKnowsHowToHandleReplacementMethods(vm);
|
|
1569
1578
|
}
|
|
1570
1579
|
|
|
1571
|
-
function makeArtController (vm) {
|
|
1580
|
+
function makeArtController (api, vm) {
|
|
1572
1581
|
const threadOffsets = getArtThreadSpec(vm).offset;
|
|
1573
1582
|
const managedStackOffsets = getArtManagedStackSpec().offset;
|
|
1574
1583
|
|
|
@@ -1776,10 +1785,9 @@ on_leave_gc_concurrent_copying_copying_phase (GumInvocationContext * ic)
|
|
|
1776
1785
|
const replacements = methods.add(methodsSize);
|
|
1777
1786
|
const lastSeenArtMethod = replacements.add(replacementsSize);
|
|
1778
1787
|
|
|
1779
|
-
const getOatQuickMethodHeaderImpl =
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
: '_ZN3art9ArtMethod23GetOatQuickMethodHeaderEm');
|
|
1788
|
+
const getOatQuickMethodHeaderImpl = api.find((pointerSize === 4)
|
|
1789
|
+
? '_ZN3art9ArtMethod23GetOatQuickMethodHeaderEj'
|
|
1790
|
+
: '_ZN3art9ArtMethod23GetOatQuickMethodHeaderEm');
|
|
1783
1791
|
|
|
1784
1792
|
const cm = new CModule(code, {
|
|
1785
1793
|
lock,
|
|
@@ -1853,19 +1861,31 @@ function instrumentArtQuickEntrypoints (vm) {
|
|
|
1853
1861
|
}
|
|
1854
1862
|
|
|
1855
1863
|
function instrumentArtMethodInvocationFromInterpreter () {
|
|
1864
|
+
const api = getApi();
|
|
1865
|
+
|
|
1856
1866
|
const apiLevel = getAndroidApiLevel();
|
|
1867
|
+
const { isApiLevel34OrApexEquivalent } = api;
|
|
1857
1868
|
|
|
1858
1869
|
let artInterpreterDoCallExportRegex;
|
|
1859
1870
|
if (apiLevel <= 22) {
|
|
1860
1871
|
artInterpreterDoCallExportRegex = /^_ZN3art11interpreter6DoCallILb[0-1]ELb[0-1]EEEbPNS_6mirror9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE$/;
|
|
1861
|
-
} else if (apiLevel <= 33) {
|
|
1872
|
+
} else if (apiLevel <= 33 && !isApiLevel34OrApexEquivalent) {
|
|
1862
1873
|
artInterpreterDoCallExportRegex = /^_ZN3art11interpreter6DoCallILb[0-1]ELb[0-1]EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE$/;
|
|
1863
|
-
} else {
|
|
1874
|
+
} else if (isApiLevel34OrApexEquivalent) {
|
|
1864
1875
|
artInterpreterDoCallExportRegex = /^_ZN3art11interpreter6DoCallILb[0-1]EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtbPNS_6JValueE$/;
|
|
1876
|
+
} else {
|
|
1877
|
+
throw new Error('Unable to find method invocation in ART; please file a bug');
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
const art = api.module;
|
|
1881
|
+
const entries = [...art.enumerateExports(), ...art.enumerateSymbols()].filter(entry => artInterpreterDoCallExportRegex.test(entry.name));
|
|
1882
|
+
|
|
1883
|
+
if (entries.length === 0) {
|
|
1884
|
+
throw new Error('Unable to find method invocation in ART; please file a bug');
|
|
1865
1885
|
}
|
|
1866
1886
|
|
|
1867
|
-
for (const
|
|
1868
|
-
Interceptor.attach(
|
|
1887
|
+
for (const entry of entries) {
|
|
1888
|
+
Interceptor.attach(entry.address, artController.hooks.Interpreter.doCall);
|
|
1869
1889
|
}
|
|
1870
1890
|
}
|
|
1871
1891
|
|
|
@@ -1893,29 +1913,24 @@ function ensureArtKnowsHowToHandleReplacementMethods (vm) {
|
|
|
1893
1913
|
|
|
1894
1914
|
const apiLevel = getAndroidApiLevel();
|
|
1895
1915
|
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1916
|
+
let copyingPhase = null;
|
|
1917
|
+
const api = getApi();
|
|
1918
|
+
if (apiLevel > 28) {
|
|
1919
|
+
copyingPhase = api.find('_ZN3art2gc9collector17ConcurrentCopying12CopyingPhaseEv');
|
|
1920
|
+
} else if (apiLevel > 22) {
|
|
1921
|
+
copyingPhase = api.find('_ZN3art2gc9collector17ConcurrentCopying12MarkingPhaseEv');
|
|
1922
|
+
}
|
|
1923
|
+
if (copyingPhase !== null) {
|
|
1924
|
+
Interceptor.attach(copyingPhase, artController.hooks.Gc.copyingPhase);
|
|
1925
|
+
}
|
|
1906
1926
|
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
copyingPhase = Module.findExportByName('libart.so', '_ZN3art2gc9collector17ConcurrentCopying12MarkingPhaseEv');
|
|
1915
|
-
}
|
|
1916
|
-
if (copyingPhase !== null) {
|
|
1917
|
-
Interceptor.attach(copyingPhase, artController.hooks.Gc.copyingPhase);
|
|
1918
|
-
}
|
|
1927
|
+
let runFlip = null;
|
|
1928
|
+
runFlip = api.find('_ZN3art6Thread15RunFlipFunctionEPS0_');
|
|
1929
|
+
if (runFlip === null) {
|
|
1930
|
+
runFlip = api.find('_ZN3art6Thread15RunFlipFunctionEPS0_b');
|
|
1931
|
+
}
|
|
1932
|
+
if (runFlip !== null) {
|
|
1933
|
+
Interceptor.attach(runFlip, artController.hooks.Gc.runFlip);
|
|
1919
1934
|
}
|
|
1920
1935
|
}
|
|
1921
1936
|
|
|
@@ -3414,7 +3429,7 @@ class ArtMethodMangler {
|
|
|
3414
3429
|
|
|
3415
3430
|
// Replace Nterp quick entrypoints with art_quick_to_interpreter_bridge to force stepping out
|
|
3416
3431
|
// of ART's next-generation interpreter and use the quick stub instead.
|
|
3417
|
-
if (artNterpEntryPoint !==
|
|
3432
|
+
if (artNterpEntryPoint !== null && quickCode.equals(artNterpEntryPoint)) {
|
|
3418
3433
|
patchArtMethod(hookedMethodId, {
|
|
3419
3434
|
quickCode: api.artQuickToInterpreterBridge
|
|
3420
3435
|
}, vm);
|
|
@@ -3925,9 +3940,24 @@ const threadStateTransitionRecompilers = {
|
|
|
3925
3940
|
};
|
|
3926
3941
|
|
|
3927
3942
|
function makeArtThreadStateTransitionImpl (vm, env, callback) {
|
|
3943
|
+
const api = getApi();
|
|
3928
3944
|
const envVtable = env.handle.readPointer();
|
|
3929
|
-
|
|
3930
|
-
|
|
3945
|
+
|
|
3946
|
+
let exceptionClearImpl;
|
|
3947
|
+
const innerExceptionClearImpl = api.find('_ZN3art3JNIILb1EE14ExceptionClearEP7_JNIEnv');
|
|
3948
|
+
if (innerExceptionClearImpl !== null) {
|
|
3949
|
+
exceptionClearImpl = innerExceptionClearImpl;
|
|
3950
|
+
} else {
|
|
3951
|
+
exceptionClearImpl = envVtable.add(ENV_VTABLE_OFFSET_EXCEPTION_CLEAR).readPointer();
|
|
3952
|
+
}
|
|
3953
|
+
|
|
3954
|
+
let nextFuncImpl;
|
|
3955
|
+
const innerNextFuncImpl = api.find('_ZN3art3JNIILb1EE10FatalErrorEP7_JNIEnvPKc');
|
|
3956
|
+
if (innerNextFuncImpl !== null) {
|
|
3957
|
+
nextFuncImpl = innerNextFuncImpl;
|
|
3958
|
+
} else {
|
|
3959
|
+
nextFuncImpl = envVtable.add(ENV_VTABLE_OFFSET_FATAL_ERROR).readPointer();
|
|
3960
|
+
}
|
|
3931
3961
|
|
|
3932
3962
|
const recompile = threadStateTransitionRecompilers[Process.arch];
|
|
3933
3963
|
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/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 = {
|