• 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 GetLiteralArrayByOffset(pandasm::LiteralArray *litArray, panda_file::File::EntityId offset) const;
91     void GetLiteralArray(pandasm::LiteralArray *litArray, size_t index);
92     template <typename T>
93     void FillLiteralArrayData(pandasm::LiteralArray *litArray, const panda_file::LiteralTag &tag,
94                               const panda_file::LiteralDataAccessor::LiteralValue &value) const;
95     std::variant<bool, uint8_t, uint16_t, uint32_t, uint64_t, float, double, std::string> ParseLiteralValue(
96         const panda_file::LiteralDataAccessor::LiteralValue &value, const panda_file::LiteralTag &tag) const;
97     std::string ParseStringData(const panda_file::LiteralDataAccessor::LiteralValue &value) const;
98     std::string ParseLiteralArrayData(const panda_file::LiteralDataAccessor::LiteralValue &value) const;
99     void FillLiteralData(pandasm::LiteralArray *litArray, const panda_file::LiteralDataAccessor::LiteralValue &value,
100                          const panda_file::LiteralTag &tag) const;
101 
102     static inline bool IsPandasmFriendly(char c);
103     void GetLiteralArrays();
104     void GetRecords();
105     void GetFields(pandasm::Record &record, const panda_file::File::EntityId &recordId);
106 
107     void GetField(pandasm::Field &field, const panda_file::FieldDataAccessor &fieldAccessor);
108     void AddExternalFieldsToRecords();
109     void AddExternalFieldsInfoToRecords();
110 
111     void GetMethods(const panda_file::File::EntityId &recordId);
112     void GetParams(pandasm::Function *method, const panda_file::File::EntityId &protoId) const;
113     IdList GetInstructions(pandasm::Function *method, panda_file::File::EntityId methodId,
114                            panda_file::File::EntityId codeId);
115     LabelTable GetExceptions(pandasm::Function *method, panda_file::File::EntityId methodId,
116                              panda_file::File::EntityId codeId) const;
117     // CC-OFFNXT(G.FUN.01) solid logic
118     bool LocateTryBlock(const BytecodeInstruction &bcIns, const BytecodeInstruction &bcInsLast,
119                         const panda_file::CodeDataAccessor::TryBlock &tryBlock,
120                         pandasm::Function::CatchBlock *catchBlockPa, LabelTable *labelTable, size_t tryIdx) const;
121     // CC-OFFNXT(G.FUN.01) solid logic
122     bool LocateCatchBlock(const BytecodeInstruction &bcIns, const BytecodeInstruction &bcInsLast,
123                           const panda_file::CodeDataAccessor::CatchBlock &catchBlock,
124                           pandasm::Function::CatchBlock *catchBlockPa, LabelTable *labelTable, size_t tryIdx,
125                           size_t catchIdx) const;
126 
127     void GetMetaData(pandasm::Record *record, const panda_file::File::EntityId &recordId) const;
128     void GetMetaData(pandasm::Function *method, const panda_file::File::EntityId &methodId) const;
129     void GetMetaData(pandasm::Field *field, const panda_file::File::EntityId &fieldId) const;
130 
131     void GetLanguageSpecificMetadata();
132 
133     std::string AnnotationTagToString(const char tag) const;
134 
135     std::string ScalarValueToString(const panda_file::ScalarValue &value, const std::string &type);
136     std::string ArrayValueToString(const panda_file::ArrayValue &value, const std::string &type, size_t idx);
137 
138     std::string GetFullMethodName(const panda_file::File::EntityId &methodId) const;
139     std::string GetMethodSignature(const panda_file::File::EntityId &methodId) const;
140     std::string GetFullRecordName(const panda_file::File::EntityId &classId) const;
141 
142     void GetRecordInfo(const panda_file::File::EntityId &recordId, RecordInfo *recordInfo) const;
143     void GetMethodInfo(const panda_file::File::EntityId &methodId, MethodInfo *methodInfo) const;
144     void GetInsInfo(panda_file::MethodDataAccessor &mda, const panda_file::File::EntityId &codeId,
145                     MethodInfo *methodInfo) const;
146     template <typename T>
147     void SerializeValue(bool isSigned, const pandasm::LiteralArray::Literal &lit, std::ostream &os) const;
148     void Serialize(const std::string &name, const pandasm::LiteralArray &litArray, std::ostream &os) const;
149     void SerializeValues(const pandasm::LiteralArray &litArray, bool isConst, std::ostream &os) const;
150     std::string LiteralTagToString(const panda_file::LiteralTag &tag) const;
151     std::string LiteralValueToString(const pandasm::LiteralArray::Literal &lit) const;
152     void Serialize(const pandasm::Record &record, std::ostream &os, bool printInformation = false) const;
153     void SerializeFields(const pandasm::Record &record, std::ostream &os, bool printInformation,
154                          bool isUnion = false) const;
155     void SerializeUnionFields(const pandasm::Record &record, std::ostream &os, bool printInformation) const;
156     void Serialize(const pandasm::Function::CatchBlock &catchBlock, std::ostream &os) const;
157     void Serialize(const pandasm::ItemMetadata &meta, const AnnotationList &annList, std::ostream &os) const;
158     void SerializeLineNumberTable(const panda_file::LineNumberTable &lineNumberTable, std::ostream &os) const;
159     void SerializeLocalVariableTable(const panda_file::LocalVariableTable &localVariableTable,
160                                      const pandasm::Function &method, std::ostream &os) const;
161     void SerializeLanguage(std::ostream &os) const;
162     void SerializeFilename(std::ostream &os) const;
163     void SerializeLitArrays(std::ostream &os, bool addSeparators = false) const;
164     void SerializeRecords(std::ostream &os, bool addSeparators = false, bool printInformation = false) const;
165     void SerializeMethods(std::ostream &os, bool addSeparators = false, bool printInformation = false) const;
166     void SerializePrintStartInfo(const pandasm::Function &method, std::ostringstream &headerSs) const;
167     void SerializeCheckEnd(const pandasm::Function &method, std::ostream &os, bool printMethodInfo,
168                            const MethodInfo *&methodInfo) const;
169     size_t SerializeIfPrintMethodInfo(
170         const pandasm::Function &method, bool printMethodInfo, std::ostringstream &headerSs,
171         const MethodInfo *&methodInfo,
172         std::map<std::string, ark::disasm::MethodInfo>::const_iterator &methodInfoIt) const;
173 
174     void EnumerateAnnotations(panda_file::AnnotationDataAccessor &annotationAccessor, AnnotationList &annList,
175                               const std::string &type, const panda_file::File::EntityId &annotationId);
176 
177     void HandleArrayAnnotation(panda_file::AnnotationDataAccessor &annotationAccessor, AnnotationList &annList,
178                                size_t i);
179 
180     pandasm::Type PFTypeToPandasmType(const panda_file::Type &type, panda_file::ProtoDataAccessor &pda,
181                                       size_t &refIdx) const;
182 
183     pandasm::Type FieldTypeToPandasmType(const uint32_t &type) const;
184 
StringDataToString(panda_file::File::StringData sd)185     static std::string StringDataToString(panda_file::File::StringData sd)
186     {
187         std::string str = std::string(utf::Mutf8AsCString(sd.data));
188         size_t symPos = 0;
189         while (symPos = str.find_first_of("\a\b\f\n\r\t\v\'\?\\", symPos), symPos != std::string::npos) {
190             std::string sym;
191             switch (str[symPos]) {
192                 case '\a':
193                     sym = R"(\a)";
194                     break;
195                 case '\b':
196                     sym = R"(\b)";
197                     break;
198                 case '\f':
199                     sym = R"(\f)";
200                     break;
201                 case '\n':
202                     sym = R"(\n)";
203                     break;
204                 case '\r':
205                     sym = R"(\r)";
206                     break;
207                 case '\t':
208                     sym = R"(\t)";
209                     break;
210                 case '\v':
211                     sym = R"(\v)";
212                     break;
213                 case '\'':
214                     sym = R"(\')";
215                     break;
216                 case '\?':
217                     sym = R"(\?)";
218                     break;
219                 case '\\':
220                     sym = R"(\\)";
221                     break;
222                 default:
223                     UNREACHABLE();
224             }
225             str = str.replace(symPos, 1, sym);
226             ASSERT(sym.size() == 2U);
227             symPos += 2U;
228         }
229         return str;
230     }
231 
232     template <typename T>
LiteralIntegralValueToString(const pandasm::LiteralArray::Literal & lit)233     std::string LiteralIntegralValueToString(const pandasm::LiteralArray::Literal &lit) const
234     {
235         std::stringstream res {};
236         T value = std::get<T>(lit.value);
237         if (lit.IsSigned()) {
238             res << +static_cast<typename std::make_signed<T>::type>(value);
239         } else {
240             res << +value;
241         }
242         return res.str();
243     }
244 
245     void DumpLiteralArray(const pandasm::LiteralArray &literalArray, std::stringstream &ss) const;
246     template <typename T, pandasm::Value::Type VALUE_TYPE>
247     void SetMetadata(panda_file::FieldDataAccessor &accessor, pandasm::Field *field) const;
248     void SerializeFieldValue(const pandasm::Field &f, std::stringstream &ss) const;
249     void GetMetadataFieldValue(panda_file::FieldDataAccessor &fieldAccessor, pandasm::Field *field) const;
250     std::string SerializeLiterals(const pandasm::LiteralArray::Literal &literal) const;
251     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(BytecodeInstruction::Opcode o) const;
252     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(uint8_t o) const;
253     void CollectExternalFields(const panda_file::FieldDataAccessor &fieldAccessor);
254 
255     pandasm::Ins BytecodeInstructionToPandasmInstruction(BytecodeInstruction bcIns,
256                                                          panda_file::File::EntityId methodId) const;
257 
258     std::string IDToString(BytecodeInstruction bcIns, panda_file::File::EntityId methodId) const;
259 
260     ark::panda_file::SourceLang GetRecordLanguage(panda_file::File::EntityId classId) const;
261 
262     std::unique_ptr<const panda_file::File> fileHolder_ {nullptr};
263     const panda_file::File *file_ {};
264     pandasm::Program prog_ {};
265 
266     ark::panda_file::SourceLang fileLanguage_ = ark::panda_file::SourceLang::PANDA_ASSEMBLY;
267 
268     std::map<std::string, panda_file::File::EntityId> recordNameToId_ {};
269     std::map<std::string, panda_file::File::EntityId> methodNameToId_ {};
270 
271     std::map<std::string, std::vector<pandasm::Field>> externalFieldTable_ {};
272     std::map<std::string, std::vector<std::string>> externalFieldsInfoTable_ {};
273 
274     ProgAnnotations progAnn_ {};
275 
276     ProgInfo progInfo_ {};
277 
278     profiling::ProfileContainer profile_ {profiling::INVALID_PROFILE};
279 
280     std::unique_ptr<panda_file::DebugInfoExtractor> debugInfoExtractor_ {nullptr};
281 
282     bool quiet_ {false};
283     bool skipStrings_ {false};
284 
285 #include "disasm_plugins.inc"
286 };
287 }  // namespace ark::disasm
288 
289 #endif
290