• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 #include "disasm_backed_debug_info_extractor.h"
17 
18 namespace ark::disasm {
DisasmBackedDebugInfoExtractor(const panda_file::File & file,std::function<void (panda_file::File::EntityId,std::string_view)> && onDisasmSourceName)19 DisasmBackedDebugInfoExtractor::DisasmBackedDebugInfoExtractor(
20     const panda_file::File &file,
21     std::function<void(panda_file::File::EntityId, std::string_view)> &&onDisasmSourceName)
22     : panda_file::DebugInfoExtractor(&file),
23       sourceNamePrefix_("disasm://" + file.GetFilename() + ":"),
24       onDisasmSourceName_(std::move(onDisasmSourceName))
25 {
26     disassembler_.SetFile(file);
27 }
28 
GetLineNumberTable(panda_file::File::EntityId methodId) const29 const panda_file::LineNumberTable &DisasmBackedDebugInfoExtractor::GetLineNumberTable(
30     panda_file::File::EntityId methodId) const
31 {
32     if (GetDisassemblySourceName(methodId)) {
33         return GetDisassembly(methodId).lineTable;
34     }
35 
36     return DebugInfoExtractor::GetLineNumberTable(methodId);
37 }
38 
GetColumnNumberTable(panda_file::File::EntityId) const39 const panda_file::ColumnNumberTable &DisasmBackedDebugInfoExtractor::GetColumnNumberTable(
40     panda_file::File::EntityId /* method_id */) const
41 {
42     static panda_file::ColumnNumberTable empty;
43     return empty;
44 }
45 
GetLocalVariableTable(panda_file::File::EntityId methodId) const46 const panda_file::LocalVariableTable &DisasmBackedDebugInfoExtractor::GetLocalVariableTable(
47     panda_file::File::EntityId methodId) const
48 {
49     if (GetDisassemblySourceName(methodId)) {
50         return GetDisassembly(methodId).localVariableTable;
51     }
52 
53     return DebugInfoExtractor::GetLocalVariableTable(methodId);
54 }
55 
GetParameterInfo(panda_file::File::EntityId methodId) const56 const std::vector<panda_file::DebugInfoExtractor::ParamInfo> &DisasmBackedDebugInfoExtractor::GetParameterInfo(
57     panda_file::File::EntityId methodId) const
58 {
59     if (GetDisassemblySourceName(methodId)) {
60         return GetDisassembly(methodId).parameterInfo;
61     }
62 
63     return DebugInfoExtractor::GetParameterInfo(methodId);
64 }
65 
GetSourceFile(panda_file::File::EntityId methodId) const66 const char *DisasmBackedDebugInfoExtractor::GetSourceFile(panda_file::File::EntityId methodId) const
67 {
68     if (auto &disassemblySourceName = GetDisassemblySourceName(methodId)) {
69         return disassemblySourceName->c_str();
70     }
71 
72     return DebugInfoExtractor::GetSourceFile(methodId);
73 }
74 
GetSourceCode(panda_file::File::EntityId methodId) const75 const char *DisasmBackedDebugInfoExtractor::GetSourceCode(panda_file::File::EntityId methodId) const
76 {
77     if (GetDisassemblySourceName(methodId)) {
78         return GetDisassembly(methodId).sourceCode.c_str();
79     }
80 
81     return DebugInfoExtractor::GetSourceCode(methodId);
82 }
83 
GetDisassemblySourceName(panda_file::File::EntityId methodId) const84 const std::optional<std::string> &DisasmBackedDebugInfoExtractor::GetDisassemblySourceName(
85     panda_file::File::EntityId methodId) const
86 {
87     os::memory::LockHolder lock(mutex_);
88 
89     auto it = sourceNames_.find(methodId);
90     if (it != sourceNames_.end()) {
91         return it->second;
92     }
93 
94     std::string_view sourceFile = DebugInfoExtractor::GetSourceFile(methodId);
95     if (!sourceFile.empty()) {
96         // Mark the queried method to be ignored, because debug information is available for it
97         return sourceNames_.emplace(methodId, std::nullopt).first->second;
98     }
99 
100     std::ostringstream name;
101     name << sourceNamePrefix_ << methodId;
102     auto &sourceName = sourceNames_.emplace(methodId, name.str()).first->second;
103 
104     onDisasmSourceName_(methodId, *sourceName);
105 
106     return sourceName;
107 }
108 
GetDisassembly(panda_file::File::EntityId methodId) const109 const DisasmBackedDebugInfoExtractor::Disassembly &DisasmBackedDebugInfoExtractor::GetDisassembly(
110     panda_file::File::EntityId methodId) const
111 {
112     os::memory::LockHolder lock(mutex_);
113 
114     auto it = disassemblies_.find(methodId);
115     if (it != disassemblies_.end()) {
116         return it->second;
117     }
118 
119     pandasm::Function method("", SourceLanguage::PANDA_ASSEMBLY);
120     disassembler_.GetMethod(&method, methodId);
121 
122     std::ostringstream sourceCode;
123     panda_file::LineNumberTable lineTable;
124     disassembler_.Serialize(method, sourceCode, true, &lineTable);
125 
126     auto paramsNum = method.GetParamsNum();
127     std::vector<ParamInfo> parameterInfo(paramsNum);
128     for (auto argumentNum = 0U; argumentNum < paramsNum; ++argumentNum) {
129         parameterInfo[argumentNum].name = "a" + std::to_string(argumentNum);
130         parameterInfo[argumentNum].signature = method.params[argumentNum].type.GetDescriptor();
131     }
132 
133     // We use -1 here as a number for Accumulator, because there is no other way
134     // to specify Accumulator as a register for local variable
135     auto totalRegNum = method.GetTotalRegs();
136     panda_file::LocalVariableTable localVariableTable(totalRegNum + 1, panda_file::LocalVariableInfo {});
137     for (auto vregNum = -1; vregNum < static_cast<int32_t>(totalRegNum); ++vregNum) {
138         localVariableTable[vregNum + 1].regNumber = vregNum;
139         localVariableTable[vregNum + 1].name = vregNum == -1 ? "acc" : "v" + std::to_string(vregNum);
140         localVariableTable[vregNum + 1].startOffset = 0;
141         localVariableTable[vregNum + 1].endOffset = UINT32_MAX;
142     }
143 
144     return disassemblies_
145         .emplace(methodId, Disassembly {sourceCode.str(), std::move(lineTable), std::move(parameterInfo),
146                                         std::move(localVariableTable)})
147         .first->second;
148 }
149 
IsUserFile() const150 bool DisasmBackedDebugInfoExtractor::IsUserFile() const
151 {
152     return isUserFile_;
153 }
154 
SetUserFile(bool isUser)155 void DisasmBackedDebugInfoExtractor::SetUserFile(bool isUser)
156 {
157     isUserFile_ = isUser;
158 }
159 
160 }  // namespace ark::disasm
161