├── LICENSE
├── README.md
├── abc12.bt
└── abc9.bt
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Zack Huang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ark Bytecode (.abc) 010Editor Template
2 |
3 | 010Editor template for .abc (Open/HarmonyOS Ark Bytecode) files
4 |
5 | Note: this is NOT a disassembler for the bytecode, but a parser for the file format that contains the bytecode. (Think .dex vs Dalvik bytecode)
6 |
7 | For a disassembler, see [https://gitee.com/openharmony/arkcompiler_runtime_core/blob/master/README.md#disassembler-ark_disasm](https://gitee.com/openharmony/arkcompiler_runtime_core/blob/master/README.md#disassembler-ark_disasm).
8 |
9 | # Known issues
10 | - Parsing of `LiteralArray` can be flawed due to poor documentation. By the documentation (see `References` section for a link), a `LiteralArray` has two fields: `num_literals` which indicates the number of literals this `LiteralArray` contains (somehow the number must be divided by 2 to get the actual number), and `literals` which is an array of `Literal`. The `Literal` struct, as it turns out, follows a Tag-Value format, which means the first field is a tag determining how the second field should be interpreted. Unfortunately, the tags are not documented at all. I had to extract them from the source code, but I'm not 100% sure if I understood everything in the relevant code correctly, especially the `LiteralTag::ARRAY_*` tags, given that this is such a huge project.
11 | - Parsing of methods referred to by `MethodRegionIndex` is still problematic, so this part of code has been commented out.
12 | - Parsing of `Proto` and `MethodHandle` is not implemented yet.
13 | - Parsing of `LineNumberProgram` is flawed too, as the operands in a line number program are not handled at all, and as such a `0x0` operand would be misinterpreted as marking the end of the program.
14 | - Should be fixed already (if I was looking at the right place in the code!). Parsing of `Value` of `any` type is not implemented. The `Value` struct is used when a `Field`, in its `field_data`, has a `TaggedValue` with the tag `VALUE` (bit of a tongue twister). `Value` follows a Tag-Value format too (but the "tag" is indicated by a field named `type_idx` in `Field`), whose tag is - surprise surprise - poorly documented. Luckily, this time the code is simpler, except for the `0x0b` tag, which means the type of the value is `any`. I have no idea what this type means and how it should be interpreted.
15 |
16 | # References
17 | - [Official documentation for the .abc format](https://gitee.com/openharmony/arkcompiler_runtime_core/blob/master/docs/file_format.md) (Careful, a few things in it are not accurate or up-to-date)
18 | - `arkcompiler\runtime_core\libpandafile\literal_data_accessor.h`
19 | - `arkcompiler\ets_runtime\ecmascript\jspandafile\js_pandafile.cpp`
20 | - FieldTag: `arkcompiler\runtime_core\libpandafile\field_data_accessor.cpp`
21 | - LiteralTag: `arkcompiler\runtime_core\libpandafile\literal_data_accessor-inl.h`
22 | - [Official ABC static defect scanner](https://gitee.com/openharmony/arkcompiler_runtime_core/tree/master/libark_defect_scan_aux)
23 |
24 | # Changelog
25 | - 2024/7/27: Added support for abc version >= 12.0.1.0
26 | - 2024/9/28: Fixed size of `modulerecord_literalarrs`; better handling of `constant_pool`
27 |
--------------------------------------------------------------------------------
/abc12.bt:
--------------------------------------------------------------------------------
1 | //------------------------------------------------
2 | //--- 010 Editor v12.0.1 Binary Template
3 | //
4 | // File: abc12.bt
5 | // Authors: hx1997
6 | // Version: 1.2
7 | // Purpose: 010Editor template for .abc (Open/HarmonyOS Ark Bytecode) files
8 | // Category: Operating Systems
9 | // History:
10 | // 1.2 2024-09-28 hx1997: Fix size of modulerecord_literalarrs; better handling of constant_pool (thanks to @alviszh)
11 | // 1.1 2024-07-27 hx1997: Add support for abc version >=12.0.1.0 (thanks to @hfkai). For older versions see https://github.com/hx1997/ark-bytecode-010editor-template
12 | // 1.0 2024-06-21 hx1997: Initial release on Script Repository
13 | //------------------------------------------------
14 |
15 | uint Align( uint value, uint alignment )
16 | {
17 | return (value + (alignment - 1)) & ~(alignment - 1);
18 | }
19 |
20 | void FAlign( uint alignment )
21 | {
22 | FSeek( Align( FTell(), alignment ) );
23 | }
24 |
25 | typedef struct {
26 | ubyte val ;
27 | if(val > 0x7f) {
28 | ubyte val ;
29 | if (val > 0x7f) {
30 | ubyte val ;
31 | if(val > 0x7f) {
32 | ubyte val ;
33 | if(val > 0x7f) {
34 | ubyte val ;
35 | }
36 | }
37 | }
38 | }
39 | } uleb128 ;
40 |
41 | // get the actual uint value of the uleb128
42 | uint uleb128_value(uleb128 &u) {
43 | local uint result;
44 | local ubyte cur;
45 |
46 | result = u.val[0];
47 | if(result > 0x7f) {
48 | cur = u.val[1];
49 | result = (result & 0x7f) | (uint)((cur & 0x7f) << 7);
50 | if(cur > 0x7f) {
51 | cur = u.val[2];
52 | result |= (uint)(cur & 0x7f) << 14;
53 | if(cur > 0x7f) {
54 | cur = u.val[3];
55 | result |= (uint)(cur & 0x7f) << 21;
56 | if(cur > 0x7f) {
57 | cur = u.val[4];
58 | result |= (uint)cur << 28;
59 | }
60 | }
61 | }
62 | }
63 |
64 | return result;
65 | }
66 |
67 | // get the number of bytes taken by a uleb128
68 | uint uleb128_size(uleb128 &u) {
69 | local uint result;
70 | local ubyte cur;
71 | local uint size = 1;
72 |
73 | result = u.val[0];
74 | if(result > 0x7f) {
75 | size = 2;
76 | cur = u.val[1];
77 | result = (result & 0x7f) | (uint)((cur & 0x7f) << 7);
78 | if(cur > 0x7f) {
79 | size = 3;
80 | cur = u.val[2];
81 | result |= (uint)(cur & 0x7f) << 14;
82 | if(cur > 0x7f) {
83 | size = 4;
84 | cur = u.val[3];
85 | result |= (uint)(cur & 0x7f) << 21;
86 | if(cur > 0x7f) {
87 | size = 5;
88 | cur = u.val[4];
89 | result |= (uint)cur << 28;
90 | }
91 | }
92 | }
93 | }
94 |
95 | return size;
96 | }
97 |
98 | typedef struct uleb128 uleb128p1;
99 |
100 | int uleb128p1_value(uleb128 &u) {
101 | return (int)uleb128_value(u) - 1;
102 | }
103 |
104 | string ULeb128Read(uleb128 &u) {
105 | local string s;
106 | s = SPrintf(s, "0x%X", uleb128_value(u));
107 | return s;
108 | }
109 |
110 | // sleb128
111 | typedef struct {
112 | ubyte val ;
113 | if(val > 0x7f) {
114 | ubyte val ;
115 | if (val > 0x7f) {
116 | ubyte val ;
117 | if(val > 0x7f) {
118 | ubyte val ;
119 | if(val > 0x7f) {
120 | ubyte val ;
121 | }
122 | }
123 | }
124 | }
125 | } sleb128 ;
126 |
127 | // get the actual uint value of the uleb128
128 | int sleb128_value(sleb128 &u) {
129 | local int result;
130 | local ubyte cur;
131 |
132 | result = u.val[0];
133 | if(result <= 0x7f) {
134 | result = (result << 25) >> 25;
135 | } else {
136 | cur = u.val[1];
137 | result = (result & 0x7f) | ((uint)(cur & 0x7f) << 7);
138 | if(cur <= 0x7f) {
139 | result = (result << 18) >> 18;
140 | } else {
141 | cur = u.val[2];
142 | result |= (uint)(cur & 0x7f) << 14;
143 | if(cur <= 0x7f) {
144 | result = (result << 11) >> 11;
145 | } else {
146 | cur = u.val[3];
147 | result |= (uint)(cur & 0x7f) << 21;
148 | if(cur <= 0x7f) {
149 | result = (result << 4) >> 4;
150 | } else {
151 | cur = u.val[4];
152 | result |= (uint)cur << 28;
153 | }
154 | }
155 | }
156 | }
157 |
158 | return result;
159 | }
160 |
161 | string SLeb128Read(sleb128 &u) {
162 | local string s;
163 | s = SPrintf(s, "%i", sleb128_value(u));
164 | return s;
165 | }
166 |
167 | typedef struct {
168 | uleb128 utf16_length ;
169 | string data ;
170 | } String ;
171 |
172 | typedef struct {
173 | char panda[5];
174 | char padding[3];
175 |
176 | if(Strcmp(panda, "PANDA") || padding[0] != 0 || padding[1] != 0 || padding[2] != 0) {
177 | PrintWarning("Invalid ABC file");
178 | return -1;
179 | }
180 | } abc_magic ;
181 |
182 | string AbcMagicRead(abc_magic &m) {
183 | string s;
184 | SPrintf(s, "%s\\0\\0\\0", m.panda);
185 | return s;
186 | }
187 |
188 | typedef struct {
189 | abc_magic magic ;
190 | uint checksum ;
191 | uchar version[4] ;
192 | uint filesize ;
193 | uint foreign_off ;
194 | uint foreign_size ;
195 | uint num_classes ;
196 | uint class_idx_off ;
197 | uint num_lnps ;
198 | uint lnp_idx_off ;
199 | uint num_literalarrays ;
200 | uint literalarray_idx_off ;
201 | uint num_index_regions ;
202 | uint index_section_off ;
203 | FAlign(4);
204 | } Header ;
205 |
206 | int readHeaderItemSize(Header &item) {
207 | return 60;
208 | }
209 |
210 | typedef struct {
211 | uleb128 type_idx ;
212 | uleb128 handler_pc ;
213 | uleb128 code_size ;
214 | } CatchBlock;
215 |
216 | typedef struct {
217 | uleb128 start_pc ;
218 | uleb128 length ;
219 | uleb128 num_catches ;
220 | CatchBlock catch_blocks[uleb128_value(num_catches)] ;
221 | } TryBlock;
222 |
223 | typedef struct {
224 | uleb128 num_vregs ;
225 | uleb128 num_args ;
226 | uleb128 code_size ;
227 | uleb128 tries_size ;
228 | uchar instructions[uleb128_value(code_size)] ;
229 | TryBlock try_blocks[uleb128_value(tries_size)] ;
230 | } Code;
231 |
232 | typedef struct {
233 | uint name_off ;
234 | readStringAt(name_off);
235 | // size of value is fixed (32-bit), see `arkcompiler\runtime_core\libpandafile\annotation_data_accessor.cpp`
236 | uint value ;
237 | } AnnotationElement;
238 |
239 | typedef struct {
240 | ushort class_idx ;
241 | ushort count ;
242 | AnnotationElement elements[count] ;
243 | uchar element_types[count] ;
244 | } Annotation;
245 |
246 | typedef struct {
247 | uint count ;
248 | uint offsets[count] ;
249 | } AnnotationArray;
250 |
251 | typedef struct {
252 | uint count ;
253 | AnnotationArray annotations[count] ;
254 | } ParamAnnotations;
255 |
256 | typedef struct {
257 | uleb128 line_start ;
258 | uleb128 num_parameters ;
259 | uleb128 parameters[uleb128_value(num_parameters)] ;
260 | uleb128 constant_pool_size ;
261 |
262 | local uint64 offset = 0;
263 | while (offset < uleb128_value(constant_pool_size)) {
264 | uleb128 constant_pool ;
265 | offset += uleb128_size(constant_pool);
266 | }
267 |
268 | uleb128 line_number_program_idx ;
269 | } DebugInfo;
270 |
271 | void readCodeAt(uint offset) {
272 | local int64 pos;
273 | local int color;
274 | if (offset != 0) {
275 | color = GetBackColor();
276 | pos = FTell();
277 | FSeek(offset);
278 | SetBackColor(0x00a5ff);
279 | Code code_data ;
280 | FSeek(pos);
281 | SetBackColor(color);
282 | }
283 | }
284 |
285 | void readAnnotationAt(uint offset) {
286 | local int64 pos;
287 | local int color;
288 | if (offset != 0) {
289 | color = GetBackColor();
290 | pos = FTell();
291 | FSeek(offset);
292 | SetBackColor(0xf09020);
293 | Annotation annotation_data;
294 | FSeek(pos);
295 | SetBackColor(color);
296 | }
297 | }
298 |
299 | void readParamAnnotationsAt(uint offset) {
300 | local int64 pos;
301 | local int color;
302 | if (offset != 0) {
303 | color = GetBackColor();
304 | pos = FTell();
305 | FSeek(offset);
306 | SetBackColor(0xf09020);
307 | ParamAnnotations annotation_data;
308 | FSeek(pos);
309 | SetBackColor(color);
310 | }
311 | }
312 |
313 | void readDebugInfoAt(uint offset) {
314 | local int64 pos;
315 | local int color;
316 | if (offset != 0) {
317 | color = GetBackColor();
318 | pos = FTell();
319 | FSeek(offset);
320 | SetBackColor(0xc0c0c0);
321 | DebugInfo debug_info_data ;
322 | FSeek(pos);
323 | SetBackColor(color);
324 | }
325 | }
326 |
327 | typedef struct {
328 | uchar tag_value ;
329 | switch (tag_value) {
330 | case 0: // NOTHING
331 | break;
332 | case 1: // INTERFACES
333 | uleb128 num_interfaces ;
334 | ushort interfaces_idx[uleb128_value(num_interfaces)] ;
335 | break;
336 | case 2: // SOURCE_LANG
337 | uchar source_lang ;
338 | break;
339 | case 3: // RUNTIME_ANNOTATION
340 | uint runtime_annotation ;
341 | readAnnotationAt(runtime_annotation);
342 | break;
343 | case 4: // ANNOTATION
344 | uint annotation ;
345 | readAnnotationAt(annotation);
346 | break;
347 | case 5: // RUNTIME_TYPE_ANNOTATION
348 | uchar runtime_type_annotation ;
349 | readAnnotationAt(runtime_type_annotation);
350 | break;
351 | case 6: // TYPE_ANNOTATION
352 | uchar type_annotation ;
353 | readAnnotationAt(type_annotation);
354 | break;
355 | case 7: // SOURCE_FILE
356 | uchar source_file ;
357 | break;
358 | }
359 | } ClassTag;
360 |
361 | uint getFieldTypeByIdx(ushort type_idx) {
362 | local int i;
363 | local uint64 pos = FTell();
364 | for (i = 0; i < abc_header.num_index_regions; i++) {
365 | if (pos < abc_region_idxs.region_headers[i].start_off || pos > abc_region_idxs.region_headers[i].end_off)
366 | continue;
367 | return abc_region_idxs.region_headers[i].class_idx.types[type_idx].field_type;
368 | }
369 | }
370 |
371 | void readFieldValue(uint field_type) {
372 | // arkcompiler\runtime_core\libpandafile\field_data_accessor.cpp
373 | if (field_type < 16) {
374 | switch (field_type) {
375 | case 0x0: // u1
376 | case 0x2: // u8
377 | case 0x1: // i8
378 | case 0x3: // i16
379 | case 0x4: // u16
380 | case 0x5: // i32
381 | case 0x6: // u32
382 | case 0x7: // f32
383 | case 0xb: // any, not sure if this is right
384 | uint value ;
385 | break;
386 | case 0x8: // f64
387 | case 0x9: // i64
388 | case 0xa: // u64
389 | uint offset;
390 | uint64 pos = FTell();
391 | FSeek(offset);
392 | uint64 value ;
393 | FSeek(pos);
394 | break;
395 | }
396 | } else {
397 | uint value ;
398 | }
399 | }
400 |
401 | typedef struct (ushort type_idx) {
402 | uchar tag_value ;
403 | switch (tag_value) {
404 | case 0: // NOTHING
405 | break;
406 | case 1: // INT_VALUE
407 | sleb128 int_value ;
408 | break;
409 | case 2: // VALUE
410 | local uint field_type = getFieldTypeByIdx(type_idx);
411 | readFieldValue(field_type);
412 | break;
413 | case 3: // RUNTIME_ANNOTATIONS
414 | uint runtime_annotations ;
415 | readAnnotationAt(runtime_annotations);
416 | break;
417 | case 4: // ANNOTATIONS
418 | uint annotations ;
419 | readAnnotationAt(annotations);
420 | break;
421 | case 5: // RUNTIME_TYPE_ANNOTATION
422 | uint runtime_type_annotation ;
423 | readAnnotationAt(runtime_type_annotation);
424 | break;
425 | case 6: // TYPE_ANNOTATION
426 | uint type_annotation ;
427 | readAnnotationAt(type_annotation);
428 | break;
429 | }
430 | } FieldTag;
431 |
432 | typedef struct {
433 | uchar tag_value ;
434 | switch (tag_value) {
435 | case 0: // NOTHING
436 | break;
437 | case 1: // CODE
438 | uint code ;
439 | readCodeAt(code);
440 | break;
441 | case 2: // SOURCE_LANG
442 | uchar source_lang ;
443 | break;
444 | case 3: // RUNTIME_ANNOTATION
445 | uint runtime_annotation ;
446 | readAnnotationAt(runtime_annotation);
447 | break;
448 | case 4: // RUNTIME_PARAM_ANNOTATION
449 | uint runtime_param_annotation ;
450 | readParamAnnotationAt(runtime_param_annotation);
451 | break;
452 | case 5: // DEBUG_INFO
453 | uint debug_info ;
454 | readDebugInfoAt(debug_info);
455 | break;
456 | case 6: // ANNOTATIONS
457 | uint annotations ;
458 | readAnnotationAt(annotations);
459 | break;
460 | case 7: // PARAM_ANNOTATION
461 | uint param_annotation ;
462 | readParamAnnotationAt(runtime_param_annotation);
463 | break;
464 | case 8: // TYPE_ANNOTATION
465 | uint type_annotation ;
466 | readAnnotationAt(type_annotation);
467 | break;
468 | case 9: // RUNTIME_TYPE_ANNOTATION
469 | uint runtime_type_annotation ;
470 | readAnnotationAt(runtime_type_annotation);
471 | break;
472 | }
473 | } MethodTag;
474 |
475 | string getShortyTypeName(uchar shorty_nibble) {
476 | switch (shorty_nibble) {
477 | case 0x0:
478 | return "end";
479 | case 0x1:
480 | return "void";
481 | case 0x2:
482 | return "u1";
483 | case 0x3:
484 | return "i8";
485 | case 0x4:
486 | return "u8";
487 | case 0x5:
488 | return "i16";
489 | case 0x6:
490 | return "u16";
491 | case 0x7:
492 | return "i32";
493 | case 0x8:
494 | return "u32";
495 | case 0x9:
496 | return "f32";
497 | case 0xa:
498 | return "f64";
499 | case 0xb:
500 | return "i64";
501 | case 0xc:
502 | return "u64";
503 | case 0xd:
504 | return "ref";
505 | case 0xe:
506 | return "any";
507 | }
508 | }
509 |
510 | uint parseShorty() {
511 | BitfieldDisablePadding();
512 | // Note that the bitfields within each byte are interpreted right-to-left. For example, if you have "0xec 0xce", this is read as 0xc (u64), 0xe (any), 0xe (any), 0xc (u64)
513 | local uint num_bits = 4;
514 | local uint num_refs = 0;
515 | ushort shorty_returntype : 4 ;
516 |
517 | if (shorty_returntype == 0xd) {
518 | num_refs++;
519 | }
520 |
521 | ushort shorty_paramlist : 4 ;
522 | while (shorty_paramlist != 0) {
523 | num_bits = (num_bits + 4) % 16;
524 | if (shorty_paramlist == 0xd) {
525 | num_refs++;
526 | }
527 |
528 | ushort shorty_paramlist : 4 ;
529 | }
530 | num_bits = (num_bits + 4) % 16;
531 |
532 | if (num_bits != 0) {
533 | // `Shorty` elements appear in groups of 16 bits. Padding is required if the `Shorty` ends when a group hasn't reached 16 bits.
534 | local uint padding_size = 16 - num_bits;
535 | ushort : padding_size;
536 | }
537 | return num_refs;
538 | }
539 |
540 | typedef struct {
541 | local uint num_refs = parseShorty();
542 | ushort reference_types[num_refs] ;
543 | } Proto;
544 |
545 | void readStringAt(uint offset) {
546 | local int64 pos;
547 | if (offset != 0) {
548 | pos = FTell();
549 | FSeek(offset);
550 | String str ;
551 | FSeek(pos);
552 | }
553 | }
554 |
555 | typedef struct {
556 | ushort class_idx ;
557 | ushort type_idx ;
558 | uint name_off ;
559 | readStringAt(name_off);
560 | uleb128 access_flags ;
561 | FieldTag field_data(type_idx);
562 | while (field_data.tag_value != 0) {
563 | FieldTag field_data(type_idx);
564 | }
565 |
566 | if (str.data == "moduleRecordIdx") {
567 | modulerecord_literalarrs[class_idx] = field_data[0].value;
568 | }
569 | } Field;
570 |
571 | typedef struct {
572 | ushort class_idx ;
573 | ushort reserved ;
574 | uint name_off ;
575 | readStringAt(name_off);
576 | uleb128 access_flags ;
577 | MethodTag method_data;
578 | while (method_data.tag_value != 0) {
579 | MethodTag method_data;
580 | }
581 | } Method;
582 |
583 | typedef struct {
584 | String name ;
585 | uint super_class_off ;
586 | uleb128 access_flags ;
587 | uleb128 num_fields ;
588 | uleb128 num_methods ;
589 | ClassTag class_data;
590 | while (class_data.tag_value != 0) {
591 | ClassTag class_data;
592 | }
593 | Field fields[uleb128_value(num_fields)] ;
594 | Method methods[uleb128_value(num_methods)] ;
595 | } class_item;
596 |
597 | typedef struct {
598 | uchar insns;
599 | while (insns != 0) { // END_SEQUENCE opcode
600 | uchar insns;
601 | }
602 | } LineNumberProgram;
603 |
604 | typedef struct {
605 | uchar tag;
606 | switch (tag) {
607 | case 0x0: // shouldn't be here according to source code but... seems to work?
608 | uchar value;
609 | break;
610 | case 0x2: // LiteralTag::INTEGER
611 | case 0x17: // LiteralTag::LITERALBUFFERINDEX
612 | uint value;
613 | break;
614 | case 0x4: // LiteralTag::DOUBLE
615 | double value;
616 | break;
617 | case 0x1: // LiteralTag::BOOL
618 | uchar value;
619 | break;
620 | case 0x3: // LiteralTag::FLOAT
621 | float value;
622 | break;
623 | case 0x5: // LiteralTag::STRING
624 | uint value;
625 | readStringAt(value);
626 | break;
627 | case 0x6: // LiteralTag::METHOD
628 | case 0x7: // LiteralTag::GENERATORMETHOD
629 | case 0x18: // LiteralTag::LITERALARRAY
630 | case 0x16: // LiteralTag::ASYNCGENERATORMETHOD
631 | uint value;
632 | break;
633 | case 0x9: // LiteralTag::METHODAFFILIATE
634 | ushort value;
635 | break;
636 | case 0x19: // LiteralTag::BUILTINTYPEINDEX
637 | case 0x8: // LiteralTag::ACCESSOR
638 | case 0xff: // LiteralTag::NULLVALUE
639 | uchar value;
640 | break;
641 | case 0xa: // LiteralTag::ARRAY_U1
642 | case 0xb: // LiteralTag::ARRAY_U8
643 | uchar value;
644 | break;
645 | case 0xc: // LiteralTag::ARRAY_I8
646 | char value;
647 | break;
648 | case 0xd: // LiteralTag::ARRAY_U16
649 | ushort value;
650 | break;
651 | case 0xe: // LiteralTag::ARRAY_I16
652 | short value;
653 | break;
654 | case 0xf: // LiteralTag::ARRAY_U32
655 | uint value;
656 | break;
657 | case 0x10: // LiteralTag::ARRAY_I32
658 | int value;
659 | break;
660 | case 0x11: // LiteralTag::ARRAY_U64
661 | uint64 value;
662 | break;
663 | case 0x12: // LiteralTag::ARRAY_I64
664 | int64 value;
665 | break;
666 | case 0x13: // LiteralTag::ARRAY_F32
667 | float value;
668 | break;
669 | case 0x14: // LiteralTag::ARRAY_F64
670 | double value;
671 | break;
672 | case 0x15: // LiteralTag::ARRAY_STRING
673 | uint value;
674 | break;
675 | }
676 | } Literal;
677 |
678 | uint GetActualNumLiterals(uint num_literals) {
679 | local uint64 pos = FTell();
680 |
681 | local int i;
682 | local uint actual_num_literals = 0;
683 | local uchar tag;
684 | for (i = 0; i < num_literals / 2; i++) {
685 | tag = ReadUByte(pos);
686 | pos++;
687 | switch (tag) {
688 | case 0x0: // shouldn't be here according to source code but... seems to work?
689 | pos += 1;
690 | actual_num_literals++;
691 | break;
692 | case 0x2: // LiteralTag::INTEGER
693 | case 0x17: // LiteralTag::LITERALBUFFERINDEX
694 | pos += 4;
695 | actual_num_literals++;
696 | break;
697 | case 0x4: // LiteralTag::DOUBLE
698 | pos += 8;
699 | actual_num_literals++;
700 | break;
701 | case 0x1: // LiteralTag::BOOL
702 | pos += 1;
703 | actual_num_literals++;
704 | break;
705 | case 0x3: // LiteralTag::FLOAT
706 | pos += 4;
707 | actual_num_literals++;
708 | break;
709 | case 0x5: // LiteralTag::STRING
710 | case 0x6: // LiteralTag::METHOD
711 | case 0x7: // LiteralTag::GENERATORMETHOD
712 | case 0x18: // LiteralTag::LITERALARRAY
713 | case 0x16: // LiteralTag::ASYNCGENERATORMETHOD
714 | pos += 4;
715 | actual_num_literals++;
716 | break;
717 | case 0x9: // LiteralTag::METHODAFFILIATE
718 | pos += 2;
719 | actual_num_literals++;
720 | break;
721 | case 0x19: // LiteralTag::BUILTINTYPEINDEX
722 | case 0x8: // LiteralTag::ACCESSOR
723 | case 0xff: // LiteralTag::NULLVALUE
724 | pos += 1;
725 | actual_num_literals++;
726 | break;
727 | case 0xa: // LiteralTag::ARRAY_U1
728 | case 0xb: // LiteralTag::ARRAY_U8
729 | case 0xc: // LiteralTag::ARRAY_I8
730 | pos += 1;
731 | actual_num_literals++;
732 | i = num_literals / 2;
733 | break;
734 | case 0xd: // LiteralTag::ARRAY_U16
735 | case 0xe: // LiteralTag::ARRAY_I16
736 | pos += 2;
737 | actual_num_literals++;
738 | i = num_literals / 2;
739 | break;
740 | case 0xf: // LiteralTag::ARRAY_U32
741 | case 0x10: // LiteralTag::ARRAY_I32
742 | pos += 4;
743 | actual_num_literals++;
744 | i = num_literals / 2;
745 | break;
746 | case 0x11: // LiteralTag::ARRAY_U64
747 | case 0x12: // LiteralTag::ARRAY_I64
748 | pos += 8;
749 | actual_num_literals++;
750 | i = num_literals / 2;
751 | break;
752 | case 0x13: // LiteralTag::ARRAY_F32
753 | pos += 4;
754 | actual_num_literals++;
755 | i = num_literals / 2;
756 | break;
757 | case 0x14: // LiteralTag::ARRAY_F64
758 | pos += 8;
759 | actual_num_literals++;
760 | i = num_literals / 2;
761 | break;
762 | case 0x15: // LiteralTag::ARRAY_STRING
763 | actual_num_literals++;
764 | i = num_literals / 2;
765 | break;
766 | default: // invalid tag
767 | i = num_literals / 2;
768 | break;
769 | }
770 | }
771 | return actual_num_literals;
772 | }
773 |
774 | int indexof(uint64 arr[], int arrlen, uint64 key) {
775 | local int i;
776 | for (i = 0; i < arrlen; i++) {
777 | if (arr[i] == key) {
778 | return i;
779 | }
780 | }
781 | return -1;
782 | }
783 |
784 | typedef struct {
785 | uint local_name_offset;
786 | readStringAt(local_name_offset);
787 | uint import_name_offset;
788 | readStringAt(import_name_offset);
789 | ushort module_request_idx;
790 | } RegularImport;
791 |
792 | typedef struct {
793 | uint local_name_offset;
794 | readStringAt(local_name_offset);
795 | ushort module_request_idx;
796 | } NamespaceImport;
797 |
798 |
799 | typedef struct {
800 | uint local_name_offset;
801 | readStringAt(local_name_offset);
802 | uint export_name_offset;
803 | readStringAt(export_name_offset);
804 | } LocalExport;
805 |
806 |
807 | typedef struct {
808 | uint export_name_offset;
809 | readStringAt(export_name_offset);
810 | uint import_name_offset;
811 | readStringAt(import_name_offset);
812 | ushort module_request_idx;
813 | } IndirectExport;
814 |
815 |
816 | typedef struct {
817 | ushort module_request_idx;
818 | } StarExport;
819 |
820 | typedef struct {
821 | uint num_literals ;
822 |
823 | local int idx = indexof(modulerecord_literalarrs, abc_region_idxs.region_headers.class_idx_size, startof(this));
824 | if (idx == -1) {
825 | // Actual number of literals is `num_literals / 2` if no `LiteralTag::ARRAY_*` types are present.
826 | // If any of these types is present, the actual number stops at the first occurrence (i.e., no more literals once a `LiteralTag::ARRAY_*` type is encountered), no matter what `num_literals / 2` is.
827 | // I don't know why this is so designed, see source code at `arkcompiler\runtime_core\libpandafile\literal_data_accessor-inl.h`
828 | local uint actual_num_literals = GetActualNumLiterals(num_literals);
829 | Literal literals[actual_num_literals] ;
830 | } else {
831 | uint num_module_requests;
832 | local int i;
833 | for (i = 0; i < num_module_requests; i++) {
834 | uint module_requests;
835 | readStringAt(module_requests);
836 | }
837 |
838 | uint regular_import_num;
839 | for (i = 0; i < regular_import_num; i++) {
840 | RegularImport regular_imports;
841 | }
842 |
843 | uint namespace_import_num;
844 | for (i = 0; i < namespace_import_num; i++) {
845 | NamespaceImport namespace_imports;
846 | }
847 |
848 | uint local_export_num;
849 | for (i = 0; i < local_export_num; i++) {
850 | LocalExport local_exports;
851 | }
852 |
853 | uint indirect_export_num;
854 | for (i = 0; i < indirect_export_num; i++) {
855 | IndirectExport indirect_exports;
856 | }
857 |
858 | uint starExportNum;
859 | for (i = 0; i < starExportNum; i++) {
860 | StarExport star_exports;
861 | }
862 | }
863 | } LiteralArray;
864 |
865 | typedef struct {
866 | uint field_type 16 bytes, any offset in the range [0; sizeof(Header)) is invalid. FieldType encoding uses this fact to encode primitive types of the field in the low 4 bits. For non-primitive type the value is an offset to Class or to ForeignClass. In both cases FieldType is uint32_t.">;
867 | } FieldType;
868 |
869 | typedef struct {
870 | String name;
871 | } ForeignClass;
872 |
873 | typedef struct {
874 | ushort class_idx ;
875 | ushort type_idx ;
876 | uint name_off ;
877 | readStringAt(name_off);
878 | } ForeignField;
879 |
880 | typedef struct {
881 | ushort class_idx ;
882 | ushort proto_idx ;
883 | uint name_off ;
884 | readStringAt(name_off);
885 | uleb128 access_flags ;
886 | } ForeignMethod;
887 |
888 | typedef struct (uint offset, int size) {
889 | local uint64 pos = FTell();
890 | FSeek(offset);
891 | SetBackColor(0xd060d0);
892 | FieldType types[size] ;
893 | FAlign(4);
894 | FSeek(pos);
895 | } ClassRegionIndex;
896 |
897 | typedef struct (uint offset, int size) {
898 | local uint64 pos = FTell();
899 | FSeek(offset);
900 | SetBackColor(0xd060d0);
901 | uint offsets[size] ;
902 | FAlign(4);
903 | FSeek(pos);
904 | } MethodStringLiteralRegionIndex;
905 |
906 | typedef struct (uint offset, int size) {
907 | local uint64 pos = FTell();
908 | FSeek(offset);
909 | SetBackColor(0xd060d0);
910 | uint offsets[size] ;
911 | FAlign(4);
912 |
913 | local int i;
914 | local uint foreign_start = abc_header.foreign_off;
915 | local uint foreign_end = foreign_start + abc_header.foreign_size;
916 | local uint field_addr;
917 | for (i = 0; i < size; i++) {
918 | field_addr = offsets[i];
919 | FSeek(field_addr);
920 | if (foreign_start <= field_addr && field_addr < foreign_end)
921 | ForeignField abc_field_items ;
922 | else
923 | Field abc_field_items ;
924 | }
925 |
926 | FSeek(pos);
927 | } FieldRegionIndex;
928 |
929 | typedef struct (uint offset, int size) {
930 | local uint64 pos = FTell();
931 | FSeek(offset);
932 | SetBackColor(0xd060d0);
933 | uint offsets[size] ;
934 | FAlign(4);
935 |
936 | local int i;
937 | local uint proto_addr;
938 | for (i = 0; i < size; i++) {
939 | proto_addr = offsets[i];
940 | FSeek(proto_addr);
941 | Proto abc_proto_items ;
942 | }
943 |
944 | FSeek(pos);
945 | } ProtoRegionIndex;
946 |
947 | typedef struct {
948 | uint start_off ;
949 | uint end_off ;
950 | uint class_idx_size ;
951 | uint class_idx_off ;
952 | ClassRegionIndex class_idx(class_idx_off, class_idx_size) ;
953 | uint method_string_literal_region_idx_size ;
954 | uint method_string_literal_region_idx_off ;
955 | MethodStringLiteralRegionIndex method_string_literal_idx(method_string_literal_region_idx_off, method_string_literal_region_idx_size) ;
956 | uint reserved1 ;
957 | uint reserved2 ;
958 | uint reserved3 ;
959 | uint reserved4 ;
960 | FAlign(4);
961 | } RegionHeader;
962 |
963 | typedef struct (int size) {
964 | uint class_def[size] ;
965 | FAlign(4);
966 | local uint64 pos = FTell();
967 |
968 | SetBackColor(cLtBlue);
969 | local int i;
970 | local uint foreign_start = abc_header.foreign_off;
971 | local uint foreign_end = foreign_start + abc_header.foreign_size;
972 | local uint class_addr;
973 | for (i = 0; i < size; i++) {
974 | class_addr = class_def[i];
975 | FSeek(class_addr);
976 | if (foreign_start <= class_addr && class_addr < foreign_end)
977 | ForeignClass abc_class_items ;
978 | else
979 | class_item abc_class_items ;
980 | }
981 | FSeek(pos);
982 | } ClassIndex;
983 |
984 | typedef struct (int size) {
985 | uint offsets[size] ;
986 | FAlign(4);
987 | local uint64 pos = FTell();
988 |
989 | SetBackColor(cLtRed);
990 | local uint i;
991 | local uint lnp_addr;
992 | for (i = 0; i < size; i++) {
993 | lnp_addr = offsets[i];
994 | FSeek(lnp_addr);
995 | LineNumberProgram abc_line_num_programs ;
996 | }
997 | FSeek(pos);
998 | } LineNumberProgramIndex;
999 |
1000 | typedef struct (int size) {
1001 | uint offsets[size] ;
1002 | FAlign(4);
1003 | local uint64 pos = FTell();
1004 |
1005 | SetBackColor(cLtAqua);
1006 | local uint i;
1007 | local uint literalarray_addr;
1008 | for (i = 0; i < size; i++) {
1009 | literalarray_addr = offsets[i];
1010 | FSeek(literalarray_addr);
1011 | LiteralArray abc_literalarrays ;
1012 | }
1013 | FSeek(pos);
1014 | } LiteralArrayIndex;
1015 |
1016 | typedef struct (int size) {
1017 | SetBackColor(0xa030a0);
1018 | RegionHeader region_headers[size] ;
1019 | FAlign(4);
1020 | } RegionIndex;
1021 |
1022 | SetBackColor(cLtGreen);
1023 | Header abc_header ;
1024 |
1025 | FSeek(abc_header.index_section_off);
1026 | SetBackColor(0xa030a0);
1027 | RegionIndex abc_region_idxs(abc_header.num_index_regions) ;
1028 |
1029 | local uint64 modulerecord_literalarrs[abc_region_idxs.region_headers.class_idx_size]; // Keep track of module record offsets when we parse Field.
1030 |
1031 | FSeek(abc_header.class_idx_off);
1032 | SetBackColor(cDkBlue);
1033 | ClassIndex abc_class_idxs(abc_header.num_classes) ;
1034 |
1035 | FSeek(abc_header.lnp_idx_off);
1036 | SetBackColor(cDkRed);
1037 | LineNumberProgramIndex abc_line_num_program_idxs(abc_header.num_lnps) ;
1038 |
1039 | FSeek(abc_header.literalarray_idx_off);
1040 | SetBackColor(cDkAqua);
1041 | LiteralArrayIndex abc_literalarray_idxs(abc_header.num_literalarrays) ;
1042 |
--------------------------------------------------------------------------------
/abc9.bt:
--------------------------------------------------------------------------------
1 | //------------------------------------------------
2 | //--- 010 Editor v12.0.1 Binary Template
3 | //
4 | // File: abc.bt
5 | // Authors: hx1997
6 | // Version: 1.1
7 | // Purpose: 010Editor template for .abc (Open/HarmonyOS Ark Bytecode) files
8 | // Category: Operating Systems
9 | // History:
10 | // 1.1 2024-09-28 hx1997: Fix size of modulerecord_literalarrs; better handling of constant_pool (thanks to @alviszh)
11 | // 1.0 2024-06-21 hx1997: Initial release on Script Repository
12 | //------------------------------------------------
13 |
14 | uint Align( uint value, uint alignment )
15 | {
16 | return (value + (alignment - 1)) & ~(alignment - 1);
17 | }
18 |
19 | void FAlign( uint alignment )
20 | {
21 | FSeek( Align( FTell(), alignment ) );
22 | }
23 |
24 | typedef struct {
25 | ubyte val ;
26 | if(val > 0x7f) {
27 | ubyte val ;
28 | if (val > 0x7f) {
29 | ubyte val ;
30 | if(val > 0x7f) {
31 | ubyte val ;
32 | if(val > 0x7f) {
33 | ubyte val ;
34 | }
35 | }
36 | }
37 | }
38 | } uleb128 ;
39 |
40 | // get the actual uint value of the uleb128
41 | uint uleb128_value(uleb128 &u) {
42 | local uint result;
43 | local ubyte cur;
44 |
45 | result = u.val[0];
46 | if(result > 0x7f) {
47 | cur = u.val[1];
48 | result = (result & 0x7f) | (uint)((cur & 0x7f) << 7);
49 | if(cur > 0x7f) {
50 | cur = u.val[2];
51 | result |= (uint)(cur & 0x7f) << 14;
52 | if(cur > 0x7f) {
53 | cur = u.val[3];
54 | result |= (uint)(cur & 0x7f) << 21;
55 | if(cur > 0x7f) {
56 | cur = u.val[4];
57 | result |= (uint)cur << 28;
58 | }
59 | }
60 | }
61 | }
62 |
63 | return result;
64 | }
65 |
66 | // get the number of bytes taken by a uleb128
67 | uint uleb128_size(uleb128 &u) {
68 | local uint result;
69 | local ubyte cur;
70 | local uint size = 1;
71 |
72 | result = u.val[0];
73 | if(result > 0x7f) {
74 | size = 2;
75 | cur = u.val[1];
76 | result = (result & 0x7f) | (uint)((cur & 0x7f) << 7);
77 | if(cur > 0x7f) {
78 | size = 3;
79 | cur = u.val[2];
80 | result |= (uint)(cur & 0x7f) << 14;
81 | if(cur > 0x7f) {
82 | size = 4;
83 | cur = u.val[3];
84 | result |= (uint)(cur & 0x7f) << 21;
85 | if(cur > 0x7f) {
86 | size = 5;
87 | cur = u.val[4];
88 | result |= (uint)cur << 28;
89 | }
90 | }
91 | }
92 | }
93 |
94 | return size;
95 | }
96 |
97 | typedef struct uleb128 uleb128p1;
98 |
99 | int uleb128p1_value(uleb128 &u) {
100 | return (int)uleb128_value(u) - 1;
101 | }
102 |
103 | string ULeb128Read(uleb128 &u) {
104 | local string s;
105 | s = SPrintf(s, "0x%X", uleb128_value(u));
106 | return s;
107 | }
108 |
109 | // sleb128
110 | typedef struct {
111 | ubyte val ;
112 | if(val > 0x7f) {
113 | ubyte val ;
114 | if (val > 0x7f) {
115 | ubyte val ;
116 | if(val > 0x7f) {
117 | ubyte val ;
118 | if(val > 0x7f) {
119 | ubyte val ;
120 | }
121 | }
122 | }
123 | }
124 | } sleb128 ;
125 |
126 | // get the actual uint value of the uleb128
127 | int sleb128_value(sleb128 &u) {
128 | local int result;
129 | local ubyte cur;
130 |
131 | result = u.val[0];
132 | if(result <= 0x7f) {
133 | result = (result << 25) >> 25;
134 | } else {
135 | cur = u.val[1];
136 | result = (result & 0x7f) | ((uint)(cur & 0x7f) << 7);
137 | if(cur <= 0x7f) {
138 | result = (result << 18) >> 18;
139 | } else {
140 | cur = u.val[2];
141 | result |= (uint)(cur & 0x7f) << 14;
142 | if(cur <= 0x7f) {
143 | result = (result << 11) >> 11;
144 | } else {
145 | cur = u.val[3];
146 | result |= (uint)(cur & 0x7f) << 21;
147 | if(cur <= 0x7f) {
148 | result = (result << 4) >> 4;
149 | } else {
150 | cur = u.val[4];
151 | result |= (uint)cur << 28;
152 | }
153 | }
154 | }
155 | }
156 |
157 | return result;
158 | }
159 |
160 | string SLeb128Read(sleb128 &u) {
161 | local string s;
162 | s = SPrintf(s, "%i", sleb128_value(u));
163 | return s;
164 | }
165 |
166 | typedef struct {
167 | uleb128 utf16_length ;
168 | string data ;
169 | } String ;
170 |
171 | typedef struct {
172 | char panda[5];
173 | char padding[3];
174 |
175 | if(Strcmp(panda, "PANDA") || padding[0] != 0 || padding[1] != 0 || padding[2] != 0) {
176 | PrintWarning("Invalid ABC file");
177 | return -1;
178 | }
179 | } abc_magic ;
180 |
181 | string AbcMagicRead(abc_magic &m) {
182 | string s;
183 | SPrintf(s, "%s\\0\\0\\0", m.panda);
184 | return s;
185 | }
186 |
187 | typedef struct {
188 | abc_magic magic ;
189 | uint checksum ;
190 | uchar version[4] ;
191 | uint filesize ;
192 | uint foreign_off ;
193 | uint foreign_size ;
194 | uint num_classes ;
195 | uint class_idx_off ;
196 | uint num_lnps ;
197 | uint lnp_idx_off ;
198 | uint num_literalarrays ;
199 | uint literalarray_idx_off ;
200 | uint num_index_regions ;
201 | uint index_section_off ;
202 | FAlign(4);
203 | } Header ;
204 |
205 | int readHeaderItemSize(Header &item) {
206 | return 60;
207 | }
208 |
209 | typedef struct {
210 | uleb128 type_idx ;
211 | uleb128 handler_pc ;
212 | uleb128 code_size ;
213 | } CatchBlock;
214 |
215 | typedef struct {
216 | uleb128 start_pc ;
217 | uleb128 length ;
218 | uleb128 num_catches ;
219 | CatchBlock catch_blocks[uleb128_value(num_catches)] ;
220 | } TryBlock;
221 |
222 | typedef struct {
223 | uleb128 num_vregs ;
224 | uleb128 num_args ;
225 | uleb128 code_size ;
226 | uleb128 tries_size ;
227 | uchar instructions[uleb128_value(code_size)] ;
228 | TryBlock try_blocks[uleb128_value(tries_size)] ;
229 | } Code;
230 |
231 | typedef struct {
232 | uint name_off ;
233 | readStringAt(name_off);
234 | // size of value is fixed (32-bit), see `arkcompiler\runtime_core\libpandafile\annotation_data_accessor.cpp`
235 | uint value ;
236 | } AnnotationElement;
237 |
238 | typedef struct {
239 | ushort class_idx ;
240 | ushort count ;
241 | AnnotationElement elements[count] ;
242 | uchar element_types[count] ;
243 | } Annotation;
244 |
245 | typedef struct {
246 | uint count ;
247 | uint offsets[count] ;
248 | } AnnotationArray;
249 |
250 | typedef struct {
251 | uint count ;
252 | AnnotationArray annotations[count] ;
253 | } ParamAnnotations;
254 |
255 | typedef struct {
256 | uleb128 line_start ;
257 | uleb128 num_parameters ;
258 | uleb128 parameters[uleb128_value(num_parameters)] ;
259 | uleb128 constant_pool_size ;
260 |
261 | local uint64 offset = 0;
262 | while (offset < uleb128_value(constant_pool_size)) {
263 | uleb128 constant_pool ;
264 | offset += uleb128_size(constant_pool);
265 | }
266 |
267 | uleb128 line_number_program_idx ;
268 | } DebugInfo;
269 |
270 | void readCodeAt(uint offset) {
271 | local int64 pos;
272 | local int color;
273 | if (offset != 0) {
274 | color = GetBackColor();
275 | pos = FTell();
276 | FSeek(offset);
277 | SetBackColor(0x00a5ff);
278 | Code code_data ;
279 | FSeek(pos);
280 | SetBackColor(color);
281 | }
282 | }
283 |
284 | void readAnnotationAt(uint offset) {
285 | local int64 pos;
286 | local int color;
287 | if (offset != 0) {
288 | color = GetBackColor();
289 | pos = FTell();
290 | FSeek(offset);
291 | SetBackColor(0xf09020);
292 | Annotation annotation_data;
293 | FSeek(pos);
294 | SetBackColor(color);
295 | }
296 | }
297 |
298 | void readParamAnnotationsAt(uint offset) {
299 | local int64 pos;
300 | local int color;
301 | if (offset != 0) {
302 | color = GetBackColor();
303 | pos = FTell();
304 | FSeek(offset);
305 | SetBackColor(0xf09020);
306 | ParamAnnotations annotation_data;
307 | FSeek(pos);
308 | SetBackColor(color);
309 | }
310 | }
311 |
312 | void readDebugInfoAt(uint offset) {
313 | local int64 pos;
314 | local int color;
315 | if (offset != 0) {
316 | color = GetBackColor();
317 | pos = FTell();
318 | FSeek(offset);
319 | SetBackColor(0xc0c0c0);
320 | DebugInfo debug_info_data ;
321 | FSeek(pos);
322 | SetBackColor(color);
323 | }
324 | }
325 |
326 | typedef struct {
327 | uchar tag_value ;
328 | switch (tag_value) {
329 | case 0: // NOTHING
330 | break;
331 | case 1: // INTERFACES
332 | uleb128 num_interfaces ;
333 | ushort interfaces_idx[uleb128_value(num_interfaces)] ;
334 | break;
335 | case 2: // SOURCE_LANG
336 | uchar source_lang ;
337 | break;
338 | case 3: // RUNTIME_ANNOTATION
339 | uint runtime_annotation ;
340 | readAnnotationAt(runtime_annotation);
341 | break;
342 | case 4: // ANNOTATION
343 | uint annotation ;
344 | readAnnotationAt(annotation);
345 | break;
346 | case 5: // RUNTIME_TYPE_ANNOTATION
347 | uchar runtime_type_annotation ;
348 | readAnnotationAt(runtime_type_annotation);
349 | break;
350 | case 6: // TYPE_ANNOTATION
351 | uchar type_annotation ;
352 | readAnnotationAt(type_annotation);
353 | break;
354 | case 7: // SOURCE_FILE
355 | uchar source_file ;
356 | break;
357 | }
358 | } ClassTag;
359 |
360 | uint getFieldTypeByIdx(ushort type_idx) {
361 | local int i;
362 | local uint64 pos = FTell();
363 | for (i = 0; i < abc_header.num_index_regions; i++) {
364 | if (pos < abc_region_idxs.region_headers[i].start_off || pos > abc_region_idxs.region_headers[i].end_off)
365 | continue;
366 | return abc_region_idxs.region_headers[i].class_idx.types[type_idx].field_type;
367 | }
368 | }
369 |
370 | void readFieldValue(uint field_type) {
371 | // arkcompiler\runtime_core\libpandafile\field_data_accessor.cpp
372 | if (field_type < 16) {
373 | switch (field_type) {
374 | case 0x0: // u1
375 | case 0x2: // u8
376 | case 0x1: // i8
377 | case 0x3: // i16
378 | case 0x4: // u16
379 | case 0x5: // i32
380 | case 0x6: // u32
381 | case 0x7: // f32
382 | case 0xb: // any, not sure if this is right
383 | uint value ;
384 | break;
385 | case 0x8: // f64
386 | case 0x9: // i64
387 | case 0xa: // u64
388 | uint offset;
389 | uint64 pos = FTell();
390 | FSeek(offset);
391 | uint64 value ;
392 | FSeek(pos);
393 | break;
394 | }
395 | } else {
396 | uint value ;
397 | }
398 | }
399 |
400 | typedef struct (ushort type_idx) {
401 | uchar tag_value ;
402 | switch (tag_value) {
403 | case 0: // NOTHING
404 | break;
405 | case 1: // INT_VALUE
406 | sleb128 int_value ;
407 | break;
408 | case 2: // VALUE
409 | local uint field_type = getFieldTypeByIdx(type_idx);
410 | readFieldValue(field_type);
411 | break;
412 | case 3: // RUNTIME_ANNOTATIONS
413 | uint runtime_annotations ;
414 | readAnnotationAt(runtime_annotations);
415 | break;
416 | case 4: // ANNOTATIONS
417 | uint annotations ;
418 | readAnnotationAt(annotations);
419 | break;
420 | case 5: // RUNTIME_TYPE_ANNOTATION
421 | uint runtime_type_annotation ;
422 | readAnnotationAt(runtime_type_annotation);
423 | break;
424 | case 6: // TYPE_ANNOTATION
425 | uint type_annotation ;
426 | readAnnotationAt(type_annotation);
427 | break;
428 | }
429 | } FieldTag;
430 |
431 | typedef struct {
432 | uchar tag_value ;
433 | switch (tag_value) {
434 | case 0: // NOTHING
435 | break;
436 | case 1: // CODE
437 | uint code ;
438 | readCodeAt(code);
439 | break;
440 | case 2: // SOURCE_LANG
441 | uchar source_lang ;
442 | break;
443 | case 3: // RUNTIME_ANNOTATION
444 | uint runtime_annotation ;
445 | readAnnotationAt(runtime_annotation);
446 | break;
447 | case 4: // RUNTIME_PARAM_ANNOTATION
448 | uint runtime_param_annotation ;
449 | readParamAnnotationAt(runtime_param_annotation);
450 | break;
451 | case 5: // DEBUG_INFO
452 | uint debug_info ;
453 | readDebugInfoAt(debug_info);
454 | break;
455 | case 6: // ANNOTATIONS
456 | uint annotations ;
457 | readAnnotationAt(annotations);
458 | break;
459 | case 7: // PARAM_ANNOTATION
460 | uint param_annotation ;
461 | readParamAnnotationAt(runtime_param_annotation);
462 | break;
463 | case 8: // TYPE_ANNOTATION
464 | uint type_annotation ;
465 | readAnnotationAt(type_annotation);
466 | break;
467 | case 9: // RUNTIME_TYPE_ANNOTATION
468 | uint runtime_type_annotation ;
469 | readAnnotationAt(runtime_type_annotation);
470 | break;
471 | }
472 | } MethodTag;
473 |
474 | string getShortyTypeName(uchar shorty_nibble) {
475 | switch (shorty_nibble) {
476 | case 0x0:
477 | return "end";
478 | case 0x1:
479 | return "void";
480 | case 0x2:
481 | return "u1";
482 | case 0x3:
483 | return "i8";
484 | case 0x4:
485 | return "u8";
486 | case 0x5:
487 | return "i16";
488 | case 0x6:
489 | return "u16";
490 | case 0x7:
491 | return "i32";
492 | case 0x8:
493 | return "u32";
494 | case 0x9:
495 | return "f32";
496 | case 0xa:
497 | return "f64";
498 | case 0xb:
499 | return "i64";
500 | case 0xc:
501 | return "u64";
502 | case 0xd:
503 | return "ref";
504 | case 0xe:
505 | return "any";
506 | }
507 | }
508 |
509 | uint parseShorty() {
510 | BitfieldDisablePadding();
511 | // Note that the bitfields within each byte are interpreted right-to-left. For example, if you have "0xec 0xce", this is read as 0xc (u64), 0xe (any), 0xe (any), 0xc (u64)
512 | local uint num_bits = 4;
513 | local uint num_refs = 0;
514 | ushort shorty_returntype : 4 ;
515 |
516 | if (shorty_returntype == 0xd) {
517 | num_refs++;
518 | }
519 |
520 | ushort shorty_paramlist : 4 ;
521 | while (shorty_paramlist != 0) {
522 | num_bits = (num_bits + 4) % 16;
523 | if (shorty_paramlist == 0xd) {
524 | num_refs++;
525 | }
526 |
527 | ushort shorty_paramlist : 4 ;
528 | }
529 | num_bits = (num_bits + 4) % 16;
530 |
531 | if (num_bits != 0) {
532 | // `Shorty` elements appear in groups of 16 bits. Padding is required if the `Shorty` ends when a group hasn't reached 16 bits.
533 | local uint padding_size = 16 - num_bits;
534 | ushort : padding_size;
535 | }
536 | return num_refs;
537 | }
538 |
539 | typedef struct {
540 | local uint num_refs = parseShorty();
541 | ushort reference_types[num_refs] ;
542 | } Proto;
543 |
544 | void readStringAt(uint offset) {
545 | local int64 pos;
546 | if (offset != 0) {
547 | pos = FTell();
548 | FSeek(offset);
549 | String str ;
550 | FSeek(pos);
551 | }
552 | }
553 |
554 | typedef struct {
555 | ushort class_idx ;
556 | ushort type_idx ;
557 | uint name_off ;
558 | readStringAt(name_off);
559 | uleb128 access_flags ;
560 | FieldTag field_data(type_idx);
561 | while (field_data.tag_value != 0) {
562 | FieldTag field_data(type_idx);
563 | }
564 |
565 | if (str.data == "moduleRecordIdx") {
566 | modulerecord_literalarrs[class_idx] = field_data[0].value;
567 | }
568 | } Field;
569 |
570 | typedef struct {
571 | ushort class_idx ;
572 | ushort proto_idx ;
573 | uint name_off ;
574 | readStringAt(name_off);
575 | uleb128 access_flags