• 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 #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) const;
154     void Serialize(const pandasm::Function::CatchBlock &catchBlock, std::ostream &os) const;
155     void Serialize(const pandasm::ItemMetadata &meta, const AnnotationList &annList, std::ostream &os) const;
156     void SerializeLineNumberTable(const panda_file::LineNumberTable &lineNumberTable, std::ostream &os) const;
157     void SerializeLocalVariableTable(const panda_file::LocalVariableTable &localVariableTable,
158                                      const pandasm::Function &method, std::ostream &os) const;
159     void SerializeLanguage(std::ostream &os) const;
160     void SerializeFilename(std::ostream &os) const;
161     void SerializeLitArrays(std::ostream &os, bool addSeparators = false) const;
162     void SerializeRecords(std::ostream &os, bool addSeparators = false, bool printInformation = false) const;
163     void SerializeMethods(std::ostream &os, bool addSeparators = false, bool printInformation = false) const;
164     void SerializePrintStartInfo(const pandasm::Function &method, std::ostringstream &headerSs) const;
165     void SerializeCheckEnd(const pandasm::Function &method, std::ostream &os, bool printMethodInfo,
166                            const MethodInfo *&methodInfo) const;
167     size_t SerializeIfPrintMethodInfo(
168         const pandasm::Function &method, bool printMethodInfo, std::ostringstream &headerSs,
169         const MethodInfo *&methodInfo,
170         std::map<std::string, ark::disasm::MethodInfo>::const_iterator &methodInfoIt) const;
171 
172     void EnumerateAnnotations(panda_file::AnnotationDataAccessor &annotationAccessor, AnnotationList &annList,
173                               const std::string &type, const panda_file::File::EntityId &annotationId);
174 
175     void HandleArrayAnnotation(panda_file::AnnotationDataAccessor &annotationAccessor, AnnotationList &annList,
176                                size_t i);
177 
178     pandasm::Type PFTypeToPandasmType(const panda_file::Type &type, panda_file::ProtoDataAccessor &pda,
179                                       size_t &refIdx) const;
180 
181     pandasm::Type FieldTypeToPandasmType(const uint32_t &type) const;
182 
StringDataToString(panda_file::File::StringData sd)183     static std::string StringDataToString(panda_file::File::StringData sd)
184     {
185         std::string str = std::string(utf::Mutf8AsCString(sd.data));
186         size_t symPos = 0;
187         while (symPos = str.find_first_of("\a\b\f\n\r\t\v\'\?\\", symPos), symPos != std::string::npos) {
188             std::string sym;
189             switch (str[symPos]) {
190                 case '\a':
191                     sym = R"(\a)";
192                     break;
193                 case '\b':
194                     sym = R"(\b)";
195                     break;
196                 case '\f':
197                     sym = R"(\f)";
198                     break;
199                 case '\n':
200                     sym = R"(\n)";
201                     break;
202                 case '\r':
203                     sym = R"(\r)";
204                     break;
205                 case '\t':
206                     sym = R"(\t)";
207                     break;
208                 case '\v':
209                     sym = R"(\v)";
210                     break;
211                 case '\'':
212                     sym = R"(\')";
213                     break;
214                 case '\?':
215                     sym = R"(\?)";
216                     break;
217                 case '\\':
218                     sym = R"(\\)";
219                     break;
220                 default:
221                     UNREACHABLE();
222             }
223             str = str.replace(symPos, 1, sym);
224             ASSERT(sym.size() == 2U);
225             symPos += 2U;
226         }
227         return str;
228     }
229 
230     template <typename T>
LiteralIntegralValueToString(const pandasm::LiteralArray::Literal & lit)231     std::string LiteralIntegralValueToString(const pandasm::LiteralArray::Literal &lit) const
232     {
233         std::stringstream res {};
234         T value = std::get<T>(lit.value);
235         if (lit.IsSigned()) {
236             res << +static_cast<typename std::make_signed<T>::type>(value);
237         } else {
238             res << +value;
239         }
240         return res.str();
241     }
242 
243     void DumpLiteralArray(const pandasm::LiteralArray &literalArray, std::stringstream &ss) const;
244     template <typename T, pandasm::Value::Type VALUE_TYPE>
245     void SetMetadata(panda_file::FieldDataAccessor &accessor, pandasm::Field *field) const;
246     void SerializeFieldValue(const pandasm::Field &f, std::stringstream &ss) const;
247     void GetMetadataFieldValue(panda_file::FieldDataAccessor &fieldAccessor, pandasm::Field *field) const;
248     std::string SerializeLiterals(const pandasm::LiteralArray::Literal &literal) const;
249     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(BytecodeInstruction::Opcode o) const;
250     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(uint8_t o) const;
251     void CollectExternalFields(const panda_file::FieldDataAccessor &fieldAccessor);
252 
253     pandasm::Ins BytecodeInstructionToPandasmInstruction(BytecodeInstruction bcIns,
254                                                          panda_file::File::EntityId methodId) const;
255 
256     std::string IDToString(BytecodeInstruction bcIns, panda_file::File::EntityId methodId) const;
257 
258     ark::panda_file::SourceLang GetRecordLanguage(panda_file::File::EntityId classId) const;
259 
260     std::unique_ptr<const panda_file::File> fileHolder_ {nullptr};
261     const panda_file::File *file_ {};
262     pandasm::Program prog_ {};
263 
264     ark::panda_file::SourceLang fileLanguage_ = ark::panda_file::SourceLang::PANDA_ASSEMBLY;
265 
266     std::map<std::string, panda_file::File::EntityId> recordNameToId_ {};
267     std::map<std::string, panda_file::File::EntityId> methodStaticNameToId_ {};
268     std::map<std::string, panda_file::File::EntityId> methodInstanceNameToId_ {};
269 
270     std::map<std::string, std::vector<pandasm::Field>> externalFieldTable_ {};
271     std::map<std::string, std::vector<std::string>> externalFieldsInfoTable_ {};
272 
273     ProgAnnotations progAnn_ {};
274 
275     ProgInfo progInfo_ {};
276 
277     profiling::ProfileContainer profile_ {profiling::INVALID_PROFILE};
278 
279     std::unique_ptr<panda_file::DebugInfoExtractor> debugInfoExtractor_ {nullptr};
280 
281     bool quiet_ {false};
282     bool skipStrings_ {false};
283 
284 #include "disasm_plugins.inc"
285 };
286 }  // namespace ark::disasm
287 
288 #endif
289