1 /*
2  * Copyright (C) 2012 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 #ifndef ART_RUNTIME_VERIFIER_DEX_GC_MAP_H_
18 #define ART_RUNTIME_VERIFIER_DEX_GC_MAP_H_
19 
20 #include <stdint.h>
21 
22 #include "base/logging.h"
23 #include "base/macros.h"
24 
25 namespace art {
26 namespace verifier {
27 
28 /*
29  * Format enumeration for RegisterMap data area.
30  */
31 enum RegisterMapFormat {
32   kRegMapFormatUnknown = 0,
33   kRegMapFormatNone = 1,       // Indicates no map data follows.
34   kRegMapFormatCompact8 = 2,   // Compact layout, 8-bit addresses.
35   kRegMapFormatCompact16 = 3,  // Compact layout, 16-bit addresses.
36 };
37 
38 // Lightweight wrapper for Dex PC to reference bit maps.
39 class DexPcToReferenceMap {
40  public:
DexPcToReferenceMap(const uint8_t * data)41   explicit DexPcToReferenceMap(const uint8_t* data) : data_(data) {
42     CHECK(data_ != NULL);
43   }
44 
45   // The total size of the reference bit map including header.
RawSize()46   size_t RawSize() const {
47     return EntryWidth() * NumEntries() + 4u /* header */;
48   }
49 
50   // The number of entries in the table
NumEntries()51   size_t NumEntries() const {
52     return GetData()[2] | (GetData()[3] << 8);
53   }
54 
55   // Get the Dex PC at the given index
GetDexPc(size_t index)56   uint16_t GetDexPc(size_t index) const {
57     size_t entry_offset = index * EntryWidth();
58     if (DexPcWidth() == 1) {
59       return Table()[entry_offset];
60     } else {
61       return Table()[entry_offset] | (Table()[entry_offset + 1] << 8);
62     }
63   }
64 
65   // Return address of bitmap encoding what are live references
GetBitMap(size_t index)66   const uint8_t* GetBitMap(size_t index) const {
67     size_t entry_offset = index * EntryWidth();
68     return &Table()[entry_offset + DexPcWidth()];
69   }
70 
71   // Find the bitmap associated with the given dex pc
72   const uint8_t* FindBitMap(uint16_t dex_pc, bool error_if_not_present = true) const;
73 
74   // The number of bytes used to encode registers
RegWidth()75   size_t RegWidth() const {
76     return GetData()[1] | ((GetData()[0] & ~kRegMapFormatMask) << kRegMapFormatShift);
77   }
78 
79  private:
80   // Table of num_entries * (dex pc, bitmap)
Table()81   const uint8_t* Table() const {
82     return GetData() + 4;
83   }
84 
85   // The format of the table of the PCs for the table
Format()86   RegisterMapFormat Format() const {
87     return static_cast<RegisterMapFormat>(GetData()[0] & kRegMapFormatMask);
88   }
89 
90   // Number of bytes used to encode a dex pc
DexPcWidth()91   size_t DexPcWidth() const {
92     RegisterMapFormat format = Format();
93     switch (format) {
94       case kRegMapFormatCompact8:
95         return 1;
96       case kRegMapFormatCompact16:
97         return 2;
98       default:
99         LOG(FATAL) << "Invalid format " << static_cast<int>(format);
100         return -1;
101     }
102   }
103 
104   // The width of an entry in the table
EntryWidth()105   size_t EntryWidth() const {
106     return DexPcWidth() + RegWidth();
107   }
108 
GetData()109   const uint8_t* GetData() const {
110     return data_;
111   }
112 
113   static const int kRegMapFormatShift = 5;
114   static const uint8_t kRegMapFormatMask = 0x7;
115 
116   const uint8_t* const data_;  // The header and table data
117 };
118 
119 }  // namespace verifier
120 }  // namespace art
121 
122 #endif  // ART_RUNTIME_VERIFIER_DEX_GC_MAP_H_
123