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