• 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 "libpandafile/module_data_accessor-inl.h"
31 #include "param_annotations_data_accessor.h"
32 #include "annotation_data_accessor.h"
33 #include "proto_data_accessor-inl.h"
34 #include "file-inl.h"
35 #include "file.h"
36 #include "os/file.h"
37 
38 #include "assembly-program.h"
39 #include "assembly-ins.h"
40 
41 #include "bytecode_instruction-inl.h"
42 #include "libpandabase/macros.h"
43 
44 #include <map>
45 #include <memory>
46 #include <string>
47 
48 #include "accumulators.h"
49 
50 namespace panda::disasm {
51 class Disassembler {
52 public:
53     NO_COPY_SEMANTIC(Disassembler);
54     DEFAULT_MOVE_SEMANTIC(Disassembler);
55 
56     Disassembler() = default;
57     ~Disassembler() = default;
58 
59     void Disassemble(const std::string &filename_in, const bool quiet = false, const bool skip_strings = false);
60     void CollectInfo();
61     void Serialize(std::ostream &os, bool add_separators = false, bool print_information = false) const;
62 
63     static inline bool IsPandasmFriendly(const char c);
64     static inline bool IsSystemType(const std::string &type_name);
65 
66     void GetRecord(pandasm::Record *record, const panda_file::File::EntityId &record_id);
67     void AddMethodToTables(const panda_file::File::EntityId &method_id);
68     void GetMethod(pandasm::Function *method, const panda_file::File::EntityId &method_id);
69     void GetLiteralArray(pandasm::LiteralArray *lit_array, size_t index) const;
70     std::optional<std::vector<std::string>> GetAnnotationByMethodName(const std::string &method_name) const;
71     std::optional<std::string> GetSerializedRecord(const std::string &record_name) const;
72     std::optional<std::string> GetSerializedMethodAnnotation(const std::string &method_name,
73                                                                            const std::string &anno_name) const;
74     std::vector<std::string> GetStrings() const;
75     std::vector<std::string> GetModuleLiterals() const;
76     template <typename T>
77     void FillLiteralArrayData(pandasm::LiteralArray *lit_array, const panda_file::LiteralTag &tag,
78                               const panda_file::LiteralDataAccessor::LiteralValue &value) const;
79     pandasm::Ins BytecodeInstructionToPandasmInstruction(BytecodeInstruction bc_ins,
80                                                          panda_file::File::EntityId method_id) const;
81 
GetProgInfo()82     const ProgInfo &GetProgInfo() const
83     {
84         return prog_info_;
85     }
86 
87     std::vector<size_t> GetColumnNumber();
88     std::vector<size_t> GetLineNumber();
89 
90 private:
91     void GetLiteralArrays();
92     void FillLiteralArrayTable(panda_file::File::EntityId &id, size_t index);
93     void FillLiteralData(pandasm::LiteralArray *lit_array, const panda_file::LiteralDataAccessor::LiteralValue &value,
94                          const panda_file::LiteralTag &tag) const;
95     void GetRecords();
96     void GetFields(pandasm::Record *record, const panda_file::File::EntityId &record_id);
97 
98     void GetMethods(const panda_file::File::EntityId &record_id);
99     void GetAnnotationElements(pandasm::Function &method, const panda_file::AnnotationDataAccessor &ada,
100                                const std::string &annotation_name);
101     void GetMethodAnnotations(pandasm::Function &method, const panda_file::File::EntityId &method_id);
102     void CreateAnnotationElement(panda_file::AnnotationDataAccessor &ada, pandasm::Function &method,
103                                  const std::string &ann_name, const std::string &ann_elem_name,
104                                  const std::string &ann_elem_index);
105     template <typename T, typename U>
106     void AddAnnotationElement(pandasm::Function &method, const std::string &annotation_name, const std::string &key,
107                               const U &value);
108     void GetParams(pandasm::Function *method, const panda_file::File::EntityId &code_id) const;
109     IdList GetInstructions(pandasm::Function *method, panda_file::File::EntityId method_id,
110                            panda_file::File::EntityId code_id) const;
111     LabelTable GetExceptions(pandasm::Function *method, panda_file::File::EntityId method_id,
112                              panda_file::File::EntityId code_id) const;
113     bool LocateTryBlock(const BytecodeInstruction &bc_ins, const BytecodeInstruction &bc_ins_last,
114                         const panda_file::CodeDataAccessor::TryBlock &try_block,
115                         pandasm::Function::CatchBlock *catch_block_pa, LabelTable *label_table, size_t try_idx) const;
116     bool LocateCatchBlock(const BytecodeInstruction &bc_ins, const BytecodeInstruction &bc_ins_last,
117                           const panda_file::CodeDataAccessor::CatchBlock &catch_block,
118                           pandasm::Function::CatchBlock *catch_block_pa, LabelTable *label_table, size_t try_idx,
119                           size_t catch_idx) const;
120 
121     void GetMetaData(pandasm::Record *record, const panda_file::File::EntityId &record_id) const;
122     void GetMetaData(pandasm::Function *method, const panda_file::File::EntityId &method_id) const;
123     void GetMetaData(pandasm::Field *field, const panda_file::File::EntityId &field_id, bool is_scope_names_record);
124     void GetMetadataFieldValue(panda_file::FieldDataAccessor &field_accessor, pandasm::Field *field,
125                                bool isScopeNamesRecord);
126 
127     void GetLanguageSpecificMetadata();
128 
129     std::string AnnotationTagToString(const char tag) const;
130 
131     std::string ScalarValueToString(const panda_file::ScalarValue &value, const std::string &type);
132     std::string ArrayValueToString(const panda_file::ArrayValue &value, const std::string &type, const size_t idx);
133 
134     std::string GetFullMethodName(const panda_file::File::EntityId &method_id) const;
135     std::string GetMethodSignature(const panda_file::File::EntityId &method_id) const;
136     std::string GetFullRecordName(const panda_file::File::EntityId &class_id) const;
137 
138     void GetRecordInfo(const panda_file::File::EntityId &record_id, RecordInfo *record_info) const;
139     void GetMethodInfo(const panda_file::File::EntityId &method_id, MethodInfo *method_info) const;
140     void GetInsInfo(const panda_file::File::EntityId &code_id, MethodInfo *method_info) const;
141 
142     template <typename T>
143     void SerializeValues(const pandasm::LiteralArray &lit_array, T &os) const;
144     std::string SerializeLiteralArray(const pandasm::LiteralArray &lit_array) const;
145     void Serialize(const std::string &key, const pandasm::LiteralArray &lit_array, std::ostream &os) const;
146     void Serialize(const std::string &module_offset, const std::vector<std::string> &module_array,
147                    std::ostream &os) const;
148     template <typename T>
149     void SerializeLiterals(const pandasm::LiteralArray &lit_array, T &os) const;
150     std::string LiteralTagToString(const panda_file::LiteralTag &tag) const;
151     void Serialize(const pandasm::Record &record, std::ostream &os, bool print_information = false) const;
152     void SerializeFields(const pandasm::Record &record, std::ostream &os, bool print_information) const;
153     void Serialize(const pandasm::Function &method, std::ostream &os, bool print_information = false) const;
154     void SerializeInstructions(const pandasm::Function &method, std::ostream &os,
155                                const std::map<std::string, MethodInfo>::const_iterator &method_info_it,
156                                bool print_method_info = false) const;
157     void SerializeMethodAnnotations(const pandasm::Function &method, std::ostream &os) const;
158     void SerializeMethodAnnotation(const pandasm::AnnotationData &anno, std::ostream &os) const;
159     void SerializeAnnotationElement(const std::vector<pandasm::AnnotationElement> &elements, std::stringstream &ss,
160                                     uint32_t idx) const;
161     void SerializeStrings(const panda_file::File::EntityId &offset, const std::string &name_value,
162                           std::ostream &os) const;
163     void Serialize(const pandasm::Function::CatchBlock &catch_block, std::ostream &os) const;
164     void Serialize(const pandasm::ItemMetadata &meta, const AnnotationList &ann_list, std::ostream &os) const;
165     void SerializeLineNumberTable(const panda_file::LineNumberTable &line_number_table, std::ostream &os) const;
166     void SerializeColumnNumberTable(const panda_file::ColumnNumberTable &column_number_table, std::ostream &os) const;
167     void SerializeLocalVariableTable(const panda_file::LocalVariableTable &local_variable_table,
168                                      const pandasm::Function &method, std::ostream &os) const;
169     bool IsModuleLiteralOffset(const panda_file::File::EntityId &id) const;
170 
171     pandasm::Type PFTypeToPandasmType(const panda_file::Type &type, panda_file::ProtoDataAccessor &pda,
172                                       size_t &ref_idx) const;
173 
174     pandasm::Type FieldTypeToPandasmType(const uint32_t &type) const;
175 
StringDataToString(panda_file::File::StringData sd)176     static inline std::string StringDataToString(panda_file::File::StringData sd)
177     {
178         return std::string(utf::Mutf8AsCString(sd.data));
179     }
180 
181     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(BytecodeInstruction::Opcode o) const;
182     pandasm::Opcode BytecodeOpcodeToPandasmOpcode(uint8_t o) const;
183 
184     std::string IDToString(BytecodeInstruction bc_ins, panda_file::File::EntityId method_id, size_t idx) const;
185 
186     panda::panda_file::SourceLang GetRecordLanguage(panda_file::File::EntityId class_id) const;
187     panda::panda_file::SourceLang GetMethodLanguage(panda_file::File::EntityId class_id) const;
188     void GetLiteralArrayByOffset(pandasm::LiteralArray *lit_array, panda_file::File::EntityId offset) const;
189 
190     std::vector<std::string> GetModuleLiteralArray(panda_file::File::EntityId &module_id) const;
191     std::string SerializeModuleLiteralArray(const std::vector<std::string> &module_array) const;
192     std::string ModuleTagToString(panda_file::ModuleTag &tag) const;
193 
194     std::string getLiteralArrayTypeFromValue(const pandasm::LiteralArray &literal_array) const;
195     void DumpLiteralArray(const pandasm::LiteralArray &literal_array, std::stringstream &ss) const;
196     void SerializeFieldValue(const pandasm::Field &f, std::stringstream &ss) const;
197 
198     std::unique_ptr<const panda_file::File> file_;
199     pandasm::Program prog_;
200 
GetStringByOffset(uint32_t offset)201     inline std::string GetStringByOffset(uint32_t offset) const
202     {
203         const auto sd = file_->GetStringData(panda_file::File::EntityId(offset));
204         return std::string(utf::Mutf8AsCString(sd.data));
205     }
206 
IsValidOffset(uint32_t offset)207     inline bool IsValidOffset(uint32_t offset) const
208     {
209         return panda_file::File::EntityId(offset).IsValid() && offset < file_->GetHeader()->file_size;
210     }
211 
GetFileNameByPath(const std::string & file_path)212     inline std::string GetFileNameByPath(const std::string &file_path) const
213     {
214         size_t pos = file_path.find_last_of(panda::os::file::File::GetPathDelim());
215         if (pos == std::string::npos) {
216             return file_path;
217         }
218 
219         return file_path.substr(pos + 1);
220     }
221 
222     std::map<std::string, panda_file::File::EntityId> record_name_to_id_;
223     std::map<std::string, panda_file::File::EntityId> method_name_to_id_;
224     std::map<std::string, std::vector<std::string>> modulearray_table_;
225     mutable std::map<panda_file::File::EntityId, std::string> string_offset_to_name_;
226 
227     ProgAnnotations prog_ann_;
228 
229     ProgInfo prog_info_;
230 
231     std::unique_ptr<panda_file::DebugInfoExtractor> debug_info_extractor_;
232 
233     bool quiet_;
234     bool skip_strings_;
235     std::unordered_set<uint32_t> module_literals_;
236     std::unordered_set<uint32_t> module_request_phase_literals_;
237 #include "disasm_plugins.inc"
238 };
239 }  // namespace panda::disasm
240 
241 #endif  // DISASSEMBLER_DISASSEMBLER_H
242