• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Access .dex (Dalvik Executable Format) files.  The code here assumes that
19  * the DEX file has been rewritten (byte-swapped, word-aligned) and that
20  * the contents can be directly accessed as a collection of C arrays.  Please
21  * see docs/dalvik/dex-format.html for a detailed description.
22  *
23  * The structure and field names were chosen to match those in the DEX spec.
24  *
25  * It's generally assumed that the DEX file will be stored in shared memory,
26  * obviating the need to copy code and constant pool entries into newly
27  * allocated storage.  Maintaining local pointers to items in the shared area
28  * is valid and encouraged.
29  *
30  * All memory-mapped structures are 32-bit aligned unless otherwise noted.
31  */
32 
33 #ifndef LIBDEX_DEXFILE_H_
34 #define LIBDEX_DEXFILE_H_
35 
36 /*
37  * Annotation to tell clang that we intend to fall through from one case to
38  * another in a switch. Sourced from android-base/macros.h.
39  */
40 #define FALLTHROUGH_INTENDED [[clang::fallthrough]]
41 
42 #ifndef LOG_TAG
43 # define LOG_TAG "libdex"
44 #endif
45 #include <log/log.h>
46 
47 #include <stdbool.h>
48 #include <stdint.h>
49 #include <stdio.h>
50 #include <assert.h>
51 
52 /*
53  * If "very verbose" logging is enabled, make it equivalent to ALOGV.
54  * Otherwise, make it disappear.
55  *
56  * Define this above the #include "Dalvik.h" to enable for only a
57  * single file.
58  */
59 /* #define VERY_VERBOSE_LOG */
60 #if defined(VERY_VERBOSE_LOG)
61 # define LOGVV      ALOGV
62 # define IF_LOGVV() IF_ALOGV()
63 #else
64 # define LOGVV(...) ((void)0)
65 # define IF_LOGVV() if (false)
66 #endif
67 
68 /*
69  * These match the definitions in the VM specification.
70  */
71 typedef uint8_t             u1;
72 typedef uint16_t            u2;
73 typedef uint32_t            u4;
74 typedef uint64_t            u8;
75 typedef int8_t              s1;
76 typedef int16_t             s2;
77 typedef int32_t             s4;
78 typedef int64_t             s8;
79 
80 #include "libdex/SysUtil.h"
81 
82 /*
83  * gcc-style inline management -- ensures we have a copy of all functions
84  * in the library, so code that links against us will work whether or not
85  * it was built with optimizations enabled.
86  */
87 #ifndef _DEX_GEN_INLINES             /* only defined by DexInlines.c */
88 # define DEX_INLINE extern __inline__
89 #else
90 # define DEX_INLINE
91 #endif
92 
93 /* DEX file magic number */
94 #define DEX_MAGIC       "dex\n"
95 
96 /* The version for android N, encoded in 4 bytes of ASCII. This differentiates dex files that may
97  * use default methods.
98  */
99 #define DEX_MAGIC_VERS_37  "037\0"
100 
101 /* The version for android O, encoded in 4 bytes of ASCII. This differentiates dex files that may
102  * contain invoke-custom, invoke-polymorphic, call-sites, and method handles.
103  */
104 #define DEX_MAGIC_VERS_38  "038\0"
105 
106 /* The version for android P, encoded in 4 bytes of ASCII. This differentiates dex files that may
107  * contain const-method-handle and const-proto.
108  */
109 #define DEX_MAGIC_VERS_39  "039\0"
110 
111 /* current version, encoded in 4 bytes of ASCII */
112 #define DEX_MAGIC_VERS  "036\0"
113 
114 /*
115  * older but still-recognized version (corresponding to Android API
116  * levels 13 and earlier
117  */
118 #define DEX_MAGIC_VERS_API_13  "035\0"
119 
120 /* same, but for optimized DEX header */
121 #define DEX_OPT_MAGIC   "dey\n"
122 #define DEX_OPT_MAGIC_VERS  "036\0"
123 
124 #define DEX_DEP_MAGIC   "deps"
125 
126 /*
127  * 160-bit SHA-1 digest.
128  */
129 enum { kSHA1DigestLen = 20,
130        kSHA1DigestOutputLen = kSHA1DigestLen*2 +1 };
131 
132 /* general constants */
133 enum {
134     kDexEndianConstant = 0x12345678,    /* the endianness indicator */
135     kDexNoIndex = 0xffffffff,           /* not a valid index value */
136 };
137 
138 /*
139  * Enumeration of all the primitive types.
140  */
141 enum PrimitiveType {
142     PRIM_NOT        = 0,       /* value is a reference type, not a primitive type */
143     PRIM_VOID       = 1,
144     PRIM_BOOLEAN    = 2,
145     PRIM_BYTE       = 3,
146     PRIM_SHORT      = 4,
147     PRIM_CHAR       = 5,
148     PRIM_INT        = 6,
149     PRIM_LONG       = 7,
150     PRIM_FLOAT      = 8,
151     PRIM_DOUBLE     = 9,
152 };
153 
154 /*
155  * access flags and masks; the "standard" ones are all <= 0x4000
156  *
157  * Note: There are related declarations in vm/oo/Object.h in the ClassFlags
158  * enum.
159  */
160 enum {
161     ACC_PUBLIC       = 0x00000001,       // class, field, method, ic
162     ACC_PRIVATE      = 0x00000002,       // field, method, ic
163     ACC_PROTECTED    = 0x00000004,       // field, method, ic
164     ACC_STATIC       = 0x00000008,       // field, method, ic
165     ACC_FINAL        = 0x00000010,       // class, field, method, ic
166     ACC_SYNCHRONIZED = 0x00000020,       // method (only allowed on natives)
167     ACC_SUPER        = 0x00000020,       // class (not used in Dalvik)
168     ACC_VOLATILE     = 0x00000040,       // field
169     ACC_BRIDGE       = 0x00000040,       // method (1.5)
170     ACC_TRANSIENT    = 0x00000080,       // field
171     ACC_VARARGS      = 0x00000080,       // method (1.5)
172     ACC_NATIVE       = 0x00000100,       // method
173     ACC_INTERFACE    = 0x00000200,       // class, ic
174     ACC_ABSTRACT     = 0x00000400,       // class, method, ic
175     ACC_STRICT       = 0x00000800,       // method
176     ACC_SYNTHETIC    = 0x00001000,       // field, method, ic
177     ACC_ANNOTATION   = 0x00002000,       // class, ic (1.5)
178     ACC_ENUM         = 0x00004000,       // class, field, ic (1.5)
179     ACC_CONSTRUCTOR  = 0x00010000,       // method (Dalvik only)
180     ACC_DECLARED_SYNCHRONIZED =
181                        0x00020000,       // method (Dalvik only)
182     ACC_CLASS_MASK =
183         (ACC_PUBLIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT
184                 | ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM),
185     ACC_INNER_CLASS_MASK =
186         (ACC_CLASS_MASK | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC),
187     ACC_FIELD_MASK =
188         (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL
189                 | ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM),
190     ACC_METHOD_MASK =
191         (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL
192                 | ACC_SYNCHRONIZED | ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE
193                 | ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC | ACC_CONSTRUCTOR
194                 | ACC_DECLARED_SYNCHRONIZED),
195 };
196 
197 /* annotation constants */
198 enum {
199     kDexVisibilityBuild         = 0x00,     /* annotation visibility */
200     kDexVisibilityRuntime       = 0x01,
201     kDexVisibilitySystem        = 0x02,
202 
203     kDexAnnotationByte          = 0x00,
204     kDexAnnotationShort         = 0x02,
205     kDexAnnotationChar          = 0x03,
206     kDexAnnotationInt           = 0x04,
207     kDexAnnotationLong          = 0x06,
208     kDexAnnotationFloat         = 0x10,
209     kDexAnnotationDouble        = 0x11,
210     kDexAnnotationMethodType    = 0x15,
211     kDexAnnotationMethodHandle  = 0x16,
212     kDexAnnotationString        = 0x17,
213     kDexAnnotationType          = 0x18,
214     kDexAnnotationField         = 0x19,
215     kDexAnnotationMethod        = 0x1a,
216     kDexAnnotationEnum          = 0x1b,
217     kDexAnnotationArray         = 0x1c,
218     kDexAnnotationAnnotation    = 0x1d,
219     kDexAnnotationNull          = 0x1e,
220     kDexAnnotationBoolean       = 0x1f,
221 
222     kDexAnnotationValueTypeMask = 0x1f,     /* low 5 bits */
223     kDexAnnotationValueArgShift = 5,
224 };
225 
226 /* map item type codes */
227 enum {
228     kDexTypeHeaderItem               = 0x0000,
229     kDexTypeStringIdItem             = 0x0001,
230     kDexTypeTypeIdItem               = 0x0002,
231     kDexTypeProtoIdItem              = 0x0003,
232     kDexTypeFieldIdItem              = 0x0004,
233     kDexTypeMethodIdItem             = 0x0005,
234     kDexTypeClassDefItem             = 0x0006,
235     kDexTypeCallSiteIdItem           = 0x0007,
236     kDexTypeMethodHandleItem         = 0x0008,
237     kDexTypeMapList                  = 0x1000,
238     kDexTypeTypeList                 = 0x1001,
239     kDexTypeAnnotationSetRefList     = 0x1002,
240     kDexTypeAnnotationSetItem        = 0x1003,
241     kDexTypeClassDataItem            = 0x2000,
242     kDexTypeCodeItem                 = 0x2001,
243     kDexTypeStringDataItem           = 0x2002,
244     kDexTypeDebugInfoItem            = 0x2003,
245     kDexTypeAnnotationItem           = 0x2004,
246     kDexTypeEncodedArrayItem         = 0x2005,
247     kDexTypeAnnotationsDirectoryItem = 0x2006,
248 };
249 
250 /* auxillary data section chunk codes */
251 enum {
252     kDexChunkClassLookup            = 0x434c4b50,   /* CLKP */
253     kDexChunkRegisterMaps           = 0x524d4150,   /* RMAP */
254 
255     kDexChunkEnd                    = 0x41454e44,   /* AEND */
256 };
257 
258 /* debug info opcodes and constants */
259 enum {
260     DBG_END_SEQUENCE         = 0x00,
261     DBG_ADVANCE_PC           = 0x01,
262     DBG_ADVANCE_LINE         = 0x02,
263     DBG_START_LOCAL          = 0x03,
264     DBG_START_LOCAL_EXTENDED = 0x04,
265     DBG_END_LOCAL            = 0x05,
266     DBG_RESTART_LOCAL        = 0x06,
267     DBG_SET_PROLOGUE_END     = 0x07,
268     DBG_SET_EPILOGUE_BEGIN   = 0x08,
269     DBG_SET_FILE             = 0x09,
270     DBG_FIRST_SPECIAL        = 0x0a,
271     DBG_LINE_BASE            = -4,
272     DBG_LINE_RANGE           = 15,
273 };
274 
275 /*
276  * Direct-mapped "header_item" struct.
277  */
278 struct DexHeader {
279     u1  magic[8];           /* includes version number */
280     u4  checksum;           /* adler32 checksum */
281     u1  signature[kSHA1DigestLen]; /* SHA-1 hash */
282     u4  fileSize;           /* length of entire file */
283     u4  headerSize;         /* offset to start of next section */
284     u4  endianTag;
285     u4  linkSize;
286     u4  linkOff;
287     u4  mapOff;
288     u4  stringIdsSize;
289     u4  stringIdsOff;
290     u4  typeIdsSize;
291     u4  typeIdsOff;
292     u4  protoIdsSize;
293     u4  protoIdsOff;
294     u4  fieldIdsSize;
295     u4  fieldIdsOff;
296     u4  methodIdsSize;
297     u4  methodIdsOff;
298     u4  classDefsSize;
299     u4  classDefsOff;
300     u4  dataSize;
301     u4  dataOff;
302 };
303 
304 /*
305  * Direct-mapped "map_item".
306  */
307 struct DexMapItem {
308     u2 type;              /* type code (see kDexType* above) */
309     u2 unused;
310     u4 size;              /* count of items of the indicated type */
311     u4 offset;            /* file offset to the start of data */
312 };
313 
314 /*
315  * Direct-mapped "map_list".
316  */
317 struct DexMapList {
318     u4  size;               /* #of entries in list */
319     DexMapItem list[1];     /* entries */
320 };
321 
322 /*
323  * Direct-mapped "string_id_item".
324  */
325 struct DexStringId {
326     u4 stringDataOff;      /* file offset to string_data_item */
327 };
328 
329 /*
330  * Direct-mapped "type_id_item".
331  */
332 struct DexTypeId {
333     u4  descriptorIdx;      /* index into stringIds list for type descriptor */
334 };
335 
336 /*
337  * Direct-mapped "field_id_item".
338  */
339 struct DexFieldId {
340     u2  classIdx;           /* index into typeIds list for defining class */
341     u2  typeIdx;            /* index into typeIds for field type */
342     u4  nameIdx;            /* index into stringIds for field name */
343 };
344 
345 /*
346  * Direct-mapped "method_id_item".
347  */
348 struct DexMethodId {
349     u2  classIdx;           /* index into typeIds list for defining class */
350     u2  protoIdx;           /* index into protoIds for method prototype */
351     u4  nameIdx;            /* index into stringIds for method name */
352 };
353 
354 /*
355  * Direct-mapped "proto_id_item".
356  */
357 struct DexProtoId {
358     u4  shortyIdx;          /* index into stringIds for shorty descriptor */
359     u4  returnTypeIdx;      /* index into typeIds list for return type */
360     u4  parametersOff;      /* file offset to type_list for parameter types */
361 };
362 
363 /*
364  * Direct-mapped "class_def_item".
365  */
366 struct DexClassDef {
367     u4  classIdx;           /* index into typeIds for this class */
368     u4  accessFlags;
369     u4  superclassIdx;      /* index into typeIds for superclass */
370     u4  interfacesOff;      /* file offset to DexTypeList */
371     u4  sourceFileIdx;      /* index into stringIds for source file name */
372     u4  annotationsOff;     /* file offset to annotations_directory_item */
373     u4  classDataOff;       /* file offset to class_data_item */
374     u4  staticValuesOff;    /* file offset to DexEncodedArray */
375 };
376 
377 /*
378  * Direct-mapped "call_site_id_item"
379  */
380 struct DexCallSiteId {
381     u4  callSiteOff;        /* file offset to DexEncodedArray */
382 };
383 
384 /*
385  * Enumeration of method handle type codes.
386  */
387 enum MethodHandleType {
388     STATIC_PUT = 0x00,
389     STATIC_GET = 0x01,
390     INSTANCE_PUT = 0x02,
391     INSTANCE_GET = 0x03,
392     INVOKE_STATIC = 0x04,
393     INVOKE_INSTANCE = 0x05,
394     INVOKE_CONSTRUCTOR = 0x06,
395     INVOKE_DIRECT = 0x07,
396     INVOKE_INTERFACE = 0x08
397 };
398 
399 /*
400  * Direct-mapped "method_handle_item"
401  */
402 struct DexMethodHandleItem {
403     u2 methodHandleType;    /* type of method handle */
404     u2 reserved1;           /* reserved for future use */
405     u2 fieldOrMethodIdx;    /* index of associated field or method */
406     u2 reserved2;           /* reserved for future use */
407 };
408 
409 /*
410  * Direct-mapped "type_item".
411  */
412 struct DexTypeItem {
413     u2  typeIdx;            /* index into typeIds */
414 };
415 
416 /*
417  * Direct-mapped "type_list".
418  */
419 struct DexTypeList {
420     u4  size;               /* #of entries in list */
421     DexTypeItem list[1];    /* entries */
422 };
423 
424 /*
425  * Direct-mapped "code_item".
426  *
427  * The "catches" table is used when throwing an exception,
428  * "debugInfo" is used when displaying an exception stack trace or
429  * debugging. An offset of zero indicates that there are no entries.
430  */
431 struct DexCode {
432     u2  registersSize;
433     u2  insSize;
434     u2  outsSize;
435     u2  triesSize;
436     u4  debugInfoOff;       /* file offset to debug info stream */
437     u4  insnsSize;          /* size of the insns array, in u2 units */
438     u2  insns[1];
439     /* followed by optional u2 padding */
440     /* followed by try_item[triesSize] */
441     /* followed by uleb128 handlersSize */
442     /* followed by catch_handler_item[handlersSize] */
443 };
444 
445 /*
446  * Direct-mapped "try_item".
447  */
448 struct DexTry {
449     u4  startAddr;          /* start address, in 16-bit code units */
450     u2  insnCount;          /* instruction count, in 16-bit code units */
451     u2  handlerOff;         /* offset in encoded handler data to handlers */
452 };
453 
454 /*
455  * Link table.  Currently undefined.
456  */
457 struct DexLink {
458     u1  bleargh;
459 };
460 
461 
462 /*
463  * Direct-mapped "annotations_directory_item".
464  */
465 struct DexAnnotationsDirectoryItem {
466     u4  classAnnotationsOff;  /* offset to DexAnnotationSetItem */
467     u4  fieldsSize;           /* count of DexFieldAnnotationsItem */
468     u4  methodsSize;          /* count of DexMethodAnnotationsItem */
469     u4  parametersSize;       /* count of DexParameterAnnotationsItem */
470     /* followed by DexFieldAnnotationsItem[fieldsSize] */
471     /* followed by DexMethodAnnotationsItem[methodsSize] */
472     /* followed by DexParameterAnnotationsItem[parametersSize] */
473 };
474 
475 /*
476  * Direct-mapped "field_annotations_item".
477  */
478 struct DexFieldAnnotationsItem {
479     u4  fieldIdx;
480     u4  annotationsOff;             /* offset to DexAnnotationSetItem */
481 };
482 
483 /*
484  * Direct-mapped "method_annotations_item".
485  */
486 struct DexMethodAnnotationsItem {
487     u4  methodIdx;
488     u4  annotationsOff;             /* offset to DexAnnotationSetItem */
489 };
490 
491 /*
492  * Direct-mapped "parameter_annotations_item".
493  */
494 struct DexParameterAnnotationsItem {
495     u4  methodIdx;
496     u4  annotationsOff;             /* offset to DexAnotationSetRefList */
497 };
498 
499 /*
500  * Direct-mapped "annotation_set_ref_item".
501  */
502 struct DexAnnotationSetRefItem {
503     u4  annotationsOff;             /* offset to DexAnnotationSetItem */
504 };
505 
506 /*
507  * Direct-mapped "annotation_set_ref_list".
508  */
509 struct DexAnnotationSetRefList {
510     u4  size;
511     DexAnnotationSetRefItem list[1];
512 };
513 
514 /*
515  * Direct-mapped "annotation_set_item".
516  */
517 struct DexAnnotationSetItem {
518     u4  size;
519     u4  entries[1];                 /* offset to DexAnnotationItem */
520 };
521 
522 /*
523  * Direct-mapped "annotation_item".
524  *
525  * NOTE: this structure is byte-aligned.
526  */
527 struct DexAnnotationItem {
528     u1  visibility;
529     u1  annotation[1];              /* data in encoded_annotation format */
530 };
531 
532 /*
533  * Direct-mapped "encoded_array".
534  *
535  * NOTE: this structure is byte-aligned.
536  */
537 struct DexEncodedArray {
538     u1  array[1];                   /* data in encoded_array format */
539 };
540 
541 /*
542  * Lookup table for classes.  It provides a mapping from class name to
543  * class definition.  Used by dexFindClass().
544  *
545  * We calculate this at DEX optimization time and embed it in the file so we
546  * don't need the same hash table in every VM.  This is slightly slower than
547  * a hash table with direct pointers to the items, but because it's shared
548  * there's less of a penalty for using a fairly sparse table.
549  */
550 struct DexClassLookup {
551     int     size;                       // total size, including "size"
552     int     numEntries;                 // size of table[]; always power of 2
553     struct {
554         u4      classDescriptorHash;    // class descriptor hash code
555         int     classDescriptorOffset;  // in bytes, from start of DEX
556         int     classDefOffset;         // in bytes, from start of DEX
557     } table[1];
558 };
559 
560 /*
561  * Header added by DEX optimization pass.  Values are always written in
562  * local byte and structure padding.  The first field (magic + version)
563  * is guaranteed to be present and directly readable for all expected
564  * compiler configurations; the rest is version-dependent.
565  *
566  * Try to keep this simple and fixed-size.
567  */
568 struct DexOptHeader {
569     u1  magic[8];           /* includes version number */
570 
571     u4  dexOffset;          /* file offset of DEX header */
572     u4  dexLength;
573     u4  depsOffset;         /* offset of optimized DEX dependency table */
574     u4  depsLength;
575     u4  optOffset;          /* file offset of optimized data tables */
576     u4  optLength;
577 
578     u4  flags;              /* some info flags */
579     u4  checksum;           /* adler32 checksum covering deps/opt */
580 
581     /* pad for 64-bit alignment if necessary */
582 };
583 
584 #define DEX_OPT_FLAG_BIG            (1<<1)  /* swapped to big-endian */
585 
586 #define DEX_INTERFACE_CACHE_SIZE    128     /* must be power of 2 */
587 
588 /*
589  * Structure representing a DEX file.
590  *
591  * Code should regard DexFile as opaque, using the API calls provided here
592  * to access specific structures.
593  */
594 struct DexFile {
595     /* directly-mapped "opt" header */
596     const DexOptHeader* pOptHeader;
597 
598     /* pointers to directly-mapped structs and arrays in base DEX */
599     const DexHeader*    pHeader;
600     const DexStringId*  pStringIds;
601     const DexTypeId*    pTypeIds;
602     const DexFieldId*   pFieldIds;
603     const DexMethodId*  pMethodIds;
604     const DexProtoId*   pProtoIds;
605     const DexClassDef*  pClassDefs;
606     const DexLink*      pLinkData;
607 
608     /*
609      * These are mapped out of the "auxillary" section, and may not be
610      * included in the file.
611      */
612     const DexClassLookup* pClassLookup;
613     const void*         pRegisterMapPool;       // RegisterMapClassPool
614 
615     /* points to start of DEX file data */
616     const u1*           baseAddr;
617 
618     /* track memory overhead for auxillary structures */
619     int                 overhead;
620 
621     /* additional app-specific data structures associated with the DEX */
622     //void*               auxData;
623 };
624 
625 /*
626  * Utility function -- rounds up to the nearest power of 2.
627  */
628 u4 dexRoundUpPower2(u4 val);
629 
630 /*
631  * Parse an optimized or unoptimized .dex file sitting in memory.
632  *
633  * On success, return a newly-allocated DexFile.
634  */
635 DexFile* dexFileParse(const u1* data, size_t length, int flags);
636 
637 /* bit values for "flags" argument to dexFileParse */
638 enum {
639     kDexParseDefault            = 0,
640     kDexParseVerifyChecksum     = 1,
641     kDexParseContinueOnError    = (1 << 1),
642 };
643 
644 /*
645  * Fix the byte ordering of all fields in the DEX file, and do
646  * structural verification. This is only required for code that opens
647  * "raw" DEX files, such as the DEX optimizer.
648  *
649  * Return 0 on success.
650  */
651 int dexSwapAndVerify(u1* addr, int len);
652 
653 /*
654  * Detect the file type of the given memory buffer via magic number.
655  * Call dexSwapAndVerify() on an unoptimized DEX file, do nothing
656  * but return successfully on an optimized DEX file, and report an
657  * error for all other cases.
658  *
659  * Return 0 on success.
660  */
661 int dexSwapAndVerifyIfNecessary(u1* addr, size_t len);
662 
663 /*
664  * Check to see if the file magic and format version in the given
665  * header are recognized as valid. Returns true if they are
666  * acceptable.
667  */
668 bool dexHasValidMagic(const DexHeader* pHeader);
669 
670 /*
671  * Compute DEX checksum.
672  */
673 u4 dexComputeChecksum(const DexHeader* pHeader);
674 
675 /*
676  * Free a DexFile structure, along with any associated structures.
677  */
678 void dexFileFree(DexFile* pDexFile);
679 
680 /*
681  * Create class lookup table.
682  */
683 DexClassLookup* dexCreateClassLookup(DexFile* pDexFile);
684 
685 /*
686  * Find a class definition by descriptor.
687  */
688 const DexClassDef* dexFindClass(const DexFile* pFile, const char* descriptor);
689 
690 /*
691  * Set up the basic raw data pointers of a DexFile. This function isn't
692  * meant for general use.
693  */
694 void dexFileSetupBasicPointers(DexFile* pDexFile, const u1* data);
695 
696 /* return the DexMapList of the file, if any */
dexGetMap(const DexFile * pDexFile)697 DEX_INLINE const DexMapList* dexGetMap(const DexFile* pDexFile) {
698     u4 mapOff = pDexFile->pHeader->mapOff;
699 
700     if (mapOff == 0) {
701         return NULL;
702     } else {
703         return (const DexMapList*) (pDexFile->baseAddr + mapOff);
704     }
705 }
706 
707 /* return the const char* string data referred to by the given string_id */
dexGetStringData(const DexFile * pDexFile,const DexStringId * pStringId)708 DEX_INLINE const char* dexGetStringData(const DexFile* pDexFile,
709         const DexStringId* pStringId) {
710     const u1* ptr = pDexFile->baseAddr + pStringId->stringDataOff;
711 
712     // Skip the uleb128 length.
713     while (*(ptr++) > 0x7f) /* empty */ ;
714 
715     return (const char*) ptr;
716 }
717 /* return the StringId with the specified index */
dexGetStringId(const DexFile * pDexFile,u4 idx)718 DEX_INLINE const DexStringId* dexGetStringId(const DexFile* pDexFile, u4 idx) {
719     assert(idx < pDexFile->pHeader->stringIdsSize);
720     return &pDexFile->pStringIds[idx];
721 }
722 /* return the UTF-8 encoded string with the specified string_id index */
dexStringById(const DexFile * pDexFile,u4 idx)723 DEX_INLINE const char* dexStringById(const DexFile* pDexFile, u4 idx) {
724     const DexStringId* pStringId = dexGetStringId(pDexFile, idx);
725     return dexGetStringData(pDexFile, pStringId);
726 }
727 
728 /* Return the UTF-8 encoded string with the specified string_id index,
729  * also filling in the UTF-16 size (number of 16-bit code points).*/
730 const char* dexStringAndSizeById(const DexFile* pDexFile, u4 idx,
731         u4* utf16Size);
732 
733 /* return the TypeId with the specified index */
dexGetTypeId(const DexFile * pDexFile,u4 idx)734 DEX_INLINE const DexTypeId* dexGetTypeId(const DexFile* pDexFile, u4 idx) {
735     assert(idx < pDexFile->pHeader->typeIdsSize);
736     return &pDexFile->pTypeIds[idx];
737 }
738 
739 /*
740  * Get the descriptor string associated with a given type index.
741  * The caller should not free() the returned string.
742  */
dexStringByTypeIdx(const DexFile * pDexFile,u4 idx)743 DEX_INLINE const char* dexStringByTypeIdx(const DexFile* pDexFile, u4 idx) {
744     const DexTypeId* typeId = dexGetTypeId(pDexFile, idx);
745     return dexStringById(pDexFile, typeId->descriptorIdx);
746 }
747 
748 /* return the MethodId with the specified index */
dexGetMethodId(const DexFile * pDexFile,u4 idx)749 DEX_INLINE const DexMethodId* dexGetMethodId(const DexFile* pDexFile, u4 idx) {
750     assert(idx < pDexFile->pHeader->methodIdsSize);
751     return &pDexFile->pMethodIds[idx];
752 }
753 
754 /* return the FieldId with the specified index */
dexGetFieldId(const DexFile * pDexFile,u4 idx)755 DEX_INLINE const DexFieldId* dexGetFieldId(const DexFile* pDexFile, u4 idx) {
756     assert(idx < pDexFile->pHeader->fieldIdsSize);
757     return &pDexFile->pFieldIds[idx];
758 }
759 
760 /* return the ProtoId with the specified index */
dexGetProtoId(const DexFile * pDexFile,u4 idx)761 DEX_INLINE const DexProtoId* dexGetProtoId(const DexFile* pDexFile, u4 idx) {
762     assert(idx < pDexFile->pHeader->protoIdsSize);
763     return &pDexFile->pProtoIds[idx];
764 }
765 
766 /*
767  * Get the parameter list from a ProtoId. The returns NULL if the ProtoId
768  * does not have a parameter list.
769  */
dexGetProtoParameters(const DexFile * pDexFile,const DexProtoId * pProtoId)770 DEX_INLINE const DexTypeList* dexGetProtoParameters(
771     const DexFile *pDexFile, const DexProtoId* pProtoId) {
772     if (pProtoId->parametersOff == 0) {
773         return NULL;
774     }
775     return (const DexTypeList*)
776         (pDexFile->baseAddr + pProtoId->parametersOff);
777 }
778 
779 /* return the ClassDef with the specified index */
dexGetClassDef(const DexFile * pDexFile,u4 idx)780 DEX_INLINE const DexClassDef* dexGetClassDef(const DexFile* pDexFile, u4 idx) {
781     assert(idx < pDexFile->pHeader->classDefsSize);
782     return &pDexFile->pClassDefs[idx];
783 }
784 
785 /* given a ClassDef pointer, recover its index */
dexGetIndexForClassDef(const DexFile * pDexFile,const DexClassDef * pClassDef)786 DEX_INLINE u4 dexGetIndexForClassDef(const DexFile* pDexFile,
787     const DexClassDef* pClassDef)
788 {
789     assert(pClassDef >= pDexFile->pClassDefs &&
790            pClassDef < pDexFile->pClassDefs + pDexFile->pHeader->classDefsSize);
791     return pClassDef - pDexFile->pClassDefs;
792 }
793 
794 /* get the interface list for a DexClass */
dexGetInterfacesList(const DexFile * pDexFile,const DexClassDef * pClassDef)795 DEX_INLINE const DexTypeList* dexGetInterfacesList(const DexFile* pDexFile,
796     const DexClassDef* pClassDef)
797 {
798     if (pClassDef->interfacesOff == 0)
799         return NULL;
800     return (const DexTypeList*)
801         (pDexFile->baseAddr + pClassDef->interfacesOff);
802 }
803 /* return the Nth entry in a DexTypeList. */
dexGetTypeItem(const DexTypeList * pList,u4 idx)804 DEX_INLINE const DexTypeItem* dexGetTypeItem(const DexTypeList* pList,
805     u4 idx)
806 {
807     assert(idx < pList->size);
808     return &pList->list[idx];
809 }
810 /* return the type_idx for the Nth entry in a TypeList */
dexTypeListGetIdx(const DexTypeList * pList,u4 idx)811 DEX_INLINE u4 dexTypeListGetIdx(const DexTypeList* pList, u4 idx) {
812     const DexTypeItem* pItem = dexGetTypeItem(pList, idx);
813     return pItem->typeIdx;
814 }
815 
816 /* get the static values list for a DexClass */
dexGetStaticValuesList(const DexFile * pDexFile,const DexClassDef * pClassDef)817 DEX_INLINE const DexEncodedArray* dexGetStaticValuesList(
818     const DexFile* pDexFile, const DexClassDef* pClassDef)
819 {
820     if (pClassDef->staticValuesOff == 0)
821         return NULL;
822     return (const DexEncodedArray*)
823         (pDexFile->baseAddr + pClassDef->staticValuesOff);
824 }
825 
826 /* get the annotations directory item for a DexClass */
dexGetAnnotationsDirectoryItem(const DexFile * pDexFile,const DexClassDef * pClassDef)827 DEX_INLINE const DexAnnotationsDirectoryItem* dexGetAnnotationsDirectoryItem(
828     const DexFile* pDexFile, const DexClassDef* pClassDef)
829 {
830     if (pClassDef->annotationsOff == 0)
831         return NULL;
832     return (const DexAnnotationsDirectoryItem*)
833         (pDexFile->baseAddr + pClassDef->annotationsOff);
834 }
835 
836 /* get the source file string */
dexGetSourceFile(const DexFile * pDexFile,const DexClassDef * pClassDef)837 DEX_INLINE const char* dexGetSourceFile(
838     const DexFile* pDexFile, const DexClassDef* pClassDef)
839 {
840     if (pClassDef->sourceFileIdx == 0xffffffff)
841         return NULL;
842     return dexStringById(pDexFile, pClassDef->sourceFileIdx);
843 }
844 
845 /* get the size, in bytes, of a DexCode */
846 size_t dexGetDexCodeSize(const DexCode* pCode);
847 
848 /* Get the list of "tries" for the given DexCode. */
dexGetTries(const DexCode * pCode)849 DEX_INLINE const DexTry* dexGetTries(const DexCode* pCode) {
850     const u2* insnsEnd = &pCode->insns[pCode->insnsSize];
851 
852     // Round to four bytes.
853     if ((((uintptr_t) insnsEnd) & 3) != 0) {
854         insnsEnd++;
855     }
856 
857     return (const DexTry*) insnsEnd;
858 }
859 
860 /* Get the base of the encoded data for the given DexCode. */
dexGetCatchHandlerData(const DexCode * pCode)861 DEX_INLINE const u1* dexGetCatchHandlerData(const DexCode* pCode) {
862     const DexTry* pTries = dexGetTries(pCode);
863     return (const u1*) &pTries[pCode->triesSize];
864 }
865 
866 /* get a pointer to the start of the debugging data */
dexGetDebugInfoStream(const DexFile * pDexFile,const DexCode * pCode)867 DEX_INLINE const u1* dexGetDebugInfoStream(const DexFile* pDexFile,
868     const DexCode* pCode)
869 {
870     if (pCode->debugInfoOff == 0) {
871         return NULL;
872     } else {
873         return pDexFile->baseAddr + pCode->debugInfoOff;
874     }
875 }
876 
877 /* DexClassDef convenience - get class descriptor */
dexGetClassDescriptor(const DexFile * pDexFile,const DexClassDef * pClassDef)878 DEX_INLINE const char* dexGetClassDescriptor(const DexFile* pDexFile,
879     const DexClassDef* pClassDef)
880 {
881     return dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
882 }
883 
884 /* DexClassDef convenience - get superclass descriptor */
dexGetSuperClassDescriptor(const DexFile * pDexFile,const DexClassDef * pClassDef)885 DEX_INLINE const char* dexGetSuperClassDescriptor(const DexFile* pDexFile,
886     const DexClassDef* pClassDef)
887 {
888     if (pClassDef->superclassIdx == 0)
889         return NULL;
890     return dexStringByTypeIdx(pDexFile, pClassDef->superclassIdx);
891 }
892 
893 /* DexClassDef convenience - get class_data_item pointer */
dexGetClassData(const DexFile * pDexFile,const DexClassDef * pClassDef)894 DEX_INLINE const u1* dexGetClassData(const DexFile* pDexFile,
895     const DexClassDef* pClassDef)
896 {
897     if (pClassDef->classDataOff == 0)
898         return NULL;
899     return (const u1*) (pDexFile->baseAddr + pClassDef->classDataOff);
900 }
901 
902 /* Get an annotation set at a particular offset. */
dexGetAnnotationSetItem(const DexFile * pDexFile,u4 offset)903 DEX_INLINE const DexAnnotationSetItem* dexGetAnnotationSetItem(
904     const DexFile* pDexFile, u4 offset)
905 {
906     if (offset == 0) {
907         return NULL;
908     }
909     return (const DexAnnotationSetItem*) (pDexFile->baseAddr + offset);
910 }
911 /* get the class' annotation set */
dexGetClassAnnotationSet(const DexFile * pDexFile,const DexAnnotationsDirectoryItem * pAnnoDir)912 DEX_INLINE const DexAnnotationSetItem* dexGetClassAnnotationSet(
913     const DexFile* pDexFile, const DexAnnotationsDirectoryItem* pAnnoDir)
914 {
915     return dexGetAnnotationSetItem(pDexFile, pAnnoDir->classAnnotationsOff);
916 }
917 
918 /* get the class' field annotation list */
dexGetFieldAnnotations(const DexFile * pDexFile,const DexAnnotationsDirectoryItem * pAnnoDir)919 DEX_INLINE const DexFieldAnnotationsItem* dexGetFieldAnnotations(
920     const DexFile* pDexFile, const DexAnnotationsDirectoryItem* pAnnoDir)
921 {
922     (void) pDexFile;
923     if (pAnnoDir->fieldsSize == 0)
924         return NULL;
925 
926     // Skip past the header to the start of the field annotations.
927     return (const DexFieldAnnotationsItem*) &pAnnoDir[1];
928 }
929 
930 /* get field annotation list size */
dexGetFieldAnnotationsSize(const DexFile * pDexFile,const DexAnnotationsDirectoryItem * pAnnoDir)931 DEX_INLINE int dexGetFieldAnnotationsSize(const DexFile* pDexFile,
932     const DexAnnotationsDirectoryItem* pAnnoDir)
933 {
934     (void) pDexFile;
935     return pAnnoDir->fieldsSize;
936 }
937 
938 /* return a pointer to the field's annotation set */
dexGetFieldAnnotationSetItem(const DexFile * pDexFile,const DexFieldAnnotationsItem * pItem)939 DEX_INLINE const DexAnnotationSetItem* dexGetFieldAnnotationSetItem(
940     const DexFile* pDexFile, const DexFieldAnnotationsItem* pItem)
941 {
942     return dexGetAnnotationSetItem(pDexFile, pItem->annotationsOff);
943 }
944 
945 /* get the class' method annotation list */
dexGetMethodAnnotations(const DexFile * pDexFile,const DexAnnotationsDirectoryItem * pAnnoDir)946 DEX_INLINE const DexMethodAnnotationsItem* dexGetMethodAnnotations(
947     const DexFile* pDexFile, const DexAnnotationsDirectoryItem* pAnnoDir)
948 {
949     (void) pDexFile;
950     if (pAnnoDir->methodsSize == 0)
951         return NULL;
952 
953     /*
954      * Skip past the header and field annotations to the start of the
955      * method annotations.
956      */
957     const u1* addr = (const u1*) &pAnnoDir[1];
958     addr += pAnnoDir->fieldsSize * sizeof (DexFieldAnnotationsItem);
959     return (const DexMethodAnnotationsItem*) addr;
960 }
961 
962 /* get method annotation list size */
dexGetMethodAnnotationsSize(const DexFile * pDexFile,const DexAnnotationsDirectoryItem * pAnnoDir)963 DEX_INLINE int dexGetMethodAnnotationsSize(const DexFile* pDexFile,
964     const DexAnnotationsDirectoryItem* pAnnoDir)
965 {
966     (void) pDexFile;
967     return pAnnoDir->methodsSize;
968 }
969 
970 /* return a pointer to the method's annotation set */
dexGetMethodAnnotationSetItem(const DexFile * pDexFile,const DexMethodAnnotationsItem * pItem)971 DEX_INLINE const DexAnnotationSetItem* dexGetMethodAnnotationSetItem(
972     const DexFile* pDexFile, const DexMethodAnnotationsItem* pItem)
973 {
974     return dexGetAnnotationSetItem(pDexFile, pItem->annotationsOff);
975 }
976 
977 /* get the class' parameter annotation list */
dexGetParameterAnnotations(const DexFile * pDexFile,const DexAnnotationsDirectoryItem * pAnnoDir)978 DEX_INLINE const DexParameterAnnotationsItem* dexGetParameterAnnotations(
979     const DexFile* pDexFile, const DexAnnotationsDirectoryItem* pAnnoDir)
980 {
981     (void) pDexFile;
982     if (pAnnoDir->parametersSize == 0)
983         return NULL;
984 
985     /*
986      * Skip past the header, field annotations, and method annotations
987      * to the start of the parameter annotations.
988      */
989     const u1* addr = (const u1*) &pAnnoDir[1];
990     addr += pAnnoDir->fieldsSize * sizeof (DexFieldAnnotationsItem);
991     addr += pAnnoDir->methodsSize * sizeof (DexMethodAnnotationsItem);
992     return (const DexParameterAnnotationsItem*) addr;
993 }
994 
995 /* get method annotation list size */
dexGetParameterAnnotationsSize(const DexFile * pDexFile,const DexAnnotationsDirectoryItem * pAnnoDir)996 DEX_INLINE int dexGetParameterAnnotationsSize(const DexFile* pDexFile,
997     const DexAnnotationsDirectoryItem* pAnnoDir)
998 {
999     (void) pDexFile;
1000     return pAnnoDir->parametersSize;
1001 }
1002 
1003 /* return the parameter annotation ref list */
dexGetParameterAnnotationSetRefList(const DexFile * pDexFile,const DexParameterAnnotationsItem * pItem)1004 DEX_INLINE const DexAnnotationSetRefList* dexGetParameterAnnotationSetRefList(
1005     const DexFile* pDexFile, const DexParameterAnnotationsItem* pItem)
1006 {
1007     if (pItem->annotationsOff == 0) {
1008         return NULL;
1009     }
1010     return (const DexAnnotationSetRefList*) (pDexFile->baseAddr + pItem->annotationsOff);
1011 }
1012 
1013 /* get method annotation list size */
dexGetParameterAnnotationSetRefSize(const DexFile * pDexFile,const DexParameterAnnotationsItem * pItem)1014 DEX_INLINE int dexGetParameterAnnotationSetRefSize(const DexFile* pDexFile,
1015     const DexParameterAnnotationsItem* pItem)
1016 {
1017     if (pItem->annotationsOff == 0) {
1018         return 0;
1019     }
1020     return dexGetParameterAnnotationSetRefList(pDexFile, pItem)->size;
1021 }
1022 
1023 /* return the Nth entry from an annotation set ref list */
dexGetParameterAnnotationSetRef(const DexAnnotationSetRefList * pList,u4 idx)1024 DEX_INLINE const DexAnnotationSetRefItem* dexGetParameterAnnotationSetRef(
1025     const DexAnnotationSetRefList* pList, u4 idx)
1026 {
1027     assert(idx < pList->size);
1028     return &pList->list[idx];
1029 }
1030 
1031 /* given a DexAnnotationSetRefItem, return the DexAnnotationSetItem */
dexGetSetRefItemItem(const DexFile * pDexFile,const DexAnnotationSetRefItem * pItem)1032 DEX_INLINE const DexAnnotationSetItem* dexGetSetRefItemItem(
1033     const DexFile* pDexFile, const DexAnnotationSetRefItem* pItem)
1034 {
1035     return dexGetAnnotationSetItem(pDexFile, pItem->annotationsOff);
1036 }
1037 
1038 /* return the Nth annotation offset from a DexAnnotationSetItem */
dexGetAnnotationOff(const DexAnnotationSetItem * pAnnoSet,u4 idx)1039 DEX_INLINE u4 dexGetAnnotationOff(
1040     const DexAnnotationSetItem* pAnnoSet, u4 idx)
1041 {
1042     assert(idx < pAnnoSet->size);
1043     return pAnnoSet->entries[idx];
1044 }
1045 
1046 /* return the Nth annotation item from a DexAnnotationSetItem */
dexGetAnnotationItem(const DexFile * pDexFile,const DexAnnotationSetItem * pAnnoSet,u4 idx)1047 DEX_INLINE const DexAnnotationItem* dexGetAnnotationItem(
1048     const DexFile* pDexFile, const DexAnnotationSetItem* pAnnoSet, u4 idx)
1049 {
1050     u4 offset = dexGetAnnotationOff(pAnnoSet, idx);
1051     if (offset == 0) {
1052         return NULL;
1053     }
1054     return (const DexAnnotationItem*) (pDexFile->baseAddr + offset);
1055 }
1056 
1057 /*
1058  * Get the type descriptor character associated with a given primitive
1059  * type. This returns '\0' if the type is invalid.
1060  */
1061 char dexGetPrimitiveTypeDescriptorChar(PrimitiveType type);
1062 
1063 /*
1064  * Get the type descriptor string associated with a given primitive
1065  * type.
1066  */
1067 const char* dexGetPrimitiveTypeDescriptor(PrimitiveType type);
1068 
1069 /*
1070  * Get the boxed type descriptor string associated with a given
1071  * primitive type. This returns NULL for an invalid type, including
1072  * particularly for type "void". In the latter case, even though there
1073  * is a class Void, there's no such thing as a boxed instance of it.
1074  */
1075 const char* dexGetBoxedTypeDescriptor(PrimitiveType type);
1076 
1077 /*
1078  * Get the primitive type constant from the given descriptor character.
1079  * This returns PRIM_NOT (note: this is a 0) if the character is invalid
1080  * as a primitive type descriptor.
1081  */
1082 PrimitiveType dexGetPrimitiveTypeFromDescriptorChar(char descriptorChar);
1083 
1084 #endif  // LIBDEX_DEXFILE_H_
1085