• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 panda::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(bool quiet = false, 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 
105     void GetMethods(const panda_file::File::EntityId &recordId);
106     void GetParams(pandasm::Function *method, const panda_file::File::EntityId &protoId) const;
107     IdList GetInstructions(pandasm::Function *method, panda_file::File::EntityId methodId,
108                            panda_file::File::EntityId codeId);
109     LabelTable GetExceptions(pandasm::Function *method, panda_file::File::EntityId methodId,
110                              panda_file::File::EntityId codeId) const;
111     bool LocateTryBlock(const BytecodeInstruction &bcIns, const BytecodeInstruction &bcInsLast,
112                         const panda_file::CodeDataAccessor::TryBlock &tryBlock,
113                         pandasm::Function::CatchBlock *catchBlockPa, LabelTable *labelTable, size_t tryIdx) const;
114     bool LocateCatchBlock(const BytecodeInstruction &bcIns, const BytecodeInstruction &bcInsLast,
115                           const panda_file::CodeDataAccessor::CatchBlock &catchBlock,
116                           pandasm::Function::CatchBlock *catchBlockPa, LabelTable *labelTable, size_t tryIdx,
117                           size_t catchIdx) const;
118 
119     void GetMetaData(pandasm::Record *record, const panda_file::File::EntityId &recordId) const;
120     void GetMetaData(pandasm::Function *method, const panda_file::File::EntityId &methodId) const;
121     void GetMetaData(pandasm::Field *field, const panda_file::File::EntityId &fieldId) const;
122 
123     void GetLanguageSpecificMetadata();
124 
125     std::string AnnotationTagToString(char tag) const;
126 
127     std::string ScalarValueToString(const panda_file::ScalarValue &value, const std::string &type);
128     std::string ArrayValueToString(const panda_file::ArrayValue &value, const std::string &type, size_t idx);
129 
130     std::string GetFullMethodName(const panda_file::File::EntityId &methodId) const;
131     std::string GetMethodSignature(const panda_file::File::EntityId &methodId) const;
132     std::string GetFullRecordName(const panda_file::File::EntityId &classId) const;
133 
134     void GetRecordInfo(const panda_file::File::EntityId &recordId, RecordInfo *recordInfo) const;
135     void GetMethodInfo(const panda_file::File::EntityId &methodId, MethodInfo *methodInfo) const;
136     void GetInsInfo(panda_file::MethodDataAccessor &mda, const panda_file::File::EntityId &codeId,
137                     MethodInfo *methodInfo) const;
138     template <typename T>
139     void SerializeValue(bool isSigned, const pandasm::LiteralArray::Literal &lit, std::ostream &os) const;
140     void Serialize(const std::string &name, const pandasm::LiteralArray &litArray, std::ostream &os) const;
141     void SerializeValues(const pandasm::LiteralArray &litArray, bool isConst, std::ostream &os) const;
142     std::string LiteralTagToString(const panda_file::LiteralTag &tag) const;
143     std::string LiteralValueToString(const pandasm::LiteralArray::Literal &lit) const;
144     void Serialize(const pandasm::Record &record, std::ostream &os, bool printInformation = false) const;
145     void SerializeFields(const pandasm::Record &record, std::ostream &os, bool printInformation,
146                          bool isUnion = false) const;
147     void SerializeUnionFields(const pandasm::Record &record, std::ostream &os, bool printInformation) const;
148     void Serialize(const pandasm::Function::CatchBlock &catchBlock, std::ostream &os) const;
149     void Serialize(const pandasm::ItemMetadata &meta, const AnnotationList &annList, std::ostream &os) const;
150     void SerializeLineNumberTable(const panda_file::LineNumberTable &lineNumberTable, std::ostream &os) const;
151     void SerializeLocalVariableTable(const panda_file::LocalVariableTable &localVariableTable,
152                                      const pandasm::Function &method, std::ostream &os) const;
153     void SerializeLanguage(std::ostream &os) const;
154     void SerializeFilename(std::ostream &os) const;
155     void SerializeLitArrays(std::ostream &os, bool addSeparators = false) const;
156     void SerializeRecords(std::ostream &os, bool addSeparators = false, bool printInformation = false) const;
157     void SerializeMethods(std::ostream &os, bool addSeparators = false, bool printInformation = false) const;
158 
159     pandasm::Type PFTypeToPandasmType(const panda_file::Type &type, panda_file::ProtoDataAccessor &pda,
160                                       size_t &refIdx) const;
161 
162     pandasm::Type FieldTypeToPandasmType(const uint32_t &type) const;
163 
StringDataToString(panda_file::File::StringData sd)164     static std::string StringDataToString(panda_file::File::StringData sd)
165     {
166         std::string str = std::string(utf::Mutf8AsCString(sd.data));
167         size_t symPos = 0;
168         while (symPos = str.find_first_of("\a\b\f\n\r\t\v\'\?\\", symPos), symPos != std::string::npos) {
169             std::string sym;
170             switch (str[symPos]) {
171                 case '\a':
172                     sym = R"(\a)";
173                     break;
174                 case '\b':
175                     sym = R"(\b)";
176                     break;
177                 case '\f':
178                     sym = R"(\f)";
179                     break;
180                 case '\n':
181                     sym = R"(\n)";
182                     break;
183                 case '\r':
184                     sym = R"(\r)";
185                     break;
186                 case '\t':
187                     sym = R"(\t)";
188                     break;
189                 case '\v':
190                     sym = R"(\v)";
191                     break;
192                 case '\'':
193                     sym = R"(\')";
194                     break;
195                 case '\?':
196                     sym = R"(\?)";
197                     break;
198                 case '\\':
199                     sym = R"(\\)";
200                     break;
201                 default:
202                     UNREACHABLE();
203             }
204             str = str.replace(symPos, 1, sym);
205             ASSERT(sym.size() == 2U);
206             symPos += 2U;
207         }
208         return str;
209     }
210 
211     template <typename T>
LiteralIntegralValueToString(const pandasm::LiteralArray::Literal & lit)212     std::string LiteralIntegralValueToString(const pandasm::LiteralArray::Literal &lit) const
213     {
214         std::stringstream res {};
215         T value = std::get<T>(lit.value);
216         if (lit.IsSigned()) {
217             res << +static_cast<typename std::make_signed<T>::type>(value);
218         } else {
219             res << +value;
220         }
221         return res.str();
222     }
223 
224     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(BytecodeInstruction::Opcode o) const;
225     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(uint8_t o) const;
226     void CollectExternalFields(const panda_file::FieldDataAccessor &fieldAccessor);
227 
228     pandasm::Ins BytecodeInstructionToPandasmInstruction(BytecodeInstruction bcIns,
229                                                          panda_file::File::EntityId methodId) const;
230 
231     std::string IDToString(BytecodeInstruction bcIns, panda_file::File::EntityId methodId) const;
232 
233     panda::panda_file::SourceLang GetRecordLanguage(panda_file::File::EntityId classId) const;
234 
235     std::unique_ptr<const panda_file::File> fileHolder_ {nullptr};
236     const panda_file::File *file_ {};
237     pandasm::Program prog_ {};
238 
239     panda::panda_file::SourceLang fileLanguage_ = panda::panda_file::SourceLang::PANDA_ASSEMBLY;
240 
241     std::map<std::string, panda_file::File::EntityId> recordNameToId_ {};
242     std::map<std::string, panda_file::File::EntityId> methodNameToId_ {};
243 
244     std::map<std::string, std::vector<pandasm::Field>> externalFieldTable_ {};
245 
246     ProgAnnotations progAnn_ {};
247 
248     ProgInfo progInfo_ {};
249 
250     profiling::ProfileContainer profile_ {profiling::INVALID_PROFILE};
251 
252     std::unique_ptr<panda_file::DebugInfoExtractor> debugInfoExtractor_ {nullptr};
253 
254     bool quiet_ {false};
255     bool skipStrings_ {false};
256 
257 #include "disasm_plugins.inc"
258 };
259 }  // namespace panda::disasm
260 
261 #endif
262