@futpib/parser 1.0.3 → 1.0.6
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/.claude/settings.local.json +24 -0
- package/.github/workflows/main.yml +1 -0
- package/build/androidPackageParser.js +30 -32
- package/build/arbitraryDalvikBytecode.d.ts +3 -3
- package/build/arbitraryDalvikBytecode.js +33 -27
- package/build/arbitraryDalvikExecutable.js +55 -17
- package/build/arbitraryJava.d.ts +31 -0
- package/build/arbitraryJava.js +532 -0
- package/build/arbitraryJavaScript.d.ts +3 -0
- package/build/arbitraryJavaScript.js +263 -0
- package/build/arbitraryJavascript.d.ts +3 -0
- package/build/arbitraryJavascript.js +263 -0
- package/build/arbitraryZig.d.ts +3 -0
- package/build/arbitraryZig.js +240 -0
- package/build/arbitraryZipStream.d.ts +1 -1
- package/build/arrayParser.js +72 -13
- package/build/backsmali.d.ts +4 -3
- package/build/backsmali.js +26 -6
- package/build/bash.d.ts +89 -0
- package/build/bash.js +1 -0
- package/build/bashParser.d.ts +6 -0
- package/build/bashParser.js +335 -0
- package/build/bashParser.test.d.ts +1 -0
- package/build/bashParser.test.js +343 -0
- package/build/bashParserEdgeCases.test.d.ts +1 -0
- package/build/bashParserEdgeCases.test.js +117 -0
- package/build/dalvikBytecodeParser/addressConversion.d.ts +110 -0
- package/build/dalvikBytecodeParser/addressConversion.js +334 -0
- package/build/dalvikBytecodeParser/formatParsers.d.ts +7 -6
- package/build/dalvikBytecodeParser/formatParsers.js +13 -14
- package/build/dalvikBytecodeParser.d.ts +60 -31
- package/build/dalvikBytecodeParser.js +92 -35
- package/build/dalvikBytecodeParser.test-d.d.ts +1 -0
- package/build/dalvikBytecodeParser.test-d.js +268 -0
- package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +9 -8
- package/build/dalvikBytecodeUnparser/formatUnparsers.js +13 -12
- package/build/dalvikBytecodeUnparser.d.ts +2 -2
- package/build/dalvikBytecodeUnparser.js +23 -23
- package/build/dalvikBytecodeUnparser.test.js +7 -7
- package/build/dalvikExecutable.d.ts +3 -3
- package/build/dalvikExecutable.test-d.d.ts +1 -0
- package/build/dalvikExecutable.test-d.js +59 -0
- package/build/dalvikExecutableParser/typedNumbers.d.ts +18 -0
- package/build/dalvikExecutableParser/typedNumbers.js +3 -0
- package/build/dalvikExecutableParser.d.ts +2 -1
- package/build/dalvikExecutableParser.js +96 -77
- package/build/dalvikExecutableParser.test.js +24 -3
- package/build/dalvikExecutableParserAgainstSmaliParser.test.js +3 -0
- package/build/dalvikExecutableUnparser/poolScanners.d.ts +2 -2
- package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +3 -3
- package/build/dalvikExecutableUnparser/sectionUnparsers.js +26 -11
- package/build/dalvikExecutableUnparser.d.ts +2 -2
- package/build/dalvikExecutableUnparser.test.js +2 -1
- package/build/disjunctionParser.d.ts +5 -3
- package/build/disjunctionParser.js +79 -17
- package/build/disjunctionParser.test-d.d.ts +1 -0
- package/build/disjunctionParser.test-d.js +72 -0
- package/build/elementSwitchParser.d.ts +4 -0
- package/build/{exactElementSwitchParser.js → elementSwitchParser.js} +3 -4
- package/build/elementSwitchParser.test-d.d.ts +1 -0
- package/build/elementSwitchParser.test-d.js +44 -0
- package/build/exactSequenceParser.d.ts +4 -2
- package/build/exactSequenceParser.test-d.d.ts +1 -0
- package/build/exactSequenceParser.test-d.js +36 -0
- package/build/fetchCid.js +2 -66
- package/build/index.d.ts +25 -2
- package/build/index.js +23 -1
- package/build/index.test.js +16 -1
- package/build/inputReader.d.ts +10 -0
- package/build/inputReader.js +36 -0
- package/build/java.d.ts +502 -0
- package/build/java.js +2 -0
- package/build/javaKeyStoreParser.js +14 -17
- package/build/javaParser.d.ts +51 -0
- package/build/javaParser.js +1538 -0
- package/build/javaParser.test.d.ts +1 -0
- package/build/javaParser.test.js +1287 -0
- package/build/javaScript.d.ts +35 -0
- package/build/javaScript.js +1 -0
- package/build/javaScriptParser.d.ts +9 -0
- package/build/javaScriptParser.js +34 -0
- package/build/javaScriptUnparser.d.ts +3 -0
- package/build/javaScriptUnparser.js +4 -0
- package/build/javaScriptUnparser.test.d.ts +1 -0
- package/build/javaScriptUnparser.test.js +24 -0
- package/build/javaUnparser.d.ts +2 -0
- package/build/javaUnparser.js +519 -0
- package/build/javaUnparser.test.d.ts +1 -0
- package/build/javaUnparser.test.js +24 -0
- package/build/javascript.d.ts +35 -0
- package/build/javascript.js +1 -0
- package/build/javascriptParser.d.ts +9 -0
- package/build/javascriptParser.js +34 -0
- package/build/javascriptUnparser.d.ts +3 -0
- package/build/javascriptUnparser.js +4 -0
- package/build/javascriptUnparser.test.d.ts +1 -0
- package/build/javascriptUnparser.test.js +24 -0
- package/build/jsonParser.js +2 -12
- package/build/lazyMessageError.d.ts +3 -0
- package/build/lookaheadParser.js +60 -3
- package/build/negativeLookaheadParser.js +70 -11
- package/build/nonEmptyArrayParser.js +72 -13
- package/build/objectParser.d.ts +12 -0
- package/build/objectParser.js +31 -0
- package/build/objectParser.test-d.d.ts +1 -0
- package/build/objectParser.test-d.js +112 -0
- package/build/objectParser.test.d.ts +1 -0
- package/build/objectParser.test.js +55 -0
- package/build/optionalParser.js +69 -10
- package/build/parser.d.ts +4 -0
- package/build/parser.js +3 -1
- package/build/parser.test.js +114 -1
- package/build/parserConsumedSequenceParser.js +66 -7
- package/build/parserContext.d.ts +6 -0
- package/build/parserContext.js +20 -11
- package/build/parserError.d.ts +119 -27
- package/build/parserError.js +16 -8
- package/build/regexpParser.d.ts +2 -0
- package/build/regexpParser.js +101 -0
- package/build/regexpParser.test.d.ts +1 -0
- package/build/regexpParser.test.js +114 -0
- package/build/regularExpression.d.ts +63 -0
- package/build/regularExpression.js +1 -0
- package/build/regularExpressionParser.d.ts +3 -0
- package/build/regularExpressionParser.js +600 -0
- package/build/regularExpressionParser.test.d.ts +1 -0
- package/build/regularExpressionParser.test.js +89 -0
- package/build/separatedArrayParser.js +73 -14
- package/build/separatedNonEmptyArrayParser.js +73 -14
- package/build/sliceBoundedParser.js +62 -5
- package/build/smaliParser.d.ts +7 -7
- package/build/smaliParser.js +185 -268
- package/build/smaliParser.test.js +58 -0
- package/build/stringEscapes.d.ts +5 -0
- package/build/stringEscapes.js +244 -0
- package/build/symbolicExpression.d.ts +29 -0
- package/build/symbolicExpression.js +1 -0
- package/build/symbolicExpressionParser.d.ts +4 -0
- package/build/symbolicExpressionParser.js +123 -0
- package/build/symbolicExpressionParser.test.d.ts +1 -0
- package/build/symbolicExpressionParser.test.js +289 -0
- package/build/terminatedArrayParser.js +113 -38
- package/build/terminatedArrayParser.test.js +4 -2
- package/build/tupleParser.d.ts +7 -15
- package/build/tupleParser.js +1 -0
- package/build/unionParser.d.ts +5 -3
- package/build/unionParser.js +7 -2
- package/build/unionParser.test-d.d.ts +1 -0
- package/build/unionParser.test-d.js +72 -0
- package/build/unionParser.test.js +10 -11
- package/build/zig.d.ts +280 -0
- package/build/zig.js +2 -0
- package/build/zigParser.d.ts +3 -0
- package/build/zigParser.js +1119 -0
- package/build/zigParser.test.d.ts +1 -0
- package/build/zigParser.test.js +1590 -0
- package/build/zigUnparser.d.ts +2 -0
- package/build/zigUnparser.js +460 -0
- package/build/zigUnparser.test.d.ts +1 -0
- package/build/zigUnparser.test.js +24 -0
- package/build/zipParser.js +19 -32
- package/build/zipUnparser.js +19 -7
- package/build/zipUnparser.test.js +1 -1
- package/node_modules-@types/s-expression/index.d.ts +5 -0
- package/package.json +25 -6
- package/src/androidPackageParser.ts +33 -60
- package/src/arbitraryDalvikBytecode.ts +39 -31
- package/src/arbitraryDalvikExecutable.ts +65 -20
- package/src/arbitraryJava.ts +804 -0
- package/src/arbitraryJavaScript.ts +410 -0
- package/src/arbitraryZig.ts +380 -0
- package/src/arrayParser.ts +1 -3
- package/src/backsmali.ts +35 -4
- package/src/bash.ts +127 -0
- package/src/bashParser.test.ts +590 -0
- package/src/bashParser.ts +498 -0
- package/src/dalvikBytecodeParser/addressConversion.ts +496 -0
- package/src/dalvikBytecodeParser/formatParsers.ts +19 -29
- package/src/dalvikBytecodeParser.test-d.ts +310 -0
- package/src/dalvikBytecodeParser.ts +194 -69
- package/src/dalvikBytecodeUnparser/formatUnparsers.ts +27 -26
- package/src/dalvikBytecodeUnparser.test.ts +7 -7
- package/src/dalvikBytecodeUnparser.ts +31 -30
- package/src/dalvikExecutable.test-d.ts +132 -0
- package/src/dalvikExecutable.ts +3 -3
- package/src/dalvikExecutableParser/typedNumbers.ts +11 -0
- package/src/dalvikExecutableParser.test.ts +37 -3
- package/src/dalvikExecutableParser.test.ts.md +163 -2
- package/src/dalvikExecutableParser.test.ts.snap +0 -0
- package/src/dalvikExecutableParser.ts +121 -139
- package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +4 -0
- package/src/dalvikExecutableUnparser/poolScanners.ts +6 -6
- package/src/dalvikExecutableUnparser/sectionUnparsers.ts +38 -14
- package/src/dalvikExecutableUnparser.test.ts +3 -2
- package/src/dalvikExecutableUnparser.ts +4 -4
- package/src/disjunctionParser.test-d.ts +105 -0
- package/src/disjunctionParser.ts +18 -15
- package/src/elementSwitchParser.test-d.ts +74 -0
- package/src/elementSwitchParser.ts +51 -0
- package/src/exactSequenceParser.test-d.ts +43 -0
- package/src/exactSequenceParser.ts +13 -8
- package/src/fetchCid.ts +2 -76
- package/src/index.test.ts +22 -1
- package/src/index.ts +119 -2
- package/src/inputReader.ts +53 -0
- package/src/java.ts +708 -0
- package/src/javaKeyStoreParser.ts +18 -32
- package/src/javaParser.test.ts +1592 -0
- package/src/javaParser.ts +2640 -0
- package/src/javaScript.ts +36 -0
- package/src/javaScriptParser.ts +57 -0
- package/src/javaScriptUnparser.test.ts +37 -0
- package/src/javaScriptUnparser.ts +7 -0
- package/src/javaUnparser.test.ts +37 -0
- package/src/javaUnparser.ts +640 -0
- package/src/jsonParser.ts +6 -27
- package/src/lookaheadParser.ts +2 -6
- package/src/negativeLookaheadParser.ts +1 -3
- package/src/nonEmptyArrayParser.ts +1 -3
- package/src/objectParser.test-d.ts +152 -0
- package/src/objectParser.test.ts +71 -0
- package/src/objectParser.ts +69 -0
- package/src/optionalParser.ts +1 -3
- package/src/parser.test.ts +151 -4
- package/src/parser.ts +11 -1
- package/src/parserConsumedSequenceParser.ts +2 -4
- package/src/parserContext.ts +26 -11
- package/src/parserError.ts +17 -3
- package/src/regexpParser.test.ts +264 -0
- package/src/regexpParser.ts +126 -0
- package/src/regularExpression.ts +24 -0
- package/src/regularExpressionParser.test.ts +102 -0
- package/src/regularExpressionParser.ts +920 -0
- package/src/separatedArrayParser.ts +1 -3
- package/src/separatedNonEmptyArrayParser.ts +1 -3
- package/src/sliceBoundedParser.test.ts +2 -2
- package/src/sliceBoundedParser.ts +15 -19
- package/src/smaliParser.test.ts +64 -0
- package/src/smaliParser.test.ts.md +12 -12
- package/src/smaliParser.test.ts.snap +0 -0
- package/src/smaliParser.ts +246 -534
- package/src/stringEscapes.ts +253 -0
- package/src/symbolicExpression.ts +17 -0
- package/src/symbolicExpressionParser.test.ts +466 -0
- package/src/symbolicExpressionParser.ts +190 -0
- package/src/terminatedArrayParser.test.ts +9 -6
- package/src/terminatedArrayParser.ts +25 -29
- package/src/tupleParser.ts +21 -18
- package/src/unionParser.test-d.ts +105 -0
- package/src/unionParser.test.ts +18 -17
- package/src/unionParser.ts +28 -16
- package/src/zig.ts +411 -0
- package/src/zigParser.test.ts +1693 -0
- package/src/zigParser.ts +1745 -0
- package/src/zigUnparser.test.ts +37 -0
- package/src/zigUnparser.ts +615 -0
- package/src/zipParser.ts +20 -56
- package/src/zipUnparser.test.ts +1 -1
- package/src/zipUnparser.ts +22 -7
- package/tsconfig.json +2 -2
- package/build/exactElementSwitchParser.d.ts +0 -3
- package/src/exactElementSwitchParser.ts +0 -41
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
import { type RawDalvikBytecodeOperation, type IndexResolvedOperation } from '../dalvikBytecodeParser.js';
|
|
2
|
+
import {
|
|
3
|
+
type CodeUnit, isoCodeUnit,
|
|
4
|
+
type InstructionIndex, isoInstructionIndex,
|
|
5
|
+
} from '../dalvikExecutableParser/typedNumbers.js';
|
|
6
|
+
import { operationFormats } from './operationFormats.js';
|
|
7
|
+
import { formatSizes } from './formatSizes.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Map from code unit offset to instruction index.
|
|
11
|
+
* Keys are raw code unit offsets, values are instruction indices.
|
|
12
|
+
*/
|
|
13
|
+
export type CodeUnitToIndexMap = Map<CodeUnit, InstructionIndex>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Map from instruction index to code unit offset.
|
|
17
|
+
* Keys are instruction indices, values are raw code unit offsets.
|
|
18
|
+
*/
|
|
19
|
+
export type IndexToCodeUnitMap = Map<InstructionIndex, CodeUnit>;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get the branch offsets array length from an operation, regardless of tier.
|
|
23
|
+
* Works with all field name variants: branchOffsetsCodeUnit, branchOffsetsIndex, targetInstructionIndices, branchOffsetIndices.
|
|
24
|
+
*/
|
|
25
|
+
function getBranchOffsetsLength(operation: { operation: string }): number | undefined {
|
|
26
|
+
const op = operation as any;
|
|
27
|
+
return op.branchOffsetsCodeUnit?.length
|
|
28
|
+
?? op.branchOffsetsIndex?.length
|
|
29
|
+
?? op.targetInstructionIndices?.length
|
|
30
|
+
?? op.branchOffsetIndices?.length;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Calculate the size of an operation in code units (16-bit words).
|
|
35
|
+
* Works with any tier of operation (Tier 1, 2, 3, or SmaliCodeOperation).
|
|
36
|
+
*/
|
|
37
|
+
export function getOperationSizeInCodeUnits(operation: { operation: string; data?: Uint8Array | number[] }): number {
|
|
38
|
+
if (operation.operation === 'packed-switch-payload') {
|
|
39
|
+
const length = getBranchOffsetsLength(operation);
|
|
40
|
+
if (length === undefined) {
|
|
41
|
+
throw new Error('packed-switch-payload missing branch offsets array');
|
|
42
|
+
}
|
|
43
|
+
// Header (4 code units) + targets (2 code units each)
|
|
44
|
+
return (length * 2) + 4;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (operation.operation === 'sparse-switch-payload') {
|
|
48
|
+
const length = getBranchOffsetsLength(operation);
|
|
49
|
+
if (length === undefined) {
|
|
50
|
+
throw new Error('sparse-switch-payload missing branch offsets array');
|
|
51
|
+
}
|
|
52
|
+
// Header (2 code units) + keys (2 code units each) + targets (2 code units each)
|
|
53
|
+
return (length * 4) + 2;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (operation.operation === 'fill-array-data-payload') {
|
|
57
|
+
// data.length is already the total number of bytes (size * elementWidth)
|
|
58
|
+
const dataSize = operation.data!.length;
|
|
59
|
+
const paddingSize = dataSize % 2;
|
|
60
|
+
const totalBytes = 8 + dataSize + paddingSize; // header (8 bytes) + data + padding
|
|
61
|
+
return totalBytes / 2; // Convert to code units
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const format = operationFormats[operation.operation as keyof typeof operationFormats];
|
|
65
|
+
if (!format) {
|
|
66
|
+
throw new Error(`Unknown operation format: ${operation.operation}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return formatSizes[format];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Build mapping from code unit offset to instruction index.
|
|
74
|
+
* Also maps the end position (total code units) to instructions.length.
|
|
75
|
+
*/
|
|
76
|
+
export function buildCodeUnitToIndexMap(
|
|
77
|
+
instructions: RawDalvikBytecodeOperation[],
|
|
78
|
+
): CodeUnitToIndexMap {
|
|
79
|
+
const map: CodeUnitToIndexMap = new Map();
|
|
80
|
+
let codeUnitOffset = 0;
|
|
81
|
+
|
|
82
|
+
for (let index = 0; index < instructions.length; index++) {
|
|
83
|
+
map.set(isoCodeUnit.wrap(codeUnitOffset), isoInstructionIndex.wrap(index));
|
|
84
|
+
codeUnitOffset += getOperationSizeInCodeUnits(instructions[index]);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Map the end position
|
|
88
|
+
map.set(isoCodeUnit.wrap(codeUnitOffset), isoInstructionIndex.wrap(instructions.length));
|
|
89
|
+
|
|
90
|
+
return map;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Build mapping from instruction index to code unit offset.
|
|
95
|
+
* Also maps instructions.length to the total code units.
|
|
96
|
+
*/
|
|
97
|
+
export function buildIndexToCodeUnitMap(
|
|
98
|
+
instructions: RawDalvikBytecodeOperation[],
|
|
99
|
+
): IndexToCodeUnitMap {
|
|
100
|
+
const map: IndexToCodeUnitMap = new Map();
|
|
101
|
+
let codeUnitOffset = 0;
|
|
102
|
+
|
|
103
|
+
for (let index = 0; index < instructions.length; index++) {
|
|
104
|
+
map.set(isoInstructionIndex.wrap(index), isoCodeUnit.wrap(codeUnitOffset));
|
|
105
|
+
codeUnitOffset += getOperationSizeInCodeUnits(instructions[index]);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Map the end position
|
|
109
|
+
map.set(isoInstructionIndex.wrap(instructions.length), isoCodeUnit.wrap(codeUnitOffset));
|
|
110
|
+
|
|
111
|
+
return map;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Convert a code unit offset to an instruction index.
|
|
116
|
+
*/
|
|
117
|
+
export function codeUnitToInstructionIndex(
|
|
118
|
+
codeUnitOffset: CodeUnit,
|
|
119
|
+
codeUnitToIndexMap: CodeUnitToIndexMap,
|
|
120
|
+
): InstructionIndex {
|
|
121
|
+
const index = codeUnitToIndexMap.get(codeUnitOffset);
|
|
122
|
+
if (index === undefined) {
|
|
123
|
+
throw new Error(`Invalid code unit offset: ${isoCodeUnit.unwrap(codeUnitOffset)}. Valid offsets: ${[...codeUnitToIndexMap.keys()].map(k => isoCodeUnit.unwrap(k)).join(', ')}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return index;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Convert an instruction index to a code unit offset.
|
|
131
|
+
*/
|
|
132
|
+
export function instructionIndexToCodeUnit(
|
|
133
|
+
instructionIndex: InstructionIndex,
|
|
134
|
+
indexToCodeUnitMap: IndexToCodeUnitMap,
|
|
135
|
+
): CodeUnit {
|
|
136
|
+
const offset = indexToCodeUnitMap.get(instructionIndex);
|
|
137
|
+
if (offset === undefined) {
|
|
138
|
+
throw new Error(`Invalid instruction index: ${isoInstructionIndex.unwrap(instructionIndex)}. Valid indices: ${[...indexToCodeUnitMap.keys()].map(k => isoInstructionIndex.unwrap(k)).join(', ')}`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return offset;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Convert a relative branch offset (in code units) to a relative instruction offset.
|
|
146
|
+
* The offset is relative to the source instruction.
|
|
147
|
+
*/
|
|
148
|
+
export function convertBranchOffsetToInstructionOffset(
|
|
149
|
+
branchOffsetInCodeUnits: CodeUnit,
|
|
150
|
+
sourceInstructionIndex: InstructionIndex,
|
|
151
|
+
indexToCodeUnitMap: IndexToCodeUnitMap,
|
|
152
|
+
codeUnitToIndexMap: CodeUnitToIndexMap,
|
|
153
|
+
): InstructionIndex {
|
|
154
|
+
const sourceCodeUnit = indexToCodeUnitMap.get(sourceInstructionIndex);
|
|
155
|
+
if (sourceCodeUnit === undefined) {
|
|
156
|
+
throw new Error(`Invalid source instruction index: ${isoInstructionIndex.unwrap(sourceInstructionIndex)}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const targetCodeUnit = isoCodeUnit.wrap(isoCodeUnit.unwrap(sourceCodeUnit) + isoCodeUnit.unwrap(branchOffsetInCodeUnits));
|
|
160
|
+
const targetIndex = codeUnitToIndexMap.get(targetCodeUnit);
|
|
161
|
+
if (targetIndex === undefined) {
|
|
162
|
+
throw new Error(`Invalid branch target code unit: ${isoCodeUnit.unwrap(targetCodeUnit)} (from source ${isoCodeUnit.unwrap(sourceCodeUnit)} + offset ${isoCodeUnit.unwrap(branchOffsetInCodeUnits)})`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return isoInstructionIndex.wrap(isoInstructionIndex.unwrap(targetIndex) - isoInstructionIndex.unwrap(sourceInstructionIndex));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Convert a relative instruction offset back to a code unit offset.
|
|
170
|
+
* The offset is relative to the source instruction.
|
|
171
|
+
*/
|
|
172
|
+
export function convertInstructionOffsetToBranchOffset(
|
|
173
|
+
instructionOffset: InstructionIndex,
|
|
174
|
+
sourceInstructionIndex: InstructionIndex,
|
|
175
|
+
indexToCodeUnitMap: IndexToCodeUnitMap,
|
|
176
|
+
): CodeUnit {
|
|
177
|
+
const sourceCodeUnit = indexToCodeUnitMap.get(sourceInstructionIndex);
|
|
178
|
+
if (sourceCodeUnit === undefined) {
|
|
179
|
+
throw new Error(`Invalid source instruction index: ${isoInstructionIndex.unwrap(sourceInstructionIndex)}`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const targetInstructionIndex = isoInstructionIndex.wrap(isoInstructionIndex.unwrap(sourceInstructionIndex) + isoInstructionIndex.unwrap(instructionOffset));
|
|
183
|
+
const targetCodeUnit = indexToCodeUnitMap.get(targetInstructionIndex);
|
|
184
|
+
if (targetCodeUnit === undefined) {
|
|
185
|
+
throw new Error(`Invalid target instruction index: ${isoInstructionIndex.unwrap(targetInstructionIndex)}`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return isoCodeUnit.wrap(isoCodeUnit.unwrap(targetCodeUnit) - isoCodeUnit.unwrap(sourceCodeUnit));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Find the switch instruction that references a payload at the given index.
|
|
193
|
+
* Returns the index of the switch instruction.
|
|
194
|
+
*/
|
|
195
|
+
export function findSwitchInstructionForPayload(
|
|
196
|
+
instructions: RawDalvikBytecodeOperation[],
|
|
197
|
+
payloadIndex: InstructionIndex,
|
|
198
|
+
indexToCodeUnitMap: IndexToCodeUnitMap,
|
|
199
|
+
): InstructionIndex {
|
|
200
|
+
const payloadCodeUnit = indexToCodeUnitMap.get(payloadIndex);
|
|
201
|
+
if (payloadCodeUnit === undefined) {
|
|
202
|
+
throw new Error(`Invalid payload index: ${isoInstructionIndex.unwrap(payloadIndex)}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
for (let i = 0; i < instructions.length; i++) {
|
|
206
|
+
const inst = instructions[i];
|
|
207
|
+
if (
|
|
208
|
+
(inst.operation === 'packed-switch' || inst.operation === 'sparse-switch')
|
|
209
|
+
&& 'branchOffsetCodeUnit' in inst
|
|
210
|
+
) {
|
|
211
|
+
const sourceCodeUnit = indexToCodeUnitMap.get(isoInstructionIndex.wrap(i));
|
|
212
|
+
if (sourceCodeUnit !== undefined && isoCodeUnit.unwrap(sourceCodeUnit) + isoCodeUnit.unwrap(inst.branchOffsetCodeUnit) === isoCodeUnit.unwrap(payloadCodeUnit)) {
|
|
213
|
+
return isoInstructionIndex.wrap(i);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
throw new Error(`No switch instruction found for payload at index ${isoInstructionIndex.unwrap(payloadIndex)}`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Type for Tier 2: InstructionIndex typed numbers (internal)
|
|
222
|
+
export type ConvertedBranchOffsetOperation<T> = T extends { branchOffsetCodeUnit: CodeUnit }
|
|
223
|
+
? Omit<T, 'branchOffsetCodeUnit'> & { branchOffsetIndex: InstructionIndex }
|
|
224
|
+
: T extends { branchOffsetsCodeUnit: CodeUnit[] }
|
|
225
|
+
? Omit<T, 'branchOffsetsCodeUnit'> & { branchOffsetsIndex: InstructionIndex[] }
|
|
226
|
+
: T;
|
|
227
|
+
|
|
228
|
+
export type ConvertedRawDalvikBytecodeOperation = ConvertedBranchOffsetOperation<RawDalvikBytecodeOperation>;
|
|
229
|
+
|
|
230
|
+
// Type for Tier 3: plain numbers with absolute instruction indices (public API)
|
|
231
|
+
export type ResolvedBranchOffsetOperation<T> = T extends { branchOffsetIndex: InstructionIndex }
|
|
232
|
+
? Omit<T, 'branchOffsetIndex'> & { targetInstructionIndex: number }
|
|
233
|
+
: T extends { branchOffsetsIndex: InstructionIndex[] }
|
|
234
|
+
? Omit<T, 'branchOffsetsIndex'> & { targetInstructionIndices: number[] }
|
|
235
|
+
: T;
|
|
236
|
+
|
|
237
|
+
// Final public type: applies both branch offset resolution and index resolution
|
|
238
|
+
// This ensures methodIndex→method, fieldIndex→field, typeIndex→type, stringIndex→string
|
|
239
|
+
export type DalvikBytecodeOperation = IndexResolvedOperation<ResolvedBranchOffsetOperation<ConvertedRawDalvikBytecodeOperation>>;
|
|
240
|
+
export type DalvikBytecode = DalvikBytecodeOperation[];
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Convert all branch offsets in instructions from code units to instruction offsets.
|
|
244
|
+
* Tier 1 (CodeUnit) -> Tier 2 (InstructionIndex)
|
|
245
|
+
*/
|
|
246
|
+
export function convertBranchOffsetsToInstructionOffsets(
|
|
247
|
+
instructions: RawDalvikBytecodeOperation[],
|
|
248
|
+
): ConvertedRawDalvikBytecodeOperation[] {
|
|
249
|
+
const codeUnitToIndexMap = buildCodeUnitToIndexMap(instructions);
|
|
250
|
+
const indexToCodeUnitMap = buildIndexToCodeUnitMap(instructions);
|
|
251
|
+
|
|
252
|
+
return instructions.map((instruction, index) => {
|
|
253
|
+
// Handle single branchOffsetCodeUnit (goto, if-*, packed-switch, sparse-switch, fill-array-data)
|
|
254
|
+
if ('branchOffsetCodeUnit' in instruction) {
|
|
255
|
+
const { branchOffsetCodeUnit, ...rest } = instruction;
|
|
256
|
+
return {
|
|
257
|
+
...rest,
|
|
258
|
+
branchOffsetIndex: convertBranchOffsetToInstructionOffset(
|
|
259
|
+
branchOffsetCodeUnit,
|
|
260
|
+
isoInstructionIndex.wrap(index),
|
|
261
|
+
indexToCodeUnitMap,
|
|
262
|
+
codeUnitToIndexMap,
|
|
263
|
+
),
|
|
264
|
+
} as ConvertedRawDalvikBytecodeOperation;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Handle branchOffsetsCodeUnit array (packed-switch-payload, sparse-switch-payload)
|
|
268
|
+
if ('branchOffsetsCodeUnit' in instruction) {
|
|
269
|
+
const { branchOffsetsCodeUnit, ...rest } = instruction;
|
|
270
|
+
// For payload instructions, find the referring switch instruction
|
|
271
|
+
const sourceIndex = findSwitchInstructionForPayload(instructions, isoInstructionIndex.wrap(index), indexToCodeUnitMap);
|
|
272
|
+
return {
|
|
273
|
+
...rest,
|
|
274
|
+
branchOffsetsIndex: branchOffsetsCodeUnit.map(offset =>
|
|
275
|
+
convertBranchOffsetToInstructionOffset(
|
|
276
|
+
offset,
|
|
277
|
+
sourceIndex,
|
|
278
|
+
indexToCodeUnitMap,
|
|
279
|
+
codeUnitToIndexMap,
|
|
280
|
+
),
|
|
281
|
+
),
|
|
282
|
+
} as ConvertedRawDalvikBytecodeOperation;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return instruction as ConvertedRawDalvikBytecodeOperation;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Unwrap instruction indices to plain numbers and convert relative to absolute.
|
|
291
|
+
* Tier 2 (InstructionIndex, relative) -> Tier 3 (plain number, absolute)
|
|
292
|
+
*/
|
|
293
|
+
export function unwrapBranchOffsets(
|
|
294
|
+
instructions: ConvertedRawDalvikBytecodeOperation[],
|
|
295
|
+
): DalvikBytecodeOperation[] {
|
|
296
|
+
// First pass: find switch instruction indices for payloads
|
|
297
|
+
const payloadToSwitchIndex = new Map<number, number>();
|
|
298
|
+
for (let i = 0; i < instructions.length; i++) {
|
|
299
|
+
const inst = instructions[i];
|
|
300
|
+
if (
|
|
301
|
+
(inst.operation === 'packed-switch' || inst.operation === 'sparse-switch')
|
|
302
|
+
&& 'branchOffsetIndex' in inst
|
|
303
|
+
) {
|
|
304
|
+
const payloadIndex = i + isoInstructionIndex.unwrap(inst.branchOffsetIndex);
|
|
305
|
+
payloadToSwitchIndex.set(payloadIndex, i);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return instructions.map((instruction, index) => {
|
|
310
|
+
if ('branchOffsetIndex' in instruction) {
|
|
311
|
+
const { branchOffsetIndex, ...rest } = instruction;
|
|
312
|
+
// Convert relative offset to absolute index
|
|
313
|
+
const targetInstructionIndex = index + isoInstructionIndex.unwrap(branchOffsetIndex);
|
|
314
|
+
return {
|
|
315
|
+
...rest,
|
|
316
|
+
targetInstructionIndex,
|
|
317
|
+
} as DalvikBytecodeOperation;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if ('branchOffsetsIndex' in instruction) {
|
|
321
|
+
const { branchOffsetsIndex, ...rest } = instruction;
|
|
322
|
+
// For payloads, the offsets are relative to the switch instruction, not the payload
|
|
323
|
+
const switchIndex = payloadToSwitchIndex.get(index);
|
|
324
|
+
if (switchIndex === undefined) {
|
|
325
|
+
throw new Error(`No switch instruction found for payload at index ${index}`);
|
|
326
|
+
}
|
|
327
|
+
// Convert relative offsets to absolute indices
|
|
328
|
+
const targetInstructionIndices = branchOffsetsIndex.map(
|
|
329
|
+
offset => switchIndex + isoInstructionIndex.unwrap(offset),
|
|
330
|
+
);
|
|
331
|
+
return {
|
|
332
|
+
...rest,
|
|
333
|
+
targetInstructionIndices,
|
|
334
|
+
} as DalvikBytecodeOperation;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return instruction as DalvikBytecodeOperation;
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Wrap plain numbers to instruction indices and convert absolute to relative.
|
|
343
|
+
* Tier 3 (plain number, absolute) -> Tier 2 (InstructionIndex, relative)
|
|
344
|
+
*/
|
|
345
|
+
export function wrapBranchOffsets(
|
|
346
|
+
instructions: DalvikBytecodeOperation[],
|
|
347
|
+
): ConvertedRawDalvikBytecodeOperation[] {
|
|
348
|
+
// First pass: find switch instruction indices for payloads
|
|
349
|
+
const payloadToSwitchIndex = new Map<number, number>();
|
|
350
|
+
for (let i = 0; i < instructions.length; i++) {
|
|
351
|
+
const inst = instructions[i];
|
|
352
|
+
if (
|
|
353
|
+
(inst.operation === 'packed-switch' || inst.operation === 'sparse-switch')
|
|
354
|
+
&& 'targetInstructionIndex' in inst
|
|
355
|
+
) {
|
|
356
|
+
const payloadIndex = inst.targetInstructionIndex;
|
|
357
|
+
payloadToSwitchIndex.set(payloadIndex, i);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return instructions.map((instruction, index) => {
|
|
362
|
+
if ('targetInstructionIndex' in instruction) {
|
|
363
|
+
const { targetInstructionIndex, ...rest } = instruction;
|
|
364
|
+
// Convert absolute index to relative offset
|
|
365
|
+
const branchOffsetIndex = isoInstructionIndex.wrap(targetInstructionIndex - index);
|
|
366
|
+
return {
|
|
367
|
+
...rest,
|
|
368
|
+
branchOffsetIndex,
|
|
369
|
+
} as ConvertedRawDalvikBytecodeOperation;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if ('targetInstructionIndices' in instruction) {
|
|
373
|
+
const { targetInstructionIndices, ...rest } = instruction;
|
|
374
|
+
// For payloads, the offsets are relative to the switch instruction, not the payload
|
|
375
|
+
const switchIndex = payloadToSwitchIndex.get(index);
|
|
376
|
+
if (switchIndex === undefined) {
|
|
377
|
+
throw new Error(`No switch instruction found for payload at index ${index}`);
|
|
378
|
+
}
|
|
379
|
+
// Convert absolute indices to relative offsets from switch instruction
|
|
380
|
+
const branchOffsetsIndex = targetInstructionIndices.map(
|
|
381
|
+
target => isoInstructionIndex.wrap(target - switchIndex),
|
|
382
|
+
);
|
|
383
|
+
return {
|
|
384
|
+
...rest,
|
|
385
|
+
branchOffsetsIndex,
|
|
386
|
+
} as ConvertedRawDalvikBytecodeOperation;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return instruction as ConvertedRawDalvikBytecodeOperation;
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Build mapping from instruction index to code unit offset.
|
|
395
|
+
* Works with any tier of operations.
|
|
396
|
+
*/
|
|
397
|
+
export function buildIndexToCodeUnitMapGeneric(
|
|
398
|
+
instructions: Array<{ operation: string; data?: Uint8Array | number[] }>,
|
|
399
|
+
): IndexToCodeUnitMap {
|
|
400
|
+
const map: IndexToCodeUnitMap = new Map();
|
|
401
|
+
let codeUnitOffset = 0;
|
|
402
|
+
|
|
403
|
+
for (let index = 0; index < instructions.length; index++) {
|
|
404
|
+
map.set(isoInstructionIndex.wrap(index), isoCodeUnit.wrap(codeUnitOffset));
|
|
405
|
+
codeUnitOffset += getOperationSizeInCodeUnits(instructions[index]);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Map the end position
|
|
409
|
+
map.set(isoInstructionIndex.wrap(instructions.length), isoCodeUnit.wrap(codeUnitOffset));
|
|
410
|
+
|
|
411
|
+
return map;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Build mapping from instruction index to code unit offset for Tier 2 operations.
|
|
416
|
+
*/
|
|
417
|
+
export function buildIndexToCodeUnitMapFromConverted(
|
|
418
|
+
instructions: ConvertedRawDalvikBytecodeOperation[],
|
|
419
|
+
): IndexToCodeUnitMap {
|
|
420
|
+
return buildIndexToCodeUnitMapGeneric(instructions);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Build mapping from instruction index to code unit offset for Tier 3 operations.
|
|
425
|
+
*/
|
|
426
|
+
export function buildIndexToCodeUnitMapFromResolved(
|
|
427
|
+
instructions: DalvikBytecodeOperation[],
|
|
428
|
+
): IndexToCodeUnitMap {
|
|
429
|
+
return buildIndexToCodeUnitMapGeneric(instructions);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Find the switch instruction that references a payload at the given index,
|
|
434
|
+
* when branch offsets are in instruction indices (Tier 2).
|
|
435
|
+
*/
|
|
436
|
+
function findSwitchInstructionForPayloadByInstructionIndex(
|
|
437
|
+
instructions: ConvertedRawDalvikBytecodeOperation[],
|
|
438
|
+
payloadIndex: InstructionIndex,
|
|
439
|
+
): InstructionIndex {
|
|
440
|
+
for (let i = 0; i < instructions.length; i++) {
|
|
441
|
+
const inst = instructions[i];
|
|
442
|
+
if (
|
|
443
|
+
(inst.operation === 'packed-switch' || inst.operation === 'sparse-switch')
|
|
444
|
+
&& 'branchOffsetIndex' in inst
|
|
445
|
+
&& i + isoInstructionIndex.unwrap(inst.branchOffsetIndex) === isoInstructionIndex.unwrap(payloadIndex)
|
|
446
|
+
) {
|
|
447
|
+
return isoInstructionIndex.wrap(i);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
throw new Error(`No switch instruction found for payload at index ${isoInstructionIndex.unwrap(payloadIndex)}`);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Convert all branch offsets in instructions from instruction offsets back to code units.
|
|
456
|
+
* Tier 2 (InstructionIndex) -> Tier 1 (CodeUnit)
|
|
457
|
+
*/
|
|
458
|
+
export function convertInstructionOffsetsToBranchOffsets(
|
|
459
|
+
instructions: ConvertedRawDalvikBytecodeOperation[],
|
|
460
|
+
): RawDalvikBytecodeOperation[] {
|
|
461
|
+
const indexToCodeUnitMap = buildIndexToCodeUnitMapFromConverted(instructions);
|
|
462
|
+
|
|
463
|
+
return instructions.map((instruction, index) => {
|
|
464
|
+
// Handle single branchOffsetIndex
|
|
465
|
+
if ('branchOffsetIndex' in instruction) {
|
|
466
|
+
const { branchOffsetIndex, ...rest } = instruction;
|
|
467
|
+
return {
|
|
468
|
+
...rest,
|
|
469
|
+
branchOffsetCodeUnit: convertInstructionOffsetToBranchOffset(
|
|
470
|
+
branchOffsetIndex,
|
|
471
|
+
isoInstructionIndex.wrap(index),
|
|
472
|
+
indexToCodeUnitMap,
|
|
473
|
+
),
|
|
474
|
+
} as RawDalvikBytecodeOperation;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Handle branchOffsetsIndex array
|
|
478
|
+
if ('branchOffsetsIndex' in instruction) {
|
|
479
|
+
const { branchOffsetsIndex, ...rest } = instruction;
|
|
480
|
+
// For payload instructions, find the referring switch instruction
|
|
481
|
+
const sourceIndex = findSwitchInstructionForPayloadByInstructionIndex(instructions, isoInstructionIndex.wrap(index));
|
|
482
|
+
return {
|
|
483
|
+
...rest,
|
|
484
|
+
branchOffsetsCodeUnit: branchOffsetsIndex.map(offset =>
|
|
485
|
+
convertInstructionOffsetToBranchOffset(
|
|
486
|
+
offset,
|
|
487
|
+
sourceIndex,
|
|
488
|
+
indexToCodeUnitMap,
|
|
489
|
+
),
|
|
490
|
+
),
|
|
491
|
+
} as RawDalvikBytecodeOperation;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
return instruction as RawDalvikBytecodeOperation;
|
|
495
|
+
});
|
|
496
|
+
}
|
|
@@ -2,7 +2,9 @@ import { type Iso } from 'monocle-ts';
|
|
|
2
2
|
import {
|
|
3
3
|
byteParser, intParser, longParser, shortParser, ubyteParser, uintParser, ushortParser,
|
|
4
4
|
} from '../dalvikExecutableParser/typeParsers.js';
|
|
5
|
+
import { type CodeUnit, isoCodeUnit } from '../dalvikExecutableParser/typedNumbers.js';
|
|
5
6
|
import { createElementParser } from '../elementParser.js';
|
|
7
|
+
import { createObjectParser } from '../objectParser.js';
|
|
6
8
|
import { type Parser, setParserName } from '../parser.js';
|
|
7
9
|
import { promiseCompose } from '../promiseCompose.js';
|
|
8
10
|
import { createTupleParser } from '../tupleParser.js';
|
|
@@ -20,13 +22,13 @@ export const nibblesParser: Parser<[ number, number ], Uint8Array> = promiseComp
|
|
|
20
22
|
setParserName(nibblesParser, 'nibblesParser');
|
|
21
23
|
|
|
22
24
|
type DalvikBytecodeFormat10t = {
|
|
23
|
-
|
|
25
|
+
branchOffsetCodeUnit: CodeUnit;
|
|
24
26
|
};
|
|
25
27
|
|
|
26
28
|
export const dalvikBytecodeFormat10tParser: Parser<DalvikBytecodeFormat10t, Uint8Array> = promiseCompose(
|
|
27
29
|
byteParser,
|
|
28
30
|
branchOffset => ({
|
|
29
|
-
branchOffset,
|
|
31
|
+
branchOffsetCodeUnit: isoCodeUnit.wrap(branchOffset),
|
|
30
32
|
}),
|
|
31
33
|
);
|
|
32
34
|
|
|
@@ -86,7 +88,7 @@ export const dalvikBytecodeFormat12xParser: Parser<DalvikBytecodeFormat12x, Uint
|
|
|
86
88
|
);
|
|
87
89
|
|
|
88
90
|
type DalvikBytecodeFormat20t = {
|
|
89
|
-
|
|
91
|
+
branchOffsetCodeUnit: CodeUnit;
|
|
90
92
|
};
|
|
91
93
|
|
|
92
94
|
export const dalvikBytecodeFormat20tParser: Parser<DalvikBytecodeFormat20t, Uint8Array> = promiseCompose(
|
|
@@ -94,11 +96,8 @@ export const dalvikBytecodeFormat20tParser: Parser<DalvikBytecodeFormat20t, Uint
|
|
|
94
96
|
ubyteParser,
|
|
95
97
|
shortParser,
|
|
96
98
|
]),
|
|
97
|
-
([
|
|
98
|
-
|
|
99
|
-
branchOffset,
|
|
100
|
-
]) => ({
|
|
101
|
-
branchOffset,
|
|
99
|
+
([ _zero, branchOffset ]) => ({
|
|
100
|
+
branchOffsetCodeUnit: isoCodeUnit.wrap(branchOffset),
|
|
102
101
|
}),
|
|
103
102
|
);
|
|
104
103
|
|
|
@@ -149,7 +148,7 @@ export const dalvikBytecodeFormat21hParser: Parser<DalvikBytecodeFormat21h, Uint
|
|
|
149
148
|
);
|
|
150
149
|
|
|
151
150
|
type DalvikBytecodeFormat21t = {
|
|
152
|
-
|
|
151
|
+
branchOffsetCodeUnit: CodeUnit;
|
|
153
152
|
registers: number[];
|
|
154
153
|
};
|
|
155
154
|
|
|
@@ -162,7 +161,7 @@ export const createDalvikBytecodeFormat21tParser = (): Parser<DalvikBytecodeForm
|
|
|
162
161
|
register0,
|
|
163
162
|
branchOffset,
|
|
164
163
|
]) => ({
|
|
165
|
-
branchOffset,
|
|
164
|
+
branchOffsetCodeUnit: isoCodeUnit.wrap(branchOffset),
|
|
166
165
|
registers: [
|
|
167
166
|
register0,
|
|
168
167
|
],
|
|
@@ -269,7 +268,7 @@ export const createDalvikBytecodeFormat22sParser = (): Parser<DalvikBytecodeForm
|
|
|
269
268
|
);
|
|
270
269
|
|
|
271
270
|
type DalvikBytecodeFormat22t = {
|
|
272
|
-
|
|
271
|
+
branchOffsetCodeUnit: CodeUnit;
|
|
273
272
|
registers: number[];
|
|
274
273
|
};
|
|
275
274
|
|
|
@@ -285,7 +284,7 @@ export const createDalvikBytecodeFormat22tParser = (): Parser<DalvikBytecodeForm
|
|
|
285
284
|
],
|
|
286
285
|
branchOffset,
|
|
287
286
|
]) => ({
|
|
288
|
-
branchOffset,
|
|
287
|
+
branchOffsetCodeUnit: isoCodeUnit.wrap(branchOffset),
|
|
289
288
|
registers: [
|
|
290
289
|
register0,
|
|
291
290
|
register1,
|
|
@@ -337,13 +336,13 @@ export const dalvikBytecodeFormat23xParser: Parser<DalvikBytecodeFormat23x, Uint
|
|
|
337
336
|
);
|
|
338
337
|
|
|
339
338
|
type DalvikBytecodeFormat30t = {
|
|
340
|
-
|
|
339
|
+
branchOffsetCodeUnit: CodeUnit;
|
|
341
340
|
};
|
|
342
341
|
|
|
343
342
|
export const dalvikBytecodeFormat30tParser: Parser<DalvikBytecodeFormat30t, Uint8Array> = promiseCompose(
|
|
344
343
|
intParser,
|
|
345
344
|
branchOffset => ({
|
|
346
|
-
branchOffset,
|
|
345
|
+
branchOffsetCodeUnit: isoCodeUnit.wrap(branchOffset),
|
|
347
346
|
}),
|
|
348
347
|
);
|
|
349
348
|
|
|
@@ -394,7 +393,7 @@ export const createDalvikBytecodeFormat31cParser = <Index>({
|
|
|
394
393
|
);
|
|
395
394
|
|
|
396
395
|
type DalvikBytecodeFormat31t = {
|
|
397
|
-
|
|
396
|
+
branchOffsetCodeUnit: CodeUnit;
|
|
398
397
|
registers: number[];
|
|
399
398
|
};
|
|
400
399
|
|
|
@@ -407,7 +406,7 @@ export const dalvikBytecodeFormat31tParser: Parser<DalvikBytecodeFormat31t, Uint
|
|
|
407
406
|
register0,
|
|
408
407
|
branchOffset,
|
|
409
408
|
]) => ({
|
|
410
|
-
branchOffset,
|
|
409
|
+
branchOffsetCodeUnit: isoCodeUnit.wrap(branchOffset),
|
|
411
410
|
registers: [
|
|
412
411
|
register0,
|
|
413
412
|
],
|
|
@@ -530,19 +529,10 @@ type DalvikBytecodeFormat20bc = {
|
|
|
530
529
|
index: number;
|
|
531
530
|
};
|
|
532
531
|
|
|
533
|
-
export const dalvikBytecodeFormat20bcParser: Parser<DalvikBytecodeFormat20bc, Uint8Array> =
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
]),
|
|
538
|
-
([
|
|
539
|
-
kind,
|
|
540
|
-
index,
|
|
541
|
-
]) => ({
|
|
542
|
-
kind,
|
|
543
|
-
index,
|
|
544
|
-
}),
|
|
545
|
-
);
|
|
532
|
+
export const dalvikBytecodeFormat20bcParser: Parser<DalvikBytecodeFormat20bc, Uint8Array> = createObjectParser({
|
|
533
|
+
kind: ubyteParser,
|
|
534
|
+
index: ushortParser,
|
|
535
|
+
});
|
|
546
536
|
|
|
547
537
|
// Format 22cs: field access quick (deprecated)
|
|
548
538
|
type DalvikBytecodeFormat22cs = {
|