• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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     auto sourceFile = std::string(DebugInfoExtractor::GetSourceFile(methodId));
95 #if defined(PANDA_TARGET_OHOS) || defined(PANDA_TARGET_MOBILE)
96     if (!sourceFile.empty()) {
97 #else
98     if (os::file::File::IsRegularFile(sourceFile)) {
99 #endif
100         return sourceNames_.emplace(methodId, std::nullopt).first->second;
101     }
102 
103     std::ostringstream name;
104     name << sourceNamePrefix_ << methodId;
105     auto &sourceName = sourceNames_.emplace(methodId, name.str()).first->second;
106 
107     onDisasmSourceName_(methodId, *sourceName);
108 
109     return sourceName;
110 }
111 
112 const DisasmBackedDebugInfoExtractor::Disassembly &DisasmBackedDebugInfoExtractor::GetDisassembly(
113     panda_file::File::EntityId methodId) const
114 {
115     os::memory::LockHolder lock(mutex_);
116 
117     auto it = disassemblies_.find(methodId);
118     if (it != disassemblies_.end()) {
119         return it->second;
120     }
121 
122     pandasm::Function method("", SourceLanguage::PANDA_ASSEMBLY);
123     disassembler_.GetMethod(&method, methodId);
124 
125     std::ostringstream sourceCode;
126     panda_file::LineNumberTable lineTable;
127     disassembler_.Serialize(method, sourceCode, true, &lineTable);
128 
129     auto paramsNum = method.GetParamsNum();
130     std::vector<ParamInfo> parameterInfo(paramsNum);
131     for (auto argumentNum = 0U; argumentNum < paramsNum; ++argumentNum) {
132         parameterInfo[argumentNum].name = "a" + std::to_string(argumentNum);
133         parameterInfo[argumentNum].signature = method.params[argumentNum].type.GetDescriptor();
134     }
135 
136     // We use -1 here as a number for Accumulator, because there is no other way
137     // to specify Accumulator as a register for local variable
138     auto totalRegNum = method.GetTotalRegs();
139     panda_file::LocalVariableTable localVariableTable(totalRegNum + 1, panda_file::LocalVariableInfo {});
140     for (auto vregNum = -1; vregNum < static_cast<int32_t>(totalRegNum); ++vregNum) {
141         localVariableTable[vregNum + 1].regNumber = vregNum;
142         localVariableTable[vregNum + 1].name = vregNum == -1 ? "acc" : "v" + std::to_string(vregNum);
143         localVariableTable[vregNum + 1].startOffset = 0;
144         localVariableTable[vregNum + 1].endOffset = UINT32_MAX;
145     }
146 
147     return disassemblies_
148         .emplace(methodId, Disassembly {sourceCode.str(), std::move(lineTable), std::move(parameterInfo),
149                                         std::move(localVariableTable)})
150         .first->second;
151 }
152 }  // namespace ark::disasm
153