1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef LIBPANDAFILE_DEBUG_HELPERS_H
17 #define LIBPANDAFILE_DEBUG_HELPERS_H
18
19 #include "debug_data_accessor-inl.h"
20 #include "file.h"
21 #include "file_items.h"
22 #include "method_data_accessor-inl.h"
23 #include "line_number_program.h"
24 #include "libpandabase/utils/span.h"
25
26 namespace panda::panda_file::debug_helpers {
27
28 class BytecodeOffsetResolver {
29 public:
BytecodeOffsetResolver(panda_file::LineProgramState * state,uint32_t bc_offset)30 BytecodeOffsetResolver(panda_file::LineProgramState *state, uint32_t bc_offset)
31 : state_(state), bc_offset_(bc_offset), prev_line_(state->GetLine()), line_(0)
32 {
33 }
34
35 ~BytecodeOffsetResolver() = default;
36
37 DEFAULT_MOVE_SEMANTIC(BytecodeOffsetResolver);
38 DEFAULT_COPY_SEMANTIC(BytecodeOffsetResolver);
39
GetState()40 panda_file::LineProgramState *GetState() const
41 {
42 return state_;
43 }
44
GetLine()45 uint32_t GetLine() const
46 {
47 return line_;
48 }
49
ProcessBegin()50 void ProcessBegin() const {}
51
ProcessEnd()52 void ProcessEnd()
53 {
54 if (line_ == 0) {
55 line_ = state_->GetLine();
56 }
57 }
58
HandleAdvanceLine(int32_t line_diff)59 bool HandleAdvanceLine(int32_t line_diff) const
60 {
61 state_->AdvanceLine(line_diff);
62 return true;
63 }
64
HandleAdvancePc(uint32_t pc_diff)65 bool HandleAdvancePc(uint32_t pc_diff) const
66 {
67 state_->AdvancePc(pc_diff);
68 return true;
69 }
70
HandleSetFile(uint32_t source_file_id)71 bool HandleSetFile([[maybe_unused]] uint32_t source_file_id) const
72 {
73 return true;
74 }
75
HandleSetSourceCode(uint32_t source_code_id)76 bool HandleSetSourceCode([[maybe_unused]] uint32_t source_code_id) const
77 {
78 return true;
79 }
80
HandleSetPrologueEnd()81 bool HandleSetPrologueEnd() const
82 {
83 return true;
84 }
85
HandleSetEpilogueBegin()86 bool HandleSetEpilogueBegin() const
87 {
88 return true;
89 }
90
HandleStartLocal(int32_t reg_number,uint32_t name_id,uint32_t type_id)91 bool HandleStartLocal([[maybe_unused]] int32_t reg_number, [[maybe_unused]] uint32_t name_id,
92 [[maybe_unused]] uint32_t type_id) const
93 {
94 return true;
95 }
96
HandleStartLocalExtended(int32_t reg_number,uint32_t name_id,uint32_t type_id,uint32_t type_signature_id)97 bool HandleStartLocalExtended([[maybe_unused]] int32_t reg_number, [[maybe_unused]] uint32_t name_id,
98 [[maybe_unused]] uint32_t type_id, [[maybe_unused]] uint32_t type_signature_id) const
99 {
100 return true;
101 }
102
HandleEndLocal(int32_t reg_number)103 bool HandleEndLocal([[maybe_unused]] int32_t reg_number) const
104 {
105 return true;
106 }
107
HandleSetColumn(int32_t column_number)108 bool HandleSetColumn([[maybe_unused]] int32_t column_number) const
109 {
110 return true;
111 }
112
HandleSpecialOpcode(uint32_t pc_offset,int32_t line_offset)113 bool HandleSpecialOpcode(uint32_t pc_offset, int32_t line_offset)
114 {
115 state_->AdvancePc(pc_offset);
116 state_->AdvanceLine(line_offset);
117
118 if (state_->GetAddress() == bc_offset_) {
119 line_ = state_->GetLine();
120 return false;
121 }
122
123 if (state_->GetAddress() > bc_offset_) {
124 line_ = prev_line_;
125 return false;
126 }
127
128 prev_line_ = state_->GetLine();
129
130 return true;
131 }
132
133 private:
134 panda_file::LineProgramState *state_;
135 uint32_t bc_offset_;
136 uint32_t prev_line_;
137 uint32_t line_;
138 };
139
GetLineNumber(panda::panda_file::MethodDataAccessor mda,uint32_t bc_offset,const panda::panda_file::File * panda_debug_file)140 inline size_t GetLineNumber(panda::panda_file::MethodDataAccessor mda, uint32_t bc_offset,
141 const panda::panda_file::File *panda_debug_file)
142 {
143 auto debug_info_id = mda.GetDebugInfoId();
144 if (!debug_info_id) {
145 return -1;
146 }
147
148 panda::panda_file::DebugInfoDataAccessor dda(*panda_debug_file, debug_info_id.value());
149 const uint8_t *program = dda.GetLineNumberProgram();
150
151 panda::panda_file::LineProgramState state(*panda_debug_file, panda::panda_file::File::EntityId(0),
152 dda.GetLineStart(), dda.GetConstantPool());
153
154 BytecodeOffsetResolver resolver(&state, bc_offset);
155 panda::panda_file::LineNumberProgramProcessor<BytecodeOffsetResolver> program_processor(program, &resolver);
156 program_processor.Process();
157
158 return resolver.GetLine();
159 }
160
161 } // namespace panda::panda_file::debug_helpers
162
163 #endif // LIBPANDAFILE_DEBUG_HELPERS_H
164