@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
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
async function* yieldAndCapture(gen) {
|
|
2
|
+
let value;
|
|
3
|
+
for await (value of gen) {
|
|
4
|
+
yield value;
|
|
5
|
+
}
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
import { ubyteUnparser, uintUnparser } from '../dalvikBytecodeUnparser/formatUnparsers.js';
|
|
9
|
+
import { alignmentUnparser, uleb128Unparser } from './utils.js';
|
|
10
|
+
export function createAnnotationUnparsers(getStringIndex, getTypeIndex, getFieldIndex, getMethodIndex, encodedValueUnparser) {
|
|
11
|
+
const annotationItemUnparser = async function* (input, unparserContext) {
|
|
12
|
+
const visibilityByte = input.visibility === 'build' ? 0x00 : input.visibility === 'runtime' ? 0x01 : 0x02;
|
|
13
|
+
yield* ubyteUnparser(visibilityByte, unparserContext);
|
|
14
|
+
const typeIndex = getTypeIndex(input.type);
|
|
15
|
+
yield* uleb128Unparser(typeIndex, unparserContext);
|
|
16
|
+
yield* uleb128Unparser(input.elements.length, unparserContext);
|
|
17
|
+
for (const element of input.elements) {
|
|
18
|
+
const nameIndex = getStringIndex(element.name);
|
|
19
|
+
yield* uleb128Unparser(nameIndex, unparserContext);
|
|
20
|
+
yield* encodedValueUnparser(element.value, unparserContext);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const annotationSetItemUnparser = (annotationItemOffsetWriteLaters) => {
|
|
24
|
+
return async function* (input, unparserContext) {
|
|
25
|
+
yield* alignmentUnparser(4)(undefined, unparserContext);
|
|
26
|
+
yield* uintUnparser(input.length, unparserContext);
|
|
27
|
+
for (const annotation of input) {
|
|
28
|
+
const annotationOffsetWriteLater = yield* yieldAndCapture(unparserContext.writeLater(4));
|
|
29
|
+
annotationItemOffsetWriteLaters.push(annotationOffsetWriteLater);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
const annotationSetRefListUnparser = (annotationSetOffsetWriteLaters) => {
|
|
34
|
+
return async function* (input, unparserContext) {
|
|
35
|
+
yield* alignmentUnparser(4)(undefined, unparserContext);
|
|
36
|
+
yield* uintUnparser(input.length, unparserContext);
|
|
37
|
+
for (const annotationSet of input) {
|
|
38
|
+
if (annotationSet.length > 0) {
|
|
39
|
+
const annotationSetOffsetWriteLater = yield* yieldAndCapture(unparserContext.writeLater(4));
|
|
40
|
+
annotationSetOffsetWriteLaters.push(annotationSetOffsetWriteLater);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
annotationSetOffsetWriteLaters.push(null);
|
|
44
|
+
yield* uintUnparser(0, unparserContext);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
const annotationsDirectoryItemUnparser = (annotationOffsetWriteLaters) => {
|
|
50
|
+
return async function* (input, unparserContext) {
|
|
51
|
+
yield* alignmentUnparser(4)(undefined, unparserContext);
|
|
52
|
+
if (input.classAnnotations.length > 0) {
|
|
53
|
+
const classAnnotationsOffsetWriteLater = yield* yieldAndCapture(unparserContext.writeLater(4));
|
|
54
|
+
annotationOffsetWriteLaters.classAnnotationsOffsetWriteLater = classAnnotationsOffsetWriteLater;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
yield* uintUnparser(0, unparserContext);
|
|
58
|
+
}
|
|
59
|
+
yield* uintUnparser(input.fieldAnnotations.length, unparserContext);
|
|
60
|
+
yield* uintUnparser(input.methodAnnotations.length, unparserContext);
|
|
61
|
+
yield* uintUnparser(input.parameterAnnotations.length, unparserContext);
|
|
62
|
+
annotationOffsetWriteLaters.fieldAnnotationsOffsetWriteLaters = [];
|
|
63
|
+
for (const fieldAnnotation of input.fieldAnnotations) {
|
|
64
|
+
const fieldIndex = getFieldIndex(fieldAnnotation.field);
|
|
65
|
+
yield* uintUnparser(fieldIndex, unparserContext);
|
|
66
|
+
if (fieldAnnotation.annotations && fieldAnnotation.annotations.length > 0) {
|
|
67
|
+
const annotationsOffsetWriteLater = yield* yieldAndCapture(unparserContext.writeLater(4));
|
|
68
|
+
annotationOffsetWriteLaters.fieldAnnotationsOffsetWriteLaters.push(annotationsOffsetWriteLater);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
annotationOffsetWriteLaters.fieldAnnotationsOffsetWriteLaters.push(null);
|
|
72
|
+
yield* uintUnparser(0, unparserContext);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
annotationOffsetWriteLaters.methodAnnotationsOffsetWriteLaters = [];
|
|
76
|
+
for (const methodAnnotation of input.methodAnnotations) {
|
|
77
|
+
const methodIndex = getMethodIndex(methodAnnotation.method);
|
|
78
|
+
yield* uintUnparser(methodIndex, unparserContext);
|
|
79
|
+
const annotationsOffsetWriteLater = yield* yieldAndCapture(unparserContext.writeLater(4));
|
|
80
|
+
annotationOffsetWriteLaters.methodAnnotationsOffsetWriteLaters.push(annotationsOffsetWriteLater);
|
|
81
|
+
}
|
|
82
|
+
annotationOffsetWriteLaters.parameterAnnotationsOffsetWriteLaters = [];
|
|
83
|
+
for (const paramAnnotation of input.parameterAnnotations) {
|
|
84
|
+
const methodIndex = getMethodIndex(paramAnnotation.method);
|
|
85
|
+
yield* uintUnparser(methodIndex, unparserContext);
|
|
86
|
+
const annotationsOffsetWriteLater = yield* yieldAndCapture(unparserContext.writeLater(4));
|
|
87
|
+
annotationOffsetWriteLaters.parameterAnnotationsOffsetWriteLaters.push(annotationsOffsetWriteLater);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
return {
|
|
92
|
+
annotationItemUnparser,
|
|
93
|
+
annotationSetItemUnparser,
|
|
94
|
+
annotationSetRefListUnparser,
|
|
95
|
+
annotationsDirectoryItemUnparser,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type DalvikExecutableField, type DalvikExecutableMethod, type DalvikExecutablePrototype } from '../dalvikExecutable.js';
|
|
2
|
+
export declare class StringPoolBuilder {
|
|
3
|
+
private strings;
|
|
4
|
+
private stringToIndex;
|
|
5
|
+
add(str: string): number;
|
|
6
|
+
getIndex(str: string): number | undefined;
|
|
7
|
+
getStrings(): string[];
|
|
8
|
+
size(): number;
|
|
9
|
+
}
|
|
10
|
+
export declare class TypePoolBuilder {
|
|
11
|
+
private types;
|
|
12
|
+
private typeToIndex;
|
|
13
|
+
add(typeDescriptor: string): number;
|
|
14
|
+
getIndex(typeDescriptor: string): number | undefined;
|
|
15
|
+
getTypes(): string[];
|
|
16
|
+
size(): number;
|
|
17
|
+
}
|
|
18
|
+
export declare class ProtoPoolBuilder {
|
|
19
|
+
private protos;
|
|
20
|
+
private protoToIndex;
|
|
21
|
+
add(proto: DalvikExecutablePrototype): number;
|
|
22
|
+
getIndex(proto: DalvikExecutablePrototype): number | undefined;
|
|
23
|
+
getProtos(): DalvikExecutablePrototype[];
|
|
24
|
+
size(): number;
|
|
25
|
+
}
|
|
26
|
+
export declare class FieldPoolBuilder {
|
|
27
|
+
private fields;
|
|
28
|
+
private fieldToIndex;
|
|
29
|
+
add(field: DalvikExecutableField): number;
|
|
30
|
+
getIndex(field: DalvikExecutableField): number | undefined;
|
|
31
|
+
getFields(): DalvikExecutableField[];
|
|
32
|
+
size(): number;
|
|
33
|
+
}
|
|
34
|
+
export declare class MethodPoolBuilder {
|
|
35
|
+
private methods;
|
|
36
|
+
private methodToIndex;
|
|
37
|
+
add(method: DalvikExecutableMethod): number;
|
|
38
|
+
getIndex(method: DalvikExecutableMethod): number | undefined;
|
|
39
|
+
getMethods(): DalvikExecutableMethod[];
|
|
40
|
+
size(): number;
|
|
41
|
+
}
|
|
42
|
+
export interface PoolBuilders {
|
|
43
|
+
stringPool: StringPoolBuilder;
|
|
44
|
+
typePool: TypePoolBuilder;
|
|
45
|
+
protoPool: ProtoPoolBuilder;
|
|
46
|
+
fieldPool: FieldPoolBuilder;
|
|
47
|
+
methodPool: MethodPoolBuilder;
|
|
48
|
+
}
|
|
49
|
+
export declare function createPoolBuilders(): PoolBuilders;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export class StringPoolBuilder {
|
|
2
|
+
strings = [];
|
|
3
|
+
stringToIndex = new Map();
|
|
4
|
+
add(str) {
|
|
5
|
+
const existing = this.stringToIndex.get(str);
|
|
6
|
+
if (existing !== undefined) {
|
|
7
|
+
return existing;
|
|
8
|
+
}
|
|
9
|
+
const index = this.strings.length;
|
|
10
|
+
this.strings.push(str);
|
|
11
|
+
this.stringToIndex.set(str, index);
|
|
12
|
+
return index;
|
|
13
|
+
}
|
|
14
|
+
getIndex(str) {
|
|
15
|
+
return this.stringToIndex.get(str);
|
|
16
|
+
}
|
|
17
|
+
getStrings() {
|
|
18
|
+
return this.strings;
|
|
19
|
+
}
|
|
20
|
+
size() {
|
|
21
|
+
return this.strings.length;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export class TypePoolBuilder {
|
|
25
|
+
types = [];
|
|
26
|
+
typeToIndex = new Map();
|
|
27
|
+
add(typeDescriptor) {
|
|
28
|
+
const existing = this.typeToIndex.get(typeDescriptor);
|
|
29
|
+
if (existing !== undefined) {
|
|
30
|
+
return existing;
|
|
31
|
+
}
|
|
32
|
+
const index = this.types.length;
|
|
33
|
+
this.types.push(typeDescriptor);
|
|
34
|
+
this.typeToIndex.set(typeDescriptor, index);
|
|
35
|
+
return index;
|
|
36
|
+
}
|
|
37
|
+
getIndex(typeDescriptor) {
|
|
38
|
+
return this.typeToIndex.get(typeDescriptor);
|
|
39
|
+
}
|
|
40
|
+
getTypes() {
|
|
41
|
+
return this.types;
|
|
42
|
+
}
|
|
43
|
+
size() {
|
|
44
|
+
return this.types.length;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function prototypeKey(proto) {
|
|
48
|
+
return `${proto.shorty}:${proto.returnType}:(${proto.parameters.join(',')})`;
|
|
49
|
+
}
|
|
50
|
+
export class ProtoPoolBuilder {
|
|
51
|
+
protos = [];
|
|
52
|
+
protoToIndex = new Map();
|
|
53
|
+
add(proto) {
|
|
54
|
+
const key = prototypeKey(proto);
|
|
55
|
+
const existing = this.protoToIndex.get(key);
|
|
56
|
+
if (existing !== undefined) {
|
|
57
|
+
return existing;
|
|
58
|
+
}
|
|
59
|
+
const index = this.protos.length;
|
|
60
|
+
this.protos.push(proto);
|
|
61
|
+
this.protoToIndex.set(key, index);
|
|
62
|
+
return index;
|
|
63
|
+
}
|
|
64
|
+
getIndex(proto) {
|
|
65
|
+
const key = prototypeKey(proto);
|
|
66
|
+
return this.protoToIndex.get(key);
|
|
67
|
+
}
|
|
68
|
+
getProtos() {
|
|
69
|
+
return this.protos;
|
|
70
|
+
}
|
|
71
|
+
size() {
|
|
72
|
+
return this.protos.length;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function fieldKey(field) {
|
|
76
|
+
return `${field.class}:${field.type}:${field.name}`;
|
|
77
|
+
}
|
|
78
|
+
export class FieldPoolBuilder {
|
|
79
|
+
fields = [];
|
|
80
|
+
fieldToIndex = new Map();
|
|
81
|
+
add(field) {
|
|
82
|
+
const key = fieldKey(field);
|
|
83
|
+
const existing = this.fieldToIndex.get(key);
|
|
84
|
+
if (existing !== undefined) {
|
|
85
|
+
return existing;
|
|
86
|
+
}
|
|
87
|
+
const index = this.fields.length;
|
|
88
|
+
this.fields.push(field);
|
|
89
|
+
this.fieldToIndex.set(key, index);
|
|
90
|
+
return index;
|
|
91
|
+
}
|
|
92
|
+
getIndex(field) {
|
|
93
|
+
const key = fieldKey(field);
|
|
94
|
+
return this.fieldToIndex.get(key);
|
|
95
|
+
}
|
|
96
|
+
getFields() {
|
|
97
|
+
return this.fields;
|
|
98
|
+
}
|
|
99
|
+
size() {
|
|
100
|
+
return this.fields.length;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function methodKey(method) {
|
|
104
|
+
const protoKey = prototypeKey(method.prototype);
|
|
105
|
+
return `${method.class}:${protoKey}:${method.name}`;
|
|
106
|
+
}
|
|
107
|
+
export class MethodPoolBuilder {
|
|
108
|
+
methods = [];
|
|
109
|
+
methodToIndex = new Map();
|
|
110
|
+
add(method) {
|
|
111
|
+
const key = methodKey(method);
|
|
112
|
+
const existing = this.methodToIndex.get(key);
|
|
113
|
+
if (existing !== undefined) {
|
|
114
|
+
return existing;
|
|
115
|
+
}
|
|
116
|
+
const index = this.methods.length;
|
|
117
|
+
this.methods.push(method);
|
|
118
|
+
this.methodToIndex.set(key, index);
|
|
119
|
+
return index;
|
|
120
|
+
}
|
|
121
|
+
getIndex(method) {
|
|
122
|
+
const key = methodKey(method);
|
|
123
|
+
return this.methodToIndex.get(key);
|
|
124
|
+
}
|
|
125
|
+
getMethods() {
|
|
126
|
+
return this.methods;
|
|
127
|
+
}
|
|
128
|
+
size() {
|
|
129
|
+
return this.methods.length;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export function createPoolBuilders() {
|
|
133
|
+
return {
|
|
134
|
+
stringPool: new StringPoolBuilder(),
|
|
135
|
+
typePool: new TypePoolBuilder(),
|
|
136
|
+
protoPool: new ProtoPoolBuilder(),
|
|
137
|
+
fieldPool: new FieldPoolBuilder(),
|
|
138
|
+
methodPool: new MethodPoolBuilder(),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type DalvikExecutable } from '../dalvikExecutable.js';
|
|
2
|
+
import { type DalvikBytecode } from '../dalvikBytecodeParser.js';
|
|
3
|
+
import { type PoolBuilders } from './poolBuilders.js';
|
|
4
|
+
export declare function scanForPoolReferences(dalvikExecutable: DalvikExecutable<DalvikBytecode>, poolBuilders: PoolBuilders): void;
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { isDalvikExecutableField, isDalvikExecutableMethod, } from '../dalvikExecutable.js';
|
|
2
|
+
export function scanForPoolReferences(dalvikExecutable, poolBuilders) {
|
|
3
|
+
const { stringPool, typePool, protoPool, fieldPool, methodPool } = poolBuilders;
|
|
4
|
+
for (const classDef of dalvikExecutable.classDefinitions) {
|
|
5
|
+
scanClassDefinition(classDef);
|
|
6
|
+
}
|
|
7
|
+
function addString(str) {
|
|
8
|
+
if (str !== undefined) {
|
|
9
|
+
stringPool.add(str);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function addType(typeDescriptor) {
|
|
13
|
+
if (typeDescriptor !== undefined) {
|
|
14
|
+
typePool.add(typeDescriptor);
|
|
15
|
+
stringPool.add(typeDescriptor);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function addPrototype(proto) {
|
|
19
|
+
protoPool.add(proto);
|
|
20
|
+
addString(proto.shorty);
|
|
21
|
+
addType(proto.returnType);
|
|
22
|
+
for (const param of proto.parameters) {
|
|
23
|
+
addType(param);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function addField(field) {
|
|
27
|
+
fieldPool.add(field);
|
|
28
|
+
addType(field.class);
|
|
29
|
+
addType(field.type);
|
|
30
|
+
addString(field.name);
|
|
31
|
+
}
|
|
32
|
+
function addMethod(method) {
|
|
33
|
+
methodPool.add(method);
|
|
34
|
+
addType(method.class);
|
|
35
|
+
addPrototype(method.prototype);
|
|
36
|
+
addString(method.name);
|
|
37
|
+
}
|
|
38
|
+
function scanEncodedValue(value) {
|
|
39
|
+
const { type, value: innerValue } = value;
|
|
40
|
+
// Handle primitive types - they don't need pool entries
|
|
41
|
+
if (type === 'byte'
|
|
42
|
+
|| type === 'short'
|
|
43
|
+
|| type === 'char'
|
|
44
|
+
|| type === 'int'
|
|
45
|
+
|| type === 'long'
|
|
46
|
+
|| type === 'float'
|
|
47
|
+
|| type === 'double'
|
|
48
|
+
|| type === 'boolean'
|
|
49
|
+
|| type === 'null'
|
|
50
|
+
|| type === 'methodHandle') {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// Handle types that need pool entries
|
|
54
|
+
if (type === 'string') {
|
|
55
|
+
addString(innerValue);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (type === 'type') {
|
|
59
|
+
addType(innerValue);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (type === 'field' || type === 'enum') {
|
|
63
|
+
addField(innerValue);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (type === 'method') {
|
|
67
|
+
addMethod(innerValue);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (type === 'methodType') {
|
|
71
|
+
addPrototype(innerValue);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Handle arrays recursively
|
|
75
|
+
if (type === 'array') {
|
|
76
|
+
for (const element of innerValue) {
|
|
77
|
+
scanEncodedValue(element);
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Handle annotations
|
|
82
|
+
if (type === 'annotation') {
|
|
83
|
+
scanAnnotation(innerValue);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function scanAnnotation(annotation) {
|
|
87
|
+
addType(annotation.type);
|
|
88
|
+
for (const element of annotation.elements) {
|
|
89
|
+
addString(element.name);
|
|
90
|
+
scanEncodedValue(element.value);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function scanAnnotations(annotations) {
|
|
94
|
+
if (!annotations) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
for (const annotation of annotations.classAnnotations) {
|
|
98
|
+
scanAnnotation(annotation);
|
|
99
|
+
}
|
|
100
|
+
for (const fieldAnnotation of annotations.fieldAnnotations) {
|
|
101
|
+
addField(fieldAnnotation.field);
|
|
102
|
+
if (fieldAnnotation.annotations) {
|
|
103
|
+
for (const annotation of fieldAnnotation.annotations) {
|
|
104
|
+
scanAnnotation(annotation);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
for (const methodAnnotation of annotations.methodAnnotations) {
|
|
109
|
+
addMethod(methodAnnotation.method);
|
|
110
|
+
for (const annotation of methodAnnotation.annotations) {
|
|
111
|
+
scanAnnotation(annotation);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (const paramAnnotation of annotations.parameterAnnotations) {
|
|
115
|
+
addMethod(paramAnnotation.method);
|
|
116
|
+
for (const paramAnnotations of paramAnnotation.annotations) {
|
|
117
|
+
for (const annotation of paramAnnotations) {
|
|
118
|
+
scanAnnotation(annotation);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function scanDebugInfo(debugInfo) {
|
|
124
|
+
if (!debugInfo) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
for (const paramName of debugInfo.parameterNames) {
|
|
128
|
+
addString(paramName);
|
|
129
|
+
}
|
|
130
|
+
for (const bytecode of debugInfo.bytecode) {
|
|
131
|
+
if (bytecode.type === 'startLocal' || bytecode.type === 'startLocalExtended') {
|
|
132
|
+
addString(bytecode.name);
|
|
133
|
+
addType(bytecode.type_);
|
|
134
|
+
}
|
|
135
|
+
if (bytecode.type === 'startLocalExtended') {
|
|
136
|
+
addString(bytecode.signature);
|
|
137
|
+
}
|
|
138
|
+
if (bytecode.type === 'setFile') {
|
|
139
|
+
addString(bytecode.name);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function scanCode(code) {
|
|
144
|
+
if (!code) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
scanDebugInfo(code.debugInfo);
|
|
148
|
+
for (const operation of code.instructions) {
|
|
149
|
+
if ('methodIndex' in operation) {
|
|
150
|
+
const methodIndex = operation.methodIndex;
|
|
151
|
+
if (isDalvikExecutableMethod(methodIndex)) {
|
|
152
|
+
addMethod(methodIndex);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if ('fieldIndex' in operation) {
|
|
156
|
+
const fieldIndex = operation.fieldIndex;
|
|
157
|
+
if (isDalvikExecutableField(fieldIndex)) {
|
|
158
|
+
addField(fieldIndex);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if ('typeIndex' in operation) {
|
|
162
|
+
const typeIndex = operation.typeIndex;
|
|
163
|
+
if (typeof typeIndex === 'string') {
|
|
164
|
+
addType(typeIndex);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if ('stringIndex' in operation) {
|
|
168
|
+
const stringIndex = operation.stringIndex;
|
|
169
|
+
if (typeof stringIndex === 'string') {
|
|
170
|
+
addString(stringIndex);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if ('protoIndex' in operation) {
|
|
174
|
+
const protoIndex = operation.protoIndex;
|
|
175
|
+
if (typeof protoIndex === 'object' && protoIndex !== null && 'returnType' in protoIndex) {
|
|
176
|
+
addPrototype(protoIndex);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
for (const tryBlock of code.tries) {
|
|
181
|
+
for (const handler of tryBlock.handler.handlers) {
|
|
182
|
+
addType(handler.type);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function scanMethod(method) {
|
|
187
|
+
addMethod(method.method);
|
|
188
|
+
scanCode(method.code);
|
|
189
|
+
}
|
|
190
|
+
function scanClassData(classData) {
|
|
191
|
+
if (!classData) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
for (const field of classData.staticFields) {
|
|
195
|
+
addField(field.field);
|
|
196
|
+
}
|
|
197
|
+
for (const field of classData.instanceFields) {
|
|
198
|
+
addField(field.field);
|
|
199
|
+
}
|
|
200
|
+
for (const method of classData.directMethods) {
|
|
201
|
+
scanMethod(method);
|
|
202
|
+
}
|
|
203
|
+
for (const method of classData.virtualMethods) {
|
|
204
|
+
scanMethod(method);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function scanClassDefinition(classDef) {
|
|
208
|
+
addType(classDef.class);
|
|
209
|
+
addType(classDef.superclass);
|
|
210
|
+
for (const iface of classDef.interfaces) {
|
|
211
|
+
addType(iface);
|
|
212
|
+
}
|
|
213
|
+
addString(classDef.sourceFile);
|
|
214
|
+
scanAnnotations(classDef.annotations);
|
|
215
|
+
for (const value of classDef.staticValues) {
|
|
216
|
+
scanEncodedValue(value);
|
|
217
|
+
}
|
|
218
|
+
scanClassData(classDef.classData);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Unparser } from '../unparser.js';
|
|
2
|
+
import { type DalvikExecutableAccessFlags, type DalvikExecutableClassData, type DalvikExecutableCode, type DalvikExecutableDebugInfo, type DalvikExecutableEncodedValue, type DalvikExecutableField, type DalvikExecutableMethod, type DalvikExecutablePrototype } from '../dalvikExecutable.js';
|
|
3
|
+
import { type DalvikBytecode } from '../dalvikBytecodeParser.js';
|
|
4
|
+
import { type PoolBuilders } from './poolBuilders.js';
|
|
5
|
+
import { WriteLater } from '../unparserContext.js';
|
|
6
|
+
export declare function createSectionUnparsers(poolBuilders: PoolBuilders): {
|
|
7
|
+
stringDataUnparser: Unparser<string, Uint8Array<ArrayBufferLike>>;
|
|
8
|
+
typeListUnparser: Unparser<string[], Uint8Array<ArrayBufferLike>>;
|
|
9
|
+
protoDataUnparser: Unparser<DalvikExecutablePrototype, Uint8Array<ArrayBufferLike>>;
|
|
10
|
+
fieldIdUnparser: Unparser<DalvikExecutableField, Uint8Array<ArrayBufferLike>>;
|
|
11
|
+
methodIdUnparser: Unparser<DalvikExecutableMethod, Uint8Array<ArrayBufferLike>>;
|
|
12
|
+
encodedValueUnparser: Unparser<DalvikExecutableEncodedValue, Uint8Array<ArrayBufferLike>>;
|
|
13
|
+
encodedArrayUnparser: Unparser<DalvikExecutableEncodedValue[], Uint8Array<ArrayBufferLike>>;
|
|
14
|
+
debugInfoUnparser: Unparser<DalvikExecutableDebugInfo, Uint8Array<ArrayBufferLike>>;
|
|
15
|
+
codeItemUnparser: (callback?: (result: {
|
|
16
|
+
debugInfoOffsetWriteLater?: WriteLater<Uint8Array, number>;
|
|
17
|
+
}) => void) => Unparser<DalvikExecutableCode<DalvikBytecode>, Uint8Array>;
|
|
18
|
+
classDataUnparser: (codeOffsetMap: Map<DalvikExecutableCode<DalvikBytecode>, number>) => Unparser<DalvikExecutableClassData<DalvikBytecode>, Uint8Array>;
|
|
19
|
+
accessFlagsToNumber: (accessFlags: DalvikExecutableAccessFlags) => number;
|
|
20
|
+
getStringIndex: (str: string | undefined) => number;
|
|
21
|
+
getTypeIndex: (typeDescriptor: string | undefined) => number;
|
|
22
|
+
getProtoIndex: (proto: DalvikExecutablePrototype) => number;
|
|
23
|
+
getFieldIndex: (field: DalvikExecutableField) => number;
|
|
24
|
+
getMethodIndex: (method: DalvikExecutableMethod) => number;
|
|
25
|
+
};
|