1*f0dffb02SXin Li /*
2*f0dffb02SXin Li * Copyright (C) 2017 The Android Open Source Project
3*f0dffb02SXin Li *
4*f0dffb02SXin Li * Licensed under the Apache License, Version 2.0 (the "License");
5*f0dffb02SXin Li * you may not use this file except in compliance with the License.
6*f0dffb02SXin Li * You may obtain a copy of the License at
7*f0dffb02SXin Li *
8*f0dffb02SXin Li * http://www.apache.org/licenses/LICENSE-2.0
9*f0dffb02SXin Li *
10*f0dffb02SXin Li * Unless required by applicable law or agreed to in writing, software
11*f0dffb02SXin Li * distributed under the License is distributed on an "AS IS" BASIS,
12*f0dffb02SXin Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*f0dffb02SXin Li * See the License for the specific language governing permissions and
14*f0dffb02SXin Li * limitations under the License.
15*f0dffb02SXin Li */
16*f0dffb02SXin Li
17*f0dffb02SXin Li #include "slicer/debuginfo_encoder.h"
18*f0dffb02SXin Li
19*f0dffb02SXin Li #include "slicer/common.h"
20*f0dffb02SXin Li
21*f0dffb02SXin Li #include <assert.h>
22*f0dffb02SXin Li #include <sstream>
23*f0dffb02SXin Li #include <iomanip>
24*f0dffb02SXin Li
25*f0dffb02SXin Li
26*f0dffb02SXin Li namespace lir {
27*f0dffb02SXin Li
Visit(DbgInfoHeader * dbg_header)28*f0dffb02SXin Li bool DebugInfoEncoder::Visit(DbgInfoHeader* dbg_header) {
29*f0dffb02SXin Li assert(param_names_ == nullptr);
30*f0dffb02SXin Li param_names_ = &dbg_header->param_names;
31*f0dffb02SXin Li return true;
32*f0dffb02SXin Li }
33*f0dffb02SXin Li
Visit(DbgInfoAnnotation * dbg_annotation)34*f0dffb02SXin Li bool DebugInfoEncoder::Visit(DbgInfoAnnotation* dbg_annotation) {
35*f0dffb02SXin Li // keep the address in sync
36*f0dffb02SXin Li if (last_address_ != dbg_annotation->offset) {
37*f0dffb02SXin Li SLICER_CHECK_GT(dbg_annotation->offset, last_address_);
38*f0dffb02SXin Li dbginfo_.Push<dex::u1>(dex::DBG_ADVANCE_PC);
39*f0dffb02SXin Li dbginfo_.PushULeb128(dbg_annotation->offset - last_address_);
40*f0dffb02SXin Li last_address_ = dbg_annotation->offset;
41*f0dffb02SXin Li }
42*f0dffb02SXin Li
43*f0dffb02SXin Li // encode the annotation itself
44*f0dffb02SXin Li switch (dbg_annotation->dbg_opcode) {
45*f0dffb02SXin Li case dex::DBG_ADVANCE_LINE: {
46*f0dffb02SXin Li // DBG_ANDVANCE_LINE is used a bit differently in the code IR
47*f0dffb02SXin Li // vs the .dex image: the code IR uses it exclusively for source
48*f0dffb02SXin Li // location (the .line directive) while .dex format uses it to
49*f0dffb02SXin Li // advance the "line" register without emitting a "position entry"
50*f0dffb02SXin Li int line = dbg_annotation->CastOperand<LineNumber>(0)->line;
51*f0dffb02SXin Li if (line_start_ == 0) {
52*f0dffb02SXin Li // it's not perfectly clear from the .dex specification
53*f0dffb02SXin Li // if initial line == 0 is valid, but a number of existing
54*f0dffb02SXin Li // .dex files do this so we have to support it
55*f0dffb02SXin Li SLICER_CHECK_GE(line, 0);
56*f0dffb02SXin Li line_start_ = line;
57*f0dffb02SXin Li } else {
58*f0dffb02SXin Li SLICER_WEAK_CHECK(line >= 0);
59*f0dffb02SXin Li int delta = line - last_line_;
60*f0dffb02SXin Li int adj_opcode = delta - dex::DBG_LINE_BASE;
61*f0dffb02SXin Li // out of range for special opcode?
62*f0dffb02SXin Li if (adj_opcode < 0 || adj_opcode >= dex::DBG_LINE_RANGE) {
63*f0dffb02SXin Li dbginfo_.Push<dex::u1>(dex::DBG_ADVANCE_LINE);
64*f0dffb02SXin Li dbginfo_.PushSLeb128(delta);
65*f0dffb02SXin Li adj_opcode = -dex::DBG_LINE_BASE;
66*f0dffb02SXin Li }
67*f0dffb02SXin Li assert(adj_opcode >= 0 && dex::DBG_FIRST_SPECIAL + adj_opcode < 256);
68*f0dffb02SXin Li dex::u1 special_opcode = dex::DBG_FIRST_SPECIAL + adj_opcode;
69*f0dffb02SXin Li dbginfo_.Push<dex::u1>(special_opcode);
70*f0dffb02SXin Li }
71*f0dffb02SXin Li last_line_ = line;
72*f0dffb02SXin Li } break;
73*f0dffb02SXin Li
74*f0dffb02SXin Li case dex::DBG_START_LOCAL: {
75*f0dffb02SXin Li auto reg = dbg_annotation->CastOperand<VReg>(0)->reg;
76*f0dffb02SXin Li auto name_index = dbg_annotation->CastOperand<String>(1)->index;
77*f0dffb02SXin Li auto type_index = dbg_annotation->CastOperand<Type>(2)->index;
78*f0dffb02SXin Li dbginfo_.Push<dex::u1>(dex::DBG_START_LOCAL);
79*f0dffb02SXin Li dbginfo_.PushULeb128(reg);
80*f0dffb02SXin Li dbginfo_.PushULeb128(name_index + 1);
81*f0dffb02SXin Li dbginfo_.PushULeb128(type_index + 1);
82*f0dffb02SXin Li } break;
83*f0dffb02SXin Li
84*f0dffb02SXin Li case dex::DBG_START_LOCAL_EXTENDED: {
85*f0dffb02SXin Li auto reg = dbg_annotation->CastOperand<VReg>(0)->reg;
86*f0dffb02SXin Li auto name_index = dbg_annotation->CastOperand<String>(1)->index;
87*f0dffb02SXin Li auto type_index = dbg_annotation->CastOperand<Type>(2)->index;
88*f0dffb02SXin Li auto sig_index = dbg_annotation->CastOperand<String>(3)->index;
89*f0dffb02SXin Li dbginfo_.Push<dex::u1>(dex::DBG_START_LOCAL_EXTENDED);
90*f0dffb02SXin Li dbginfo_.PushULeb128(reg);
91*f0dffb02SXin Li dbginfo_.PushULeb128(name_index + 1);
92*f0dffb02SXin Li dbginfo_.PushULeb128(type_index + 1);
93*f0dffb02SXin Li dbginfo_.PushULeb128(sig_index + 1);
94*f0dffb02SXin Li } break;
95*f0dffb02SXin Li
96*f0dffb02SXin Li case dex::DBG_END_LOCAL:
97*f0dffb02SXin Li case dex::DBG_RESTART_LOCAL: {
98*f0dffb02SXin Li auto reg = dbg_annotation->CastOperand<VReg>(0)->reg;
99*f0dffb02SXin Li dbginfo_.Push<dex::u1>(dbg_annotation->dbg_opcode);
100*f0dffb02SXin Li dbginfo_.PushULeb128(reg);
101*f0dffb02SXin Li } break;
102*f0dffb02SXin Li
103*f0dffb02SXin Li case dex::DBG_SET_PROLOGUE_END:
104*f0dffb02SXin Li case dex::DBG_SET_EPILOGUE_BEGIN:
105*f0dffb02SXin Li dbginfo_.Push<dex::u1>(dbg_annotation->dbg_opcode);
106*f0dffb02SXin Li break;
107*f0dffb02SXin Li
108*f0dffb02SXin Li case dex::DBG_SET_FILE: {
109*f0dffb02SXin Li auto file_name = dbg_annotation->CastOperand<String>(0);
110*f0dffb02SXin Li if (file_name->ir_string != source_file_) {
111*f0dffb02SXin Li source_file_ = file_name->ir_string;
112*f0dffb02SXin Li dbginfo_.Push<dex::u1>(dex::DBG_SET_FILE);
113*f0dffb02SXin Li dbginfo_.PushULeb128(file_name->index + 1);
114*f0dffb02SXin Li }
115*f0dffb02SXin Li } break;
116*f0dffb02SXin Li
117*f0dffb02SXin Li default: {
118*f0dffb02SXin Li std::stringstream ss;
119*f0dffb02SXin Li ss << "Unexpected debug info opcode: " << dbg_annotation->dbg_opcode;
120*f0dffb02SXin Li SLICER_FATAL(ss.str());
121*f0dffb02SXin Li }
122*f0dffb02SXin Li }
123*f0dffb02SXin Li
124*f0dffb02SXin Li return true;
125*f0dffb02SXin Li }
126*f0dffb02SXin Li
Encode(ir::EncodedMethod * ir_method,std::shared_ptr<ir::DexFile> dex_ir)127*f0dffb02SXin Li void DebugInfoEncoder::Encode(ir::EncodedMethod* ir_method, std::shared_ptr<ir::DexFile> dex_ir) {
128*f0dffb02SXin Li auto ir_debug_info = ir_method->code->debug_info;
129*f0dffb02SXin Li
130*f0dffb02SXin Li SLICER_CHECK(dbginfo_.empty());
131*f0dffb02SXin Li SLICER_CHECK_EQ(param_names_, nullptr);
132*f0dffb02SXin Li SLICER_CHECK_EQ(line_start_, 0);
133*f0dffb02SXin Li SLICER_CHECK_EQ(last_line_, 0);
134*f0dffb02SXin Li SLICER_CHECK_EQ(last_address_, 0);
135*f0dffb02SXin Li SLICER_CHECK_EQ(source_file_, nullptr);
136*f0dffb02SXin Li
137*f0dffb02SXin Li // generate new debug info
138*f0dffb02SXin Li source_file_ = ir_method->decl->parent->class_def->source_file;
139*f0dffb02SXin Li for (auto instr : instructions_) {
140*f0dffb02SXin Li instr->Accept(this);
141*f0dffb02SXin Li }
142*f0dffb02SXin Li dbginfo_.Push<dex::u1>(dex::DBG_END_SEQUENCE);
143*f0dffb02SXin Li dbginfo_.Seal(1);
144*f0dffb02SXin Li
145*f0dffb02SXin Li SLICER_CHECK(!dbginfo_.empty());
146*f0dffb02SXin Li
147*f0dffb02SXin Li // update ir::DebugInfo
148*f0dffb02SXin Li ir_debug_info->line_start = line_start_;
149*f0dffb02SXin Li ir_debug_info->data = slicer::MemView(dbginfo_.data(), dbginfo_.size());
150*f0dffb02SXin Li
151*f0dffb02SXin Li if (param_names_ != nullptr) {
152*f0dffb02SXin Li ir_debug_info->param_names = *param_names_;
153*f0dffb02SXin Li } else {
154*f0dffb02SXin Li ir_debug_info->param_names = {};
155*f0dffb02SXin Li }
156*f0dffb02SXin Li
157*f0dffb02SXin Li // attach the debug info buffer to the dex IR
158*f0dffb02SXin Li dex_ir->AttachBuffer(std::move(dbginfo_));
159*f0dffb02SXin Li }
160*f0dffb02SXin Li
161*f0dffb02SXin Li } // namespace lir
162