xref: /aosp_15_r20/tools/dexter/slicer/debuginfo_encoder.cc (revision f0dffb02cdb5c647d21204e89a92a1ffae2dad87)
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