1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
|
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// TODO: Dex helpers have ART specific APIs, we may want to refactor these for use in dexdump.
#ifndef ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_
#define ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_
#include <android-base/logging.h>
#include "dex_instruction.h"
namespace art {
namespace dex {
struct CodeItem;
struct TryItem;
} // namespace dex
class ArtMethod;
class DexFile;
class DexInstructionIterator;
template <typename Iter>
class IterationRange;
// Abstracts accesses to the instruction fields of code items for CompactDexFile and
// StandardDexFile.
class CodeItemInstructionAccessor {
public:
ALWAYS_INLINE CodeItemInstructionAccessor(const DexFile& dex_file,
const dex::CodeItem* code_item);
ALWAYS_INLINE explicit CodeItemInstructionAccessor(ArtMethod* method);
ALWAYS_INLINE DexInstructionIterator begin() const;
ALWAYS_INLINE DexInstructionIterator end() const;
IterationRange<DexInstructionIterator> InstructionsFrom(uint32_t start_dex_pc) const;
uint32_t InsnsSizeInCodeUnits() const {
return insns_size_in_code_units_;
}
uint32_t InsnsSizeInBytes() const {
static constexpr uint32_t kCodeUnitSizeInBytes = 2u;
return insns_size_in_code_units_ * kCodeUnitSizeInBytes;
}
const uint16_t* Insns() const {
return insns_;
}
// Return the instruction for a dex pc.
const Instruction& InstructionAt(uint32_t dex_pc) const {
DCHECK_LT(dex_pc, InsnsSizeInCodeUnits());
return *Instruction::At(insns_ + dex_pc);
}
// Return true if the accessor has a code item.
bool HasCodeItem() const {
return Insns() != nullptr;
}
protected:
CodeItemInstructionAccessor() = default;
ALWAYS_INLINE void Init(uint32_t insns_size_in_code_units, const uint16_t* insns);
ALWAYS_INLINE void Init(const DexFile& dex_file, const dex::CodeItem* code_item);
template <typename DexFileCodeItemType>
ALWAYS_INLINE void Init(const DexFileCodeItemType& code_item);
private:
// size of the insns array, in 2 byte code units. 0 if there is no code item.
uint32_t insns_size_in_code_units_ = 0;
// Pointer to the instructions, null if there is no code item.
const uint16_t* insns_ = nullptr;
};
// Abstracts accesses to code item fields other than debug info for CompactDexFile and
// StandardDexFile.
class CodeItemDataAccessor : public CodeItemInstructionAccessor {
public:
ALWAYS_INLINE CodeItemDataAccessor(const DexFile& dex_file, const dex::CodeItem* code_item);
uint16_t RegistersSize() const {
return registers_size_;
}
uint16_t InsSize() const {
return ins_size_;
}
uint16_t OutsSize() const {
return outs_size_;
}
uint16_t TriesSize() const {
return tries_size_;
}
IterationRange<const dex::TryItem*> TryItems() const;
const uint8_t* GetCatchHandlerData(size_t offset = 0) const;
const dex::TryItem* FindTryItem(uint32_t try_dex_pc) const;
inline const void* CodeItemDataEnd() const;
protected:
CodeItemDataAccessor() = default;
ALWAYS_INLINE void Init(const DexFile& dex_file, const dex::CodeItem* code_item);
template <typename DexFileCodeItemType>
ALWAYS_INLINE void Init(const DexFileCodeItemType& code_item);
private:
// Fields mirrored from the dex/cdex code item.
uint16_t registers_size_;
uint16_t ins_size_;
uint16_t outs_size_;
uint16_t tries_size_;
};
// Abstract accesses to code item data including debug info offset. More heavy weight than the other
// helpers.
class CodeItemDebugInfoAccessor : public CodeItemDataAccessor {
public:
CodeItemDebugInfoAccessor() = default;
// Initialize with an existing offset.
ALWAYS_INLINE CodeItemDebugInfoAccessor(const DexFile& dex_file,
const dex::CodeItem* code_item,
uint32_t dex_method_index) {
Init(dex_file, code_item, dex_method_index);
}
ALWAYS_INLINE void Init(const DexFile& dex_file,
const dex::CodeItem* code_item,
uint32_t dex_method_index);
ALWAYS_INLINE explicit CodeItemDebugInfoAccessor(ArtMethod* method);
uint32_t DebugInfoOffset() const {
return debug_info_offset_;
}
template<typename NewLocalVisitor>
bool DecodeDebugLocalInfo(bool is_static,
uint32_t method_idx,
const NewLocalVisitor& new_local) const;
// Visit each parameter in the debug information. Returns the line number.
// The argument of the Visitor is dex::StringIndex.
template <typename Visitor>
uint32_t VisitParameterNames(const Visitor& visitor) const;
template <typename Visitor>
bool DecodeDebugPositionInfo(const Visitor& visitor) const;
bool GetLineNumForPc(const uint32_t pc, uint32_t* line_num) const;
protected:
template <typename DexFileCodeItemType>
ALWAYS_INLINE void Init(const DexFileCodeItemType& code_item, uint32_t dex_method_index);
private:
const DexFile* dex_file_ = nullptr;
uint32_t debug_info_offset_ = 0u;
};
} // namespace art
#endif // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_
|