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 #include "slicer/common.h" 18 #include "slicer/debuginfo_encoder.h" 19 #include "slicer/chronometer.h" 20 21 #include <assert.h> 22 23 namespace lir { 24 Visit(DbgInfoHeader * dbg_header)25bool DebugInfoEncoder::Visit(DbgInfoHeader* dbg_header) { 26 assert(param_names_ == nullptr); 27 param_names_ = &dbg_header->param_names; 28 return true; 29 } 30 Visit(DbgInfoAnnotation * dbg_annotation)31bool DebugInfoEncoder::Visit(DbgInfoAnnotation* dbg_annotation) { 32 // keep the address in sync 33 if (last_address_ != dbg_annotation->offset) { 34 SLICER_CHECK(dbg_annotation->offset > last_address_); 35 dbginfo_.Push<dex::u1>(dex::DBG_ADVANCE_PC); 36 dbginfo_.PushULeb128(dbg_annotation->offset - last_address_); 37 last_address_ = dbg_annotation->offset; 38 } 39 40 // encode the annotation itself 41 switch (dbg_annotation->dbg_opcode) { 42 case dex::DBG_ADVANCE_LINE: { 43 // DBG_ANDVANCE_LINE is used a bit differently in the code IR 44 // vs the .dex image: the code IR uses it exclusively for source 45 // location (the .line directive) while .dex format uses it to 46 // advance the "line" register without emitting a "position entry" 47 int line = dbg_annotation->CastOperand<LineNumber>(0)->line; 48 if (line_start_ == 0) { 49 // it's not perfectly clear from the .dex specification 50 // if initial line == 0 is valid, but a number of existing 51 // .dex files do this so we have to support it 52 SLICER_CHECK(line >= 0); 53 line_start_ = line; 54 } else { 55 SLICER_WEAK_CHECK(line > 0); 56 int delta = line - last_line_; 57 int adj_opcode = delta - dex::DBG_LINE_BASE; 58 // out of range for special opcode? 59 if (adj_opcode < 0 || adj_opcode >= dex::DBG_LINE_RANGE) { 60 dbginfo_.Push<dex::u1>(dex::DBG_ADVANCE_LINE); 61 dbginfo_.PushSLeb128(delta); 62 adj_opcode = -dex::DBG_LINE_BASE; 63 } 64 assert(adj_opcode >= 0 && dex::DBG_FIRST_SPECIAL + adj_opcode < 256); 65 dex::u1 special_opcode = dex::DBG_FIRST_SPECIAL + adj_opcode; 66 dbginfo_.Push<dex::u1>(special_opcode); 67 } 68 last_line_ = line; 69 } break; 70 71 case dex::DBG_START_LOCAL: { 72 auto reg = dbg_annotation->CastOperand<VReg>(0)->reg; 73 auto name_index = dbg_annotation->CastOperand<String>(1)->index; 74 auto type_index = dbg_annotation->CastOperand<Type>(2)->index; 75 dbginfo_.Push<dex::u1>(dex::DBG_START_LOCAL); 76 dbginfo_.PushULeb128(reg); 77 dbginfo_.PushULeb128(name_index + 1); 78 dbginfo_.PushULeb128(type_index + 1); 79 } break; 80 81 case dex::DBG_START_LOCAL_EXTENDED: { 82 auto reg = dbg_annotation->CastOperand<VReg>(0)->reg; 83 auto name_index = dbg_annotation->CastOperand<String>(1)->index; 84 auto type_index = dbg_annotation->CastOperand<Type>(2)->index; 85 auto sig_index = dbg_annotation->CastOperand<String>(3)->index; 86 dbginfo_.Push<dex::u1>(dex::DBG_START_LOCAL_EXTENDED); 87 dbginfo_.PushULeb128(reg); 88 dbginfo_.PushULeb128(name_index + 1); 89 dbginfo_.PushULeb128(type_index + 1); 90 dbginfo_.PushULeb128(sig_index + 1); 91 } break; 92 93 case dex::DBG_END_LOCAL: 94 case dex::DBG_RESTART_LOCAL: { 95 auto reg = dbg_annotation->CastOperand<VReg>(0)->reg; 96 dbginfo_.Push<dex::u1>(dbg_annotation->dbg_opcode); 97 dbginfo_.PushULeb128(reg); 98 } break; 99 100 case dex::DBG_SET_PROLOGUE_END: 101 case dex::DBG_SET_EPILOGUE_BEGIN: 102 dbginfo_.Push<dex::u1>(dbg_annotation->dbg_opcode); 103 break; 104 105 case dex::DBG_SET_FILE: { 106 auto file_name = dbg_annotation->CastOperand<String>(0); 107 if (file_name->ir_string != source_file_) { 108 source_file_ = file_name->ir_string; 109 dbginfo_.Push<dex::u1>(dex::DBG_SET_FILE); 110 dbginfo_.PushULeb128(file_name->index + 1); 111 } 112 } break; 113 114 default: 115 SLICER_FATAL("Unexpected debug info opcode: 0x%02x", dbg_annotation->dbg_opcode); 116 } 117 118 return true; 119 } 120 Encode(ir::EncodedMethod * ir_method,std::shared_ptr<ir::DexFile> dex_ir)121void DebugInfoEncoder::Encode(ir::EncodedMethod* ir_method, std::shared_ptr<ir::DexFile> dex_ir) { 122 auto ir_debug_info = ir_method->code->debug_info; 123 124 SLICER_CHECK(dbginfo_.empty()); 125 SLICER_CHECK(param_names_ == nullptr); 126 SLICER_CHECK(line_start_ == 0); 127 SLICER_CHECK(last_line_ == 0); 128 SLICER_CHECK(last_address_ == 0); 129 SLICER_CHECK(source_file_ == nullptr); 130 131 // generate new debug info 132 source_file_ = ir_method->decl->parent->class_def->source_file; 133 for (auto instr : instructions_) { 134 instr->Accept(this); 135 } 136 dbginfo_.Push<dex::u1>(dex::DBG_END_SEQUENCE); 137 dbginfo_.Seal(1); 138 139 SLICER_CHECK(!dbginfo_.empty()); 140 141 // update ir::DebugInfo 142 ir_debug_info->line_start = line_start_; 143 ir_debug_info->data = slicer::MemView(dbginfo_.data(), dbginfo_.size()); 144 145 if (param_names_ != nullptr) { 146 ir_debug_info->param_names = *param_names_; 147 } else { 148 ir_debug_info->param_names = {}; 149 } 150 151 // attach the debug info buffer to the dex IR 152 dex_ir->AttachBuffer(std::move(dbginfo_)); 153 } 154 155 } // namespace lir 156