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_JSPANDAFILE_DEBUG_INFO_EXTRACTOR_H 17 #define ECMASCRIPT_JSPANDAFILE_DEBUG_INFO_EXTRACTOR_H 18 19 #include "ecmascript/common.h" 20 #include "ecmascript/debugger/js_pt_location.h" 21 #include "ecmascript/jspandafile/js_pandafile.h" 22 #include "ecmascript/mem/c_containers.h" 23 #include "ecmascript/mem/c_string.h" 24 25 #include "libpandafile/file.h" 26 27 namespace panda::ecmascript { 28 class JSPandaFile; 29 30 struct LineTableEntry { 31 uint32_t offset; 32 int32_t line; 33 34 bool operator<(const LineTableEntry &other) const 35 { 36 return offset < other.offset; 37 } 38 }; 39 40 struct ColumnTableEntry { 41 uint32_t offset; 42 int32_t column; 43 44 bool operator<(const ColumnTableEntry &other) const 45 { 46 return offset < other.offset; 47 } 48 }; 49 50 using LineNumberTable = CVector<LineTableEntry>; 51 using ColumnNumberTable = CVector<ColumnTableEntry>; 52 using JSPtLocation = tooling::JSPtLocation; 53 54 /* 55 * LocalVariableInfo define in frontend, now only use name and regNumber: 56 * std::string name 57 * std::string type 58 * std::string typeSignature 59 * int32_t regNumber 60 * uint32_t startOffset 61 * uint32_t endOffset 62 */ 63 using LocalVariableTable = CUnorderedMap<std::string, int32_t>; // name, regNumber 64 65 // public for debugger 66 class PUBLIC_API DebugInfoExtractor { 67 public: 68 explicit DebugInfoExtractor(const JSPandaFile *jsPandaFile); 69 70 ~DebugInfoExtractor() = default; 71 72 DEFAULT_COPY_SEMANTIC(DebugInfoExtractor); 73 DEFAULT_MOVE_SEMANTIC(DebugInfoExtractor); 74 75 const LineNumberTable &GetLineNumberTable(panda_file::File::EntityId methodId) const; 76 77 const ColumnNumberTable &GetColumnNumberTable(panda_file::File::EntityId methodId) const; 78 79 const LocalVariableTable &GetLocalVariableTable(panda_file::File::EntityId methodId) const; 80 81 const std::string &GetSourceFile(panda_file::File::EntityId methodId) const; 82 83 const std::string &GetSourceCode(panda_file::File::EntityId methodId) const; 84 85 CVector<panda_file::File::EntityId> GetMethodIdList() const; 86 87 bool ContainsMethod(panda_file::File::EntityId methodId) const; 88 89 template<class Callback> MatchWithLocation(const Callback & cb,int32_t line,int32_t column,const std::string & url)90 bool MatchWithLocation(const Callback &cb, int32_t line, int32_t column, const std::string &url) const 91 { 92 if (line == SPECIAL_LINE_MARK) { 93 return false; 94 } 95 96 for (const auto &[id, debugInfo] : methods_) { 97 // the url for testcases is empty 98 if (!url.empty() && url != debugInfo.sourceFile) { 99 continue; 100 } 101 auto methodId = panda_file::File::EntityId(id); 102 const LineNumberTable &lineTable = GetLineNumberTable(methodId); 103 const ColumnNumberTable &columnTable = GetColumnNumberTable(methodId); 104 for (uint32_t i = 0; i < lineTable.size(); i++) { 105 if (lineTable[i].line != line) { 106 continue; 107 } 108 uint32_t currentOffset = lineTable[i].offset; 109 uint32_t nextOffset = ((i == lineTable.size() - 1) ? UINT32_MAX : lineTable[i + 1].offset); 110 for (const auto &pair : columnTable) { 111 if (pair.column == column && pair.offset >= currentOffset && pair.offset < nextOffset) { 112 return cb(JSPtLocation(jsPandaFile_, methodId, pair.offset, url)); 113 } 114 } 115 return cb(JSPtLocation(jsPandaFile_, methodId, currentOffset, url)); 116 } 117 } 118 return false; 119 } 120 121 template<class Callback> MatchLineWithOffset(const Callback & cb,panda_file::File::EntityId methodId,uint32_t offset)122 bool MatchLineWithOffset(const Callback &cb, panda_file::File::EntityId methodId, uint32_t offset) 123 { 124 int32_t line = 0; 125 const LineNumberTable &lineTable = GetLineNumberTable(methodId); 126 auto iter = std::upper_bound(lineTable.begin(), lineTable.end(), LineTableEntry {offset, 0}); 127 if (iter != lineTable.begin()) { 128 line = (iter - 1)->line; 129 } 130 return cb(line); 131 } 132 133 template<class Callback> MatchColumnWithOffset(const Callback & cb,panda_file::File::EntityId methodId,uint32_t offset)134 bool MatchColumnWithOffset(const Callback &cb, panda_file::File::EntityId methodId, uint32_t offset) 135 { 136 int32_t column = 0; 137 const ColumnNumberTable &columnTable = GetColumnNumberTable(methodId); 138 auto iter = std::upper_bound(columnTable.begin(), columnTable.end(), ColumnTableEntry {offset, 0}); 139 if (iter != columnTable.begin()) { 140 column = (iter - 1)->column; 141 } 142 return cb(column); 143 } 144 145 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER) GetFristLine(panda_file::File::EntityId methodId)146 int32_t GetFristLine(panda_file::File::EntityId methodId) 147 { 148 const LineNumberTable &lineTable = GetLineNumberTable(methodId); 149 if (lineTable.size() <= 1) { 150 return 0; 151 } 152 return lineTable[1].line + 1; 153 } 154 GetFristColumn(panda_file::File::EntityId methodId)155 int32_t GetFristColumn(panda_file::File::EntityId methodId) 156 { 157 const ColumnNumberTable &columnTable = GetColumnNumberTable(methodId); 158 if (columnTable.size() == 0) { 159 return 0; 160 } 161 return columnTable[0].column + 1; 162 } 163 #endif 164 165 constexpr static int32_t SPECIAL_LINE_MARK = -1; 166 167 private: 168 void Extract(); 169 170 struct MethodDebugInfo { 171 std::string sourceFile; 172 std::string sourceCode; 173 LineNumberTable lineNumberTable; 174 ColumnNumberTable columnNumberTable; 175 LocalVariableTable localVariableTable; 176 }; 177 178 CUnorderedMap<uint32_t, MethodDebugInfo> methods_; 179 const JSPandaFile *jsPandaFile_ {nullptr}; 180 }; 181 } // namespace panda::ecmascript 182 183 #endif // ECMASCRIPT_JSPANDAFILE_DEBUG_INFO_EXTRACTOR_H 184