1 /* 2 * Copyright (C) 2017 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 #pragma once 18 19 #include "common.h" 20 #include "memview.h" 21 #include "dex_bytecode.h" 22 #include "dex_format.h" 23 #include "dex_ir.h" 24 #include "intrusive_list.h" 25 26 #include <assert.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 30 #include <algorithm> 31 #include <cstdint> 32 #include <list> 33 #include <map> 34 #include <memory> 35 #include <utility> 36 #include <vector> 37 38 namespace lir { 39 40 template <class T> 41 using own = std::unique_ptr<T>; 42 43 constexpr dex::u4 kInvalidOffset = dex::u4(-1); 44 45 struct Bytecode; 46 struct PackedSwitchPayload; 47 struct SparseSwitchPayload; 48 struct ArrayData; 49 struct Label; 50 struct TryBlockBegin; 51 struct TryBlockEnd; 52 struct Const32; 53 struct Const64; 54 struct VReg; 55 struct VRegPair; 56 struct VRegList; 57 struct VRegRange; 58 struct CodeLocation; 59 struct String; 60 struct Type; 61 struct Field; 62 struct Method; 63 struct DbgInfoHeader; 64 struct LineNumber; 65 struct DbgInfoAnnotation; 66 67 // Code IR visitor interface 68 class Visitor { 69 public: 70 Visitor() = default; 71 virtual ~Visitor() = default; 72 73 Visitor(const Visitor&) = delete; 74 Visitor& operator=(const Visitor&) = delete; 75 76 // instructions 77 virtual bool Visit(Bytecode* bytecode) { return false; } 78 virtual bool Visit(PackedSwitchPayload* packed_switch) { return false; } 79 virtual bool Visit(SparseSwitchPayload* sparse_switch) { return false; } 80 virtual bool Visit(ArrayData* array_data) { return false; } 81 virtual bool Visit(Label* label) { return false; } 82 virtual bool Visit(DbgInfoHeader* dbg_header) { return false; } 83 virtual bool Visit(DbgInfoAnnotation* dbg_annotation) { return false; } 84 virtual bool Visit(TryBlockBegin* try_begin) { return false; } 85 virtual bool Visit(TryBlockEnd* try_end) { return false; } 86 87 // operands 88 virtual bool Visit(CodeLocation* location) { return false; } 89 virtual bool Visit(Const32* const32) { return false; } 90 virtual bool Visit(Const64* const64) { return false; } 91 virtual bool Visit(VReg* vreg) { return false; } 92 virtual bool Visit(VRegPair* vreg_pair) { return false; } 93 virtual bool Visit(VRegList* vreg_list) { return false; } 94 virtual bool Visit(VRegRange* vreg_range) { return false; } 95 virtual bool Visit(String* string) { return false; } 96 virtual bool Visit(Type* type) { return false; } 97 virtual bool Visit(Field* field) { return false; } 98 virtual bool Visit(Method* method) { return false; } 99 virtual bool Visit(LineNumber* line) { return false; } 100 }; 101 102 // The root of the polymorphic code IR nodes hierarchy 103 // 104 // NOTE: in general it's possible to "reuse" code IR nodes 105 // (ie. refcount > 1) although extra care is required since 106 // modifications to shared nodes will be visible in multiple places 107 // (notable exception: instruction nodes can't be reused) 108 // 109 struct Node { 110 Node() = default; 111 virtual ~Node() = default; 112 113 Node(const Node&) = delete; 114 Node& operator=(const Node&) = delete; 115 116 virtual bool Accept(Visitor* visitor) { return false; } 117 118 template<class T> 119 bool IsA() const { 120 return dynamic_cast<const T*>(this) != nullptr; 121 } 122 }; 123 124 struct Operand : public Node {}; 125 126 struct Const32 : public Operand { 127 union { 128 dex::s4 s4_value; 129 dex::u4 u4_value; 130 float float_value; 131 } u; 132 133 Const32(dex::u4 value) { u.u4_value = value; } 134 135 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 136 }; 137 138 struct Const64 : public Operand { 139 union { 140 dex::s8 s8_value; 141 dex::u8 u8_value; 142 double double_value; 143 } u; 144 145 Const64(dex::u8 value) { u.u8_value = value; } 146 147 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 148 }; 149 150 struct VReg : public Operand { 151 dex::u4 reg; 152 153 VReg(dex::u4 reg) : reg(reg) {} 154 155 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 156 }; 157 158 struct VRegPair : public Operand { 159 dex::u4 base_reg; 160 161 VRegPair(dex::u4 base_reg) : base_reg(base_reg) {} 162 163 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 164 }; 165 166 struct VRegList : public Operand { 167 std::vector<dex::u4> registers; 168 169 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 170 }; 171 172 struct VRegRange : public Operand { 173 dex::u4 base_reg; 174 int count; 175 176 VRegRange(dex::u4 base_reg, int count) : base_reg(base_reg), count(count) {} 177 178 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 179 }; 180 181 struct IndexedOperand : public Operand { 182 dex::u4 index; 183 184 IndexedOperand(dex::u4 index) : index(index) {} 185 }; 186 187 struct String : public IndexedOperand { 188 ir::String* ir_string; 189 190 String(ir::String* ir_string, dex::u4 index) : IndexedOperand(index), ir_string(ir_string) {} 191 192 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 193 }; 194 195 struct Type : public IndexedOperand { 196 ir::Type* ir_type; 197 198 Type(ir::Type* ir_type, dex::u4 index) : IndexedOperand(index), ir_type(ir_type) {} 199 200 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 201 }; 202 203 struct Field : public IndexedOperand { 204 ir::FieldDecl* ir_field; 205 206 Field(ir::FieldDecl* ir_field, dex::u4 index) : IndexedOperand(index), ir_field(ir_field) {} 207 208 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 209 }; 210 211 struct Method : public IndexedOperand { 212 ir::MethodDecl* ir_method; 213 214 Method(ir::MethodDecl* ir_method, dex::u4 index) : IndexedOperand(index), ir_method(ir_method) {} 215 216 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 217 }; 218 219 struct CodeLocation : public Operand { 220 Label* label; 221 222 CodeLocation(Label* label) : label(label) {} 223 224 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 225 }; 226 227 // Code IR is a linked list of Instructions 228 struct Instruction : public Node { 229 // absolute offset from the start of the method 230 dex::u4 offset = 0; 231 232 Instruction* prev = nullptr; 233 Instruction* next = nullptr; 234 }; 235 236 using InstructionsList = slicer::IntrusiveList<Instruction>; 237 238 struct Bytecode : public Instruction { 239 dex::Opcode opcode = dex::OP_NOP; 240 std::vector<Operand*> operands; 241 242 template<class T> 243 T* CastOperand(int index) const { 244 T* operand = dynamic_cast<T*>(operands[index]); 245 SLICER_CHECK(operand != nullptr); 246 return operand; 247 } 248 249 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 250 }; 251 252 struct PackedSwitchPayload : public Instruction { 253 dex::s4 first_key = 0; 254 std::vector<Label*> targets; 255 256 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 257 }; 258 259 struct SparseSwitchPayload : public Instruction { 260 struct SwitchCase { 261 dex::s4 key = 0; 262 Label* target = nullptr; 263 }; 264 265 std::vector<SwitchCase> switch_cases; 266 267 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 268 }; 269 270 struct ArrayData : public Instruction { 271 slicer::MemView data; 272 273 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 274 }; 275 276 struct Label : public Instruction { 277 int id = 0; 278 int refCount = 0; 279 bool aligned = false; 280 281 Label(dex::u4 offset) { this->offset = offset; } 282 283 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 284 }; 285 286 struct TryBlockBegin : public Instruction { 287 int id = 0; 288 289 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 290 }; 291 292 struct CatchHandler { 293 ir::Type* ir_type = nullptr; 294 Label* label = nullptr; 295 }; 296 297 struct TryBlockEnd : public Instruction { 298 TryBlockBegin* try_begin = nullptr; 299 std::vector<CatchHandler> handlers; 300 Label* catch_all = nullptr; 301 302 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 303 }; 304 305 struct DbgInfoHeader : public Instruction { 306 std::vector<ir::String*> param_names; 307 308 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 309 }; 310 311 struct LineNumber : public Operand { 312 int line = 0; 313 314 LineNumber(int line) : line(line) { 315 SLICER_WEAK_CHECK(line > 0); 316 } 317 318 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 319 }; 320 321 struct DbgInfoAnnotation : public Instruction { 322 dex::u1 dbg_opcode = 0; 323 std::vector<Operand*> operands; 324 325 DbgInfoAnnotation(dex::u1 dbg_opcode) : dbg_opcode(dbg_opcode) {} 326 327 template<class T> 328 T* CastOperand(int index) const { 329 T* operand = dynamic_cast<T*>(operands[index]); 330 SLICER_CHECK(operand != nullptr); 331 return operand; 332 } 333 334 virtual bool Accept(Visitor* visitor) override { return visitor->Visit(this); } 335 }; 336 337 // Code IR container and manipulation interface 338 struct CodeIr { 339 // linked list of the method's instructions 340 InstructionsList instructions; 341 342 ir::EncodedMethod* ir_method = nullptr; 343 std::shared_ptr<ir::DexFile> dex_ir; 344 345 public: 346 CodeIr(ir::EncodedMethod* ir_method, std::shared_ptr<ir::DexFile> dex_ir) 347 : ir_method(ir_method), dex_ir(dex_ir) { 348 Dissasemble(); 349 } 350 351 // No copy/move semantics 352 CodeIr(const CodeIr&) = delete; 353 CodeIr& operator=(const CodeIr&) = delete; 354 355 void Assemble(); 356 357 void Accept(Visitor* visitor) { 358 for (auto instr : instructions) { 359 instr->Accept(visitor); 360 } 361 } 362 363 template <class T, class... Args> 364 T* Alloc(Args&&... args) { 365 auto p = new T(std::forward<Args>(args)...); 366 nodes_.push_back(own<T>(p)); 367 return p; 368 } 369 370 private: 371 void Dissasemble(); 372 void DissasembleBytecode(const ir::Code* ir_code); 373 void DissasembleTryBlocks(const ir::Code* ir_code); 374 void DissasembleDebugInfo(const ir::DebugInfo* ir_debug_info); 375 376 void FixupSwitches(); 377 void FixupPackedSwitch(PackedSwitchPayload* instr, dex::u4 base_offset, const dex::u2* ptr); 378 void FixupSparseSwitch(SparseSwitchPayload* instr, dex::u4 base_offset, const dex::u2* ptr); 379 380 SparseSwitchPayload* DecodeSparseSwitch(const dex::u2* /*ptr*/, dex::u4 offset); 381 PackedSwitchPayload* DecodePackedSwitch(const dex::u2* /*ptr*/, dex::u4 offset); 382 ArrayData* DecodeArrayData(const dex::u2* ptr, dex::u4 offset); 383 Bytecode* DecodeBytecode(const dex::u2* ptr, dex::u4 offset); 384 385 IndexedOperand* GetIndexedOperand(dex::InstructionIndexType index_type, dex::u4 index); 386 387 Type* GetType(dex::u4 index); 388 String* GetString(dex::u4 index); 389 Label* GetLabel(dex::u4 offset); 390 391 Operand* GetRegA(const dex::Instruction& dex_instr); 392 Operand* GetRegB(const dex::Instruction& dex_instr); 393 Operand* GetRegC(const dex::Instruction& dex_instr); 394 395 private: 396 // the "master index" of all the LIR owned nodes 397 std::vector<own<Node>> nodes_; 398 399 // data structures for fixing up switch payloads 400 struct PackedSwitchFixup { 401 PackedSwitchPayload* instr = nullptr; 402 dex::u4 base_offset = kInvalidOffset; 403 }; 404 405 struct SparseSwitchFixup { 406 SparseSwitchPayload* instr = nullptr; 407 dex::u4 base_offset = kInvalidOffset; 408 }; 409 410 // used during bytecode raising 411 std::map<dex::u4, Label*> labels_; 412 std::map<dex::u4, PackedSwitchFixup> packed_switches_; 413 std::map<dex::u4, SparseSwitchFixup> sparse_switches_; 414 415 // extra instructions/annotations created during raising 416 // (intended to be merged in with the main instruction 417 // list at end of the IR raising phase) 418 std::vector<TryBlockBegin*> try_begins_; 419 std::vector<TryBlockEnd*> try_ends_; 420 std::vector<Instruction*> dbg_annotations_; 421 }; 422 423 } // namespace lir 424