• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 DISASSEMBLER_DISASSEMBLER_H
17 #define DISASSEMBLER_DISASSEMBLER_H
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 "assembly-program.h"
38 #include "assembly-ins.h"
39 
40 #include "bytecode_instruction-inl.h"
41 #include "libpandabase/macros.h"
42 
43 #include <map>
44 #include <memory>
45 #include <string>
46 
47 #include "accumulators.h"
48 
49 namespace panda::disasm {
50 class Disassembler {
51 public:
52     NO_COPY_SEMANTIC(Disassembler);
53     DEFAULT_MOVE_SEMANTIC(Disassembler);
54 
55     Disassembler() = default;
56     ~Disassembler() = default;
57 
58     void Disassemble(const std::string &filename_in, const bool quiet = false, const bool skip_strings = false);
59     void CollectInfo();
60     void Serialize(std::ostream &os, bool add_separators = false, bool print_information = false) const;
61 
62     static inline bool IsPandasmFriendly(const char c);
63     static inline bool IsSystemType(const std::string &type_name);
64 
65     void GetRecord(pandasm::Record *record, const panda_file::File::EntityId &record_id);
66     void AddMethodToTables(const panda_file::File::EntityId &method_id);
67     void GetMethod(pandasm::Function *method, const panda_file::File::EntityId &method_id);
68     void GetLiteralArray(pandasm::LiteralArray *lit_array, size_t index) const;
69     template <typename T>
70     void FillLiteralArrayData(pandasm::LiteralArray *lit_array, const panda_file::LiteralTag &tag,
71                               const panda_file::LiteralDataAccessor::LiteralValue &value) const;
72 
GetProgInfo()73     const ProgInfo &GetProgInfo() const
74     {
75         return prog_info_;
76     }
77 
78 private:
79     void GetLiteralArrays();
80     void FillLiteralData(pandasm::LiteralArray *lit_array, const panda_file::LiteralDataAccessor::LiteralValue &value,
81                          const panda_file::LiteralTag &tag) const;
82     void GetRecords();
83     void GetFields(pandasm::Record *record, const panda_file::File::EntityId &record_id);
84 
85     void GetMethods(const panda_file::File::EntityId &record_id);
86     void GetParams(pandasm::Function *method, const panda_file::File::EntityId &proto_id) const;
87     IdList GetInstructions(pandasm::Function *method, panda_file::File::EntityId method_id,
88                            panda_file::File::EntityId code_id) const;
89     LabelTable GetExceptions(pandasm::Function *method, panda_file::File::EntityId method_id,
90                              panda_file::File::EntityId code_id) const;
91     bool LocateTryBlock(const BytecodeInstruction &bc_ins, const BytecodeInstruction &bc_ins_last,
92                         const panda_file::CodeDataAccessor::TryBlock &try_block,
93                         pandasm::Function::CatchBlock *catch_block_pa, LabelTable *label_table, size_t try_idx) const;
94     bool LocateCatchBlock(const BytecodeInstruction &bc_ins, const BytecodeInstruction &bc_ins_last,
95                           const panda_file::CodeDataAccessor::CatchBlock &catch_block,
96                           pandasm::Function::CatchBlock *catch_block_pa, LabelTable *label_table, size_t try_idx,
97                           size_t catch_idx) const;
98 
99     void GetMetaData(pandasm::Record *record, const panda_file::File::EntityId &record_id) const;
100     void GetMetaData(pandasm::Function *method, const panda_file::File::EntityId &method_id) const;
101     void GetMetaData(pandasm::Field *field, const panda_file::File::EntityId &field_id);
102 
103     void GetLanguageSpecificMetadata();
104 
105     std::string AnnotationTagToString(const char tag) const;
106 
107     std::string ScalarValueToString(const panda_file::ScalarValue &value, const std::string &type);
108     std::string ArrayValueToString(const panda_file::ArrayValue &value, const std::string &type, const size_t idx);
109 
110     std::string GetFullMethodName(const panda_file::File::EntityId &method_id) const;
111     std::string GetMethodSignature(const panda_file::File::EntityId &method_id) const;
112     std::string GetFullRecordName(const panda_file::File::EntityId &class_id) const;
113 
114     void GetRecordInfo(const panda_file::File::EntityId &record_id, RecordInfo *record_info) const;
115     void GetMethodInfo(const panda_file::File::EntityId &method_id, MethodInfo *method_info) const;
116     void GetInsInfo(const panda_file::File::EntityId &code_id, MethodInfo *method_info) const;
117 
118     template <typename T>
119     void SerializeValues(const pandasm::LiteralArray &lit_array, T &os) const;
120     std::string SerializeLiteralArray(const pandasm::LiteralArray &lit_array) const;
121     void Serialize(const std::string &key, const pandasm::LiteralArray &lit_array, std::ostream &os) const;
122     template <typename T>
123     void SerializeLiterals(const pandasm::LiteralArray &lit_array, T &os) const;
124     std::string LiteralTagToString(const panda_file::LiteralTag &tag) const;
125     void Serialize(const pandasm::Record &record, std::ostream &os, bool print_information = false) const;
126     void SerializeFields(const pandasm::Record &record, std::ostream &os, bool print_information) const;
127     void Serialize(const pandasm::Function &method, std::ostream &os, bool print_information = false) const;
128     void Serialize(const pandasm::Function::CatchBlock &catch_block, std::ostream &os) const;
129     void Serialize(const pandasm::ItemMetadata &meta, const AnnotationList &ann_list, std::ostream &os) const;
130     void SerializeLineNumberTable(const panda_file::LineNumberTable &line_number_table, std::ostream &os) const;
131     void SerializeLocalVariableTable(const panda_file::LocalVariableTable &local_variable_table,
132                                      const pandasm::Function &method, std::ostream &os) const;
133     bool IsModuleLiteralOffset(const panda_file::File::EntityId &id) const;
SerializeLanguage(std::ostream & os)134     inline void SerializeLanguage(std::ostream &os) const
135     {
136         os << ".language " << panda::panda_file::LanguageToString(file_language_) << "\n\n";
137     }
138 
139     pandasm::Type PFTypeToPandasmType(const panda_file::Type &type, panda_file::ProtoDataAccessor &pda,
140                                       size_t &ref_idx) const;
141 
142     pandasm::Type FieldTypeToPandasmType(const uint32_t &type) const;
143 
StringDataToString(panda_file::File::StringData sd)144     static inline std::string StringDataToString(panda_file::File::StringData sd)
145     {
146         return std::string(utf::Mutf8AsCString(sd.data));
147     }
148 
149     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(BytecodeInstruction::Opcode o) const;
150     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(uint8_t o) const;
151 
152     pandasm::Ins BytecodeInstructionToPandasmInstruction(BytecodeInstruction bc_ins,
153                                                          panda_file::File::EntityId method_id) const;
154 
155     std::string IDToString(BytecodeInstruction bc_ins, panda_file::File::EntityId method_id, size_t idx) const;
156 
157     panda::panda_file::SourceLang GetRecordLanguage(panda_file::File::EntityId class_id) const;
158 
159     void GetLiteralArrayByOffset(pandasm::LiteralArray *lit_array, panda_file::File::EntityId offset) const;
160 
161     std::unique_ptr<const panda_file::File> file_;
162     pandasm::Program prog_;
163 
164     panda::panda_file::SourceLang file_language_ = panda::panda_file::SourceLang::PANDA_ASSEMBLY;
165 
166     std::map<std::string, panda_file::File::EntityId> record_name_to_id_;
167     std::map<std::string, panda_file::File::EntityId> method_name_to_id_;
168 
169     ProgAnnotations prog_ann_;
170 
171     ProgInfo prog_info_;
172 
173     std::unique_ptr<panda_file::DebugInfoExtractor> debug_info_extractor_;
174 
175     bool quiet_;
176     bool skip_strings_;
177     std::unordered_set<uint32_t> module_literals_;
178 #include "disasm_plugins.inc"
179 };
180 }  // namespace panda::disasm
181 
182 #endif  // DISASSEMBLER_DISASSEMBLER_H
183