@futpib/parser 1.0.2 → 1.0.3
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/.github/copilot-instructions.md +149 -0
- package/.github/workflows/copilot-setup-steps.yml +18 -0
- package/.github/workflows/main.yml +29 -8
- package/.yarn/releases/yarn-4.9.4.cjs +942 -0
- package/.yarnrc.yml +1 -1
- package/build/allSettledStream.js +1 -1
- package/build/allSettledStream.test.js +2 -2
- package/build/androidPackageParser.d.ts +1 -1
- package/build/androidPackageParser.js +5 -3
- package/build/androidPackageParser.test.js +7 -7
- package/build/androidPackageUnparser.d.ts +2 -2
- package/build/androidPackageUnparser.js +18 -14
- package/build/androidPackageUnparser.test.js +7 -7
- package/build/arbitrarilySlicedAsyncInterator.js +2 -1
- package/build/arbitraryDalvikBytecode.d.ts +4 -0
- package/build/arbitraryDalvikBytecode.js +640 -0
- package/build/arbitraryDalvikExecutable.d.ts +3 -0
- package/build/arbitraryDalvikExecutable.js +282 -0
- package/build/arbitraryDosDateTime.js +1 -0
- package/build/arbitraryZipStream.js +1 -1
- package/build/arrayParser.js +2 -2
- package/build/arrayUnparser.d.ts +1 -1
- package/build/backsmali.d.ts +3 -1
- package/build/backsmali.js +31 -3
- package/build/customInvariant.d.ts +2 -1
- package/build/customInvariant.js +4 -6
- package/build/dalvikBytecodeParser/formatParsers.d.ts +76 -2
- package/build/dalvikBytecodeParser/formatParsers.js +146 -11
- package/build/dalvikBytecodeParser/formatSizes.d.ts +34 -0
- package/build/dalvikBytecodeParser/formatSizes.js +34 -0
- package/build/dalvikBytecodeParser/operationFormats.d.ts +225 -0
- package/build/dalvikBytecodeParser/operationFormats.js +225 -0
- package/build/dalvikBytecodeParser.d.ts +1105 -5
- package/build/dalvikBytecodeParser.js +658 -205
- package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +152 -0
- package/build/dalvikBytecodeUnparser/formatUnparsers.js +225 -0
- package/build/dalvikBytecodeUnparser.d.ts +3 -0
- package/build/dalvikBytecodeUnparser.js +642 -0
- package/build/dalvikBytecodeUnparser.test.d.ts +1 -0
- package/build/dalvikBytecodeUnparser.test.js +25 -0
- package/build/dalvikExecutable.d.ts +65 -8
- package/build/dalvikExecutable.js +36 -0
- package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +1 -1
- package/build/dalvikExecutableParser/stringSyntaxParser.js +17 -17
- package/build/dalvikExecutableParser/typeParsers.d.ts +2 -1
- package/build/dalvikExecutableParser/typeParsers.js +16 -11
- package/build/dalvikExecutableParser/typedNumbers.d.ts +85 -69
- package/build/dalvikExecutableParser/typedNumbers.js +0 -1
- package/build/dalvikExecutableParser.d.ts +2 -2
- package/build/dalvikExecutableParser.js +655 -337
- package/build/dalvikExecutableParser.test.js +24 -22
- package/build/dalvikExecutableParserAgainstSmaliParser.test.js +223 -246
- package/build/dalvikExecutableUnparser/annotationUnparsers.d.ts +14 -0
- package/build/dalvikExecutableUnparser/annotationUnparsers.js +97 -0
- package/build/dalvikExecutableUnparser/poolBuilders.d.ts +49 -0
- package/build/dalvikExecutableUnparser/poolBuilders.js +140 -0
- package/build/dalvikExecutableUnparser/poolScanners.d.ts +4 -0
- package/build/dalvikExecutableUnparser/poolScanners.js +220 -0
- package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +25 -0
- package/build/dalvikExecutableUnparser/sectionUnparsers.js +581 -0
- package/build/dalvikExecutableUnparser/utils.d.ts +10 -0
- package/build/dalvikExecutableUnparser/utils.js +108 -0
- package/build/dalvikExecutableUnparser.d.ts +4 -0
- package/build/dalvikExecutableUnparser.js +406 -0
- package/build/dalvikExecutableUnparser.test.d.ts +1 -0
- package/build/dalvikExecutableUnparser.test.js +31 -0
- package/build/debugLogInputParser.js +1 -1
- package/build/disjunctionParser.d.ts +2 -2
- package/build/disjunctionParser.js +2 -2
- package/build/elementTerminatedArrayParser.d.ts +2 -2
- package/build/elementTerminatedArrayParser.js +1 -1
- package/build/elementTerminatedArrayParser.test.js +5 -5
- package/build/elementTerminatedSequenceArrayParser.d.ts +2 -2
- package/build/elementTerminatedSequenceArrayParser.js +1 -1
- package/build/elementTerminatedSequenceArrayParser.test.js +2 -2
- package/build/elementTerminatedSequenceParser.d.ts +2 -2
- package/build/elementTerminatedSequenceParser.js +1 -1
- package/build/elementTerminatedSequenceParser.test.js +2 -2
- package/build/endOfInputParser.d.ts +1 -1
- package/build/exactElementSwitchParser.d.ts +3 -0
- package/build/exactElementSwitchParser.js +22 -0
- package/build/fetchCid.js +2 -6
- package/build/fetchCid.test.d.ts +1 -0
- package/build/fetchCid.test.js +16 -0
- package/build/fixedLengthSequenceParser.test.js +2 -2
- package/build/hasExecutable.js +2 -2
- package/build/highResolutionTimer.js +1 -1
- package/build/inputReader.d.ts +1 -1
- package/build/inputReader.test.js +33 -45
- package/build/javaKeyStoreParser.test.js +6 -6
- package/build/jsonParser.js +8 -8
- package/build/lazyMessageError.d.ts +48 -0
- package/build/lazyMessageError.js +53 -0
- package/build/lazyMessageError.test.d.ts +1 -0
- package/build/lazyMessageError.test.js +15 -0
- package/build/leb128Parser.d.ts +1 -1
- package/build/leb128Parser.js +10 -10
- package/build/leb128Parser.test.js +7 -7
- package/build/negativeLookaheadParser.js +2 -2
- package/build/negativeLookaheadParser.test.js +4 -4
- package/build/noStackCaptureOverheadError.d.ts +4 -0
- package/build/noStackCaptureOverheadError.js +9 -0
- package/build/noStackCaptureOverheadError.test.d.ts +1 -0
- package/build/noStackCaptureOverheadError.test.js +15 -0
- package/build/nonEmptyArrayParser.js +2 -2
- package/build/nonEmptyArrayParser.test.js +2 -1
- package/build/optionalParser.js +2 -2
- package/build/parser.d.ts +2 -1
- package/build/parser.js +23 -8
- package/build/parser.test.js +78 -29
- package/build/parserConsumedSequenceParser.d.ts +1 -1
- package/build/parserConsumedSequenceParser.js +2 -2
- package/build/parserContext.d.ts +8 -6
- package/build/parserContext.js +60 -33
- package/build/parserContext.test.js +7 -3
- package/build/parserError.d.ts +603 -44
- package/build/parserError.js +98 -53
- package/build/parserImplementationInvariant.d.ts +1 -1
- package/build/parserImplementationInvariant.js +2 -2
- package/build/parserInputCompanion.js +2 -2
- package/build/promiseCompose.js +1 -2
- package/build/separatedArrayParser.js +2 -2
- package/build/separatedNonEmptyArrayParser.d.ts +2 -0
- package/build/separatedNonEmptyArrayParser.js +40 -0
- package/build/separatedNonEmptyArrayParser.test.d.ts +1 -0
- package/build/separatedNonEmptyArrayParser.test.js +66 -0
- package/build/sequenceBuffer.js +1 -1
- package/build/sequenceTerminatedSequenceParser.d.ts +2 -2
- package/build/sequenceTerminatedSequenceParser.js +3 -3
- package/build/sequenceTerminatedSequenceParser.test.js +1 -1
- package/build/sequenceUnparser.d.ts +1 -1
- package/build/skipToParser.d.ts +1 -1
- package/build/skipToParser.js +2 -2
- package/build/sliceBoundedParser.test.js +4 -9
- package/build/smali.d.ts +1 -1
- package/build/smali.js +6 -2
- package/build/smaliParser.d.ts +62 -6
- package/build/smaliParser.js +1721 -296
- package/build/smaliParser.test.js +338 -43
- package/build/stringFromAsyncIterable.d.ts +1 -0
- package/build/stringFromAsyncIterable.js +7 -0
- package/build/terminatedArrayParser.js +4 -4
- package/build/terminatedArrayParser.test.js +7 -7
- package/build/toAsyncIterator.js +4 -4
- package/build/unionParser.d.ts +1 -1
- package/build/unionParser.js +2 -2
- package/build/unionParser.test.js +3 -3
- package/build/unparser.d.ts +3 -3
- package/build/unparser.js +6 -4
- package/build/unparser.test.js +7 -19
- package/build/unparserContext.d.ts +2 -2
- package/build/unparserContext.js +2 -3
- package/build/unparserError.d.ts +2 -1
- package/build/unparserError.js +2 -1
- package/build/unparserImplementationInvariant.d.ts +1 -1
- package/build/unparserOutputCompanion.d.ts +1 -1
- package/build/unparserOutputCompanion.js +1 -1
- package/build/zipParser.js +1 -1
- package/build/zipUnparser.d.ts +3 -3
- package/build/zipUnparser.js +9 -19
- package/build/zipUnparser.test.js +1 -1
- package/package.json +19 -26
- package/src/allSettledStream.test.ts +2 -2
- package/src/allSettledStream.ts +3 -3
- package/src/androidPackageParser.test.ts +17 -19
- package/src/androidPackageParser.ts +129 -171
- package/src/androidPackageUnparser.test.ts +19 -21
- package/src/androidPackageUnparser.ts +23 -17
- package/src/arbitrarilySlicedAsyncInterable.ts +1 -1
- package/src/arbitrarilySlicedAsyncInterator.ts +4 -4
- package/src/arbitraryDalvikBytecode.ts +992 -0
- package/src/arbitraryDalvikExecutable.ts +434 -0
- package/src/arbitraryDosDateTime.ts +1 -0
- package/src/arbitraryZipStream.ts +1 -1
- package/src/arrayParser.ts +2 -2
- package/src/arrayUnparser.ts +2 -2
- package/src/backsmali.ts +48 -4
- package/src/bsonParser.test.ts +12 -14
- package/src/customInvariant.ts +8 -12
- package/src/dalvikBytecodeParser/formatParsers.ts +376 -17
- package/src/dalvikBytecodeParser/formatSizes.ts +35 -0
- package/src/dalvikBytecodeParser/operationFormats.ts +226 -0
- package/src/dalvikBytecodeParser.ts +1042 -243
- package/src/dalvikBytecodeUnparser/formatUnparsers.ts +442 -0
- package/src/dalvikBytecodeUnparser.test.ts +44 -0
- package/src/dalvikBytecodeUnparser.ts +758 -0
- package/src/dalvikExecutable.ts +110 -48
- package/src/dalvikExecutableParser/stringSyntaxParser.ts +33 -33
- package/src/dalvikExecutableParser/typeParsers.ts +23 -14
- package/src/dalvikExecutableParser/typedNumbers.ts +19 -19
- package/src/dalvikExecutableParser.test.ts +60 -60
- package/src/dalvikExecutableParser.test.ts.md +6 -6
- package/src/dalvikExecutableParser.test.ts.snap +0 -0
- package/src/dalvikExecutableParser.ts +911 -434
- package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +256 -239
- package/src/dalvikExecutableUnparser/annotationUnparsers.ts +135 -0
- package/src/dalvikExecutableUnparser/poolBuilders.ts +189 -0
- package/src/dalvikExecutableUnparser/poolScanners.ts +297 -0
- package/src/dalvikExecutableUnparser/sectionUnparsers.ts +683 -0
- package/src/dalvikExecutableUnparser/utils.ts +149 -0
- package/src/dalvikExecutableUnparser.test.ts +57 -0
- package/src/dalvikExecutableUnparser.ts +581 -0
- package/src/debugLogInputParser.ts +1 -1
- package/src/disjunctionParser.ts +5 -5
- package/src/elementTerminatedArrayParser.test.ts +8 -8
- package/src/elementTerminatedArrayParser.ts +2 -2
- package/src/elementTerminatedSequenceArrayParser.test.ts +4 -6
- package/src/elementTerminatedSequenceArrayParser.ts +2 -2
- package/src/elementTerminatedSequenceParser.test.ts +4 -6
- package/src/elementTerminatedSequenceParser.ts +2 -2
- package/src/endOfInputParser.ts +1 -1
- package/src/exactElementSwitchParser.ts +41 -0
- package/src/fetchCid.test.ts +20 -0
- package/src/fetchCid.ts +3 -7
- package/src/fixedLengthSequenceParser.test.ts +10 -12
- package/src/hasExecutable.ts +2 -2
- package/src/highResolutionTimer.ts +1 -1
- package/src/inputReader.test.ts +39 -52
- package/src/inputReader.ts +2 -4
- package/src/inputReaderState.ts +1 -1
- package/src/inspect.ts +1 -1
- package/src/javaKeyStoreParser.test.ts +12 -14
- package/src/javaKeyStoreParser.ts +2 -6
- package/src/jsonParser.test.ts +2 -4
- package/src/jsonParser.ts +34 -38
- package/src/lazyMessageError.test.ts +21 -0
- package/src/lazyMessageError.ts +88 -0
- package/src/leb128Parser.test.ts +25 -23
- package/src/leb128Parser.ts +19 -19
- package/src/negativeLookaheadParser.test.ts +7 -11
- package/src/negativeLookaheadParser.ts +2 -2
- package/src/noStackCaptureOverheadError.test.ts +17 -0
- package/src/noStackCaptureOverheadError.ts +12 -0
- package/src/nonEmptyArrayParser.test.ts +3 -2
- package/src/nonEmptyArrayParser.ts +2 -2
- package/src/optionalParser.ts +2 -2
- package/src/parser.test.ts +96 -43
- package/src/parser.test.ts.md +13 -6
- package/src/parser.test.ts.snap +0 -0
- package/src/parser.ts +35 -12
- package/src/parserAccessorParser.ts +1 -1
- package/src/parserConsumedSequenceParser.ts +3 -3
- package/src/parserContext.test.ts +7 -3
- package/src/parserContext.ts +82 -48
- package/src/parserError.ts +143 -63
- package/src/parserImplementationInvariant.ts +3 -3
- package/src/parserInputCompanion.ts +2 -2
- package/src/promiseCompose.ts +2 -2
- package/src/separatedArrayParser.ts +3 -3
- package/src/separatedNonEmptyArrayParser.test.ts +117 -0
- package/src/separatedNonEmptyArrayParser.ts +61 -0
- package/src/sequenceBuffer.test.ts +9 -9
- package/src/sequenceBuffer.ts +4 -4
- package/src/sequenceTerminatedSequenceParser.test.ts +3 -5
- package/src/sequenceTerminatedSequenceParser.ts +4 -4
- package/src/sequenceUnparser.ts +2 -2
- package/src/skipToParser.ts +2 -2
- package/src/sliceBoundedParser.test.ts +4 -12
- package/src/sliceBoundedParser.ts +2 -2
- package/src/smali.ts +8 -3
- package/src/smaliParser.test.ts +377 -66
- package/src/smaliParser.test.ts.md +1635 -48
- package/src/smaliParser.test.ts.snap +0 -0
- package/src/smaliParser.ts +2751 -569
- package/src/stringFromAsyncIterable.ts +9 -0
- package/src/terminatedArrayParser.test.ts +11 -11
- package/src/terminatedArrayParser.ts +5 -7
- package/src/toAsyncIterator.ts +8 -8
- package/src/uint8Array.ts +2 -3
- package/src/unionParser.test.ts +22 -23
- package/src/unionParser.ts +6 -8
- package/src/unparser.test.ts +18 -34
- package/src/unparser.ts +13 -9
- package/src/unparserContext.ts +9 -13
- package/src/unparserError.ts +2 -1
- package/src/unparserImplementationInvariant.ts +1 -1
- package/src/unparserOutputCompanion.ts +1 -1
- package/src/zip.ts +2 -6
- package/src/zipParser.ts +10 -18
- package/src/zipUnparser.test.ts +1 -1
- package/src/zipUnparser.ts +52 -64
- package/tsconfig.json +7 -1
- package/xo.config.ts +15 -0
- package/.yarn/releases/yarn-4.5.3.cjs +0 -934
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import invariant from 'invariant';
|
|
2
|
-
import { MUtf8Decoder } from
|
|
2
|
+
import { MUtf8Decoder } from 'mutf-8';
|
|
3
|
+
import { type Iso } from 'monocle-ts';
|
|
3
4
|
import { createExactElementParser } from './exactElementParser.js';
|
|
4
5
|
import { createExactSequenceParser } from './exactSequenceParser.js';
|
|
5
6
|
import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js';
|
|
@@ -11,19 +12,69 @@ import { createTupleParser } from './tupleParser.js';
|
|
|
11
12
|
import { createParserAccessorParser } from './parserAccessorParser.js';
|
|
12
13
|
import { createSkipToParser } from './skipToParser.js';
|
|
13
14
|
import { createLookaheadParser } from './lookaheadParser.js';
|
|
14
|
-
import {
|
|
15
|
-
|
|
15
|
+
import {
|
|
16
|
+
getIsoTypedNumberArray,
|
|
17
|
+
type IndexIntoFieldIds,
|
|
18
|
+
type IndexIntoMethodIds,
|
|
19
|
+
type IndexIntoPrototypeIds,
|
|
20
|
+
type IndexIntoStringIds,
|
|
21
|
+
type IndexIntoTypeIds,
|
|
22
|
+
isoIndexIntoFieldIds,
|
|
23
|
+
isoIndexIntoMethodIds,
|
|
24
|
+
isoIndexIntoPrototypeIds,
|
|
25
|
+
isoIndexIntoStringIds,
|
|
26
|
+
isoIndexIntoTypeIds,
|
|
27
|
+
isoOffsetFromEncodedCatchHandlerListToEncodedCatchHandler,
|
|
28
|
+
isoOffsetToAnnotationItem,
|
|
29
|
+
isoOffsetToAnnotationsDirectoryItem,
|
|
30
|
+
isoOffsetToAnnotationSetItem,
|
|
31
|
+
isoOffsetToAnnotationSetRefListItem,
|
|
32
|
+
isoOffsetToClassDataItem,
|
|
33
|
+
isoOffsetToCodeItem,
|
|
34
|
+
isoOffsetToDebugInfoItem,
|
|
35
|
+
isoOffsetToEncodedArrayItem,
|
|
36
|
+
isoOffsetToStringDataItem,
|
|
37
|
+
isoOffsetToTypeList,
|
|
38
|
+
type OffsetFromEncodedCatchHandlerListToEncodedCatchHandler,
|
|
39
|
+
type OffsetToAnnotationItem,
|
|
40
|
+
type OffsetToAnnotationsDirectoryItem,
|
|
41
|
+
type OffsetToAnnotationSetItem,
|
|
42
|
+
type OffsetToAnnotationSetRefListItem,
|
|
43
|
+
type OffsetToClassDataItem,
|
|
44
|
+
type OffsetToCodeItem,
|
|
45
|
+
type OffsetToDebugInfoItem,
|
|
46
|
+
type OffsetToEncodedArrayItem,
|
|
47
|
+
type OffsetToStringDataItem,
|
|
48
|
+
type OffsetToTypeList,
|
|
49
|
+
type TypedNumberArray,
|
|
50
|
+
} from './dalvikExecutableParser/typedNumbers.js';
|
|
16
51
|
import { sleb128NumberParser, uleb128NumberParser } from './leb128Parser.js';
|
|
17
52
|
import { createDisjunctionParser } from './disjunctionParser.js';
|
|
18
53
|
import { createElementTerminatedSequenceParser } from './elementTerminatedSequenceParser.js';
|
|
19
54
|
import { createElementTerminatedArrayParserUnsafe } from './elementTerminatedArrayParser.js';
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
55
|
+
import {
|
|
56
|
+
createDalvikBytecodeParser, type DalvikBytecode, type DalvikBytecodeOperation, type DalvikBytecodeOperationResolvers, resolveDalvikBytecodeOperation,
|
|
57
|
+
} from './dalvikBytecodeParser.js';
|
|
58
|
+
import {
|
|
59
|
+
byteParser, ubyteParser, uintParser, uleb128p1NumberParser, ushortParser,
|
|
60
|
+
} from './dalvikExecutableParser/typeParsers.js';
|
|
61
|
+
import {
|
|
62
|
+
type DalvikExecutable,
|
|
63
|
+
type DalvikExecutableAccessFlags,
|
|
64
|
+
type DalvikExecutableAnnotation,
|
|
65
|
+
type DalvikExecutableClassAnnotations,
|
|
66
|
+
type DalvikExecutableClassData,
|
|
67
|
+
type DalvikExecutableClassFieldAnnotation,
|
|
68
|
+
type DalvikExecutableClassMethodAnnotation,
|
|
69
|
+
type DalvikExecutableClassParameterAnnotation,
|
|
70
|
+
type DalvikExecutableCode,
|
|
71
|
+
type DalvikExecutableDebugInfo,
|
|
72
|
+
type DalvikExecutableEncodedValue,
|
|
73
|
+
} from './dalvikExecutable.js';
|
|
23
74
|
|
|
24
75
|
// https://source.android.com/docs/core/runtime/dex-format
|
|
25
76
|
|
|
26
|
-
const createByteAlignParser = (byteAlignment: number): Parser<void, Uint8Array> => async
|
|
77
|
+
const createByteAlignParser = (byteAlignment: number): Parser<void, Uint8Array> => async parserContext => {
|
|
27
78
|
const toSkip = (byteAlignment - (parserContext.position % byteAlignment)) % byteAlignment;
|
|
28
79
|
|
|
29
80
|
parserContext.skip(toSkip);
|
|
@@ -46,8 +97,8 @@ const dalvikExecutableHeaderVersionParser: Parser<number, Uint8Array> = promiseC
|
|
|
46
97
|
);
|
|
47
98
|
|
|
48
99
|
type SizeOffset = {
|
|
49
|
-
size: number
|
|
50
|
-
offset: number
|
|
100
|
+
size: number;
|
|
101
|
+
offset: number;
|
|
51
102
|
};
|
|
52
103
|
|
|
53
104
|
const sizeOffsetParser: Parser<SizeOffset, Uint8Array> = promiseCompose(
|
|
@@ -59,21 +110,21 @@ const sizeOffsetParser: Parser<SizeOffset, Uint8Array> = promiseCompose(
|
|
|
59
110
|
);
|
|
60
111
|
|
|
61
112
|
type DalvikExecutableHeaderItem = {
|
|
62
|
-
version: number
|
|
63
|
-
checksum: number
|
|
64
|
-
sha1Hash: Uint8Array
|
|
65
|
-
fileSize: number
|
|
66
|
-
headerSize: number
|
|
67
|
-
endianTag: number
|
|
68
|
-
link: SizeOffset
|
|
69
|
-
mapOffset: number
|
|
70
|
-
stringIds: SizeOffset
|
|
71
|
-
typeIds: SizeOffset
|
|
72
|
-
prototypeIds: SizeOffset
|
|
73
|
-
fieldIds: SizeOffset
|
|
74
|
-
methodIds: SizeOffset
|
|
75
|
-
classDefinitions: SizeOffset
|
|
76
|
-
data: SizeOffset
|
|
113
|
+
version: number;
|
|
114
|
+
checksum: number;
|
|
115
|
+
sha1Hash: Uint8Array;
|
|
116
|
+
fileSize: number;
|
|
117
|
+
headerSize: number;
|
|
118
|
+
endianTag: number;
|
|
119
|
+
link: SizeOffset;
|
|
120
|
+
mapOffset: number;
|
|
121
|
+
stringIds: SizeOffset;
|
|
122
|
+
typeIds: SizeOffset;
|
|
123
|
+
prototypeIds: SizeOffset;
|
|
124
|
+
fieldIds: SizeOffset;
|
|
125
|
+
methodIds: SizeOffset;
|
|
126
|
+
classDefinitions: SizeOffset;
|
|
127
|
+
data: SizeOffset;
|
|
77
128
|
};
|
|
78
129
|
|
|
79
130
|
const dalvikExecutableHeaderItemParser: Parser<DalvikExecutableHeaderItem, Uint8Array> = promiseCompose(
|
|
@@ -133,7 +184,7 @@ type DalvikExecutableStringIdItem = OffsetToStringDataItem;
|
|
|
133
184
|
|
|
134
185
|
const dalvikExecutableStringIdItemParser: Parser<DalvikExecutableStringIdItem, Uint8Array> = promiseCompose(
|
|
135
186
|
cloneParser(uintParser),
|
|
136
|
-
|
|
187
|
+
offset => isoOffsetToStringDataItem.wrap(offset),
|
|
137
188
|
);
|
|
138
189
|
|
|
139
190
|
type DalvikExecutableStringIdItems = TypedNumberArray<IndexIntoStringIds, DalvikExecutableStringIdItem>;
|
|
@@ -159,7 +210,7 @@ type DalvikExecutableTypeIdItem = IndexIntoStringIds;
|
|
|
159
210
|
|
|
160
211
|
const dalvikExecutableTypeIdItemParser: Parser<DalvikExecutableTypeIdItem, Uint8Array> = promiseCompose(
|
|
161
212
|
cloneParser(uintParser),
|
|
162
|
-
|
|
213
|
+
index => isoIndexIntoStringIds.wrap(index),
|
|
163
214
|
);
|
|
164
215
|
|
|
165
216
|
type DalvikExecutableTypeIdItems = TypedNumberArray<IndexIntoTypeIds, DalvikExecutableTypeIdItem>;
|
|
@@ -233,7 +284,7 @@ const createSkipToThenItemByOffsetParser = <Offset, Item>({
|
|
|
233
284
|
isoOffset: Iso<Offset, number>;
|
|
234
285
|
parserName: string;
|
|
235
286
|
}): Parser<Map<Offset, Item>, Uint8Array> => {
|
|
236
|
-
const skipToThenItemByOffsetParser: Parser<Map<Offset, Item>, Uint8Array> = async
|
|
287
|
+
const skipToThenItemByOffsetParser: Parser<Map<Offset, Item>, Uint8Array> = async parserContext => {
|
|
237
288
|
const itemByOffset = new Map<Offset, Item>();
|
|
238
289
|
|
|
239
290
|
if (size === 0) {
|
|
@@ -338,54 +389,62 @@ const createSkipToThenMethodIdItemsParser = ({ size, offset }: SizeOffset): Pars
|
|
|
338
389
|
)
|
|
339
390
|
);
|
|
340
391
|
|
|
392
|
+
const parseAccessFlagsCommon = (flags: number): DalvikExecutableAccessFlags => ({
|
|
393
|
+
public: Boolean(flags & 0b0000_0001),
|
|
394
|
+
private: Boolean(flags & 0b0000_0010),
|
|
395
|
+
protected: Boolean(flags & 0b0000_0100),
|
|
396
|
+
static: Boolean(flags & 0b0000_1000),
|
|
397
|
+
final: Boolean(flags & 0b0001_0000),
|
|
398
|
+
synchronized: Boolean(flags & 0b0010_0000),
|
|
399
|
+
volatile: false,
|
|
400
|
+
bridge: false,
|
|
401
|
+
transient: Boolean(flags & 0b1000_0000),
|
|
402
|
+
varargs: Boolean(flags & 0b1000_0000),
|
|
403
|
+
native: Boolean(flags & 0b0000_0001_0000_0000),
|
|
404
|
+
interface: Boolean(flags & 0b0000_0010_0000_0000),
|
|
405
|
+
abstract: Boolean(flags & 0b0000_0100_0000_0000),
|
|
406
|
+
strict: Boolean(flags & 0b0000_1000_0000_0000),
|
|
407
|
+
synthetic: Boolean(flags & 0b0001_0000_0000_0000),
|
|
408
|
+
annotation: Boolean(flags & 0b0010_0000_0000_0000),
|
|
409
|
+
enum: Boolean(flags & 0b0100_0000_0000_0000),
|
|
410
|
+
constructor: Boolean(flags & 0b0000_0001_0000_0000_0000_0000),
|
|
411
|
+
declaredSynchronized: Boolean(flags & 0b0000_0010_0000_0000_0000_0000),
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
const parseAccessFlags = (flags: number): DalvikExecutableAccessFlags => parseAccessFlagsCommon(flags);
|
|
415
|
+
|
|
416
|
+
const parseFieldAccessFlags = (flags: number): DalvikExecutableAccessFlags => ({
|
|
417
|
+
...parseAccessFlagsCommon(flags),
|
|
418
|
+
volatile: Boolean(flags & 0b0100_0000),
|
|
419
|
+
varargs: false, // Varargs is only for methods, not fields
|
|
420
|
+
bridge: false,
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
const parseMethodAccessFlags = (flags: number): DalvikExecutableAccessFlags => ({
|
|
424
|
+
...parseAccessFlagsCommon(flags),
|
|
425
|
+
volatile: false,
|
|
426
|
+
transient: false, // Transient is only for fields, not methods
|
|
427
|
+
bridge: Boolean(flags & 0b0100_0000),
|
|
428
|
+
});
|
|
429
|
+
|
|
341
430
|
const uintAccessFlagsParser: Parser<DalvikExecutableAccessFlags, Uint8Array> = promiseCompose(
|
|
342
431
|
uintParser,
|
|
343
|
-
|
|
344
|
-
public: Boolean(flags & 0b00000001),
|
|
345
|
-
private: Boolean(flags & 0b00000010),
|
|
346
|
-
protected: Boolean(flags & 0b00000100),
|
|
347
|
-
static: Boolean(flags & 0b00001000),
|
|
348
|
-
final: Boolean(flags & 0b00010000),
|
|
349
|
-
synchronized: Boolean(flags & 0b00100000),
|
|
350
|
-
volatile: Boolean(flags & 0b01000000),
|
|
351
|
-
bridge: Boolean(flags & 0b01000000),
|
|
352
|
-
transient: Boolean(flags & 0b10000000),
|
|
353
|
-
varargs: Boolean(flags & 0b10000000),
|
|
354
|
-
native: false,
|
|
355
|
-
interface: false,
|
|
356
|
-
abstract: false,
|
|
357
|
-
strict: false,
|
|
358
|
-
synthetic: false,
|
|
359
|
-
annotation: false,
|
|
360
|
-
enum: false,
|
|
361
|
-
constructor: false,
|
|
362
|
-
declaredSynchronized: false,
|
|
363
|
-
}),
|
|
432
|
+
parseAccessFlags,
|
|
364
433
|
);
|
|
365
434
|
|
|
366
435
|
const uleb128AccessFlagsParser: Parser<DalvikExecutableAccessFlags, Uint8Array> = promiseCompose(
|
|
367
436
|
uleb128NumberParser,
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
native: Boolean(flags & 0b00000001_00000000),
|
|
380
|
-
interface: Boolean(flags & 0b00000010_00000000),
|
|
381
|
-
abstract: Boolean(flags & 0b00000100_00000000),
|
|
382
|
-
strict: Boolean(flags & 0b00001000_00000000),
|
|
383
|
-
synthetic: Boolean(flags & 0b00010000_00000000),
|
|
384
|
-
annotation: Boolean(flags & 0b00100000_00000000),
|
|
385
|
-
enum: Boolean(flags & 0b01000000_00000000),
|
|
386
|
-
constructor: Boolean(flags & 0b00000001_00000000_00000000),
|
|
387
|
-
declaredSynchronized: Boolean(flags & 0b00000010_00000000_00000000),
|
|
388
|
-
}),
|
|
437
|
+
parseAccessFlags,
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
const uleb128FieldAccessFlagsParser: Parser<DalvikExecutableAccessFlags, Uint8Array> = promiseCompose(
|
|
441
|
+
uleb128NumberParser,
|
|
442
|
+
parseFieldAccessFlags,
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
const uleb128MethodAccessFlagsParser: Parser<DalvikExecutableAccessFlags, Uint8Array> = promiseCompose(
|
|
446
|
+
uleb128NumberParser,
|
|
447
|
+
parseMethodAccessFlags,
|
|
389
448
|
);
|
|
390
449
|
|
|
391
450
|
type DalvikExecutableClassDefinitionItem = {
|
|
@@ -399,7 +458,7 @@ type DalvikExecutableClassDefinitionItem = {
|
|
|
399
458
|
staticValuesOffset: OffsetToEncodedArrayItem;
|
|
400
459
|
};
|
|
401
460
|
|
|
402
|
-
const DEX_CLASS_DEFINITION_ITEM_SOURCE_FILE_NO_INDEX =
|
|
461
|
+
const DEX_CLASS_DEFINITION_ITEM_SOURCE_FILE_NO_INDEX = 0xFF_FF_FF_FF;
|
|
403
462
|
|
|
404
463
|
const createSkipToThenClassDefinitionItemsParser = ({ size, offset }: SizeOffset): Parser<DalvikExecutableClassDefinitionItem[], Uint8Array> => (
|
|
405
464
|
size === 0
|
|
@@ -470,9 +529,7 @@ type DalvikExecutableStringDataItem = {
|
|
|
470
529
|
const stringDataItemParser: Parser<DalvikExecutableStringDataItem, Uint8Array> = promiseCompose(
|
|
471
530
|
createTupleParser([
|
|
472
531
|
uleb128NumberParser,
|
|
473
|
-
createElementTerminatedSequenceParser(
|
|
474
|
-
0,
|
|
475
|
-
),
|
|
532
|
+
createElementTerminatedSequenceParser(0),
|
|
476
533
|
]),
|
|
477
534
|
([ utf16Size, data ]) => ({
|
|
478
535
|
utf16Size,
|
|
@@ -506,7 +563,7 @@ type DalvikExecutableTypeItem = IndexIntoTypeIds;
|
|
|
506
563
|
|
|
507
564
|
const dalvikExecutableTypeItemParser: Parser<DalvikExecutableTypeItem, Uint8Array> = promiseCompose(
|
|
508
565
|
cloneParser(ushortParser),
|
|
509
|
-
|
|
566
|
+
index => isoIndexIntoTypeIds.wrap(index),
|
|
510
567
|
);
|
|
511
568
|
|
|
512
569
|
type DalvikExecutableTypeList = TypedNumberArray<IndexIntoTypeIds, DalvikExecutableTypeItem>;
|
|
@@ -523,7 +580,7 @@ const dalvikExecutableTypeListParser: Parser<DalvikExecutableTypeList, Uint8Arra
|
|
|
523
580
|
dalvikExecutableTypeItemParser,
|
|
524
581
|
size,
|
|
525
582
|
),
|
|
526
|
-
|
|
583
|
+
typeItems => isoDalvikExecutableTypeList.wrap(typeItems),
|
|
527
584
|
),
|
|
528
585
|
)();
|
|
529
586
|
|
|
@@ -669,7 +726,7 @@ type DalvikExecutableEncodedFieldDiff = {
|
|
|
669
726
|
const encodedFieldParser: Parser<DalvikExecutableEncodedFieldDiff, Uint8Array> = promiseCompose(
|
|
670
727
|
createTupleParser([
|
|
671
728
|
uleb128NumberParser,
|
|
672
|
-
|
|
729
|
+
uleb128FieldAccessFlagsParser,
|
|
673
730
|
]),
|
|
674
731
|
([ fieldIndexDiff, accessFlags ]) => ({ fieldIndexDiff, accessFlags }),
|
|
675
732
|
);
|
|
@@ -684,7 +741,7 @@ const createEncodedFieldsParser = (fieldsSize: number): Parser<DalvikExecutableE
|
|
|
684
741
|
encodedFieldParser,
|
|
685
742
|
fieldsSize,
|
|
686
743
|
),
|
|
687
|
-
|
|
744
|
+
encodedFields => {
|
|
688
745
|
let previousFieldIndex = 0;
|
|
689
746
|
return encodedFields.map(({ fieldIndexDiff, accessFlags }) => {
|
|
690
747
|
previousFieldIndex += fieldIndexDiff;
|
|
@@ -705,7 +762,7 @@ type DalvikExecutableEncodedMethodDiff = {
|
|
|
705
762
|
const encodedMethodParser: Parser<DalvikExecutableEncodedMethodDiff, Uint8Array> = promiseCompose(
|
|
706
763
|
createTupleParser([
|
|
707
764
|
uleb128NumberParser,
|
|
708
|
-
|
|
765
|
+
uleb128MethodAccessFlagsParser,
|
|
709
766
|
uleb128NumberParser,
|
|
710
767
|
]),
|
|
711
768
|
([
|
|
@@ -730,7 +787,7 @@ const createEncodedMethodsParser = (methodsSize: number): Parser<DalvikExecutabl
|
|
|
730
787
|
encodedMethodParser,
|
|
731
788
|
methodsSize,
|
|
732
789
|
),
|
|
733
|
-
|
|
790
|
+
encodedMethods => {
|
|
734
791
|
let previousMethodIndex = 0;
|
|
735
792
|
return encodedMethods.map(({ methodIndexDiff, accessFlags, codeOffset }) => {
|
|
736
793
|
previousMethodIndex += methodIndexDiff;
|
|
@@ -744,10 +801,10 @@ const createEncodedMethodsParser = (methodsSize: number): Parser<DalvikExecutabl
|
|
|
744
801
|
);
|
|
745
802
|
|
|
746
803
|
type DalvikExecutableClassDataItem = {
|
|
747
|
-
staticFields: DalvikExecutableEncodedField[]
|
|
748
|
-
instanceFields: DalvikExecutableEncodedField[]
|
|
749
|
-
directMethods: DalvikExecutableEncodedMethod[]
|
|
750
|
-
virtualMethods: DalvikExecutableEncodedMethod[]
|
|
804
|
+
staticFields: DalvikExecutableEncodedField[];
|
|
805
|
+
instanceFields: DalvikExecutableEncodedField[];
|
|
806
|
+
directMethods: DalvikExecutableEncodedMethod[];
|
|
807
|
+
virtualMethods: DalvikExecutableEncodedMethod[];
|
|
751
808
|
};
|
|
752
809
|
|
|
753
810
|
const classDataItemParser: Parser<DalvikExecutableClassDataItem, Uint8Array> = parserCreatorCompose(
|
|
@@ -793,11 +850,33 @@ const createSkipToThenClassDataItemsParser = (sizeOffset: SizeOffset): Parser<Da
|
|
|
793
850
|
parserName: 'skipToThenClassDataItemsParser',
|
|
794
851
|
});
|
|
795
852
|
|
|
853
|
+
// Internal type for encoded values with type tags during parsing
|
|
854
|
+
type DalvikExecutableTaggedEncodedValue =
|
|
855
|
+
| { type: 'byte'; value: number }
|
|
856
|
+
| { type: 'short'; value: number }
|
|
857
|
+
| { type: 'char'; value: number }
|
|
858
|
+
| { type: 'int'; value: number }
|
|
859
|
+
| { type: 'long'; value: bigint }
|
|
860
|
+
| { type: 'float'; value: number }
|
|
861
|
+
| { type: 'double'; value: number }
|
|
862
|
+
| { type: 'methodType'; value: IndexIntoPrototypeIds }
|
|
863
|
+
| { type: 'methodHandle'; value: number }
|
|
864
|
+
| { type: 'string'; value: IndexIntoStringIds }
|
|
865
|
+
| { type: 'type'; value: IndexIntoTypeIds }
|
|
866
|
+
| { type: 'field'; value: IndexIntoFieldIds }
|
|
867
|
+
| { type: 'method'; value: IndexIntoMethodIds }
|
|
868
|
+
| { type: 'enum'; value: IndexIntoFieldIds }
|
|
869
|
+
| { type: 'array'; value: DalvikExecutableTaggedEncodedValue[] }
|
|
870
|
+
| { type: 'annotation'; value: DalvikExecutableEncodedAnnotation }
|
|
871
|
+
// eslint-disable-next-line @typescript-eslint/no-restricted-types
|
|
872
|
+
| { type: 'null'; value: null }
|
|
873
|
+
| { type: 'boolean'; value: boolean };
|
|
874
|
+
|
|
796
875
|
const createByteWith5LeastSignificantBitsEqualParser = (leastSignificant5: number): Parser<number, Uint8Array> => {
|
|
797
|
-
const byteWith5LeastSignificantBitsEqualParser: Parser<number, Uint8Array> = async
|
|
876
|
+
const byteWith5LeastSignificantBitsEqualParser: Parser<number, Uint8Array> = async parserContext => {
|
|
798
877
|
const byte = await parserContext.read(0);
|
|
799
878
|
parserContext.invariant(
|
|
800
|
-
(byte &
|
|
879
|
+
(byte & 0b0001_1111) === leastSignificant5,
|
|
801
880
|
'Expected byte with 5 least significant bits equal to %s, but got %s',
|
|
802
881
|
leastSignificant5.toString(2).padStart(8, '0'),
|
|
803
882
|
byte.toString(2).padStart(8, '0'),
|
|
@@ -812,20 +891,20 @@ const createByteWith5LeastSignificantBitsEqualParser = (leastSignificant5: numbe
|
|
|
812
891
|
|
|
813
892
|
const createEncodedValueArgParser = (valueType: number): Parser<number, Uint8Array> => promiseCompose(
|
|
814
893
|
createByteWith5LeastSignificantBitsEqualParser(valueType),
|
|
815
|
-
|
|
894
|
+
byte => byte >> 5,
|
|
816
895
|
);
|
|
817
896
|
|
|
818
|
-
const encodedValueByteParser: Parser<
|
|
897
|
+
const encodedValueByteParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = promiseCompose(
|
|
819
898
|
createTupleParser([
|
|
820
899
|
createExactElementParser(0),
|
|
821
|
-
|
|
900
|
+
byteParser,
|
|
822
901
|
]),
|
|
823
|
-
([ _, value ]) => value,
|
|
902
|
+
([ _, value ]) => ({ type: 'byte' as const, value }),
|
|
824
903
|
);
|
|
825
904
|
|
|
826
905
|
setParserName(encodedValueByteParser, 'encodedValueByteParser');
|
|
827
906
|
|
|
828
|
-
const encodedValueShortParser: Parser<
|
|
907
|
+
const encodedValueShortParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
829
908
|
() => createEncodedValueArgParser(0x02),
|
|
830
909
|
sizeSubOne => {
|
|
831
910
|
const size = sizeSubOne + 1;
|
|
@@ -833,9 +912,9 @@ const encodedValueShortParser: Parser<number, Uint8Array> = parserCreatorCompose
|
|
|
833
912
|
if (size === 1) {
|
|
834
913
|
return promiseCompose(
|
|
835
914
|
createFixedLengthSequenceParser(size),
|
|
836
|
-
|
|
915
|
+
uint8Array => {
|
|
837
916
|
const buffer = Buffer.from(uint8Array);
|
|
838
|
-
return buffer.readInt8(0);
|
|
917
|
+
return { type: 'short' as const, value: buffer.readInt8(0) };
|
|
839
918
|
},
|
|
840
919
|
);
|
|
841
920
|
}
|
|
@@ -844,9 +923,9 @@ const encodedValueShortParser: Parser<number, Uint8Array> = parserCreatorCompose
|
|
|
844
923
|
|
|
845
924
|
return promiseCompose(
|
|
846
925
|
createFixedLengthSequenceParser(size),
|
|
847
|
-
|
|
926
|
+
uint8Array => {
|
|
848
927
|
const buffer = Buffer.from(uint8Array);
|
|
849
|
-
return buffer.readInt16LE(0);
|
|
928
|
+
return { type: 'short' as const, value: buffer.readInt16LE(0) };
|
|
850
929
|
},
|
|
851
930
|
);
|
|
852
931
|
},
|
|
@@ -854,7 +933,7 @@ const encodedValueShortParser: Parser<number, Uint8Array> = parserCreatorCompose
|
|
|
854
933
|
|
|
855
934
|
setParserName(encodedValueShortParser, 'encodedValueShortParser');
|
|
856
935
|
|
|
857
|
-
const encodedValueCharParser: Parser<
|
|
936
|
+
const encodedValueCharParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
858
937
|
() => createEncodedValueArgParser(0x03),
|
|
859
938
|
sizeSubOne => {
|
|
860
939
|
const size = sizeSubOne + 1;
|
|
@@ -862,9 +941,9 @@ const encodedValueCharParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
862
941
|
if (size == 1) {
|
|
863
942
|
return promiseCompose(
|
|
864
943
|
createFixedLengthSequenceParser(size),
|
|
865
|
-
|
|
866
|
-
const buffer = Buffer.from([
|
|
867
|
-
return buffer.readUInt16LE(0);
|
|
944
|
+
uint8Array => {
|
|
945
|
+
const buffer = Buffer.from([ ...uint8Array, 0 ]);
|
|
946
|
+
return { type: 'char' as const, value: buffer.readUInt16LE(0) };
|
|
868
947
|
},
|
|
869
948
|
);
|
|
870
949
|
}
|
|
@@ -873,9 +952,9 @@ const encodedValueCharParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
873
952
|
|
|
874
953
|
return promiseCompose(
|
|
875
954
|
createFixedLengthSequenceParser(size),
|
|
876
|
-
|
|
955
|
+
uint8Array => {
|
|
877
956
|
const buffer = Buffer.from(uint8Array);
|
|
878
|
-
return buffer.readUInt16LE(0);
|
|
957
|
+
return { type: 'char' as const, value: buffer.readUInt16LE(0) };
|
|
879
958
|
},
|
|
880
959
|
);
|
|
881
960
|
},
|
|
@@ -883,7 +962,7 @@ const encodedValueCharParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
883
962
|
|
|
884
963
|
setParserName(encodedValueCharParser, 'encodedValueCharParser');
|
|
885
964
|
|
|
886
|
-
const encodedValueIntParser: Parser<
|
|
965
|
+
const encodedValueIntParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
887
966
|
() => createEncodedValueArgParser(0x04),
|
|
888
967
|
sizeSubOne => {
|
|
889
968
|
const size = sizeSubOne + 1;
|
|
@@ -891,9 +970,9 @@ const encodedValueIntParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
891
970
|
if (size === 1) {
|
|
892
971
|
return promiseCompose(
|
|
893
972
|
createFixedLengthSequenceParser(size),
|
|
894
|
-
|
|
973
|
+
uint8Array => {
|
|
895
974
|
const buffer = Buffer.from(uint8Array);
|
|
896
|
-
return buffer.readInt8(0);
|
|
975
|
+
return { type: 'int' as const, value: buffer.readInt8(0) };
|
|
897
976
|
},
|
|
898
977
|
);
|
|
899
978
|
}
|
|
@@ -901,9 +980,9 @@ const encodedValueIntParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
901
980
|
if (size === 2) {
|
|
902
981
|
return promiseCompose(
|
|
903
982
|
createFixedLengthSequenceParser(size),
|
|
904
|
-
|
|
983
|
+
uint8Array => {
|
|
905
984
|
const buffer = Buffer.from(uint8Array);
|
|
906
|
-
return buffer.readInt16LE(0);
|
|
985
|
+
return { type: 'int' as const, value: buffer.readInt16LE(0) };
|
|
907
986
|
},
|
|
908
987
|
);
|
|
909
988
|
}
|
|
@@ -911,13 +990,13 @@ const encodedValueIntParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
911
990
|
if (size === 3) {
|
|
912
991
|
return promiseCompose(
|
|
913
992
|
createFixedLengthSequenceParser(size),
|
|
914
|
-
|
|
915
|
-
const
|
|
916
|
-
const
|
|
917
|
-
const extensionByte =
|
|
993
|
+
uint8Array => {
|
|
994
|
+
const lastByte = uint8Array[uint8Array.length - 1];
|
|
995
|
+
const signBit = (lastByte & 0b1000_0000) >> 7;
|
|
996
|
+
const extensionByte = signBit === 1 ? 0xFF : 0x00;
|
|
918
997
|
|
|
919
|
-
const buffer = Buffer.from([
|
|
920
|
-
return buffer.readInt32LE(0);
|
|
998
|
+
const buffer = Buffer.from([ ...uint8Array, extensionByte ]);
|
|
999
|
+
return { type: 'int' as const, value: buffer.readInt32LE(0) };
|
|
921
1000
|
},
|
|
922
1001
|
);
|
|
923
1002
|
}
|
|
@@ -926,9 +1005,9 @@ const encodedValueIntParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
926
1005
|
|
|
927
1006
|
return promiseCompose(
|
|
928
1007
|
createFixedLengthSequenceParser(size),
|
|
929
|
-
|
|
1008
|
+
uint8Array => {
|
|
930
1009
|
const buffer = Buffer.from(uint8Array);
|
|
931
|
-
return buffer.readInt32LE(0);
|
|
1010
|
+
return { type: 'int' as const, value: buffer.readInt32LE(0) };
|
|
932
1011
|
},
|
|
933
1012
|
);
|
|
934
1013
|
},
|
|
@@ -936,7 +1015,7 @@ const encodedValueIntParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
936
1015
|
|
|
937
1016
|
setParserName(encodedValueIntParser, 'encodedValueIntParser');
|
|
938
1017
|
|
|
939
|
-
const encodedValueLongParser: Parser<
|
|
1018
|
+
const encodedValueLongParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
940
1019
|
() => createEncodedValueArgParser(0x06),
|
|
941
1020
|
sizeSubOne => {
|
|
942
1021
|
const size = sizeSubOne + 1;
|
|
@@ -944,9 +1023,9 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
|
|
|
944
1023
|
if (size === 1) {
|
|
945
1024
|
return promiseCompose(
|
|
946
1025
|
createFixedLengthSequenceParser(size),
|
|
947
|
-
|
|
1026
|
+
uint8Array => {
|
|
948
1027
|
const buffer = Buffer.from(uint8Array);
|
|
949
|
-
return BigInt(buffer.readInt8(0));
|
|
1028
|
+
return { type: 'long' as const, value: BigInt(buffer.readInt8(0)) };
|
|
950
1029
|
},
|
|
951
1030
|
);
|
|
952
1031
|
}
|
|
@@ -954,9 +1033,9 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
|
|
|
954
1033
|
if (size === 2) {
|
|
955
1034
|
return promiseCompose(
|
|
956
1035
|
createFixedLengthSequenceParser(size),
|
|
957
|
-
|
|
1036
|
+
uint8Array => {
|
|
958
1037
|
const buffer = Buffer.from(uint8Array);
|
|
959
|
-
return BigInt(buffer.readInt16LE(0));
|
|
1038
|
+
return { type: 'long' as const, value: BigInt(buffer.readInt16LE(0)) };
|
|
960
1039
|
},
|
|
961
1040
|
);
|
|
962
1041
|
}
|
|
@@ -964,13 +1043,13 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
|
|
|
964
1043
|
if (size === 3) {
|
|
965
1044
|
return promiseCompose(
|
|
966
1045
|
createFixedLengthSequenceParser(size),
|
|
967
|
-
|
|
968
|
-
const
|
|
969
|
-
const firstBit = (
|
|
970
|
-
const extensionByte = firstBit === 1 ?
|
|
1046
|
+
uint8Array => {
|
|
1047
|
+
const lastByte = uint8Array[size - 1];
|
|
1048
|
+
const firstBit = (lastByte & 0b1000_0000) >> 7;
|
|
1049
|
+
const extensionByte = firstBit === 1 ? 0xFF : 0x00;
|
|
971
1050
|
|
|
972
|
-
const buffer = Buffer.from([
|
|
973
|
-
return BigInt(buffer.readInt32LE(0));
|
|
1051
|
+
const buffer = Buffer.from([ ...uint8Array, extensionByte ]);
|
|
1052
|
+
return { type: 'long' as const, value: BigInt(buffer.readInt32LE(0)) };
|
|
974
1053
|
},
|
|
975
1054
|
);
|
|
976
1055
|
}
|
|
@@ -978,9 +1057,9 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
|
|
|
978
1057
|
if (size === 4) {
|
|
979
1058
|
return promiseCompose(
|
|
980
1059
|
createFixedLengthSequenceParser(size),
|
|
981
|
-
|
|
1060
|
+
uint8Array => {
|
|
982
1061
|
const buffer = Buffer.from(uint8Array);
|
|
983
|
-
return BigInt(buffer.readInt32LE(0));
|
|
1062
|
+
return { type: 'long' as const, value: BigInt(buffer.readInt32LE(0)) };
|
|
984
1063
|
},
|
|
985
1064
|
);
|
|
986
1065
|
}
|
|
@@ -988,13 +1067,41 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
|
|
|
988
1067
|
if (size === 5) {
|
|
989
1068
|
return promiseCompose(
|
|
990
1069
|
createFixedLengthSequenceParser(size),
|
|
991
|
-
|
|
992
|
-
const
|
|
993
|
-
const firstBit = (
|
|
994
|
-
const extensionByte = firstBit === 1 ?
|
|
1070
|
+
uint8Array => {
|
|
1071
|
+
const lastByte = uint8Array[size - 1];
|
|
1072
|
+
const firstBit = (lastByte & 0b1000_0000) >> 7;
|
|
1073
|
+
const extensionByte = firstBit === 1 ? 0xFF : 0x00;
|
|
1074
|
+
|
|
1075
|
+
const buffer = Buffer.from([ ...uint8Array, extensionByte, extensionByte, extensionByte ]);
|
|
1076
|
+
return { type: 'long' as const, value: BigInt(buffer.readBigInt64LE(0)) };
|
|
1077
|
+
},
|
|
1078
|
+
);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
if (size === 6) {
|
|
1082
|
+
return promiseCompose(
|
|
1083
|
+
createFixedLengthSequenceParser(size),
|
|
1084
|
+
uint8Array => {
|
|
1085
|
+
const lastByte = uint8Array[size - 1];
|
|
1086
|
+
const firstBit = (lastByte & 0b1000_0000) >> 7;
|
|
1087
|
+
const extensionByte = firstBit === 1 ? 0xFF : 0x00;
|
|
995
1088
|
|
|
996
|
-
const buffer = Buffer.from([
|
|
997
|
-
return BigInt(buffer.readBigInt64LE(0));
|
|
1089
|
+
const buffer = Buffer.from([ ...uint8Array, extensionByte, extensionByte ]);
|
|
1090
|
+
return { type: 'long' as const, value: BigInt(buffer.readBigInt64LE(0)) };
|
|
1091
|
+
},
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
if (size === 7) {
|
|
1096
|
+
return promiseCompose(
|
|
1097
|
+
createFixedLengthSequenceParser(size),
|
|
1098
|
+
uint8Array => {
|
|
1099
|
+
const lastByte = uint8Array[size - 1];
|
|
1100
|
+
const firstBit = (lastByte & 0b1000_0000) >> 7;
|
|
1101
|
+
const extensionByte = firstBit === 1 ? 0xFF : 0x00;
|
|
1102
|
+
|
|
1103
|
+
const buffer = Buffer.from([ ...uint8Array, extensionByte ]);
|
|
1104
|
+
return { type: 'long' as const, value: BigInt(buffer.readBigInt64LE(0)) };
|
|
998
1105
|
},
|
|
999
1106
|
);
|
|
1000
1107
|
}
|
|
@@ -1003,9 +1110,9 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
|
|
|
1003
1110
|
|
|
1004
1111
|
return promiseCompose(
|
|
1005
1112
|
createFixedLengthSequenceParser(size),
|
|
1006
|
-
|
|
1113
|
+
uint8Array => {
|
|
1007
1114
|
const buffer = Buffer.from(uint8Array);
|
|
1008
|
-
return buffer.readBigInt64LE(0);
|
|
1115
|
+
return { type: 'long' as const, value: buffer.readBigInt64LE(0) };
|
|
1009
1116
|
},
|
|
1010
1117
|
);
|
|
1011
1118
|
},
|
|
@@ -1013,7 +1120,7 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
|
|
|
1013
1120
|
|
|
1014
1121
|
setParserName(encodedValueLongParser, 'encodedValueLongParser');
|
|
1015
1122
|
|
|
1016
|
-
const encodedValueFloatParser: Parser<
|
|
1123
|
+
const encodedValueFloatParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
1017
1124
|
() => createEncodedValueArgParser(0x10),
|
|
1018
1125
|
sizeSubOne => {
|
|
1019
1126
|
const size = sizeSubOne + 1;
|
|
@@ -1021,9 +1128,9 @@ const encodedValueFloatParser: Parser<number, Uint8Array> = parserCreatorCompose
|
|
|
1021
1128
|
if (size === 1) {
|
|
1022
1129
|
return promiseCompose(
|
|
1023
1130
|
createFixedLengthSequenceParser(size),
|
|
1024
|
-
|
|
1025
|
-
const buffer = Buffer.from([
|
|
1026
|
-
return buffer.readFloatLE(0);
|
|
1131
|
+
uint8Array => {
|
|
1132
|
+
const buffer = Buffer.from([ 0, 0, 0, ...uint8Array ]);
|
|
1133
|
+
return { type: 'float' as const, value: buffer.readFloatLE(0) };
|
|
1027
1134
|
},
|
|
1028
1135
|
);
|
|
1029
1136
|
}
|
|
@@ -1031,9 +1138,19 @@ const encodedValueFloatParser: Parser<number, Uint8Array> = parserCreatorCompose
|
|
|
1031
1138
|
if (size === 2) {
|
|
1032
1139
|
return promiseCompose(
|
|
1033
1140
|
createFixedLengthSequenceParser(size),
|
|
1034
|
-
|
|
1035
|
-
const buffer = Buffer.from([
|
|
1036
|
-
return buffer.readFloatLE(0);
|
|
1141
|
+
uint8Array => {
|
|
1142
|
+
const buffer = Buffer.from([ 0, 0, ...uint8Array ]);
|
|
1143
|
+
return { type: 'float' as const, value: buffer.readFloatLE(0) };
|
|
1144
|
+
},
|
|
1145
|
+
);
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
if (size === 3) {
|
|
1149
|
+
return promiseCompose(
|
|
1150
|
+
createFixedLengthSequenceParser(size),
|
|
1151
|
+
uint8Array => {
|
|
1152
|
+
const buffer = Buffer.from([ 0, ...uint8Array ]);
|
|
1153
|
+
return { type: 'float' as const, value: buffer.readFloatLE(0) };
|
|
1037
1154
|
},
|
|
1038
1155
|
);
|
|
1039
1156
|
}
|
|
@@ -1042,9 +1159,9 @@ const encodedValueFloatParser: Parser<number, Uint8Array> = parserCreatorCompose
|
|
|
1042
1159
|
|
|
1043
1160
|
return promiseCompose(
|
|
1044
1161
|
createFixedLengthSequenceParser(size),
|
|
1045
|
-
|
|
1162
|
+
uint8Array => {
|
|
1046
1163
|
const buffer = Buffer.from(uint8Array);
|
|
1047
|
-
return buffer.readFloatLE(0);
|
|
1164
|
+
return { type: 'float' as const, value: buffer.readFloatLE(0) };
|
|
1048
1165
|
},
|
|
1049
1166
|
);
|
|
1050
1167
|
},
|
|
@@ -1052,7 +1169,7 @@ const encodedValueFloatParser: Parser<number, Uint8Array> = parserCreatorCompose
|
|
|
1052
1169
|
|
|
1053
1170
|
setParserName(encodedValueFloatParser, 'encodedValueFloatParser');
|
|
1054
1171
|
|
|
1055
|
-
const encodedValueDoubleParser: Parser<
|
|
1172
|
+
const encodedValueDoubleParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
1056
1173
|
() => createEncodedValueArgParser(0x11),
|
|
1057
1174
|
sizeSubOne => {
|
|
1058
1175
|
const size = sizeSubOne + 1;
|
|
@@ -1060,9 +1177,9 @@ const encodedValueDoubleParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1060
1177
|
if (size === 1) {
|
|
1061
1178
|
return promiseCompose(
|
|
1062
1179
|
createFixedLengthSequenceParser(size),
|
|
1063
|
-
|
|
1064
|
-
const buffer = Buffer.from([
|
|
1065
|
-
return buffer.readDoubleLE(0);
|
|
1180
|
+
uint8Array => {
|
|
1181
|
+
const buffer = Buffer.from([ 0, 0, 0, 0, 0, 0, 0, ...uint8Array ]);
|
|
1182
|
+
return { type: 'double' as const, value: buffer.readDoubleLE(0) };
|
|
1066
1183
|
},
|
|
1067
1184
|
);
|
|
1068
1185
|
}
|
|
@@ -1070,9 +1187,19 @@ const encodedValueDoubleParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1070
1187
|
if (size === 2) {
|
|
1071
1188
|
return promiseCompose(
|
|
1072
1189
|
createFixedLengthSequenceParser(size),
|
|
1073
|
-
|
|
1074
|
-
const buffer = Buffer.from([
|
|
1075
|
-
return buffer.readDoubleLE(0);
|
|
1190
|
+
uint8Array => {
|
|
1191
|
+
const buffer = Buffer.from([ 0, 0, 0, 0, 0, 0, ...uint8Array ]);
|
|
1192
|
+
return { type: 'double' as const, value: buffer.readDoubleLE(0) };
|
|
1193
|
+
},
|
|
1194
|
+
);
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
if (size === 3) {
|
|
1198
|
+
return promiseCompose(
|
|
1199
|
+
createFixedLengthSequenceParser(size),
|
|
1200
|
+
uint8Array => {
|
|
1201
|
+
const buffer = Buffer.from([ 0, 0, 0, 0, 0, ...uint8Array ]);
|
|
1202
|
+
return { type: 'double' as const, value: buffer.readDoubleLE(0) };
|
|
1076
1203
|
},
|
|
1077
1204
|
);
|
|
1078
1205
|
}
|
|
@@ -1080,9 +1207,39 @@ const encodedValueDoubleParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1080
1207
|
if (size === 4) {
|
|
1081
1208
|
return promiseCompose(
|
|
1082
1209
|
createFixedLengthSequenceParser(size),
|
|
1083
|
-
|
|
1084
|
-
const buffer = Buffer.from([
|
|
1085
|
-
return buffer.readDoubleLE(0);
|
|
1210
|
+
uint8Array => {
|
|
1211
|
+
const buffer = Buffer.from([ 0, 0, 0, 0, ...uint8Array ]);
|
|
1212
|
+
return { type: 'double' as const, value: buffer.readDoubleLE(0) };
|
|
1213
|
+
},
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
if (size === 5) {
|
|
1218
|
+
return promiseCompose(
|
|
1219
|
+
createFixedLengthSequenceParser(size),
|
|
1220
|
+
uint8Array => {
|
|
1221
|
+
const buffer = Buffer.from([ 0, 0, 0, ...uint8Array ]);
|
|
1222
|
+
return { type: 'double' as const, value: buffer.readDoubleLE(0) };
|
|
1223
|
+
},
|
|
1224
|
+
);
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
if (size === 6) {
|
|
1228
|
+
return promiseCompose(
|
|
1229
|
+
createFixedLengthSequenceParser(size),
|
|
1230
|
+
uint8Array => {
|
|
1231
|
+
const buffer = Buffer.from([ 0, 0, ...uint8Array ]);
|
|
1232
|
+
return { type: 'double' as const, value: buffer.readDoubleLE(0) };
|
|
1233
|
+
},
|
|
1234
|
+
);
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
if (size === 7) {
|
|
1238
|
+
return promiseCompose(
|
|
1239
|
+
createFixedLengthSequenceParser(size),
|
|
1240
|
+
uint8Array => {
|
|
1241
|
+
const buffer = Buffer.from([ 0, ...uint8Array ]);
|
|
1242
|
+
return { type: 'double' as const, value: buffer.readDoubleLE(0) };
|
|
1086
1243
|
},
|
|
1087
1244
|
);
|
|
1088
1245
|
}
|
|
@@ -1091,9 +1248,9 @@ const encodedValueDoubleParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1091
1248
|
|
|
1092
1249
|
return promiseCompose(
|
|
1093
1250
|
createFixedLengthSequenceParser(size),
|
|
1094
|
-
|
|
1251
|
+
uint8Array => {
|
|
1095
1252
|
const buffer = Buffer.from(uint8Array);
|
|
1096
|
-
return buffer.readDoubleLE(0);
|
|
1253
|
+
return { type: 'double' as const, value: buffer.readDoubleLE(0) };
|
|
1097
1254
|
},
|
|
1098
1255
|
);
|
|
1099
1256
|
},
|
|
@@ -1101,7 +1258,7 @@ const encodedValueDoubleParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1101
1258
|
|
|
1102
1259
|
setParserName(encodedValueDoubleParser, 'encodedValueDoubleParser');
|
|
1103
1260
|
|
|
1104
|
-
const encodedValueMethodTypeParser: Parser<
|
|
1261
|
+
const encodedValueMethodTypeParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
1105
1262
|
() => createEncodedValueArgParser(0x15),
|
|
1106
1263
|
sizeSubOne => {
|
|
1107
1264
|
const size = sizeSubOne + 1;
|
|
@@ -1109,9 +1266,9 @@ const encodedValueMethodTypeParser: Parser<number, Uint8Array> = parserCreatorCo
|
|
|
1109
1266
|
if (size === 1) {
|
|
1110
1267
|
return promiseCompose(
|
|
1111
1268
|
createFixedLengthSequenceParser(size),
|
|
1112
|
-
|
|
1269
|
+
uint8Array => {
|
|
1113
1270
|
const buffer = Buffer.from(uint8Array);
|
|
1114
|
-
return buffer.readUint8(0);
|
|
1271
|
+
return { type: 'methodType' as const, value: isoIndexIntoPrototypeIds.wrap(buffer.readUint8(0)) };
|
|
1115
1272
|
},
|
|
1116
1273
|
);
|
|
1117
1274
|
}
|
|
@@ -1119,9 +1276,9 @@ const encodedValueMethodTypeParser: Parser<number, Uint8Array> = parserCreatorCo
|
|
|
1119
1276
|
if (size === 2) {
|
|
1120
1277
|
return promiseCompose(
|
|
1121
1278
|
createFixedLengthSequenceParser(size),
|
|
1122
|
-
|
|
1279
|
+
uint8Array => {
|
|
1123
1280
|
const buffer = Buffer.from(uint8Array);
|
|
1124
|
-
return buffer.readUInt16LE(0);
|
|
1281
|
+
return { type: 'methodType' as const, value: isoIndexIntoPrototypeIds.wrap(buffer.readUInt16LE(0)) };
|
|
1125
1282
|
},
|
|
1126
1283
|
);
|
|
1127
1284
|
}
|
|
@@ -1130,9 +1287,9 @@ const encodedValueMethodTypeParser: Parser<number, Uint8Array> = parserCreatorCo
|
|
|
1130
1287
|
|
|
1131
1288
|
return promiseCompose(
|
|
1132
1289
|
createFixedLengthSequenceParser(size),
|
|
1133
|
-
|
|
1290
|
+
uint8Array => {
|
|
1134
1291
|
const buffer = Buffer.from(uint8Array);
|
|
1135
|
-
return buffer.readUInt32LE(0);
|
|
1292
|
+
return { type: 'methodType' as const, value: isoIndexIntoPrototypeIds.wrap(buffer.readUInt32LE(0)) };
|
|
1136
1293
|
},
|
|
1137
1294
|
);
|
|
1138
1295
|
},
|
|
@@ -1140,7 +1297,7 @@ const encodedValueMethodTypeParser: Parser<number, Uint8Array> = parserCreatorCo
|
|
|
1140
1297
|
|
|
1141
1298
|
setParserName(encodedValueMethodTypeParser, 'encodedValueMethodTypeParser');
|
|
1142
1299
|
|
|
1143
|
-
const encodedValueMethodHandleParser: Parser<
|
|
1300
|
+
const encodedValueMethodHandleParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
1144
1301
|
() => createEncodedValueArgParser(0x16),
|
|
1145
1302
|
sizeSubOne => {
|
|
1146
1303
|
const size = sizeSubOne + 1;
|
|
@@ -1148,9 +1305,9 @@ const encodedValueMethodHandleParser: Parser<number, Uint8Array> = parserCreator
|
|
|
1148
1305
|
if (size === 1) {
|
|
1149
1306
|
return promiseCompose(
|
|
1150
1307
|
createFixedLengthSequenceParser(size),
|
|
1151
|
-
|
|
1308
|
+
uint8Array => {
|
|
1152
1309
|
const buffer = Buffer.from(uint8Array);
|
|
1153
|
-
return buffer.readUInt8(0);
|
|
1310
|
+
return { type: 'methodHandle' as const, value: buffer.readUInt8(0) };
|
|
1154
1311
|
},
|
|
1155
1312
|
);
|
|
1156
1313
|
}
|
|
@@ -1158,9 +1315,9 @@ const encodedValueMethodHandleParser: Parser<number, Uint8Array> = parserCreator
|
|
|
1158
1315
|
if (size === 2) {
|
|
1159
1316
|
return promiseCompose(
|
|
1160
1317
|
createFixedLengthSequenceParser(size),
|
|
1161
|
-
|
|
1318
|
+
uint8Array => {
|
|
1162
1319
|
const buffer = Buffer.from(uint8Array);
|
|
1163
|
-
return buffer.readUInt16LE(0);
|
|
1320
|
+
return { type: 'methodHandle' as const, value: buffer.readUInt16LE(0) };
|
|
1164
1321
|
},
|
|
1165
1322
|
);
|
|
1166
1323
|
}
|
|
@@ -1169,9 +1326,9 @@ const encodedValueMethodHandleParser: Parser<number, Uint8Array> = parserCreator
|
|
|
1169
1326
|
|
|
1170
1327
|
return promiseCompose(
|
|
1171
1328
|
createFixedLengthSequenceParser(size),
|
|
1172
|
-
|
|
1329
|
+
uint8Array => {
|
|
1173
1330
|
const buffer = Buffer.from(uint8Array);
|
|
1174
|
-
return buffer.readUInt32LE(0);
|
|
1331
|
+
return { type: 'methodHandle' as const, value: buffer.readUInt32LE(0) };
|
|
1175
1332
|
},
|
|
1176
1333
|
);
|
|
1177
1334
|
},
|
|
@@ -1179,7 +1336,7 @@ const encodedValueMethodHandleParser: Parser<number, Uint8Array> = parserCreator
|
|
|
1179
1336
|
|
|
1180
1337
|
setParserName(encodedValueMethodHandleParser, 'encodedValueMethodHandleParser');
|
|
1181
1338
|
|
|
1182
|
-
const encodedValueStringParser: Parser<
|
|
1339
|
+
const encodedValueStringParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
1183
1340
|
() => createEncodedValueArgParser(0x17),
|
|
1184
1341
|
sizeSubOne => {
|
|
1185
1342
|
const size = sizeSubOne + 1;
|
|
@@ -1187,9 +1344,9 @@ const encodedValueStringParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1187
1344
|
if (size === 1) {
|
|
1188
1345
|
return promiseCompose(
|
|
1189
1346
|
createFixedLengthSequenceParser(size),
|
|
1190
|
-
|
|
1347
|
+
uint8Array => {
|
|
1191
1348
|
const buffer = Buffer.from(uint8Array);
|
|
1192
|
-
return buffer.readUInt8(0);
|
|
1349
|
+
return { type: 'string' as const, value: isoIndexIntoStringIds.wrap(buffer.readUInt8(0)) };
|
|
1193
1350
|
},
|
|
1194
1351
|
);
|
|
1195
1352
|
}
|
|
@@ -1197,9 +1354,9 @@ const encodedValueStringParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1197
1354
|
if (size === 2) {
|
|
1198
1355
|
return promiseCompose(
|
|
1199
1356
|
createFixedLengthSequenceParser(size),
|
|
1200
|
-
|
|
1357
|
+
uint8Array => {
|
|
1201
1358
|
const buffer = Buffer.from(uint8Array);
|
|
1202
|
-
return buffer.readUInt16LE(0);
|
|
1359
|
+
return { type: 'string' as const, value: isoIndexIntoStringIds.wrap(buffer.readUInt16LE(0)) };
|
|
1203
1360
|
},
|
|
1204
1361
|
);
|
|
1205
1362
|
}
|
|
@@ -1208,9 +1365,9 @@ const encodedValueStringParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1208
1365
|
|
|
1209
1366
|
return promiseCompose(
|
|
1210
1367
|
createFixedLengthSequenceParser(size),
|
|
1211
|
-
|
|
1368
|
+
uint8Array => {
|
|
1212
1369
|
const buffer = Buffer.from(uint8Array);
|
|
1213
|
-
return buffer.readUInt32LE(0);
|
|
1370
|
+
return { type: 'string' as const, value: isoIndexIntoStringIds.wrap(buffer.readUInt32LE(0)) };
|
|
1214
1371
|
},
|
|
1215
1372
|
);
|
|
1216
1373
|
},
|
|
@@ -1218,7 +1375,7 @@ const encodedValueStringParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1218
1375
|
|
|
1219
1376
|
setParserName(encodedValueStringParser, 'encodedValueStringParser');
|
|
1220
1377
|
|
|
1221
|
-
const encodedValueTypeParser: Parser<
|
|
1378
|
+
const encodedValueTypeParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
1222
1379
|
() => createEncodedValueArgParser(0x18),
|
|
1223
1380
|
sizeSubOne => {
|
|
1224
1381
|
const size = sizeSubOne + 1;
|
|
@@ -1226,9 +1383,9 @@ const encodedValueTypeParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
1226
1383
|
if (size === 1) {
|
|
1227
1384
|
return promiseCompose(
|
|
1228
1385
|
createFixedLengthSequenceParser(size),
|
|
1229
|
-
|
|
1386
|
+
uint8Array => {
|
|
1230
1387
|
const buffer = Buffer.from(uint8Array);
|
|
1231
|
-
return buffer.readUInt8(0);
|
|
1388
|
+
return { type: 'type' as const, value: isoIndexIntoTypeIds.wrap(buffer.readUInt8(0)) };
|
|
1232
1389
|
},
|
|
1233
1390
|
);
|
|
1234
1391
|
}
|
|
@@ -1236,9 +1393,9 @@ const encodedValueTypeParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
1236
1393
|
if (size === 2) {
|
|
1237
1394
|
return promiseCompose(
|
|
1238
1395
|
createFixedLengthSequenceParser(size),
|
|
1239
|
-
|
|
1396
|
+
uint8Array => {
|
|
1240
1397
|
const buffer = Buffer.from(uint8Array);
|
|
1241
|
-
return buffer.readUInt16LE(0);
|
|
1398
|
+
return { type: 'type' as const, value: isoIndexIntoTypeIds.wrap(buffer.readUInt16LE(0)) };
|
|
1242
1399
|
},
|
|
1243
1400
|
);
|
|
1244
1401
|
}
|
|
@@ -1247,9 +1404,9 @@ const encodedValueTypeParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
1247
1404
|
|
|
1248
1405
|
return promiseCompose(
|
|
1249
1406
|
createFixedLengthSequenceParser(size),
|
|
1250
|
-
|
|
1407
|
+
uint8Array => {
|
|
1251
1408
|
const buffer = Buffer.from(uint8Array);
|
|
1252
|
-
return buffer.readUInt32LE(0);
|
|
1409
|
+
return { type: 'type' as const, value: isoIndexIntoTypeIds.wrap(buffer.readUInt32LE(0)) };
|
|
1253
1410
|
},
|
|
1254
1411
|
);
|
|
1255
1412
|
},
|
|
@@ -1257,7 +1414,7 @@ const encodedValueTypeParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
1257
1414
|
|
|
1258
1415
|
setParserName(encodedValueTypeParser, 'encodedValueTypeParser');
|
|
1259
1416
|
|
|
1260
|
-
const encodedValueFieldParser: Parser<
|
|
1417
|
+
const encodedValueFieldParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
1261
1418
|
() => createEncodedValueArgParser(0x19),
|
|
1262
1419
|
sizeSubOne => {
|
|
1263
1420
|
const size = sizeSubOne + 1;
|
|
@@ -1265,9 +1422,9 @@ const encodedValueFieldParser: Parser<number, Uint8Array> = parserCreatorCompose
|
|
|
1265
1422
|
if (size === 1) {
|
|
1266
1423
|
return promiseCompose(
|
|
1267
1424
|
createFixedLengthSequenceParser(size),
|
|
1268
|
-
|
|
1425
|
+
uint8Array => {
|
|
1269
1426
|
const buffer = Buffer.from(uint8Array);
|
|
1270
|
-
return buffer.readUInt8(0);
|
|
1427
|
+
return { type: 'field' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt8(0)) };
|
|
1271
1428
|
},
|
|
1272
1429
|
);
|
|
1273
1430
|
}
|
|
@@ -1275,9 +1432,9 @@ const encodedValueFieldParser: Parser<number, Uint8Array> = parserCreatorCompose
|
|
|
1275
1432
|
if (size === 2) {
|
|
1276
1433
|
return promiseCompose(
|
|
1277
1434
|
createFixedLengthSequenceParser(size),
|
|
1278
|
-
|
|
1435
|
+
uint8Array => {
|
|
1279
1436
|
const buffer = Buffer.from(uint8Array);
|
|
1280
|
-
return buffer.readUInt16LE(0);
|
|
1437
|
+
return { type: 'field' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt16LE(0)) };
|
|
1281
1438
|
},
|
|
1282
1439
|
);
|
|
1283
1440
|
}
|
|
@@ -1286,9 +1443,9 @@ const encodedValueFieldParser: Parser<number, Uint8Array> = parserCreatorCompose
|
|
|
1286
1443
|
|
|
1287
1444
|
return promiseCompose(
|
|
1288
1445
|
createFixedLengthSequenceParser(size),
|
|
1289
|
-
|
|
1446
|
+
uint8Array => {
|
|
1290
1447
|
const buffer = Buffer.from(uint8Array);
|
|
1291
|
-
return buffer.readUInt32LE(0);
|
|
1448
|
+
return { type: 'field' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt32LE(0)) };
|
|
1292
1449
|
},
|
|
1293
1450
|
);
|
|
1294
1451
|
},
|
|
@@ -1296,17 +1453,17 @@ const encodedValueFieldParser: Parser<number, Uint8Array> = parserCreatorCompose
|
|
|
1296
1453
|
|
|
1297
1454
|
setParserName(encodedValueFieldParser, 'encodedValueFieldParser');
|
|
1298
1455
|
|
|
1299
|
-
const encodedValueMethodParser: Parser<
|
|
1300
|
-
() => createEncodedValueArgParser(
|
|
1456
|
+
const encodedValueMethodParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
1457
|
+
() => createEncodedValueArgParser(0x1A),
|
|
1301
1458
|
sizeSubOne => {
|
|
1302
1459
|
const size = sizeSubOne + 1;
|
|
1303
1460
|
|
|
1304
1461
|
if (size === 1) {
|
|
1305
1462
|
return promiseCompose(
|
|
1306
1463
|
createFixedLengthSequenceParser(size),
|
|
1307
|
-
|
|
1464
|
+
uint8Array => {
|
|
1308
1465
|
const buffer = Buffer.from(uint8Array);
|
|
1309
|
-
return buffer.readUInt8(0);
|
|
1466
|
+
return { type: 'method' as const, value: isoIndexIntoMethodIds.wrap(buffer.readUInt8(0)) };
|
|
1310
1467
|
},
|
|
1311
1468
|
);
|
|
1312
1469
|
}
|
|
@@ -1314,9 +1471,9 @@ const encodedValueMethodParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1314
1471
|
if (size === 2) {
|
|
1315
1472
|
return promiseCompose(
|
|
1316
1473
|
createFixedLengthSequenceParser(size),
|
|
1317
|
-
|
|
1474
|
+
uint8Array => {
|
|
1318
1475
|
const buffer = Buffer.from(uint8Array);
|
|
1319
|
-
return buffer.readUInt16LE(0);
|
|
1476
|
+
return { type: 'method' as const, value: isoIndexIntoMethodIds.wrap(buffer.readUInt16LE(0)) };
|
|
1320
1477
|
},
|
|
1321
1478
|
);
|
|
1322
1479
|
}
|
|
@@ -1325,9 +1482,9 @@ const encodedValueMethodParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1325
1482
|
|
|
1326
1483
|
return promiseCompose(
|
|
1327
1484
|
createFixedLengthSequenceParser(size),
|
|
1328
|
-
|
|
1485
|
+
uint8Array => {
|
|
1329
1486
|
const buffer = Buffer.from(uint8Array);
|
|
1330
|
-
return buffer.readUInt32LE(0);
|
|
1487
|
+
return { type: 'method' as const, value: isoIndexIntoMethodIds.wrap(buffer.readUInt32LE(0)) };
|
|
1331
1488
|
},
|
|
1332
1489
|
);
|
|
1333
1490
|
},
|
|
@@ -1335,17 +1492,17 @@ const encodedValueMethodParser: Parser<number, Uint8Array> = parserCreatorCompos
|
|
|
1335
1492
|
|
|
1336
1493
|
setParserName(encodedValueMethodParser, 'encodedValueMethodParser');
|
|
1337
1494
|
|
|
1338
|
-
const encodedValueEnumParser: Parser<
|
|
1339
|
-
() => createEncodedValueArgParser(
|
|
1495
|
+
const encodedValueEnumParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
1496
|
+
() => createEncodedValueArgParser(0x1B),
|
|
1340
1497
|
sizeSubOne => {
|
|
1341
1498
|
const size = sizeSubOne + 1;
|
|
1342
1499
|
|
|
1343
1500
|
if (size === 1) {
|
|
1344
1501
|
return promiseCompose(
|
|
1345
1502
|
createFixedLengthSequenceParser(size),
|
|
1346
|
-
|
|
1503
|
+
uint8Array => {
|
|
1347
1504
|
const buffer = Buffer.from(uint8Array);
|
|
1348
|
-
return buffer.readUInt8(0);
|
|
1505
|
+
return { type: 'enum' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt8(0)) };
|
|
1349
1506
|
},
|
|
1350
1507
|
);
|
|
1351
1508
|
}
|
|
@@ -1353,9 +1510,9 @@ const encodedValueEnumParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
1353
1510
|
if (size === 2) {
|
|
1354
1511
|
return promiseCompose(
|
|
1355
1512
|
createFixedLengthSequenceParser(size),
|
|
1356
|
-
|
|
1513
|
+
uint8Array => {
|
|
1357
1514
|
const buffer = Buffer.from(uint8Array);
|
|
1358
|
-
return buffer.readUInt16LE(0);
|
|
1515
|
+
return { type: 'enum' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt16LE(0)) };
|
|
1359
1516
|
},
|
|
1360
1517
|
);
|
|
1361
1518
|
}
|
|
@@ -1364,9 +1521,9 @@ const encodedValueEnumParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
1364
1521
|
|
|
1365
1522
|
return promiseCompose(
|
|
1366
1523
|
createFixedLengthSequenceParser(size),
|
|
1367
|
-
|
|
1524
|
+
uint8Array => {
|
|
1368
1525
|
const buffer = Buffer.from(uint8Array);
|
|
1369
|
-
return buffer.readUInt32LE(0);
|
|
1526
|
+
return { type: 'enum' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt32LE(0)) };
|
|
1370
1527
|
},
|
|
1371
1528
|
);
|
|
1372
1529
|
},
|
|
@@ -1374,11 +1531,11 @@ const encodedValueEnumParser: Parser<number, Uint8Array> = parserCreatorCompose(
|
|
|
1374
1531
|
|
|
1375
1532
|
setParserName(encodedValueEnumParser, 'encodedValueEnumParser');
|
|
1376
1533
|
|
|
1377
|
-
type DalvikExecutableEncodedArray =
|
|
1534
|
+
type DalvikExecutableEncodedArray = DalvikExecutableTaggedEncodedValue[];
|
|
1378
1535
|
|
|
1379
|
-
const encodedArrayParser: Parser<
|
|
1536
|
+
const encodedArrayParser: Parser<DalvikExecutableTaggedEncodedValue[], Uint8Array> = parserCreatorCompose(
|
|
1380
1537
|
() => uleb128NumberParser,
|
|
1381
|
-
|
|
1538
|
+
size => createQuantifierParser(
|
|
1382
1539
|
encodedValueParser,
|
|
1383
1540
|
size,
|
|
1384
1541
|
),
|
|
@@ -1386,24 +1543,24 @@ const encodedArrayParser: Parser<DalvikExecutableEncodedArray, Uint8Array> = par
|
|
|
1386
1543
|
|
|
1387
1544
|
setParserName(encodedArrayParser, 'encodedArrayParser');
|
|
1388
1545
|
|
|
1389
|
-
const encodedValueArrayParser: Parser<
|
|
1546
|
+
const encodedValueArrayParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = promiseCompose(
|
|
1390
1547
|
createTupleParser([
|
|
1391
1548
|
parserCreatorCompose(
|
|
1392
|
-
() => createEncodedValueArgParser(
|
|
1549
|
+
() => createEncodedValueArgParser(0x1C),
|
|
1393
1550
|
valueArg => parserContext => {
|
|
1394
1551
|
parserContext.invariant(valueArg === 0, '(encodedValueArrayParser) valueArg: %s', valueArg);
|
|
1395
1552
|
},
|
|
1396
1553
|
)(),
|
|
1397
1554
|
encodedArrayParser,
|
|
1398
1555
|
]),
|
|
1399
|
-
([ _, array ]) => array,
|
|
1556
|
+
([ _, array ]) => ({ type: 'array' as const, value: array }),
|
|
1400
1557
|
);
|
|
1401
1558
|
|
|
1402
1559
|
setParserName(encodedValueArrayParser, 'encodedValueArrayParser');
|
|
1403
1560
|
|
|
1404
1561
|
type DalvikExecutableAnnotationElement = {
|
|
1405
1562
|
nameIndex: IndexIntoStringIds;
|
|
1406
|
-
value:
|
|
1563
|
+
value: DalvikExecutableTaggedEncodedValue;
|
|
1407
1564
|
};
|
|
1408
1565
|
|
|
1409
1566
|
type DalvikExecutableEncodedAnnotation = {
|
|
@@ -1455,39 +1612,39 @@ const encodedAnnotationParser: Parser<DalvikExecutableEncodedAnnotation, Uint8Ar
|
|
|
1455
1612
|
|
|
1456
1613
|
setParserName(encodedAnnotationParser, 'encodedAnnotationParser');
|
|
1457
1614
|
|
|
1458
|
-
const encodedValueAnnotationParser: Parser<
|
|
1615
|
+
const encodedValueAnnotationParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = promiseCompose(
|
|
1459
1616
|
createTupleParser([
|
|
1460
1617
|
parserCreatorCompose(
|
|
1461
|
-
() => createEncodedValueArgParser(
|
|
1618
|
+
() => createEncodedValueArgParser(0x1D),
|
|
1462
1619
|
valueArg => parserContext => {
|
|
1463
1620
|
parserContext.invariant(valueArg === 0, '(encodedValueAnnotationParser) valueArg: %s', valueArg);
|
|
1464
1621
|
},
|
|
1465
1622
|
)(),
|
|
1466
1623
|
encodedAnnotationParser,
|
|
1467
1624
|
]),
|
|
1468
|
-
([ _, annotation ]) => annotation,
|
|
1625
|
+
([ _, annotation ]) => ({ type: 'annotation' as const, value: annotation }),
|
|
1469
1626
|
);
|
|
1470
1627
|
|
|
1471
1628
|
setParserName(encodedValueAnnotationParser, 'encodedValueAnnotationParser');
|
|
1472
1629
|
|
|
1473
|
-
const encodedValueNullParser: Parser<
|
|
1474
|
-
() => createEncodedValueArgParser(
|
|
1630
|
+
const encodedValueNullParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
|
|
1631
|
+
() => createEncodedValueArgParser(0x1E),
|
|
1475
1632
|
valueArg => parserContext => {
|
|
1476
1633
|
parserContext.invariant(valueArg === 0, '(encodedValueNullParser) valueArg: %s', valueArg);
|
|
1477
|
-
return null;
|
|
1634
|
+
return ({ type: 'null' as const, value: null });
|
|
1478
1635
|
},
|
|
1479
1636
|
)();
|
|
1480
1637
|
|
|
1481
1638
|
setParserName(encodedValueNullParser, 'encodedValueNullParser');
|
|
1482
1639
|
|
|
1483
|
-
const encodedValueBooleanParser: Parser<
|
|
1484
|
-
createEncodedValueArgParser(
|
|
1485
|
-
(value
|
|
1640
|
+
const encodedValueBooleanParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = promiseCompose(
|
|
1641
|
+
createEncodedValueArgParser(0x1F),
|
|
1642
|
+
valueArg => ({ type: 'boolean' as const, value: Boolean(valueArg) }),
|
|
1486
1643
|
);
|
|
1487
1644
|
|
|
1488
1645
|
setParserName(encodedValueBooleanParser, 'encodedValueBooleanParser');
|
|
1489
1646
|
|
|
1490
|
-
const encodedValueParser: Parser<
|
|
1647
|
+
const encodedValueParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = createDisjunctionParser([
|
|
1491
1648
|
encodedValueByteParser,
|
|
1492
1649
|
encodedValueShortParser,
|
|
1493
1650
|
encodedValueCharParser,
|
|
@@ -1555,8 +1712,8 @@ const encodedTypeAddressPairParser: Parser<DalvikExecutableEncodedTypeAddressPai
|
|
|
1555
1712
|
);
|
|
1556
1713
|
|
|
1557
1714
|
type DalvikExecutableEncodedCatchHandler_ = {
|
|
1558
|
-
handlers: DalvikExecutableEncodedTypeAddressPair_[]
|
|
1559
|
-
catchAllAddress: undefined | number
|
|
1715
|
+
handlers: DalvikExecutableEncodedTypeAddressPair_[];
|
|
1716
|
+
catchAllAddress: undefined | number;
|
|
1560
1717
|
};
|
|
1561
1718
|
|
|
1562
1719
|
const encodedCatchHandlerParser: Parser<DalvikExecutableEncodedCatchHandler_, Uint8Array> = parserCreatorCompose(
|
|
@@ -1584,16 +1741,14 @@ setParserName(encodedCatchHandlerParser, 'encodedCatchHandlerParser');
|
|
|
1584
1741
|
|
|
1585
1742
|
type DalvikExecutableEncodedCatchHandlerByRelativeOffset = Map<OffsetFromEncodedCatchHandlerListToEncodedCatchHandler, DalvikExecutableEncodedCatchHandler_>;
|
|
1586
1743
|
|
|
1587
|
-
const encodedCatchHandlerListParser: Parser<DalvikExecutableEncodedCatchHandlerByRelativeOffset, Uint8Array> = async
|
|
1744
|
+
const encodedCatchHandlerListParser: Parser<DalvikExecutableEncodedCatchHandlerByRelativeOffset, Uint8Array> = async parserContext => {
|
|
1588
1745
|
const listOffset = parserContext.position;
|
|
1589
1746
|
const handlers: DalvikExecutableEncodedCatchHandlerByRelativeOffset = new Map();
|
|
1590
1747
|
|
|
1591
1748
|
const size = await uleb128NumberParser(parserContext);
|
|
1592
1749
|
|
|
1593
1750
|
for (let i = 0; i < size; i += 1) {
|
|
1594
|
-
const handlerRelativeOffset = isoOffsetFromEncodedCatchHandlerListToEncodedCatchHandler.wrap(
|
|
1595
|
-
parserContext.position - listOffset,
|
|
1596
|
-
);
|
|
1751
|
+
const handlerRelativeOffset = isoOffsetFromEncodedCatchHandlerListToEncodedCatchHandler.wrap(parserContext.position - listOffset);
|
|
1597
1752
|
const handler = await encodedCatchHandlerParser(parserContext);
|
|
1598
1753
|
|
|
1599
1754
|
handlers.set(handlerRelativeOffset, handler);
|
|
@@ -1639,51 +1794,47 @@ const createDalvikExecutableCodeItemParser = <Instructions>({
|
|
|
1639
1794
|
triesSize,
|
|
1640
1795
|
debugInfoOffset,
|
|
1641
1796
|
instructionsSize,
|
|
1642
|
-
]) =>
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
(
|
|
1647
|
-
(
|
|
1648
|
-
triesSize !== 0
|
|
1649
|
-
&& instructionsSize % 2 === 1
|
|
1650
|
-
)
|
|
1651
|
-
? byteAlign4Parser
|
|
1652
|
-
: () => undefined
|
|
1653
|
-
),
|
|
1654
|
-
(
|
|
1655
|
-
triesSize !== 0
|
|
1656
|
-
? createQuantifierParser(
|
|
1657
|
-
tryItemParser,
|
|
1658
|
-
triesSize,
|
|
1659
|
-
)
|
|
1660
|
-
: () => []
|
|
1661
|
-
),
|
|
1797
|
+
]) => promiseCompose(
|
|
1798
|
+
createTupleParser([
|
|
1799
|
+
createInstructionsParser(instructionsSize * 2),
|
|
1800
|
+
(
|
|
1662
1801
|
(
|
|
1663
1802
|
triesSize !== 0
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1803
|
+
&& instructionsSize % 2 === 1
|
|
1804
|
+
)
|
|
1805
|
+
? byteAlign4Parser
|
|
1806
|
+
: () => undefined
|
|
1807
|
+
),
|
|
1808
|
+
(
|
|
1809
|
+
triesSize === 0
|
|
1810
|
+
? () => []
|
|
1811
|
+
: createQuantifierParser(
|
|
1812
|
+
tryItemParser,
|
|
1813
|
+
triesSize,
|
|
1814
|
+
)
|
|
1815
|
+
),
|
|
1816
|
+
(
|
|
1817
|
+
triesSize === 0
|
|
1818
|
+
? () => new Map()
|
|
1819
|
+
: encodedCatchHandlerListParser
|
|
1820
|
+
),
|
|
1821
|
+
]),
|
|
1822
|
+
([
|
|
1823
|
+
instructions,
|
|
1824
|
+
_padding,
|
|
1825
|
+
tryItems,
|
|
1826
|
+
handlers,
|
|
1827
|
+
]) => ({
|
|
1828
|
+
registersSize,
|
|
1829
|
+
insSize,
|
|
1830
|
+
outsSize,
|
|
1831
|
+
triesSize,
|
|
1832
|
+
debugInfoOffset: isoOffsetToDebugInfoItem.wrap(debugInfoOffset),
|
|
1833
|
+
instructions,
|
|
1834
|
+
tryItems,
|
|
1835
|
+
handlers,
|
|
1836
|
+
}),
|
|
1837
|
+
),
|
|
1687
1838
|
)();
|
|
1688
1839
|
|
|
1689
1840
|
setParserName(dalvikExecutableCodeItemParser, 'dalvikExecutableCodeItemParser');
|
|
@@ -1721,15 +1872,15 @@ type DalvikExecutableDebugByteCodeValueItem =
|
|
|
1721
1872
|
| {
|
|
1722
1873
|
type: 'startLocal';
|
|
1723
1874
|
registerNum: number;
|
|
1724
|
-
nameIndex: IndexIntoStringIds;
|
|
1725
|
-
typeIndex: IndexIntoTypeIds;
|
|
1875
|
+
nameIndex: undefined | IndexIntoStringIds;
|
|
1876
|
+
typeIndex: undefined | IndexIntoTypeIds;
|
|
1726
1877
|
}
|
|
1727
1878
|
| {
|
|
1728
1879
|
type: 'startLocalExtended';
|
|
1729
1880
|
registerNum: number;
|
|
1730
|
-
nameIndex: IndexIntoStringIds;
|
|
1731
|
-
typeIndex: IndexIntoTypeIds;
|
|
1732
|
-
signatureIndex: IndexIntoStringIds;
|
|
1881
|
+
nameIndex: undefined | IndexIntoStringIds;
|
|
1882
|
+
typeIndex: undefined | IndexIntoTypeIds;
|
|
1883
|
+
signatureIndex: undefined | IndexIntoStringIds;
|
|
1733
1884
|
}
|
|
1734
1885
|
| {
|
|
1735
1886
|
type: 'endLocal';
|
|
@@ -1747,7 +1898,7 @@ type DalvikExecutableDebugByteCodeValueItem =
|
|
|
1747
1898
|
}
|
|
1748
1899
|
| {
|
|
1749
1900
|
type: 'setFile';
|
|
1750
|
-
nameIndex: IndexIntoStringIds;
|
|
1901
|
+
nameIndex: undefined | IndexIntoStringIds;
|
|
1751
1902
|
}
|
|
1752
1903
|
| {
|
|
1753
1904
|
type: 'special';
|
|
@@ -1759,62 +1910,81 @@ const dalvikExecutableDebugByteCodeValueParser: Parser<DalvikExecutableDebugByte
|
|
|
1759
1910
|
() => ubyteParser,
|
|
1760
1911
|
(value): Parser<DalvikExecutableDebugByteCodeValueItem, Uint8Array> => {
|
|
1761
1912
|
switch (value) {
|
|
1762
|
-
case 0x01: return promiseCompose(
|
|
1913
|
+
case 0x01: { return promiseCompose(
|
|
1763
1914
|
uleb128NumberParser,
|
|
1764
|
-
|
|
1915
|
+
addressDiff => ({ type: 'advancePc', addressDiff }),
|
|
1765
1916
|
);
|
|
1766
|
-
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
case 0x02: { return promiseCompose(
|
|
1767
1920
|
sleb128NumberParser,
|
|
1768
|
-
|
|
1921
|
+
lineDiff => ({ type: 'advanceLine', lineDiff }),
|
|
1769
1922
|
);
|
|
1770
|
-
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
case 0x03: { return promiseCompose(
|
|
1771
1926
|
createTupleParser([
|
|
1772
1927
|
uleb128NumberParser,
|
|
1773
|
-
|
|
1774
|
-
|
|
1928
|
+
uleb128p1NumberParser,
|
|
1929
|
+
uleb128p1NumberParser,
|
|
1775
1930
|
]),
|
|
1776
|
-
([
|
|
1931
|
+
([ registerNumber, nameIndex, typeIndex ]) => ({
|
|
1777
1932
|
type: 'startLocal',
|
|
1778
|
-
registerNum,
|
|
1779
|
-
nameIndex: isoIndexIntoStringIds.wrap(nameIndex),
|
|
1780
|
-
typeIndex: isoIndexIntoTypeIds.wrap(typeIndex),
|
|
1933
|
+
registerNum: registerNumber,
|
|
1934
|
+
nameIndex: nameIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(nameIndex),
|
|
1935
|
+
typeIndex: typeIndex === -1 ? undefined : isoIndexIntoTypeIds.wrap(typeIndex),
|
|
1781
1936
|
}),
|
|
1782
1937
|
);
|
|
1783
|
-
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
case 0x04: { return promiseCompose(
|
|
1784
1941
|
createTupleParser([
|
|
1785
1942
|
uleb128NumberParser,
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1943
|
+
uleb128p1NumberParser,
|
|
1944
|
+
uleb128p1NumberParser,
|
|
1945
|
+
uleb128p1NumberParser,
|
|
1789
1946
|
]),
|
|
1790
|
-
([
|
|
1947
|
+
([ registerNumber, nameIndex, typeIndex, signatureIndex ]) => ({
|
|
1791
1948
|
type: 'startLocalExtended',
|
|
1792
|
-
registerNum,
|
|
1793
|
-
nameIndex: isoIndexIntoStringIds.wrap(nameIndex),
|
|
1794
|
-
typeIndex: isoIndexIntoTypeIds.wrap(typeIndex),
|
|
1795
|
-
signatureIndex: isoIndexIntoStringIds.wrap(signatureIndex),
|
|
1949
|
+
registerNum: registerNumber,
|
|
1950
|
+
nameIndex: nameIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(nameIndex),
|
|
1951
|
+
typeIndex: typeIndex === -1 ? undefined : isoIndexIntoTypeIds.wrap(typeIndex),
|
|
1952
|
+
signatureIndex: signatureIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(signatureIndex),
|
|
1796
1953
|
}),
|
|
1797
1954
|
);
|
|
1798
|
-
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
case 0x05: { return promiseCompose(
|
|
1799
1958
|
uleb128NumberParser,
|
|
1800
|
-
|
|
1959
|
+
registerNumber => ({ type: 'endLocal', registerNum: registerNumber }),
|
|
1801
1960
|
);
|
|
1802
|
-
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
case 0x06: { return promiseCompose(
|
|
1803
1964
|
uleb128NumberParser,
|
|
1804
|
-
|
|
1965
|
+
registerNumber => ({ type: 'restartLocal', registerNum: registerNumber }),
|
|
1805
1966
|
);
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
case
|
|
1809
|
-
|
|
1810
|
-
|
|
1967
|
+
}
|
|
1968
|
+
|
|
1969
|
+
case 0x07: { return () => ({ type: 'setPrologueEnd' });
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
case 0x08: { return () => ({ type: 'setEpilogueBegin' });
|
|
1973
|
+
}
|
|
1974
|
+
|
|
1975
|
+
case 0x09: { return promiseCompose(
|
|
1976
|
+
uleb128p1NumberParser,
|
|
1977
|
+
nameIndex => ({ type: 'setFile', nameIndex: nameIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(nameIndex) }),
|
|
1811
1978
|
);
|
|
1812
|
-
|
|
1813
|
-
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
default: { return parserContext => {
|
|
1982
|
+
parserContext.invariant(value >= 0x0A, 'Unexpected special value: %s', value);
|
|
1814
1983
|
return { type: 'special', value };
|
|
1815
1984
|
};
|
|
1985
|
+
}
|
|
1816
1986
|
}
|
|
1817
|
-
}
|
|
1987
|
+
},
|
|
1818
1988
|
)();
|
|
1819
1989
|
|
|
1820
1990
|
setParserName(dalvikExecutableDebugByteCodeValueParser, 'dalvikExecutableDebugByteCodeValueParser');
|
|
@@ -1830,7 +2000,7 @@ setParserName(debugByteCodeParser, 'debugByteCodeParser');
|
|
|
1830
2000
|
|
|
1831
2001
|
type DalvikExecutableDebugInfoItem = {
|
|
1832
2002
|
lineStart: number;
|
|
1833
|
-
parameterNames:
|
|
2003
|
+
parameterNames: Array<undefined | IndexIntoStringIds>;
|
|
1834
2004
|
bytecode: DalvikExecutableDebugByteCodeItem;
|
|
1835
2005
|
};
|
|
1836
2006
|
|
|
@@ -1880,12 +2050,19 @@ type DalvikExecutableAnnotationItemVisibility =
|
|
|
1880
2050
|
|
|
1881
2051
|
const dalvikExecutableAnnotationItemVisibilityParser: Parser<DalvikExecutableAnnotationItemVisibility, Uint8Array> = promiseCompose(
|
|
1882
2052
|
ubyteParser,
|
|
1883
|
-
|
|
2053
|
+
visibility => {
|
|
1884
2054
|
switch (visibility) {
|
|
1885
|
-
case 0x00: return 'build';
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
2055
|
+
case 0x00: { return 'build';
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
case 0x01: { return 'runtime';
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
case 0x02: { return 'system';
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
default: { invariant(false, 'Unexpected visibility: %s', visibility);
|
|
2065
|
+
}
|
|
1889
2066
|
}
|
|
1890
2067
|
},
|
|
1891
2068
|
);
|
|
@@ -1924,19 +2101,19 @@ type DalvikExecutableHeaderAndMap = {
|
|
|
1924
2101
|
|
|
1925
2102
|
const dalvikExecutableHeaderAndMapParser: Parser<DalvikExecutableHeaderAndMap, Uint8Array> = parserCreatorCompose(
|
|
1926
2103
|
() => dalvikExecutableHeaderItemParser,
|
|
1927
|
-
|
|
2104
|
+
headerItem => promiseCompose(
|
|
1928
2105
|
createLookaheadParser(createDalvikExecutableMapListParser(headerItem.mapOffset)),
|
|
1929
|
-
|
|
2106
|
+
mapList => ({ headerItem, mapList }),
|
|
1930
2107
|
),
|
|
1931
2108
|
)();
|
|
1932
2109
|
|
|
1933
2110
|
type DalvikExecutableAnnotationOffsetItem = {
|
|
1934
2111
|
annotationOffset: OffsetToAnnotationItem;
|
|
1935
|
-
}
|
|
2112
|
+
};
|
|
1936
2113
|
|
|
1937
2114
|
const dalvikExecutableAnnotationOffsetItemParser: Parser<DalvikExecutableAnnotationOffsetItem, Uint8Array> = promiseCompose(
|
|
1938
2115
|
uintParser,
|
|
1939
|
-
|
|
2116
|
+
annotationOffset => ({
|
|
1940
2117
|
annotationOffset: isoOffsetToAnnotationItem.wrap(annotationOffset),
|
|
1941
2118
|
}),
|
|
1942
2119
|
);
|
|
@@ -1955,7 +2132,7 @@ const dalvikExecutableAnnotationSetItemParser: Parser<DalvikExecutableAnnotation
|
|
|
1955
2132
|
dalvikExecutableAnnotationOffsetItemParser,
|
|
1956
2133
|
size,
|
|
1957
2134
|
),
|
|
1958
|
-
|
|
2135
|
+
entries => ({ entries }),
|
|
1959
2136
|
),
|
|
1960
2137
|
)();
|
|
1961
2138
|
|
|
@@ -1973,7 +2150,7 @@ type DalvikExecutableAnnotationSetRefItem = OffsetToAnnotationSetItem;
|
|
|
1973
2150
|
|
|
1974
2151
|
const dalvikExecutableAnnotationSetRefItemParser: Parser<DalvikExecutableAnnotationSetRefItem, Uint8Array> = promiseCompose(
|
|
1975
2152
|
uintParser,
|
|
1976
|
-
|
|
2153
|
+
annotationsOffset => isoOffsetToAnnotationSetItem.wrap(annotationsOffset),
|
|
1977
2154
|
);
|
|
1978
2155
|
|
|
1979
2156
|
type DalvikExecutableAnnotationSetRefList = {
|
|
@@ -1990,7 +2167,7 @@ const dalvikExecutableAnnotationSetRefListParser: Parser<DalvikExecutableAnnotat
|
|
|
1990
2167
|
dalvikExecutableAnnotationSetRefItemParser,
|
|
1991
2168
|
size,
|
|
1992
2169
|
),
|
|
1993
|
-
|
|
2170
|
+
list => ({ list }),
|
|
1994
2171
|
),
|
|
1995
2172
|
)();
|
|
1996
2173
|
|
|
@@ -2030,30 +2207,73 @@ type DalvikExecutableMapItemType =
|
|
|
2030
2207
|
|
|
2031
2208
|
const dalvikExecutableMapItemTypeParser: Parser<DalvikExecutableMapItemType, Uint8Array> = promiseCompose(
|
|
2032
2209
|
ushortParser,
|
|
2033
|
-
|
|
2210
|
+
type => {
|
|
2034
2211
|
switch (type) {
|
|
2035
|
-
case
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
case
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
case
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
case
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
case
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
case
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
case
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2212
|
+
case 0x00_00: { return 'headerItem';
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
case 0x00_01: { return 'stringIdItem';
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
case 0x00_02: { return 'typeIdItem';
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
case 0x00_03: { return 'prototypeIdItem';
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
case 0x00_04: { return 'fieldIdItem';
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
case 0x00_05: { return 'methodIdItem';
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
case 0x00_06: { return 'classDefinitionItem';
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
case 0x00_07: { return 'callSiteIdItem';
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
case 0x00_08: { return 'methodHandleItem';
|
|
2237
|
+
}
|
|
2238
|
+
|
|
2239
|
+
case 0x10_00: { return 'mapList';
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2242
|
+
case 0x10_01: { return 'typeList';
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
case 0x10_02: { return 'annotationSetRefList';
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
case 0x10_03: { return 'annotationSetItem';
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
case 0x20_00: { return 'classDataItem';
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
case 0x20_01: { return 'codeItem';
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
case 0x20_02: { return 'stringDataItem';
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
case 0x20_03: { return 'debugInfoItem';
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
case 0x20_04: { return 'annotationItem';
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
case 0x20_05: { return 'encodedArrayItem';
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
case 0x20_06: { return 'annotationsDirectoryItem';
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
case 0xF0_00: { return 'hiddenApiClassDataItem';
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
default: { invariant(false, 'Unexpected map item type: %s', type);
|
|
2276
|
+
}
|
|
2057
2277
|
}
|
|
2058
2278
|
},
|
|
2059
2279
|
);
|
|
@@ -2078,12 +2298,10 @@ type DalvikExecutableMapList = DalvikExecutableMapItem[];
|
|
|
2078
2298
|
|
|
2079
2299
|
const dalvikExecutableMapListParser: Parser<DalvikExecutableMapList, Uint8Array> = parserCreatorCompose(
|
|
2080
2300
|
() => uintParser,
|
|
2081
|
-
size =>
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
);
|
|
2086
|
-
},
|
|
2301
|
+
size => createQuantifierParser(
|
|
2302
|
+
dalvikExecutableMapItemParser,
|
|
2303
|
+
size,
|
|
2304
|
+
),
|
|
2087
2305
|
)();
|
|
2088
2306
|
|
|
2089
2307
|
setParserName(dalvikExecutableMapListParser, 'dalvikExecutableMapListParser');
|
|
@@ -2142,6 +2360,7 @@ type DalvikExecutableData<Instructions> = {
|
|
|
2142
2360
|
encodedArrayItemByOffset: DalvikExecutableEncodedArrayItemByOffset;
|
|
2143
2361
|
annotationsDirectoryItemByOffset: DalvikExecutableAnnotationsDirectoryItemByOffset;
|
|
2144
2362
|
hiddenApiClassDataItems: DalvikExecutableHiddenApiClassDataItem[];
|
|
2363
|
+
link: undefined | Uint8Array;
|
|
2145
2364
|
};
|
|
2146
2365
|
|
|
2147
2366
|
const createDalvikExecutableDataParser = <Instructions>({
|
|
@@ -2151,15 +2370,15 @@ const createDalvikExecutableDataParser = <Instructions>({
|
|
|
2151
2370
|
}: DalvikExecutableHeaderAndMap & {
|
|
2152
2371
|
createInstructionsParser: CreateInstructionsParser<Instructions>;
|
|
2153
2372
|
}): Parser<DalvikExecutableData<Instructions>, Uint8Array> => {
|
|
2154
|
-
const dalvikExecutableDataParser: Parser<DalvikExecutableData<Instructions>, Uint8Array> = async
|
|
2373
|
+
const dalvikExecutableDataParser: Parser<DalvikExecutableData<Instructions>, Uint8Array> = async parserContext => {
|
|
2155
2374
|
let stringIdItems: DalvikExecutableStringIdItems = isoDalvikExecutableStringIdItems.wrap([]);
|
|
2156
2375
|
let typeIdItems: DalvikExecutableTypeIdItems = isoDalvikExecutableTypeIdItems.wrap([]);
|
|
2157
2376
|
let prototypeIdItems: DalvikExecutablePrototypeIdItems = isoDalvikExecutablePrototypeIdItems.wrap([]);
|
|
2158
2377
|
let fieldIdItems: DalvikExecutableFieldIdItems = isoDalvikExecutableFieldIdItems.wrap([]);
|
|
2159
2378
|
let methodIdItems: DalvikExecutableMethodIdItems = isoDalvikExecutableMethodIdItems.wrap([]);
|
|
2160
2379
|
let classDefinitionItems: DalvikExecutableClassDefinitionItem[] = [];
|
|
2161
|
-
|
|
2162
|
-
|
|
2380
|
+
const callSiteIdItems: DalvikExecutableCallSiteIdItem[] = [];
|
|
2381
|
+
const methodHandleItems: DalvikExecutableMethodHandleItem[] = [];
|
|
2163
2382
|
let typeListByOffset: DalvikExecutableTypeListByOffset = new Map();
|
|
2164
2383
|
let annotationSetRefListItemByOffset: DalvikExecutableAnnotationSetRefListItemByOffset = new Map();
|
|
2165
2384
|
let annotationSetItemByOffset: DalvikExecutableAnnotationSetItemByOffset = new Map();
|
|
@@ -2170,9 +2389,19 @@ const createDalvikExecutableDataParser = <Instructions>({
|
|
|
2170
2389
|
let annotationItemByOffset: DalvikExecutableAnnotationItemByOffset = new Map();
|
|
2171
2390
|
let encodedArrayItemByOffset: DalvikExecutableEncodedArrayItemByOffset = new Map();
|
|
2172
2391
|
let annotationsDirectoryItemByOffset: DalvikExecutableAnnotationsDirectoryItemByOffset = new Map();
|
|
2173
|
-
|
|
2392
|
+
const hiddenApiClassDataItems: DalvikExecutableHiddenApiClassDataItem[] = [];
|
|
2393
|
+
|
|
2394
|
+
// Track if link has been parsed
|
|
2395
|
+
let link: undefined | Uint8Array = undefined;
|
|
2396
|
+
let linkParsed = false;
|
|
2174
2397
|
|
|
2175
2398
|
for (const dexMapItem of mapList) {
|
|
2399
|
+
// Parse link data before any map item that comes after it in the file
|
|
2400
|
+
// Link data is not included in the map items, but is referenced in the header
|
|
2401
|
+
if (!linkParsed && headerItem.link.size > 0 && headerItem.link.offset < dexMapItem.offset) {
|
|
2402
|
+
link = await createRawDataParser(headerItem.link)(parserContext);
|
|
2403
|
+
linkParsed = true;
|
|
2404
|
+
}
|
|
2176
2405
|
if (dexMapItem.type === 'headerItem') {
|
|
2177
2406
|
continue;
|
|
2178
2407
|
}
|
|
@@ -2216,6 +2445,7 @@ const createDalvikExecutableDataParser = <Instructions>({
|
|
|
2216
2445
|
}
|
|
2217
2446
|
|
|
2218
2447
|
if (dexMapItem.type === 'mapList') {
|
|
2448
|
+
// Re-parse the map itself to consume it from the input
|
|
2219
2449
|
await createDalvikExecutableMapListParser(dexMapItem.offset)(parserContext);
|
|
2220
2450
|
continue;
|
|
2221
2451
|
}
|
|
@@ -2280,6 +2510,12 @@ const createDalvikExecutableDataParser = <Instructions>({
|
|
|
2280
2510
|
invariant(false, 'Unexpected map item type: %s', dexMapItem.type);
|
|
2281
2511
|
}
|
|
2282
2512
|
|
|
2513
|
+
// Parse link data after the loop if it hasn't been parsed yet
|
|
2514
|
+
// This handles the case where link comes after all map items
|
|
2515
|
+
if (!linkParsed && headerItem.link.size > 0) {
|
|
2516
|
+
link = await createRawDataParser(headerItem.link)(parserContext);
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2283
2519
|
return {
|
|
2284
2520
|
headerItem,
|
|
2285
2521
|
stringIdItems,
|
|
@@ -2302,6 +2538,7 @@ const createDalvikExecutableDataParser = <Instructions>({
|
|
|
2302
2538
|
encodedArrayItemByOffset,
|
|
2303
2539
|
annotationsDirectoryItemByOffset,
|
|
2304
2540
|
hiddenApiClassDataItems,
|
|
2541
|
+
link,
|
|
2305
2542
|
};
|
|
2306
2543
|
};
|
|
2307
2544
|
|
|
@@ -2320,41 +2557,36 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2320
2557
|
headerItem,
|
|
2321
2558
|
mapList,
|
|
2322
2559
|
}) => promiseCompose(
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
annotationItemByOffset,
|
|
2351
|
-
encodedArrayItemByOffset,
|
|
2352
|
-
annotationsDirectoryItemByOffset,
|
|
2353
|
-
// hiddenApiClassDataItems,
|
|
2354
|
-
},
|
|
2560
|
+
createDalvikExecutableDataParser({
|
|
2561
|
+
headerItem,
|
|
2562
|
+
mapList,
|
|
2563
|
+
createInstructionsParser,
|
|
2564
|
+
}),
|
|
2565
|
+
async ({
|
|
2566
|
+
headerItem: _headerItem,
|
|
2567
|
+
stringIdItems,
|
|
2568
|
+
typeIdItems,
|
|
2569
|
+
prototypeIdItems,
|
|
2570
|
+
fieldIdItems,
|
|
2571
|
+
methodIdItems,
|
|
2572
|
+
classDefinitionItems,
|
|
2573
|
+
// CallSiteIdItems,
|
|
2574
|
+
// methodHandleItems,
|
|
2575
|
+
mapList: _mapList,
|
|
2576
|
+
typeListByOffset,
|
|
2577
|
+
annotationSetRefListItemByOffset,
|
|
2578
|
+
annotationSetItemByOffset,
|
|
2579
|
+
classDataItemByOffset,
|
|
2580
|
+
codeItemByOffset,
|
|
2581
|
+
stringDataItemStringByOffset,
|
|
2582
|
+
debugInfoItemByOffset,
|
|
2583
|
+
annotationItemByOffset,
|
|
2584
|
+
encodedArrayItemByOffset,
|
|
2585
|
+
annotationsDirectoryItemByOffset,
|
|
2586
|
+
// HiddenApiClassDataItems,
|
|
2355
2587
|
link,
|
|
2356
|
-
|
|
2357
|
-
const strings = stringIdItems.map(
|
|
2588
|
+
}) => {
|
|
2589
|
+
const strings = stringIdItems.map(stringId => {
|
|
2358
2590
|
const stringOffset = stringId;
|
|
2359
2591
|
const string = stringDataItemStringByOffset.get(stringOffset);
|
|
2360
2592
|
invariant(string !== undefined, 'String must be there. String offset: %s', stringOffset);
|
|
@@ -2362,7 +2594,7 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2362
2594
|
return string;
|
|
2363
2595
|
});
|
|
2364
2596
|
|
|
2365
|
-
const types = typeIdItems.map(
|
|
2597
|
+
const types = typeIdItems.map(typeId => {
|
|
2366
2598
|
const type = strings.at(typeId);
|
|
2367
2599
|
invariant(type, 'Type string must be there. Type id: %s', typeId);
|
|
2368
2600
|
|
|
@@ -2374,7 +2606,7 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2374
2606
|
]);
|
|
2375
2607
|
|
|
2376
2608
|
for (const [ offset, typeIndexes ] of typeListByOffset) {
|
|
2377
|
-
const typeNames = isoDalvikExecutableTypeList.unwrap(typeIndexes).map(
|
|
2609
|
+
const typeNames = isoDalvikExecutableTypeList.unwrap(typeIndexes).map(typeIndex => {
|
|
2378
2610
|
const type = types.at(typeIndex);
|
|
2379
2611
|
invariant(type, 'Type must be there. Type id: %s', typeIndex);
|
|
2380
2612
|
|
|
@@ -2384,7 +2616,7 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2384
2616
|
resolvedTypeListByOffset.set(offset, typeNames);
|
|
2385
2617
|
}
|
|
2386
2618
|
|
|
2387
|
-
const prototypes = prototypeIdItems.map(
|
|
2619
|
+
const prototypes = prototypeIdItems.map(prototypeId => {
|
|
2388
2620
|
const shorty = strings.at(prototypeId.shortyIndex);
|
|
2389
2621
|
invariant(shorty, 'Shorty must be there. Shorty id: %s', prototypeId.shortyIndex);
|
|
2390
2622
|
|
|
@@ -2397,7 +2629,7 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2397
2629
|
return { shorty, returnType, parameters };
|
|
2398
2630
|
});
|
|
2399
2631
|
|
|
2400
|
-
const fields = fieldIdItems.map(
|
|
2632
|
+
const fields = fieldIdItems.map(fieldId => {
|
|
2401
2633
|
const class_ = types.at(fieldId.classIndex);
|
|
2402
2634
|
invariant(class_, 'Class must be there. Class id: %s', fieldId.classIndex);
|
|
2403
2635
|
|
|
@@ -2410,7 +2642,7 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2410
2642
|
return { class: class_, type, name };
|
|
2411
2643
|
});
|
|
2412
2644
|
|
|
2413
|
-
const methods = methodIdItems.map(
|
|
2645
|
+
const methods = methodIdItems.map(methodId => {
|
|
2414
2646
|
const class_ = types.at(methodId.classIndex);
|
|
2415
2647
|
invariant(class_, 'Class must be there. Class id: %s', methodId.classIndex);
|
|
2416
2648
|
|
|
@@ -2430,7 +2662,7 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2430
2662
|
for (const [ offset, debugInfoItem ] of debugInfoItemByOffset) {
|
|
2431
2663
|
debugInfoByOffset.set(offset, {
|
|
2432
2664
|
lineStart: debugInfoItem.lineStart,
|
|
2433
|
-
parameterNames: debugInfoItem.parameterNames.map(
|
|
2665
|
+
parameterNames: debugInfoItem.parameterNames.map(index => {
|
|
2434
2666
|
if (index === undefined) {
|
|
2435
2667
|
return undefined;
|
|
2436
2668
|
}
|
|
@@ -2440,23 +2672,30 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2440
2672
|
|
|
2441
2673
|
return string;
|
|
2442
2674
|
}),
|
|
2443
|
-
bytecode: debugInfoItem.bytecode.map(
|
|
2675
|
+
bytecode: debugInfoItem.bytecode.map(value => {
|
|
2444
2676
|
switch (value.type) {
|
|
2445
|
-
case 'startLocal': return {
|
|
2677
|
+
case 'startLocal': { return {
|
|
2446
2678
|
type: 'startLocal',
|
|
2447
2679
|
registerNum: value.registerNum,
|
|
2448
2680
|
name: value.nameIndex === undefined ? undefined : strings.at(value.nameIndex),
|
|
2449
2681
|
type_: value.typeIndex === undefined ? undefined : types.at(value.typeIndex),
|
|
2450
2682
|
};
|
|
2451
|
-
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
case 'startLocalExtended': { return {
|
|
2452
2686
|
type: 'startLocalExtended',
|
|
2453
2687
|
registerNum: value.registerNum,
|
|
2454
2688
|
name: value.nameIndex === undefined ? undefined : strings.at(value.nameIndex),
|
|
2455
2689
|
type_: value.typeIndex === undefined ? undefined : types.at(value.typeIndex),
|
|
2456
2690
|
signature: value.signatureIndex === undefined ? undefined : strings.at(value.signatureIndex),
|
|
2457
2691
|
};
|
|
2458
|
-
|
|
2459
|
-
|
|
2692
|
+
}
|
|
2693
|
+
|
|
2694
|
+
case 'setFile': { return { type: 'setFile', name: value.nameIndex === undefined ? undefined : strings.at(value.nameIndex) };
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
default: { return value;
|
|
2698
|
+
}
|
|
2460
2699
|
}
|
|
2461
2700
|
}),
|
|
2462
2701
|
});
|
|
@@ -2473,15 +2712,14 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2473
2712
|
registersSize: codeItem.registersSize,
|
|
2474
2713
|
insSize: codeItem.insSize,
|
|
2475
2714
|
outsSize: codeItem.outsSize,
|
|
2476
|
-
debugInfo
|
|
2715
|
+
debugInfo,
|
|
2477
2716
|
instructions: codeItem.instructions,
|
|
2478
|
-
tries: codeItem.tryItems.map(
|
|
2717
|
+
tries: codeItem.tryItems.map(tryItem => {
|
|
2479
2718
|
const handler_ = codeItem.handlers.get(tryItem.handlerOffset);
|
|
2480
2719
|
invariant(handler_, 'Handler must be there. Handler offset: %s', tryItem.handlerOffset);
|
|
2481
2720
|
|
|
2482
2721
|
const handler = {
|
|
2483
|
-
|
|
2484
|
-
handlers: handler_.handlers.map((encodedHandler) => {
|
|
2722
|
+
handlers: handler_.handlers.map(encodedHandler => {
|
|
2485
2723
|
const type = types.at(encodedHandler.typeIndex);
|
|
2486
2724
|
invariant(type, 'Type must be there. Type id: %s', encodedHandler.typeIndex);
|
|
2487
2725
|
|
|
@@ -2490,6 +2728,7 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2490
2728
|
address: encodedHandler.address,
|
|
2491
2729
|
};
|
|
2492
2730
|
}),
|
|
2731
|
+
catchAllAddress: handler_.catchAllAddress,
|
|
2493
2732
|
};
|
|
2494
2733
|
|
|
2495
2734
|
return {
|
|
@@ -2508,28 +2747,28 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2508
2747
|
const resolvers: DalvikBytecodeOperationResolvers = {
|
|
2509
2748
|
resolveIndexIntoStringIds(indexIntoStringIds) {
|
|
2510
2749
|
const string = strings.at(indexIntoStringIds);
|
|
2511
|
-
invariant(string, 'String must be there. String id: %s', indexIntoStringIds);
|
|
2750
|
+
invariant(string !== undefined, 'String must be there. String id: %s', indexIntoStringIds);
|
|
2512
2751
|
|
|
2513
2752
|
return string;
|
|
2514
2753
|
},
|
|
2515
2754
|
|
|
2516
2755
|
resolveIndexIntoTypeIds(indexIntoTypeIds) {
|
|
2517
2756
|
const type = types.at(indexIntoTypeIds);
|
|
2518
|
-
invariant(type, 'Type must be there. Type id: %s', indexIntoTypeIds);
|
|
2757
|
+
invariant(type !== undefined, 'Type must be there. Type id: %s', indexIntoTypeIds);
|
|
2519
2758
|
|
|
2520
2759
|
return type;
|
|
2521
2760
|
},
|
|
2522
2761
|
|
|
2523
2762
|
resolveIndexIntoMethodIds(indexIntoMethodIds) {
|
|
2524
2763
|
const method = methods.at(indexIntoMethodIds);
|
|
2525
|
-
invariant(method, 'Method must be there. Method id: %s', indexIntoMethodIds);
|
|
2764
|
+
invariant(method !== undefined, 'Method must be there. Method id: %s', indexIntoMethodIds);
|
|
2526
2765
|
|
|
2527
2766
|
return method;
|
|
2528
2767
|
},
|
|
2529
2768
|
|
|
2530
2769
|
resolveIndexIntoFieldIds(indexIntoFieldIds) {
|
|
2531
2770
|
const field = fields.at(indexIntoFieldIds);
|
|
2532
|
-
invariant(field, 'Field must be there. Field id: %s', indexIntoFieldIds);
|
|
2771
|
+
invariant(field !== undefined, 'Field must be there. Field id: %s', indexIntoFieldIds);
|
|
2533
2772
|
|
|
2534
2773
|
return field;
|
|
2535
2774
|
},
|
|
@@ -2548,15 +2787,13 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2548
2787
|
|
|
2549
2788
|
return {
|
|
2550
2789
|
...rest,
|
|
2551
|
-
instructions: instructions.map((instruction: DalvikBytecodeOperation) =>
|
|
2552
|
-
return resolveDalvikBytecodeOperation(instruction, resolvers);
|
|
2553
|
-
}) as Instructions,
|
|
2790
|
+
instructions: instructions.map((instruction: DalvikBytecodeOperation) => resolveDalvikBytecodeOperation(instruction, resolvers)) as Instructions,
|
|
2554
2791
|
};
|
|
2555
2792
|
}
|
|
2556
2793
|
|
|
2557
2794
|
for (const [ offset, classDataItem ] of classDataItemByOffset) {
|
|
2558
2795
|
classDataByOffset.set(offset, {
|
|
2559
|
-
staticFields: classDataItem.staticFields.map(
|
|
2796
|
+
staticFields: classDataItem.staticFields.map(encodedField => {
|
|
2560
2797
|
const field = fields.at(encodedField.fieldIndex);
|
|
2561
2798
|
invariant(field, 'Field must be there. Field id: %s', encodedField.fieldIndex);
|
|
2562
2799
|
|
|
@@ -2566,7 +2803,7 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2566
2803
|
};
|
|
2567
2804
|
}),
|
|
2568
2805
|
|
|
2569
|
-
instanceFields: classDataItem.instanceFields.map(
|
|
2806
|
+
instanceFields: classDataItem.instanceFields.map(encodedField => {
|
|
2570
2807
|
const field = fields.at(encodedField.fieldIndex);
|
|
2571
2808
|
invariant(field, 'Field must be there. Field id: %s', encodedField.fieldIndex);
|
|
2572
2809
|
|
|
@@ -2576,7 +2813,7 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2576
2813
|
};
|
|
2577
2814
|
}),
|
|
2578
2815
|
|
|
2579
|
-
directMethods: classDataItem.directMethods.map(
|
|
2816
|
+
directMethods: classDataItem.directMethods.map(method => {
|
|
2580
2817
|
const method_ = methods.at(method.methodIndex);
|
|
2581
2818
|
invariant(method_, 'Method must be there. Method id: %s', method.methodIndex);
|
|
2582
2819
|
|
|
@@ -2590,7 +2827,7 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2590
2827
|
};
|
|
2591
2828
|
}),
|
|
2592
2829
|
|
|
2593
|
-
virtualMethods: classDataItem.virtualMethods.map(
|
|
2830
|
+
virtualMethods: classDataItem.virtualMethods.map(method => {
|
|
2594
2831
|
const method_ = methods.at(method.methodIndex);
|
|
2595
2832
|
invariant(method_, 'Method must be there. Method id: %s', method.methodIndex);
|
|
2596
2833
|
|
|
@@ -2606,6 +2843,176 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2606
2843
|
});
|
|
2607
2844
|
}
|
|
2608
2845
|
|
|
2846
|
+
// Resolve TaggedEncodedValue to DalvikExecutableEncodedValue for static values
|
|
2847
|
+
// Resolves internal index types to actual values while preserving type tags
|
|
2848
|
+
function resolveTaggedEncodedValueForStaticValues(taggedValue: DalvikExecutableTaggedEncodedValue): DalvikExecutableEncodedValue {
|
|
2849
|
+
const { type, value } = taggedValue;
|
|
2850
|
+
|
|
2851
|
+
// For primitive types, keep the type tag and value
|
|
2852
|
+
if (
|
|
2853
|
+
type === 'byte'
|
|
2854
|
+
|| type === 'short'
|
|
2855
|
+
|| type === 'char'
|
|
2856
|
+
|| type === 'int'
|
|
2857
|
+
|| type === 'float'
|
|
2858
|
+
|| type === 'double'
|
|
2859
|
+
|| type === 'long'
|
|
2860
|
+
|| type === 'boolean'
|
|
2861
|
+
|| type === 'null'
|
|
2862
|
+
|| type === 'methodHandle'
|
|
2863
|
+
) {
|
|
2864
|
+
return { type, value } as DalvikExecutableEncodedValue;
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2867
|
+
// For types that reference the pool, resolve the index to the actual value
|
|
2868
|
+
if (type === 'methodType') {
|
|
2869
|
+
const prototype = prototypes.at(value);
|
|
2870
|
+
invariant(prototype, 'Prototype must be there. Prototype id: %s', isoIndexIntoPrototypeIds.unwrap(value));
|
|
2871
|
+
return { type, value: prototype };
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2874
|
+
if (type === 'string') {
|
|
2875
|
+
const string = strings.at(value);
|
|
2876
|
+
invariant(string !== undefined, 'String must be there. String id: %s', isoIndexIntoStringIds.unwrap(value));
|
|
2877
|
+
return { type, value: string };
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
if (type === 'type') {
|
|
2881
|
+
const typeString = types.at(value);
|
|
2882
|
+
invariant(typeString !== undefined, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value));
|
|
2883
|
+
return { type, value: typeString };
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2886
|
+
if (type === 'field' || type === 'enum') {
|
|
2887
|
+
const field = fields.at(value);
|
|
2888
|
+
invariant(field, 'Field must be there. Field id: %s', isoIndexIntoFieldIds.unwrap(value));
|
|
2889
|
+
return { type, value: field };
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2892
|
+
if (type === 'method') {
|
|
2893
|
+
const method = methods.at(value);
|
|
2894
|
+
invariant(method, 'Method must be there. Method id: %s', isoIndexIntoMethodIds.unwrap(value));
|
|
2895
|
+
return { type, value: method };
|
|
2896
|
+
}
|
|
2897
|
+
|
|
2898
|
+
if (type === 'array') {
|
|
2899
|
+
return { type, value: value.map(resolveTaggedEncodedValueForStaticValues) };
|
|
2900
|
+
}
|
|
2901
|
+
|
|
2902
|
+
if (type === 'annotation') {
|
|
2903
|
+
// Resolve the encoded annotation
|
|
2904
|
+
const annotationType = types.at(value.typeIndex);
|
|
2905
|
+
invariant(annotationType, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value.typeIndex));
|
|
2906
|
+
|
|
2907
|
+
const resolvedElements = value.elements.map(element => {
|
|
2908
|
+
const name = strings.at(element.nameIndex);
|
|
2909
|
+
invariant(name, 'Name string must be there. String offset: %s', element.nameIndex);
|
|
2910
|
+
|
|
2911
|
+
return {
|
|
2912
|
+
name,
|
|
2913
|
+
value: resolveTaggedEncodedValueForAnnotations(element.value),
|
|
2914
|
+
};
|
|
2915
|
+
});
|
|
2916
|
+
|
|
2917
|
+
const annotation: DalvikExecutableAnnotation = {
|
|
2918
|
+
visibility: 'build', // Default visibility for embedded annotations
|
|
2919
|
+
type: annotationType,
|
|
2920
|
+
elements: resolvedElements,
|
|
2921
|
+
};
|
|
2922
|
+
|
|
2923
|
+
return { type, value: annotation };
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2926
|
+
// This should never happen
|
|
2927
|
+
throw new Error(`Unknown encoded value type: ${type}`);
|
|
2928
|
+
}
|
|
2929
|
+
|
|
2930
|
+
// Resolve TaggedEncodedValue to DalvikExecutableEncodedValue for annotation elements
|
|
2931
|
+
// Resolves internal index types to actual values while preserving type tags
|
|
2932
|
+
function resolveTaggedEncodedValueForAnnotations(taggedValue: DalvikExecutableTaggedEncodedValue): DalvikExecutableEncodedValue {
|
|
2933
|
+
const { type, value } = taggedValue;
|
|
2934
|
+
|
|
2935
|
+
// For primitive types, keep the type tag and value
|
|
2936
|
+
if (
|
|
2937
|
+
type === 'byte'
|
|
2938
|
+
|| type === 'short'
|
|
2939
|
+
|| type === 'char'
|
|
2940
|
+
|| type === 'int'
|
|
2941
|
+
|| type === 'float'
|
|
2942
|
+
|| type === 'double'
|
|
2943
|
+
|| type === 'long'
|
|
2944
|
+
|| type === 'boolean'
|
|
2945
|
+
|| type === 'null'
|
|
2946
|
+
|| type === 'methodHandle'
|
|
2947
|
+
) {
|
|
2948
|
+
return { type, value } as DalvikExecutableEncodedValue;
|
|
2949
|
+
}
|
|
2950
|
+
|
|
2951
|
+
// For types that reference the pool, resolve the index to the actual value
|
|
2952
|
+
if (type === 'methodType') {
|
|
2953
|
+
const prototype = prototypes.at(value);
|
|
2954
|
+
invariant(prototype, 'Prototype must be there. Prototype id: %s', isoIndexIntoPrototypeIds.unwrap(value));
|
|
2955
|
+
return { type, value: prototype };
|
|
2956
|
+
}
|
|
2957
|
+
|
|
2958
|
+
if (type === 'string') {
|
|
2959
|
+
const string = strings.at(value);
|
|
2960
|
+
invariant(string !== undefined, 'String must be there. String id: %s', isoIndexIntoStringIds.unwrap(value));
|
|
2961
|
+
return { type, value: string };
|
|
2962
|
+
}
|
|
2963
|
+
|
|
2964
|
+
if (type === 'type') {
|
|
2965
|
+
const typeString = types.at(value);
|
|
2966
|
+
invariant(typeString !== undefined, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value));
|
|
2967
|
+
return { type, value: typeString };
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
if (type === 'field' || type === 'enum') {
|
|
2971
|
+
const field = fields.at(value);
|
|
2972
|
+
invariant(field, 'Field must be there. Field id: %s', isoIndexIntoFieldIds.unwrap(value));
|
|
2973
|
+
return { type, value: field };
|
|
2974
|
+
}
|
|
2975
|
+
|
|
2976
|
+
if (type === 'method') {
|
|
2977
|
+
const method = methods.at(value);
|
|
2978
|
+
invariant(method, 'Method must be there. Method id: %s', isoIndexIntoMethodIds.unwrap(value));
|
|
2979
|
+
return { type, value: method };
|
|
2980
|
+
}
|
|
2981
|
+
|
|
2982
|
+
// For arrays, recursively resolve elements
|
|
2983
|
+
if (type === 'array') {
|
|
2984
|
+
return { type, value: value.map(resolveTaggedEncodedValueForAnnotations) };
|
|
2985
|
+
}
|
|
2986
|
+
|
|
2987
|
+
// For annotations
|
|
2988
|
+
if (type === 'annotation') {
|
|
2989
|
+
// Resolve the encoded annotation (subannotation)
|
|
2990
|
+
const annotationType = types.at(value.typeIndex);
|
|
2991
|
+
invariant(annotationType, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value.typeIndex));
|
|
2992
|
+
|
|
2993
|
+
const resolvedElements = value.elements.map(element => {
|
|
2994
|
+
const name = strings.at(element.nameIndex);
|
|
2995
|
+
invariant(name, 'Name string must be there. String offset: %s', element.nameIndex);
|
|
2996
|
+
|
|
2997
|
+
return {
|
|
2998
|
+
name,
|
|
2999
|
+
value: resolveTaggedEncodedValueForAnnotations(element.value),
|
|
3000
|
+
};
|
|
3001
|
+
});
|
|
3002
|
+
|
|
3003
|
+
const annotation: DalvikExecutableAnnotation = {
|
|
3004
|
+
visibility: 'build', // Default visibility for embedded annotations
|
|
3005
|
+
type: annotationType,
|
|
3006
|
+
elements: resolvedElements,
|
|
3007
|
+
};
|
|
3008
|
+
|
|
3009
|
+
return { type, value: annotation };
|
|
3010
|
+
}
|
|
3011
|
+
|
|
3012
|
+
// This should never happen
|
|
3013
|
+
throw new Error(`Unknown encoded value type: ${type}`);
|
|
3014
|
+
}
|
|
3015
|
+
|
|
2609
3016
|
function resolveAnnotationOffsetItem({ annotationOffset }: DalvikExecutableAnnotationOffsetItem): DalvikExecutableAnnotation {
|
|
2610
3017
|
const annotationItem = annotationItemByOffset.get(annotationOffset);
|
|
2611
3018
|
invariant(annotationItem, 'Annotation must be there. Annotation offset: %s', annotationOffset);
|
|
@@ -2613,13 +3020,13 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2613
3020
|
const type = types.at(annotationItem.encodedAnnotation.typeIndex);
|
|
2614
3021
|
invariant(type, 'Type must be there. Type id: %s', annotationItem.encodedAnnotation.typeIndex);
|
|
2615
3022
|
|
|
2616
|
-
const elements = annotationItem.encodedAnnotation.elements.map(
|
|
3023
|
+
const elements = annotationItem.encodedAnnotation.elements.map(element => {
|
|
2617
3024
|
const name = strings.at(element.nameIndex);
|
|
2618
3025
|
invariant(name, 'Name string must be there. String offset: %s', element.nameIndex);
|
|
2619
3026
|
|
|
2620
3027
|
return {
|
|
2621
3028
|
name,
|
|
2622
|
-
value: element.value,
|
|
3029
|
+
value: resolveTaggedEncodedValueForAnnotations(element.value),
|
|
2623
3030
|
};
|
|
2624
3031
|
});
|
|
2625
3032
|
|
|
@@ -2631,10 +3038,20 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2631
3038
|
}
|
|
2632
3039
|
|
|
2633
3040
|
function resolveAnnotationSetItem(annotationSetItem: undefined | DalvikExecutableAnnotationSetItem): undefined | DalvikExecutableAnnotation[] {
|
|
2634
|
-
|
|
3041
|
+
if (!annotationSetItem) {
|
|
3042
|
+
return undefined;
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
const annotationSet = annotationSetItem.entries.map(resolveAnnotationOffsetItem);
|
|
3046
|
+
|
|
3047
|
+
if (!annotationSet.length) {
|
|
3048
|
+
return [];
|
|
3049
|
+
}
|
|
3050
|
+
|
|
3051
|
+
return annotationSet;
|
|
2635
3052
|
}
|
|
2636
3053
|
|
|
2637
|
-
const classDefinitions = classDefinitionItems.map(
|
|
3054
|
+
const classDefinitions = classDefinitionItems.map(classDefinitionItem => {
|
|
2638
3055
|
const class_ = types.at(classDefinitionItem.classIndex);
|
|
2639
3056
|
invariant(class_, 'Class must be there. Class id: %s', classDefinitionItem.classIndex);
|
|
2640
3057
|
|
|
@@ -2669,23 +3086,33 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2669
3086
|
classAnnotationSetItem
|
|
2670
3087
|
? resolveAnnotationSetItem(classAnnotationSetItem)
|
|
2671
3088
|
: undefined
|
|
2672
|
-
);
|
|
3089
|
+
) ?? [];
|
|
2673
3090
|
|
|
2674
|
-
const fieldAnnotations: DalvikExecutableClassFieldAnnotation[] = annotationsDirectoryItem.fieldAnnotations.
|
|
3091
|
+
const fieldAnnotations: DalvikExecutableClassFieldAnnotation[] = annotationsDirectoryItem.fieldAnnotations.flatMap(fieldAnnotation => {
|
|
2675
3092
|
const field = fields.at(fieldAnnotation.fieldIndex);
|
|
2676
3093
|
invariant(field, 'Field must be there. Field id: %s', fieldAnnotation.fieldIndex);
|
|
2677
3094
|
|
|
2678
|
-
const
|
|
3095
|
+
const annotationSetItem = annotationSetItemByOffset.get(fieldAnnotation.annotationsOffset);
|
|
2679
3096
|
invariant(
|
|
2680
|
-
isoOffsetToAnnotationSetItem.unwrap(fieldAnnotation.annotationsOffset) === 0 ||
|
|
3097
|
+
isoOffsetToAnnotationSetItem.unwrap(fieldAnnotation.annotationsOffset) === 0 || annotationSetItem,
|
|
2681
3098
|
'Annotations must be there. Annotations offset: %s',
|
|
2682
3099
|
fieldAnnotation.annotationsOffset,
|
|
2683
3100
|
);
|
|
2684
3101
|
|
|
2685
|
-
|
|
3102
|
+
const annotations = resolveAnnotationSetItem(annotationSetItem);
|
|
3103
|
+
|
|
3104
|
+
// Skip fields with no annotations (undefined or empty array)
|
|
3105
|
+
if (!annotations || annotations.length === 0) {
|
|
3106
|
+
return [];
|
|
3107
|
+
}
|
|
3108
|
+
|
|
3109
|
+
return [{
|
|
3110
|
+
field,
|
|
3111
|
+
annotations,
|
|
3112
|
+
}];
|
|
2686
3113
|
});
|
|
2687
3114
|
|
|
2688
|
-
const methodAnnotations: DalvikExecutableClassMethodAnnotation[] = annotationsDirectoryItem.methodAnnotations.
|
|
3115
|
+
const methodAnnotations: DalvikExecutableClassMethodAnnotation[] = annotationsDirectoryItem.methodAnnotations.flatMap(methodAnnotation => {
|
|
2689
3116
|
const method = methods.at(methodAnnotation.methodIndex);
|
|
2690
3117
|
invariant(method, 'Method must be there. Method id: %s', methodAnnotation.methodIndex);
|
|
2691
3118
|
|
|
@@ -2696,10 +3123,20 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2696
3123
|
methodAnnotation.annotationsOffset,
|
|
2697
3124
|
);
|
|
2698
3125
|
|
|
2699
|
-
|
|
3126
|
+
const annotations = resolveAnnotationSetItem(annotationSetItem) ?? [];
|
|
3127
|
+
|
|
3128
|
+
// Skip methods with no annotations
|
|
3129
|
+
if (annotations.length === 0) {
|
|
3130
|
+
return [];
|
|
3131
|
+
}
|
|
3132
|
+
|
|
3133
|
+
return [{
|
|
3134
|
+
method,
|
|
3135
|
+
annotations,
|
|
3136
|
+
}];
|
|
2700
3137
|
});
|
|
2701
3138
|
|
|
2702
|
-
const parameterAnnotations: DalvikExecutableClassParameterAnnotation[] = annotationsDirectoryItem.parameterAnnotations.
|
|
3139
|
+
const parameterAnnotations: DalvikExecutableClassParameterAnnotation[] = annotationsDirectoryItem.parameterAnnotations.flatMap(parameterAnnotation => {
|
|
2703
3140
|
const method = methods.at(parameterAnnotation.methodIndex);
|
|
2704
3141
|
invariant(method, 'Method must be there. Method id: %s', parameterAnnotation.methodIndex);
|
|
2705
3142
|
|
|
@@ -2710,7 +3147,7 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2710
3147
|
parameterAnnotation.annotationsOffset,
|
|
2711
3148
|
);
|
|
2712
3149
|
|
|
2713
|
-
const annotations = annotationSetRefList?.list.map(
|
|
3150
|
+
const annotations: DalvikExecutableClassParameterAnnotation['annotations'] = annotationSetRefList?.list.map(annotationSetRefItem => {
|
|
2714
3151
|
const annotationSetItem = annotationSetItemByOffset.get(annotationSetRefItem);
|
|
2715
3152
|
invariant(
|
|
2716
3153
|
isoOffsetToAnnotationSetItem.unwrap(annotationSetRefItem) === 0 || annotationSetItem,
|
|
@@ -2718,8 +3155,10 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2718
3155
|
annotationSetRefItem,
|
|
2719
3156
|
);
|
|
2720
3157
|
|
|
2721
|
-
|
|
2722
|
-
|
|
3158
|
+
const annotationSet = resolveAnnotationSetItem(annotationSetItem);
|
|
3159
|
+
|
|
3160
|
+
return annotationSet ?? [];
|
|
3161
|
+
}) ?? [];
|
|
2723
3162
|
|
|
2724
3163
|
return { method, annotations };
|
|
2725
3164
|
});
|
|
@@ -2734,12 +3173,32 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2734
3173
|
|
|
2735
3174
|
const classData = classDataByOffset.get(classDefinitionItem.classDataOffset);
|
|
2736
3175
|
|
|
2737
|
-
const
|
|
2738
|
-
invariant(
|
|
3176
|
+
const staticValuesTagged = isoOffsetToEncodedArrayItem.unwrap(classDefinitionItem.staticValuesOffset) === 0 ? [] : encodedArrayItemByOffset.get(classDefinitionItem.staticValuesOffset);
|
|
3177
|
+
invariant(staticValuesTagged, 'Static values must be there. Static values offset: %s', classDefinitionItem.staticValuesOffset);
|
|
3178
|
+
|
|
3179
|
+
const staticValues = staticValuesTagged.map(resolveTaggedEncodedValueForStaticValues);
|
|
3180
|
+
|
|
3181
|
+
const allMembers = [
|
|
3182
|
+
...classData?.staticFields ?? [],
|
|
3183
|
+
...classData?.instanceFields ?? [],
|
|
3184
|
+
...classData?.directMethods ?? [],
|
|
3185
|
+
// ...classData?.virtualMethods ?? [], // TODO?
|
|
3186
|
+
];
|
|
3187
|
+
|
|
3188
|
+
const allMembersAreSynthetic = (
|
|
3189
|
+
allMembers.every(member => member.accessFlags.synthetic)
|
|
3190
|
+
&& allMembers.length > 0
|
|
3191
|
+
);
|
|
3192
|
+
|
|
3193
|
+
const accessFlags = {
|
|
3194
|
+
...classDefinitionItem.accessFlags,
|
|
3195
|
+
// Use the synthetic flag from the class definition, or compute it from members if not set
|
|
3196
|
+
synthetic: classDefinitionItem.accessFlags.synthetic || allMembersAreSynthetic,
|
|
3197
|
+
};
|
|
2739
3198
|
|
|
2740
3199
|
return {
|
|
2741
3200
|
class: class_,
|
|
2742
|
-
accessFlags
|
|
3201
|
+
accessFlags,
|
|
2743
3202
|
superclass,
|
|
2744
3203
|
interfaces,
|
|
2745
3204
|
sourceFile,
|
|
@@ -2749,6 +3208,24 @@ const createDalvikExecutableParser = <Instructions>({
|
|
|
2749
3208
|
};
|
|
2750
3209
|
});
|
|
2751
3210
|
|
|
3211
|
+
// Sort parameter annotations in each class by method index in classData
|
|
3212
|
+
for (const classDef of classDefinitions) {
|
|
3213
|
+
if (classDef.annotations?.parameterAnnotations && classDef.classData) {
|
|
3214
|
+
const allMethods = [...(classDef.classData.directMethods ?? []), ...(classDef.classData.virtualMethods ?? [])];
|
|
3215
|
+
classDef.annotations.parameterAnnotations.sort((a, b) => {
|
|
3216
|
+
const indexA = allMethods.findIndex(m =>
|
|
3217
|
+
m.method.name === a.method.name &&
|
|
3218
|
+
m.method.prototype.shorty === a.method.prototype.shorty
|
|
3219
|
+
);
|
|
3220
|
+
const indexB = allMethods.findIndex(m =>
|
|
3221
|
+
m.method.name === b.method.name &&
|
|
3222
|
+
m.method.prototype.shorty === b.method.prototype.shorty
|
|
3223
|
+
);
|
|
3224
|
+
return indexA - indexB;
|
|
3225
|
+
});
|
|
3226
|
+
}
|
|
3227
|
+
}
|
|
3228
|
+
|
|
2752
3229
|
return {
|
|
2753
3230
|
classDefinitions,
|
|
2754
3231
|
link,
|