@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.
Files changed (262) hide show
  1. package/.claude/settings.local.json +24 -0
  2. package/.github/workflows/main.yml +1 -0
  3. package/build/androidPackageParser.js +30 -32
  4. package/build/arbitraryDalvikBytecode.d.ts +3 -3
  5. package/build/arbitraryDalvikBytecode.js +33 -27
  6. package/build/arbitraryDalvikExecutable.js +55 -17
  7. package/build/arbitraryJava.d.ts +31 -0
  8. package/build/arbitraryJava.js +532 -0
  9. package/build/arbitraryJavaScript.d.ts +3 -0
  10. package/build/arbitraryJavaScript.js +263 -0
  11. package/build/arbitraryJavascript.d.ts +3 -0
  12. package/build/arbitraryJavascript.js +263 -0
  13. package/build/arbitraryZig.d.ts +3 -0
  14. package/build/arbitraryZig.js +240 -0
  15. package/build/arbitraryZipStream.d.ts +1 -1
  16. package/build/arrayParser.js +72 -13
  17. package/build/backsmali.d.ts +4 -3
  18. package/build/backsmali.js +26 -6
  19. package/build/bash.d.ts +89 -0
  20. package/build/bash.js +1 -0
  21. package/build/bashParser.d.ts +6 -0
  22. package/build/bashParser.js +335 -0
  23. package/build/bashParser.test.d.ts +1 -0
  24. package/build/bashParser.test.js +343 -0
  25. package/build/bashParserEdgeCases.test.d.ts +1 -0
  26. package/build/bashParserEdgeCases.test.js +117 -0
  27. package/build/dalvikBytecodeParser/addressConversion.d.ts +110 -0
  28. package/build/dalvikBytecodeParser/addressConversion.js +334 -0
  29. package/build/dalvikBytecodeParser/formatParsers.d.ts +7 -6
  30. package/build/dalvikBytecodeParser/formatParsers.js +13 -14
  31. package/build/dalvikBytecodeParser.d.ts +60 -31
  32. package/build/dalvikBytecodeParser.js +92 -35
  33. package/build/dalvikBytecodeParser.test-d.d.ts +1 -0
  34. package/build/dalvikBytecodeParser.test-d.js +268 -0
  35. package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +9 -8
  36. package/build/dalvikBytecodeUnparser/formatUnparsers.js +13 -12
  37. package/build/dalvikBytecodeUnparser.d.ts +2 -2
  38. package/build/dalvikBytecodeUnparser.js +23 -23
  39. package/build/dalvikBytecodeUnparser.test.js +7 -7
  40. package/build/dalvikExecutable.d.ts +3 -3
  41. package/build/dalvikExecutable.test-d.d.ts +1 -0
  42. package/build/dalvikExecutable.test-d.js +59 -0
  43. package/build/dalvikExecutableParser/typedNumbers.d.ts +18 -0
  44. package/build/dalvikExecutableParser/typedNumbers.js +3 -0
  45. package/build/dalvikExecutableParser.d.ts +2 -1
  46. package/build/dalvikExecutableParser.js +96 -77
  47. package/build/dalvikExecutableParser.test.js +24 -3
  48. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +3 -0
  49. package/build/dalvikExecutableUnparser/poolScanners.d.ts +2 -2
  50. package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +3 -3
  51. package/build/dalvikExecutableUnparser/sectionUnparsers.js +26 -11
  52. package/build/dalvikExecutableUnparser.d.ts +2 -2
  53. package/build/dalvikExecutableUnparser.test.js +2 -1
  54. package/build/disjunctionParser.d.ts +5 -3
  55. package/build/disjunctionParser.js +79 -17
  56. package/build/disjunctionParser.test-d.d.ts +1 -0
  57. package/build/disjunctionParser.test-d.js +72 -0
  58. package/build/elementSwitchParser.d.ts +4 -0
  59. package/build/{exactElementSwitchParser.js → elementSwitchParser.js} +3 -4
  60. package/build/elementSwitchParser.test-d.d.ts +1 -0
  61. package/build/elementSwitchParser.test-d.js +44 -0
  62. package/build/exactSequenceParser.d.ts +4 -2
  63. package/build/exactSequenceParser.test-d.d.ts +1 -0
  64. package/build/exactSequenceParser.test-d.js +36 -0
  65. package/build/fetchCid.js +2 -66
  66. package/build/index.d.ts +25 -2
  67. package/build/index.js +23 -1
  68. package/build/index.test.js +16 -1
  69. package/build/inputReader.d.ts +10 -0
  70. package/build/inputReader.js +36 -0
  71. package/build/java.d.ts +502 -0
  72. package/build/java.js +2 -0
  73. package/build/javaKeyStoreParser.js +14 -17
  74. package/build/javaParser.d.ts +51 -0
  75. package/build/javaParser.js +1538 -0
  76. package/build/javaParser.test.d.ts +1 -0
  77. package/build/javaParser.test.js +1287 -0
  78. package/build/javaScript.d.ts +35 -0
  79. package/build/javaScript.js +1 -0
  80. package/build/javaScriptParser.d.ts +9 -0
  81. package/build/javaScriptParser.js +34 -0
  82. package/build/javaScriptUnparser.d.ts +3 -0
  83. package/build/javaScriptUnparser.js +4 -0
  84. package/build/javaScriptUnparser.test.d.ts +1 -0
  85. package/build/javaScriptUnparser.test.js +24 -0
  86. package/build/javaUnparser.d.ts +2 -0
  87. package/build/javaUnparser.js +519 -0
  88. package/build/javaUnparser.test.d.ts +1 -0
  89. package/build/javaUnparser.test.js +24 -0
  90. package/build/javascript.d.ts +35 -0
  91. package/build/javascript.js +1 -0
  92. package/build/javascriptParser.d.ts +9 -0
  93. package/build/javascriptParser.js +34 -0
  94. package/build/javascriptUnparser.d.ts +3 -0
  95. package/build/javascriptUnparser.js +4 -0
  96. package/build/javascriptUnparser.test.d.ts +1 -0
  97. package/build/javascriptUnparser.test.js +24 -0
  98. package/build/jsonParser.js +2 -12
  99. package/build/lazyMessageError.d.ts +3 -0
  100. package/build/lookaheadParser.js +60 -3
  101. package/build/negativeLookaheadParser.js +70 -11
  102. package/build/nonEmptyArrayParser.js +72 -13
  103. package/build/objectParser.d.ts +12 -0
  104. package/build/objectParser.js +31 -0
  105. package/build/objectParser.test-d.d.ts +1 -0
  106. package/build/objectParser.test-d.js +112 -0
  107. package/build/objectParser.test.d.ts +1 -0
  108. package/build/objectParser.test.js +55 -0
  109. package/build/optionalParser.js +69 -10
  110. package/build/parser.d.ts +4 -0
  111. package/build/parser.js +3 -1
  112. package/build/parser.test.js +114 -1
  113. package/build/parserConsumedSequenceParser.js +66 -7
  114. package/build/parserContext.d.ts +6 -0
  115. package/build/parserContext.js +20 -11
  116. package/build/parserError.d.ts +119 -27
  117. package/build/parserError.js +16 -8
  118. package/build/regexpParser.d.ts +2 -0
  119. package/build/regexpParser.js +101 -0
  120. package/build/regexpParser.test.d.ts +1 -0
  121. package/build/regexpParser.test.js +114 -0
  122. package/build/regularExpression.d.ts +63 -0
  123. package/build/regularExpression.js +1 -0
  124. package/build/regularExpressionParser.d.ts +3 -0
  125. package/build/regularExpressionParser.js +600 -0
  126. package/build/regularExpressionParser.test.d.ts +1 -0
  127. package/build/regularExpressionParser.test.js +89 -0
  128. package/build/separatedArrayParser.js +73 -14
  129. package/build/separatedNonEmptyArrayParser.js +73 -14
  130. package/build/sliceBoundedParser.js +62 -5
  131. package/build/smaliParser.d.ts +7 -7
  132. package/build/smaliParser.js +185 -268
  133. package/build/smaliParser.test.js +58 -0
  134. package/build/stringEscapes.d.ts +5 -0
  135. package/build/stringEscapes.js +244 -0
  136. package/build/symbolicExpression.d.ts +29 -0
  137. package/build/symbolicExpression.js +1 -0
  138. package/build/symbolicExpressionParser.d.ts +4 -0
  139. package/build/symbolicExpressionParser.js +123 -0
  140. package/build/symbolicExpressionParser.test.d.ts +1 -0
  141. package/build/symbolicExpressionParser.test.js +289 -0
  142. package/build/terminatedArrayParser.js +113 -38
  143. package/build/terminatedArrayParser.test.js +4 -2
  144. package/build/tupleParser.d.ts +7 -15
  145. package/build/tupleParser.js +1 -0
  146. package/build/unionParser.d.ts +5 -3
  147. package/build/unionParser.js +7 -2
  148. package/build/unionParser.test-d.d.ts +1 -0
  149. package/build/unionParser.test-d.js +72 -0
  150. package/build/unionParser.test.js +10 -11
  151. package/build/zig.d.ts +280 -0
  152. package/build/zig.js +2 -0
  153. package/build/zigParser.d.ts +3 -0
  154. package/build/zigParser.js +1119 -0
  155. package/build/zigParser.test.d.ts +1 -0
  156. package/build/zigParser.test.js +1590 -0
  157. package/build/zigUnparser.d.ts +2 -0
  158. package/build/zigUnparser.js +460 -0
  159. package/build/zigUnparser.test.d.ts +1 -0
  160. package/build/zigUnparser.test.js +24 -0
  161. package/build/zipParser.js +19 -32
  162. package/build/zipUnparser.js +19 -7
  163. package/build/zipUnparser.test.js +1 -1
  164. package/node_modules-@types/s-expression/index.d.ts +5 -0
  165. package/package.json +25 -6
  166. package/src/androidPackageParser.ts +33 -60
  167. package/src/arbitraryDalvikBytecode.ts +39 -31
  168. package/src/arbitraryDalvikExecutable.ts +65 -20
  169. package/src/arbitraryJava.ts +804 -0
  170. package/src/arbitraryJavaScript.ts +410 -0
  171. package/src/arbitraryZig.ts +380 -0
  172. package/src/arrayParser.ts +1 -3
  173. package/src/backsmali.ts +35 -4
  174. package/src/bash.ts +127 -0
  175. package/src/bashParser.test.ts +590 -0
  176. package/src/bashParser.ts +498 -0
  177. package/src/dalvikBytecodeParser/addressConversion.ts +496 -0
  178. package/src/dalvikBytecodeParser/formatParsers.ts +19 -29
  179. package/src/dalvikBytecodeParser.test-d.ts +310 -0
  180. package/src/dalvikBytecodeParser.ts +194 -69
  181. package/src/dalvikBytecodeUnparser/formatUnparsers.ts +27 -26
  182. package/src/dalvikBytecodeUnparser.test.ts +7 -7
  183. package/src/dalvikBytecodeUnparser.ts +31 -30
  184. package/src/dalvikExecutable.test-d.ts +132 -0
  185. package/src/dalvikExecutable.ts +3 -3
  186. package/src/dalvikExecutableParser/typedNumbers.ts +11 -0
  187. package/src/dalvikExecutableParser.test.ts +37 -3
  188. package/src/dalvikExecutableParser.test.ts.md +163 -2
  189. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  190. package/src/dalvikExecutableParser.ts +121 -139
  191. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +4 -0
  192. package/src/dalvikExecutableUnparser/poolScanners.ts +6 -6
  193. package/src/dalvikExecutableUnparser/sectionUnparsers.ts +38 -14
  194. package/src/dalvikExecutableUnparser.test.ts +3 -2
  195. package/src/dalvikExecutableUnparser.ts +4 -4
  196. package/src/disjunctionParser.test-d.ts +105 -0
  197. package/src/disjunctionParser.ts +18 -15
  198. package/src/elementSwitchParser.test-d.ts +74 -0
  199. package/src/elementSwitchParser.ts +51 -0
  200. package/src/exactSequenceParser.test-d.ts +43 -0
  201. package/src/exactSequenceParser.ts +13 -8
  202. package/src/fetchCid.ts +2 -76
  203. package/src/index.test.ts +22 -1
  204. package/src/index.ts +119 -2
  205. package/src/inputReader.ts +53 -0
  206. package/src/java.ts +708 -0
  207. package/src/javaKeyStoreParser.ts +18 -32
  208. package/src/javaParser.test.ts +1592 -0
  209. package/src/javaParser.ts +2640 -0
  210. package/src/javaScript.ts +36 -0
  211. package/src/javaScriptParser.ts +57 -0
  212. package/src/javaScriptUnparser.test.ts +37 -0
  213. package/src/javaScriptUnparser.ts +7 -0
  214. package/src/javaUnparser.test.ts +37 -0
  215. package/src/javaUnparser.ts +640 -0
  216. package/src/jsonParser.ts +6 -27
  217. package/src/lookaheadParser.ts +2 -6
  218. package/src/negativeLookaheadParser.ts +1 -3
  219. package/src/nonEmptyArrayParser.ts +1 -3
  220. package/src/objectParser.test-d.ts +152 -0
  221. package/src/objectParser.test.ts +71 -0
  222. package/src/objectParser.ts +69 -0
  223. package/src/optionalParser.ts +1 -3
  224. package/src/parser.test.ts +151 -4
  225. package/src/parser.ts +11 -1
  226. package/src/parserConsumedSequenceParser.ts +2 -4
  227. package/src/parserContext.ts +26 -11
  228. package/src/parserError.ts +17 -3
  229. package/src/regexpParser.test.ts +264 -0
  230. package/src/regexpParser.ts +126 -0
  231. package/src/regularExpression.ts +24 -0
  232. package/src/regularExpressionParser.test.ts +102 -0
  233. package/src/regularExpressionParser.ts +920 -0
  234. package/src/separatedArrayParser.ts +1 -3
  235. package/src/separatedNonEmptyArrayParser.ts +1 -3
  236. package/src/sliceBoundedParser.test.ts +2 -2
  237. package/src/sliceBoundedParser.ts +15 -19
  238. package/src/smaliParser.test.ts +64 -0
  239. package/src/smaliParser.test.ts.md +12 -12
  240. package/src/smaliParser.test.ts.snap +0 -0
  241. package/src/smaliParser.ts +246 -534
  242. package/src/stringEscapes.ts +253 -0
  243. package/src/symbolicExpression.ts +17 -0
  244. package/src/symbolicExpressionParser.test.ts +466 -0
  245. package/src/symbolicExpressionParser.ts +190 -0
  246. package/src/terminatedArrayParser.test.ts +9 -6
  247. package/src/terminatedArrayParser.ts +25 -29
  248. package/src/tupleParser.ts +21 -18
  249. package/src/unionParser.test-d.ts +105 -0
  250. package/src/unionParser.test.ts +18 -17
  251. package/src/unionParser.ts +28 -16
  252. package/src/zig.ts +411 -0
  253. package/src/zigParser.test.ts +1693 -0
  254. package/src/zigParser.ts +1745 -0
  255. package/src/zigUnparser.test.ts +37 -0
  256. package/src/zigUnparser.ts +615 -0
  257. package/src/zipParser.ts +20 -56
  258. package/src/zipUnparser.test.ts +1 -1
  259. package/src/zipUnparser.ts +22 -7
  260. package/tsconfig.json +2 -2
  261. package/build/exactElementSwitchParser.d.ts +0 -3
  262. package/src/exactElementSwitchParser.ts +0 -41
@@ -129,10 +129,10 @@ Generated by [AVA](https://avajs.dev).
129
129
  value: 90,
130
130
  },
131
131
  {
132
- name: 'onCreate',
132
+ name: 'label',
133
133
  registerNum: 0,
134
134
  type: 'startLocal',
135
- type_: 'Ljava/lang/CharSequence;',
135
+ type_: 'Landroid/widget/TextView;',
136
136
  },
137
137
  {
138
138
  type: 'special',
@@ -632,3 +632,164 @@ Generated by [AVA](https://avajs.dev).
632
632
  ],
633
633
  link: undefined,
634
634
  }
635
+
636
+ ## method Lpl/czak/minimal/MainActivity;.getPackedSwitchResult from bafkreifycfnx4xf3nlml4qavlyxr6bes66nxsow3iaqjghewfsozoj2h3q
637
+
638
+ > Snapshot 1
639
+
640
+ {
641
+ accessFlags: @Object {
642
+ abstract: false,
643
+ annotation: false,
644
+ bridge: false,
645
+ constructor: false,
646
+ declaredSynchronized: false,
647
+ enum: false,
648
+ final: false,
649
+ interface: false,
650
+ native: false,
651
+ private: true,
652
+ protected: false,
653
+ public: false,
654
+ static: false,
655
+ strict: false,
656
+ synchronized: false,
657
+ synthetic: false,
658
+ transient: false,
659
+ varargs: false,
660
+ volatile: false,
661
+ },
662
+ code: {
663
+ debugInfo: {
664
+ bytecode: [
665
+ {
666
+ type: 'special',
667
+ value: 14,
668
+ },
669
+ {
670
+ type: 'special',
671
+ value: 64,
672
+ },
673
+ {
674
+ type: 'special',
675
+ value: 58,
676
+ },
677
+ {
678
+ type: 'special',
679
+ value: 58,
680
+ },
681
+ {
682
+ type: 'special',
683
+ value: 58,
684
+ },
685
+ {
686
+ type: 'special',
687
+ value: 58,
688
+ },
689
+ ],
690
+ lineStart: 102,
691
+ parameterNames: [
692
+ 'value',
693
+ ],
694
+ },
695
+ insSize: 2,
696
+ instructions: [
697
+ {
698
+ operation: 'packed-switch',
699
+ registers: [
700
+ 2,
701
+ ],
702
+ targetInstructionIndex: 11,
703
+ },
704
+ {
705
+ operation: 'const-string',
706
+ registers: [
707
+ 0,
708
+ ],
709
+ string: 'other',
710
+ },
711
+ {
712
+ operation: 'return-object',
713
+ registers: [
714
+ 0,
715
+ ],
716
+ },
717
+ {
718
+ operation: 'const-string',
719
+ registers: [
720
+ 0,
721
+ ],
722
+ string: 'three',
723
+ },
724
+ {
725
+ operation: 'return-object',
726
+ registers: [
727
+ 0,
728
+ ],
729
+ },
730
+ {
731
+ operation: 'const-string',
732
+ registers: [
733
+ 0,
734
+ ],
735
+ string: 'two',
736
+ },
737
+ {
738
+ operation: 'return-object',
739
+ registers: [
740
+ 0,
741
+ ],
742
+ },
743
+ {
744
+ operation: 'const-string',
745
+ registers: [
746
+ 0,
747
+ ],
748
+ string: 'one',
749
+ },
750
+ {
751
+ operation: 'return-object',
752
+ registers: [
753
+ 0,
754
+ ],
755
+ },
756
+ {
757
+ operation: 'const-string',
758
+ registers: [
759
+ 0,
760
+ ],
761
+ string: 'zero',
762
+ },
763
+ {
764
+ operation: 'return-object',
765
+ registers: [
766
+ 0,
767
+ ],
768
+ },
769
+ {
770
+ operation: 'packed-switch-payload',
771
+ targetInstructionIndices: [
772
+ 9,
773
+ 7,
774
+ 5,
775
+ 3,
776
+ ],
777
+ value: 0,
778
+ },
779
+ ],
780
+ outsSize: 0,
781
+ registersSize: 3,
782
+ tries: [],
783
+ },
784
+ method: {
785
+ class: 'Lpl/czak/minimal/MainActivity;',
786
+ name: 'getPackedSwitchResult',
787
+ prototype: {
788
+ parameters: [
789
+ 'I',
790
+ ],
791
+ returnType: 'Ljava/lang/String;',
792
+ shorty: 'LI',
793
+ },
794
+ },
795
+ }
@@ -4,6 +4,7 @@ import { type Iso } from 'monocle-ts';
4
4
  import { createExactElementParser } from './exactElementParser.js';
5
5
  import { createExactSequenceParser } from './exactSequenceParser.js';
6
6
  import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js';
7
+ import { createObjectParser } from './objectParser.js';
7
8
  import { cloneParser, setParserName, type Parser } from './parser.js';
8
9
  import { parserCreatorCompose } from './parserCreatorCompose.js';
9
10
  import { promiseCompose } from './promiseCompose.js';
@@ -53,8 +54,17 @@ import { createDisjunctionParser } from './disjunctionParser.js';
53
54
  import { createElementTerminatedSequenceParser } from './elementTerminatedSequenceParser.js';
54
55
  import { createElementTerminatedArrayParserUnsafe } from './elementTerminatedArrayParser.js';
55
56
  import {
56
- createDalvikBytecodeParser, type DalvikBytecode, type DalvikBytecodeOperation, type DalvikBytecodeOperationResolvers, resolveDalvikBytecodeOperation,
57
+ createRawDalvikBytecodeParser, type RawDalvikBytecode, type RawDalvikBytecodeOperation, type RawDalvikBytecodeOperationResolvers, resolveRawDalvikBytecodeOperationIndices,
57
58
  } from './dalvikBytecodeParser.js';
59
+ import {
60
+ buildCodeUnitToIndexMap,
61
+ codeUnitToInstructionIndex,
62
+ convertBranchOffsetsToInstructionOffsets,
63
+ unwrapBranchOffsets,
64
+ type DalvikBytecode,
65
+ type DalvikBytecodeOperation,
66
+ } from './dalvikBytecodeParser/addressConversion.js';
67
+ import { isoCodeUnit, isoInstructionIndex } from './dalvikExecutableParser/typedNumbers.js';
58
68
  import {
59
69
  byteParser, ubyteParser, uintParser, uleb128p1NumberParser, ushortParser,
60
70
  } from './dalvikExecutableParser/typeParsers.js';
@@ -70,6 +80,7 @@ import {
70
80
  type DalvikExecutableCode,
71
81
  type DalvikExecutableDebugInfo,
72
82
  type DalvikExecutableEncodedValue,
83
+ dalvikExecutableMethodEquals,
73
84
  } from './dalvikExecutable.js';
74
85
 
75
86
  // https://source.android.com/docs/core/runtime/dex-format
@@ -101,13 +112,10 @@ type SizeOffset = {
101
112
  offset: number;
102
113
  };
103
114
 
104
- const sizeOffsetParser: Parser<SizeOffset, Uint8Array> = promiseCompose(
105
- createTupleParser([
106
- uintParser,
107
- uintParser,
108
- ]),
109
- ([ size, offset ]) => ({ size, offset }),
110
- );
115
+ const sizeOffsetParser: Parser<SizeOffset, Uint8Array> = createObjectParser({
116
+ size: uintParser,
117
+ offset: uintParser,
118
+ });
111
119
 
112
120
  type DalvikExecutableHeaderItem = {
113
121
  version: number;
@@ -127,58 +135,23 @@ type DalvikExecutableHeaderItem = {
127
135
  data: SizeOffset;
128
136
  };
129
137
 
130
- const dalvikExecutableHeaderItemParser: Parser<DalvikExecutableHeaderItem, Uint8Array> = promiseCompose(
131
- createTupleParser([
132
- dalvikExecutableHeaderVersionParser,
133
- uintParser,
134
- createFixedLengthSequenceParser(20),
135
- uintParser,
136
- uintParser,
137
- uintParser,
138
- sizeOffsetParser,
139
- uintParser,
140
- sizeOffsetParser,
141
- sizeOffsetParser,
142
- sizeOffsetParser,
143
- sizeOffsetParser,
144
- sizeOffsetParser,
145
- sizeOffsetParser,
146
- sizeOffsetParser,
147
- ]),
148
- ([
149
- version,
150
- checksum,
151
- sha1Hash,
152
- fileSize,
153
- headerSize,
154
- endianTag,
155
- link,
156
- mapOffset,
157
- stringIds,
158
- typeIds,
159
- prototypeIds,
160
- fieldIds,
161
- methodIds,
162
- classDefinitions,
163
- data,
164
- ]) => ({
165
- version,
166
- checksum,
167
- sha1Hash,
168
- fileSize,
169
- headerSize,
170
- endianTag,
171
- link,
172
- mapOffset,
173
- stringIds,
174
- typeIds,
175
- prototypeIds,
176
- fieldIds,
177
- methodIds,
178
- classDefinitions,
179
- data,
180
- }),
181
- );
138
+ const dalvikExecutableHeaderItemParser: Parser<DalvikExecutableHeaderItem, Uint8Array> = createObjectParser({
139
+ version: dalvikExecutableHeaderVersionParser,
140
+ checksum: uintParser,
141
+ sha1Hash: createFixedLengthSequenceParser<Uint8Array>(20),
142
+ fileSize: uintParser,
143
+ headerSize: uintParser,
144
+ endianTag: uintParser,
145
+ link: sizeOffsetParser,
146
+ mapOffset: uintParser,
147
+ stringIds: sizeOffsetParser,
148
+ typeIds: sizeOffsetParser,
149
+ prototypeIds: sizeOffsetParser,
150
+ fieldIds: sizeOffsetParser,
151
+ methodIds: sizeOffsetParser,
152
+ classDefinitions: sizeOffsetParser,
153
+ data: sizeOffsetParser,
154
+ });
182
155
 
183
156
  type DalvikExecutableStringIdItem = OffsetToStringDataItem;
184
157
 
@@ -723,13 +696,10 @@ type DalvikExecutableEncodedFieldDiff = {
723
696
  accessFlags: DalvikExecutableAccessFlags;
724
697
  };
725
698
 
726
- const encodedFieldParser: Parser<DalvikExecutableEncodedFieldDiff, Uint8Array> = promiseCompose(
727
- createTupleParser([
728
- uleb128NumberParser,
729
- uleb128FieldAccessFlagsParser,
730
- ]),
731
- ([ fieldIndexDiff, accessFlags ]) => ({ fieldIndexDiff, accessFlags }),
732
- );
699
+ const encodedFieldParser: Parser<DalvikExecutableEncodedFieldDiff, Uint8Array> = createObjectParser({
700
+ fieldIndexDiff: uleb128NumberParser,
701
+ accessFlags: uleb128FieldAccessFlagsParser,
702
+ });
733
703
 
734
704
  type DalvikExecutableEncodedField = {
735
705
  fieldIndex: IndexIntoFieldIds;
@@ -894,13 +864,11 @@ const createEncodedValueArgParser = (valueType: number): Parser<number, Uint8Arr
894
864
  byte => byte >> 5,
895
865
  );
896
866
 
897
- const encodedValueByteParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = promiseCompose(
898
- createTupleParser([
899
- createExactElementParser(0),
900
- byteParser,
901
- ]),
902
- ([ _, value ]) => ({ type: 'byte' as const, value }),
903
- );
867
+ const encodedValueByteParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = createObjectParser({
868
+ type: 'byte' as const,
869
+ _tag: createExactElementParser(0),
870
+ value: byteParser,
871
+ });
904
872
 
905
873
  setParserName(encodedValueByteParser, 'encodedValueByteParser');
906
874
 
@@ -1543,18 +1511,16 @@ const encodedArrayParser: Parser<DalvikExecutableTaggedEncodedValue[], Uint8Arra
1543
1511
 
1544
1512
  setParserName(encodedArrayParser, 'encodedArrayParser');
1545
1513
 
1546
- const encodedValueArrayParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = promiseCompose(
1547
- createTupleParser([
1548
- parserCreatorCompose(
1549
- () => createEncodedValueArgParser(0x1C),
1550
- valueArg => parserContext => {
1551
- parserContext.invariant(valueArg === 0, '(encodedValueArrayParser) valueArg: %s', valueArg);
1552
- },
1553
- )(),
1554
- encodedArrayParser,
1555
- ]),
1556
- ([ _, array ]) => ({ type: 'array' as const, value: array }),
1557
- );
1514
+ const encodedValueArrayParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = createObjectParser({
1515
+ type: 'array' as const,
1516
+ _tag: parserCreatorCompose(
1517
+ () => createEncodedValueArgParser(0x1C),
1518
+ valueArg => parserContext => {
1519
+ parserContext.invariant(valueArg === 0, '(encodedValueArrayParser) valueArg: %s', valueArg);
1520
+ },
1521
+ )(),
1522
+ value: encodedArrayParser,
1523
+ });
1558
1524
 
1559
1525
  setParserName(encodedValueArrayParser, 'encodedValueArrayParser');
1560
1526
 
@@ -1612,18 +1578,16 @@ const encodedAnnotationParser: Parser<DalvikExecutableEncodedAnnotation, Uint8Ar
1612
1578
 
1613
1579
  setParserName(encodedAnnotationParser, 'encodedAnnotationParser');
1614
1580
 
1615
- const encodedValueAnnotationParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = promiseCompose(
1616
- createTupleParser([
1617
- parserCreatorCompose(
1618
- () => createEncodedValueArgParser(0x1D),
1619
- valueArg => parserContext => {
1620
- parserContext.invariant(valueArg === 0, '(encodedValueAnnotationParser) valueArg: %s', valueArg);
1621
- },
1622
- )(),
1623
- encodedAnnotationParser,
1624
- ]),
1625
- ([ _, annotation ]) => ({ type: 'annotation' as const, value: annotation }),
1626
- );
1581
+ const encodedValueAnnotationParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = createObjectParser({
1582
+ type: 'annotation' as const,
1583
+ _tag: parserCreatorCompose(
1584
+ () => createEncodedValueArgParser(0x1D),
1585
+ valueArg => parserContext => {
1586
+ parserContext.invariant(valueArg === 0, '(encodedValueAnnotationParser) valueArg: %s', valueArg);
1587
+ },
1588
+ )(),
1589
+ value: encodedAnnotationParser,
1590
+ });
1627
1591
 
1628
1592
  setParserName(encodedValueAnnotationParser, 'encodedValueAnnotationParser');
1629
1593
 
@@ -1910,16 +1874,16 @@ const dalvikExecutableDebugByteCodeValueParser: Parser<DalvikExecutableDebugByte
1910
1874
  () => ubyteParser,
1911
1875
  (value): Parser<DalvikExecutableDebugByteCodeValueItem, Uint8Array> => {
1912
1876
  switch (value) {
1913
- case 0x01: { return promiseCompose(
1914
- uleb128NumberParser,
1915
- addressDiff => ({ type: 'advancePc', addressDiff }),
1916
- );
1877
+ case 0x01: { return createObjectParser({
1878
+ type: 'advancePc' as const,
1879
+ addressDiff: uleb128NumberParser,
1880
+ });
1917
1881
  }
1918
1882
 
1919
- case 0x02: { return promiseCompose(
1920
- sleb128NumberParser,
1921
- lineDiff => ({ type: 'advanceLine', lineDiff }),
1922
- );
1883
+ case 0x02: { return createObjectParser({
1884
+ type: 'advanceLine' as const,
1885
+ lineDiff: sleb128NumberParser,
1886
+ });
1923
1887
  }
1924
1888
 
1925
1889
  case 0x03: { return promiseCompose(
@@ -2074,13 +2038,10 @@ type DalvikExecutableAnnotationItem = {
2074
2038
  encodedAnnotation: DalvikExecutableEncodedAnnotation;
2075
2039
  };
2076
2040
 
2077
- const dalvikExecutableAnnotationItemParser: Parser<DalvikExecutableAnnotationItem, Uint8Array> = promiseCompose(
2078
- createTupleParser([
2079
- dalvikExecutableAnnotationItemVisibilityParser,
2080
- encodedAnnotationParser,
2081
- ]),
2082
- ([ visibility, encodedAnnotation ]) => ({ visibility, encodedAnnotation }),
2083
- );
2041
+ const dalvikExecutableAnnotationItemParser: Parser<DalvikExecutableAnnotationItem, Uint8Array> = createObjectParser({
2042
+ visibility: dalvikExecutableAnnotationItemVisibilityParser,
2043
+ encodedAnnotation: encodedAnnotationParser,
2044
+ });
2084
2045
 
2085
2046
  setParserName(dalvikExecutableAnnotationItemParser, 'dalvikExecutableAnnotationItemParser');
2086
2047
 
@@ -2284,15 +2245,12 @@ type DalvikExecutableMapItem = {
2284
2245
  offset: number;
2285
2246
  };
2286
2247
 
2287
- const dalvikExecutableMapItemParser: Parser<DalvikExecutableMapItem, Uint8Array> = promiseCompose(
2288
- createTupleParser([
2289
- dalvikExecutableMapItemTypeParser,
2290
- ushortParser,
2291
- uintParser,
2292
- uintParser,
2293
- ]),
2294
- ([ type, _unused, size, offset ]) => ({ type, size, offset }),
2295
- );
2248
+ const dalvikExecutableMapItemParser: Parser<DalvikExecutableMapItem, Uint8Array> = createObjectParser({
2249
+ type: dalvikExecutableMapItemTypeParser,
2250
+ _unused: ushortParser,
2251
+ size: uintParser,
2252
+ offset: uintParser,
2253
+ });
2296
2254
 
2297
2255
  type DalvikExecutableMapList = DalvikExecutableMapItem[];
2298
2256
 
@@ -2708,16 +2666,27 @@ const createDalvikExecutableParser = <Instructions>({
2708
2666
  for (const [ offset, codeItem ] of codeItemByOffset) {
2709
2667
  const debugInfo = debugInfoByOffset.get(codeItem.debugInfoOffset);
2710
2668
 
2669
+ // Build code unit to instruction index mapping for address conversion
2670
+ const rawInstructions = codeItem.instructions as RawDalvikBytecodeOperation[];
2671
+ const codeUnitToIndexMap = Array.isArray(rawInstructions) ? buildCodeUnitToIndexMap(rawInstructions) : undefined;
2672
+
2673
+ // Convert branch offsets from code units to instruction offsets
2674
+ // Tier 1 (CodeUnit) -> Tier 2 (InstructionIndex) -> Tier 3 (plain numbers)
2675
+ const convertedInstructions: Instructions = (Array.isArray(rawInstructions) && codeUnitToIndexMap)
2676
+ ? unwrapBranchOffsets(convertBranchOffsetsToInstructionOffsets(rawInstructions)) as Instructions
2677
+ : codeItem.instructions;
2678
+
2711
2679
  codeByOffset.set(offset, {
2712
2680
  registersSize: codeItem.registersSize,
2713
2681
  insSize: codeItem.insSize,
2714
2682
  outsSize: codeItem.outsSize,
2715
2683
  debugInfo,
2716
- instructions: codeItem.instructions,
2684
+ instructions: convertedInstructions,
2717
2685
  tries: codeItem.tryItems.map(tryItem => {
2718
2686
  const handler_ = codeItem.handlers.get(tryItem.handlerOffset);
2719
2687
  invariant(handler_, 'Handler must be there. Handler offset: %s', tryItem.handlerOffset);
2720
2688
 
2689
+ // Convert handler addresses from code units to instruction indices (unwrapped for Tier 3)
2721
2690
  const handler = {
2722
2691
  handlers: handler_.handlers.map(encodedHandler => {
2723
2692
  const type = types.at(encodedHandler.typeIndex);
@@ -2725,15 +2694,27 @@ const createDalvikExecutableParser = <Instructions>({
2725
2694
 
2726
2695
  return {
2727
2696
  type,
2728
- address: encodedHandler.address,
2697
+ handlerInstructionIndex: codeUnitToIndexMap
2698
+ ? isoInstructionIndex.unwrap(codeUnitToInstructionIndex(isoCodeUnit.wrap(encodedHandler.address), codeUnitToIndexMap))
2699
+ : encodedHandler.address,
2729
2700
  };
2730
2701
  }),
2731
- catchAllAddress: handler_.catchAllAddress,
2702
+ catchAllInstructionIndex: (handler_.catchAllAddress !== undefined && codeUnitToIndexMap)
2703
+ ? isoInstructionIndex.unwrap(codeUnitToInstructionIndex(isoCodeUnit.wrap(handler_.catchAllAddress), codeUnitToIndexMap))
2704
+ : handler_.catchAllAddress,
2732
2705
  };
2733
2706
 
2707
+ // Convert try block addresses from code units to instruction indices (unwrapped for Tier 3)
2708
+ const startInstructionIndex = codeUnitToIndexMap
2709
+ ? isoInstructionIndex.unwrap(codeUnitToInstructionIndex(isoCodeUnit.wrap(tryItem.startAddress), codeUnitToIndexMap))
2710
+ : tryItem.startAddress;
2711
+ const endInstructionIndex = codeUnitToIndexMap
2712
+ ? isoInstructionIndex.unwrap(codeUnitToInstructionIndex(isoCodeUnit.wrap(tryItem.startAddress + tryItem.instructionCount), codeUnitToIndexMap))
2713
+ : tryItem.startAddress + tryItem.instructionCount;
2714
+
2734
2715
  return {
2735
- startAddress: tryItem.startAddress,
2736
- instructionCount: tryItem.instructionCount,
2716
+ startInstructionIndex,
2717
+ instructionCount: endInstructionIndex - startInstructionIndex,
2737
2718
  handler,
2738
2719
  };
2739
2720
  }),
@@ -2744,7 +2725,7 @@ const createDalvikExecutableParser = <Instructions>({
2744
2725
  [ isoOffsetToClassDataItem.wrap(0), undefined ],
2745
2726
  ]);
2746
2727
 
2747
- const resolvers: DalvikBytecodeOperationResolvers = {
2728
+ const resolvers: RawDalvikBytecodeOperationResolvers = {
2748
2729
  resolveIndexIntoStringIds(indexIntoStringIds) {
2749
2730
  const string = strings.at(indexIntoStringIds);
2750
2731
  invariant(string !== undefined, 'String must be there. String id: %s', indexIntoStringIds);
@@ -2787,7 +2768,7 @@ const createDalvikExecutableParser = <Instructions>({
2787
2768
 
2788
2769
  return {
2789
2770
  ...rest,
2790
- instructions: instructions.map((instruction: DalvikBytecodeOperation) => resolveDalvikBytecodeOperation(instruction, resolvers)) as Instructions,
2771
+ instructions: instructions.map((instruction: DalvikBytecodeOperation) => resolveRawDalvikBytecodeOperationIndices(instruction as RawDalvikBytecodeOperation, resolvers)) as Instructions,
2791
2772
  };
2792
2773
  }
2793
2774
 
@@ -3213,14 +3194,8 @@ const createDalvikExecutableParser = <Instructions>({
3213
3194
  if (classDef.annotations?.parameterAnnotations && classDef.classData) {
3214
3195
  const allMethods = [...(classDef.classData.directMethods ?? []), ...(classDef.classData.virtualMethods ?? [])];
3215
3196
  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
- );
3197
+ const indexA = allMethods.findIndex(m => dalvikExecutableMethodEquals(m.method, a.method));
3198
+ const indexB = allMethods.findIndex(m => dalvikExecutableMethodEquals(m.method, b.method));
3224
3199
  return indexA - indexB;
3225
3200
  });
3226
3201
  }
@@ -3234,9 +3209,16 @@ const createDalvikExecutableParser = <Instructions>({
3234
3209
  ),
3235
3210
  )();
3236
3211
 
3212
+ // The factory creates a parser that outputs RawDalvikBytecode, but the parser internally transforms
3213
+ // instructions via unwrapBranchOffsets(convertBranchOffsetsToInstructionOffsets(...)) and
3214
+ // resolveRawDalvikBytecodeOperationIndices to produce DalvikBytecode with plain number indices.
3215
+ // The cast is required because TypeScript can't track this internal transformation.
3237
3216
  export const dalvikExecutableParser: Parser<DalvikExecutable<DalvikBytecode>, Uint8Array> = createDalvikExecutableParser({
3238
- createInstructionsParser: createDalvikBytecodeParser,
3239
- });
3217
+ createInstructionsParser: createRawDalvikBytecodeParser,
3218
+ }) as Parser<DalvikExecutable<DalvikBytecode>, Uint8Array>;
3219
+
3220
+ // Re-export public types
3221
+ export { type DalvikBytecodeOperation, type DalvikBytecode } from './dalvikBytecodeParser/addressConversion.js';
3240
3222
 
3241
3223
  setParserName(dalvikExecutableParser, 'dalvikExecutableParser');
3242
3224
 
@@ -217,6 +217,9 @@ const parseAllClassesInDexAgainstSmaliMacro = test.macro({
217
217
  });
218
218
 
219
219
  const testCasesByCid: Record<string, Array<string | { smaliFilePath: string; isolate?: boolean }>> = {
220
+ bafkreifycfnx4xf3nlml4qavlyxr6bes66nxsow3iaqjghewfsozoj2h3q: [
221
+ { smaliFilePath: 'pl/czak/minimal/MainActivity', isolate: true },
222
+ ],
220
223
  bafybeicb3qajmwy6li7hche2nkucvytaxcyxhwhphmi73tgydjzmyoqoda: [
221
224
  { smaliFilePath: 'androidx/activity/ComponentActivity$1', isolate: true },
222
225
  { smaliFilePath: 'androidx/activity/R$id', isolate: true },
@@ -361,3 +364,4 @@ test.serial(
361
364
  );
362
365
  },
363
366
  );
367
+
@@ -14,11 +14,11 @@ import {
14
14
  isDalvikExecutableField,
15
15
  isDalvikExecutableMethod,
16
16
  } from '../dalvikExecutable.js';
17
- import { type DalvikBytecode } from '../dalvikBytecodeParser.js';
17
+ import { type DalvikBytecodeOperation } from '../dalvikBytecodeParser/addressConversion.js';
18
18
  import { type PoolBuilders } from './poolBuilders.js';
19
19
 
20
20
  export function scanForPoolReferences(
21
- dalvikExecutable: DalvikExecutable<DalvikBytecode>,
21
+ dalvikExecutable: DalvikExecutable<DalvikBytecodeOperation[]>,
22
22
  poolBuilders: PoolBuilders,
23
23
  ): void {
24
24
  const { stringPool, typePool, protoPool, fieldPool, methodPool } = poolBuilders;
@@ -198,7 +198,7 @@ export function scanForPoolReferences(
198
198
  }
199
199
  }
200
200
 
201
- function scanCode(code: undefined | DalvikExecutableCode<DalvikBytecode>): void {
201
+ function scanCode(code: undefined | DalvikExecutableCode<DalvikBytecodeOperation[]>): void {
202
202
  if (!code) {
203
203
  return;
204
204
  }
@@ -249,12 +249,12 @@ export function scanForPoolReferences(
249
249
  }
250
250
  }
251
251
 
252
- function scanMethod(method: DalvikExecutableMethodWithAccess<DalvikBytecode>): void {
252
+ function scanMethod(method: DalvikExecutableMethodWithAccess<DalvikBytecodeOperation[]>): void {
253
253
  addMethod(method.method);
254
254
  scanCode(method.code);
255
255
  }
256
256
 
257
- function scanClassData(classData: undefined | DalvikExecutableClassData<DalvikBytecode>): void {
257
+ function scanClassData(classData: undefined | DalvikExecutableClassData<DalvikBytecodeOperation[]>): void {
258
258
  if (!classData) {
259
259
  return;
260
260
  }
@@ -276,7 +276,7 @@ export function scanForPoolReferences(
276
276
  }
277
277
  }
278
278
 
279
- function scanClassDefinition(classDef: DalvikExecutableClassDefinition<DalvikBytecode>): void {
279
+ function scanClassDefinition(classDef: DalvikExecutableClassDefinition<DalvikBytecodeOperation[]>): void {
280
280
  addType(classDef.class);
281
281
  addType(classDef.superclass);
282
282