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