1 /* 2 * Copyright (c) 2021 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 ECMASCRIPT_TOOLING_BACKEND_JS_PT_EXTRACTOR_H 17 #define ECMASCRIPT_TOOLING_BACKEND_JS_PT_EXTRACTOR_H 18 19 #include "ecmascript/js_method.h" 20 #include "ecmascript/js_thread.h" 21 #include "ecmascript/jspandafile/debug_info_extractor.h" 22 #include "ecmascript/tooling/backend/js_debugger_interface.h" 23 #include "libpandabase/macros.h" 24 25 namespace panda::ecmascript::tooling { 26 using panda::panda_file::File; 27 28 class JSPtExtractor : public DebugInfoExtractor { 29 public: 30 class SingleStepper { 31 public: 32 enum class Type { INTO, OVER, OUT }; SingleStepper(const EcmaVM * ecmaVm,JSMethod * method,std::list<JSPtStepRange> stepRanges,Type type)33 SingleStepper(const EcmaVM *ecmaVm, JSMethod *method, std::list<JSPtStepRange> stepRanges, Type type) 34 : ecmaVm_(ecmaVm), 35 method_(method), 36 stepRanges_(std::move(stepRanges)), 37 stackDepth_(GetStackDepth()), 38 type_(type) 39 { 40 } 41 virtual ~SingleStepper() = default; 42 NO_COPY_SEMANTIC(SingleStepper); 43 NO_MOVE_SEMANTIC(SingleStepper); 44 45 bool StepComplete(uint32_t bcOffset) const; 46 47 private: 48 uint32_t GetStackDepth() const; 49 bool InStepRange(uint32_t pc) const; 50 51 const EcmaVM *ecmaVm_; 52 JSMethod *method_; 53 std::list<JSPtStepRange> stepRanges_; 54 uint32_t stackDepth_; 55 Type type_; 56 }; 57 JSPtExtractor(const JSPandaFile * jsPandaFile)58 explicit JSPtExtractor(const JSPandaFile *jsPandaFile) : DebugInfoExtractor(jsPandaFile) {} 59 virtual ~JSPtExtractor() = default; 60 61 template<class Callback> MatchWithLocation(const Callback & cb,int32_t line,int32_t column)62 bool MatchWithLocation(const Callback &cb, int32_t line, int32_t column) 63 { 64 if (line == SPECIAL_LINE_MARK) { 65 return false; 66 } 67 68 auto methods = GetMethodIdList(); 69 for (const auto &method : methods) { 70 const LineNumberTable &lineTable = GetLineNumberTable(method); 71 const ColumnNumberTable &columnTable = GetColumnNumberTable(method); 72 for (uint32_t i = 0; i < lineTable.size(); i++) { 73 if (lineTable[i].line != line) { 74 continue; 75 } 76 uint32_t currentOffset = lineTable[i].offset; 77 uint32_t nextOffset = ((i == lineTable.size() - 1) ? UINT32_MAX : lineTable[i + 1].offset); 78 for (const auto &pair : columnTable) { 79 if (pair.column == column && pair.offset >= currentOffset && pair.offset < nextOffset) { 80 return cb(method, pair.offset); 81 } 82 } 83 return cb(method, currentOffset); 84 } 85 } 86 return false; 87 } 88 89 template<class Callback> MatchLineWithOffset(const Callback & cb,File::EntityId methodId,uint32_t offset)90 bool MatchLineWithOffset(const Callback &cb, File::EntityId methodId, uint32_t offset) 91 { 92 int32_t line = 0; 93 const LineNumberTable &lineTable = GetLineNumberTable(methodId); 94 auto iter = std::upper_bound(lineTable.begin(), lineTable.end(), LineTableEntry {offset, 0}); 95 if (iter != lineTable.begin()) { 96 line = (iter - 1)->line; 97 } 98 return cb(line); 99 } 100 101 template<class Callback> MatchColumnWithOffset(const Callback & cb,File::EntityId methodId,uint32_t offset)102 bool MatchColumnWithOffset(const Callback &cb, File::EntityId methodId, uint32_t offset) 103 { 104 int32_t column = 0; 105 const ColumnNumberTable &columnTable = GetColumnNumberTable(methodId); 106 auto iter = std::upper_bound(columnTable.begin(), columnTable.end(), ColumnTableEntry {offset, 0}); 107 if (iter != columnTable.begin()) { 108 column = (iter - 1)->column; 109 } 110 return cb(column); 111 } 112 std::unique_ptr<SingleStepper> GetStepIntoStepper(const EcmaVM *ecmaVm); 113 std::unique_ptr<SingleStepper> GetStepOverStepper(const EcmaVM *ecmaVm); 114 std::unique_ptr<SingleStepper> GetStepOutStepper(const EcmaVM *ecmaVm); 115 116 constexpr static int32_t SPECIAL_LINE_MARK = -1; 117 118 private: 119 NO_COPY_SEMANTIC(JSPtExtractor); 120 NO_MOVE_SEMANTIC(JSPtExtractor); 121 std::list<JSPtStepRange> GetStepRanges(File::EntityId methodId, uint32_t offset); 122 std::unique_ptr<SingleStepper> GetStepper(const EcmaVM *ecmaVm, SingleStepper::Type type); 123 }; 124 } // namespace panda::ecmascript::tooling 125 #endif // ECMASCRIPT_TOOLING_BACKEND_JS_PT_EXTRACTOR_H 126