• 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 #ifndef DISASM_LIB_H_INCLUDED
17 #define DISASM_LIB_H_INCLUDED
18 
19 #include "macros.h"
20 #include "utils/type_helpers.h"
21 #include "utils/span.h"
22 
23 #include "class_data_accessor-inl.h"
24 #include "code_data_accessor-inl.h"
25 #include "debug_data_accessor-inl.h"
26 #include "debug_info_extractor.h"
27 #include "field_data_accessor-inl.h"
28 #include "method_data_accessor-inl.h"
29 #include "literal_data_accessor-inl.h"
30 #include "param_annotations_data_accessor.h"
31 #include "annotation_data_accessor.h"
32 #include "proto_data_accessor-inl.h"
33 #include "file-inl.h"
34 #include "file.h"
35 #include "os/file.h"
36 
37 #include "runtime/profiling/profiling-disasm-inl.h"
38 
39 #include "assembly-program.h"
40 #include "assembly-ins.h"
41 
42 #include "bytecode_instruction-inl.h"
43 #include "libpandabase/macros.h"
44 
45 #include <map>
46 #include <memory>
47 #include <string>
48 
49 #include "accumulators.h"
50 
51 namespace ark::disasm {
52 class Disassembler {
53 public:
54     NO_COPY_SEMANTIC(Disassembler);
55     DEFAULT_MOVE_SEMANTIC(Disassembler);
56 
57     Disassembler() = default;
~Disassembler()58     ~Disassembler()
59     {
60         profiling::DestroyProfile(profile_, fileLanguage_);
61     }
62 
63     PANDA_PUBLIC_API void Serialize(std::ostream &os, bool addSeparators = false, bool printInformation = false) const;
64     PANDA_PUBLIC_API void Disassemble(std::string_view filenameIn, bool quiet = false, bool skipStrings = false);
65     PANDA_PUBLIC_API void Disassemble(const panda_file::File &file, bool quiet = false, bool skipStrings = false);
66     PANDA_PUBLIC_API void Disassemble(std::unique_ptr<const panda_file::File> &file, bool quiet = false,
67                                       bool skipStrings = false);
68     PANDA_PUBLIC_API void CollectInfo();
69 
70     PANDA_PUBLIC_API void SetProfile(std::string_view fname);
71 
72     PANDA_PUBLIC_API void SetFile(std::unique_ptr<const panda_file::File> &file);
73     PANDA_PUBLIC_API void SetFile(const panda_file::File &file);
74 
75     PANDA_PUBLIC_API void Serialize(const pandasm::Function &method, std::ostream &os, bool printInformation = false,
76                                     panda_file::LineNumberTable *lineTable = nullptr) const;
77     PANDA_PUBLIC_API void GetMethod(pandasm::Function *method, const panda_file::File::EntityId &methodId);
78 
GetProgInfo()79     const ProgInfo &GetProgInfo() const
80     {
81         return progInfo_;
82     }
83 
84 private:
85     void DisassembleImpl(const bool quiet = false, const bool skipStrings = false);
86     static inline bool IsSystemType(const std::string &typeName);
87 
88     void GetRecord(pandasm::Record &record, const panda_file::File::EntityId &recordId);
89     void AddMethodToTables(const panda_file::File::EntityId &methodId);
90     void GetLiteralArray(pandasm::LiteralArray *litArray, size_t index);
91     template <typename T>
92     void FillLiteralArrayData(pandasm::LiteralArray *litArray, const panda_file::LiteralTag &tag,
93                               const panda_file::LiteralDataAccessor::LiteralValue &value) const;
94     void FillLiteralData(pandasm::LiteralArray *litArray, const panda_file::LiteralDataAccessor::LiteralValue &value,
95                          const panda_file::LiteralTag &tag) const;
96 
97     static inline bool IsPandasmFriendly(char c);
98     void GetLiteralArrays();
99     void GetRecords();
100     void GetFields(pandasm::Record &record, const panda_file::File::EntityId &recordId);
101 
102     void GetField(pandasm::Field &field, const panda_file::FieldDataAccessor &fieldAccessor);
103     void AddExternalFieldsToRecords();
104     void AddExternalFieldsInfoToRecords();
105 
106     void GetMethods(const panda_file::File::EntityId &recordId);
107     void GetParams(pandasm::Function *method, const panda_file::File::EntityId &protoId) const;
108     IdList GetInstructions(pandasm::Function *method, panda_file::File::EntityId methodId,
109                            panda_file::File::EntityId codeId);
110     LabelTable GetExceptions(pandasm::Function *method, panda_file::File::EntityId methodId,
111                              panda_file::File::EntityId codeId) const;
112     bool LocateTryBlock(const BytecodeInstruction &bcIns, const BytecodeInstruction &bcInsLast,
113                         const panda_file::CodeDataAccessor::TryBlock &tryBlock,
114                         pandasm::Function::CatchBlock *catchBlockPa, LabelTable *labelTable, size_t tryIdx) const;
115     bool LocateCatchBlock(const BytecodeInstruction &bcIns, const BytecodeInstruction &bcInsLast,
116                           const panda_file::CodeDataAccessor::CatchBlock &catchBlock,
117                           pandasm::Function::CatchBlock *catchBlockPa, LabelTable *labelTable, size_t tryIdx,
118                           size_t catchIdx) const;
119 
120     void GetMetaData(pandasm::Record *record, const panda_file::File::EntityId &recordId) const;
121     void GetMetaData(pandasm::Function *method, const panda_file::File::EntityId &methodId) const;
122     void GetMetaData(pandasm::Field *field, const panda_file::File::EntityId &fieldId) const;
123 
124     void GetLanguageSpecificMetadata();
125 
126     std::string AnnotationTagToString(const char tag) const;
127 
128     std::string ScalarValueToString(const panda_file::ScalarValue &value, const std::string &type);
129     std::string ArrayValueToString(const panda_file::ArrayValue &value, const std::string &type, size_t idx);
130 
131     std::string GetFullMethodName(const panda_file::File::EntityId &methodId) const;
132     std::string GetMethodSignature(const panda_file::File::EntityId &methodId) const;
133     std::string GetFullRecordName(const panda_file::File::EntityId &classId) const;
134 
135     void GetRecordInfo(const panda_file::File::EntityId &recordId, RecordInfo *recordInfo) const;
136     void GetMethodInfo(const panda_file::File::EntityId &methodId, MethodInfo *methodInfo) const;
137     void GetInsInfo(panda_file::MethodDataAccessor &mda, const panda_file::File::EntityId &codeId,
138                     MethodInfo *methodInfo) const;
139     template <typename T>
140     void SerializeValue(bool isSigned, const pandasm::LiteralArray::Literal &lit, std::ostream &os) const;
141     void Serialize(const std::string &name, const pandasm::LiteralArray &litArray, std::ostream &os) const;
142     void SerializeValues(const pandasm::LiteralArray &litArray, bool isConst, std::ostream &os) const;
143     std::string LiteralTagToString(const panda_file::LiteralTag &tag) const;
144     std::string LiteralValueToString(const pandasm::LiteralArray::Literal &lit) const;
145     void Serialize(const pandasm::Record &record, std::ostream &os, bool printInformation = false) const;
146     void SerializeFields(const pandasm::Record &record, std::ostream &os, bool printInformation,
147                          bool isUnion = false) const;
148     void SerializeUnionFields(const pandasm::Record &record, std::ostream &os, bool printInformation) const;
149     void Serialize(const pandasm::Function::CatchBlock &catchBlock, std::ostream &os) const;
150     void Serialize(const pandasm::ItemMetadata &meta, const AnnotationList &annList, std::ostream &os) const;
151     void SerializeLineNumberTable(const panda_file::LineNumberTable &lineNumberTable, std::ostream &os) const;
152     void SerializeLocalVariableTable(const panda_file::LocalVariableTable &localVariableTable,
153                                      const pandasm::Function &method, std::ostream &os) const;
154     void SerializeLanguage(std::ostream &os) const;
155     void SerializeFilename(std::ostream &os) const;
156     void SerializeLitArrays(std::ostream &os, bool addSeparators = false) const;
157     void SerializeRecords(std::ostream &os, bool addSeparators = false, bool printInformation = false) const;
158     void SerializeMethods(std::ostream &os, bool addSeparators = false, bool printInformation = false) const;
159     void SerializePrintStartInfo(const pandasm::Function &method, std::ostringstream &headerSs) const;
160     void SerializeCheckEnd(const pandasm::Function &method, std::ostream &os, bool printMethodInfo,
161                            const MethodInfo *&methodInfo) const;
162     size_t SerializeIfPrintMethodInfo(
163         const pandasm::Function &method, bool printMethodInfo, std::ostringstream &headerSs,
164         const MethodInfo *&methodInfo,
165         std::map<std::string, ark::disasm::MethodInfo>::const_iterator &methodInfoIt) const;
166 
167     void EnumerateAnnotations(panda_file::AnnotationDataAccessor &annotationAccessor, AnnotationList &annList,
168                               const std::string &type, const panda_file::File::EntityId &annotationId);
169 
170     void HandleArrayAnnotation(panda_file::AnnotationDataAccessor &annotationAccessor, AnnotationList &annList,
171                                size_t i);
172 
173     pandasm::Type PFTypeToPandasmType(const panda_file::Type &type, panda_file::ProtoDataAccessor &pda,
174                                       size_t &refIdx) const;
175 
176     pandasm::Type FieldTypeToPandasmType(const uint32_t &type) const;
177 
StringDataToString(panda_file::File::StringData sd)178     static std::string StringDataToString(panda_file::File::StringData sd)
179     {
180         std::string str = std::string(utf::Mutf8AsCString(sd.data));
181         size_t symPos = 0;
182         while (symPos = str.find_first_of("\a\b\f\n\r\t\v\'\?\\", symPos), symPos != std::string::npos) {
183             std::string sym;
184             switch (str[symPos]) {
185                 case '\a':
186                     sym = R"(\a)";
187                     break;
188                 case '\b':
189                     sym = R"(\b)";
190                     break;
191                 case '\f':
192                     sym = R"(\f)";
193                     break;
194                 case '\n':
195                     sym = R"(\n)";
196                     break;
197                 case '\r':
198                     sym = R"(\r)";
199                     break;
200                 case '\t':
201                     sym = R"(\t)";
202                     break;
203                 case '\v':
204                     sym = R"(\v)";
205                     break;
206                 case '\'':
207                     sym = R"(\')";
208                     break;
209                 case '\?':
210                     sym = R"(\?)";
211                     break;
212                 case '\\':
213                     sym = R"(\\)";
214                     break;
215                 default:
216                     UNREACHABLE();
217             }
218             str = str.replace(symPos, 1, sym);
219             ASSERT(sym.size() == 2U);
220             symPos += 2U;
221         }
222         return str;
223     }
224 
225     template <typename T>
LiteralIntegralValueToString(const pandasm::LiteralArray::Literal & lit)226     std::string LiteralIntegralValueToString(const pandasm::LiteralArray::Literal &lit) const
227     {
228         std::stringstream res {};
229         T value = std::get<T>(lit.value);
230         if (lit.IsSigned()) {
231             res << +static_cast<typename std::make_signed<T>::type>(value);
232         } else {
233             res << +value;
234         }
235         return res.str();
236     }
237 
238     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(BytecodeInstruction::Opcode o) const;
239     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(uint8_t o) const;
240     void CollectExternalFields(const panda_file::FieldDataAccessor &fieldAccessor);
241 
242     pandasm::Ins BytecodeInstructionToPandasmInstruction(BytecodeInstruction bcIns,
243                                                          panda_file::File::EntityId methodId) const;
244 
245     std::string IDToString(BytecodeInstruction bcIns, panda_file::File::EntityId methodId) const;
246 
247     ark::panda_file::SourceLang GetRecordLanguage(panda_file::File::EntityId classId) const;
248 
249     std::unique_ptr<const panda_file::File> fileHolder_ {nullptr};
250     const panda_file::File *file_ {};
251     pandasm::Program prog_ {};
252 
253     ark::panda_file::SourceLang fileLanguage_ = ark::panda_file::SourceLang::PANDA_ASSEMBLY;
254 
255     std::map<std::string, panda_file::File::EntityId> recordNameToId_ {};
256     std::map<std::string, panda_file::File::EntityId> methodNameToId_ {};
257 
258     std::map<std::string, std::vector<pandasm::Field>> externalFieldTable_ {};
259     std::map<std::string, std::vector<std::string>> externalFieldsInfoTable_ {};
260 
261     ProgAnnotations progAnn_ {};
262 
263     ProgInfo progInfo_ {};
264 
265     profiling::ProfileContainer profile_ {profiling::INVALID_PROFILE};
266 
267     std::unique_ptr<panda_file::DebugInfoExtractor> debugInfoExtractor_ {nullptr};
268 
269     bool quiet_ {false};
270     bool skipStrings_ {false};
271 
272 #include "disasm_plugins.inc"
273 };
274 }  // namespace ark::disasm
275 
276 #endif
277