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