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#include "disassembler.h" 17 18namespace panda::disasm { 19 20pandasm::Ins Disassembler::BytecodeInstructionToPandasmInstruction(BytecodeInstruction bc_ins, 21 panda_file::File::EntityId method_id) const { 22 pandasm::Ins ins{}; 23 24 ins.opcode = BytecodeOpcodeToPandasmOpcode(bc_ins.GetOpcode()); 25 26 const BytecodeInstruction::Format format = bc_ins.GetFormat(); 27 28 switch (format) { 29% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| 30% imm_count = 0 31% reg_count = 0 32% id_count = 0 33 case BytecodeInstruction::Format::<%=i.format.pretty.upcase%>: 34% 35% i.operands.each do |operand| 36% if (operand.name == :imm) 37% if (operand.type != "i64") 38 ins.imms.push_back(static_cast<int64_t>(bc_ins.GetImm<BytecodeInstruction::Format::<%=i.format.pretty.upcase%>, <%=imm_count%>>())); 39% else 40 ins.imms.push_back(bc_ins.GetImm<BytecodeInstruction::Format::<%=i.format.pretty.upcase%>, <%=imm_count%>>()); 41% end 42% imm_count += 1 43% 44% elsif (operand.name == :v) 45 ins.regs.push_back(bc_ins.GetVReg(<%=reg_count%>)); 46% reg_count += 1 47% elsif (i.operands.count(&:id?) != 0) 48 ins.ids.push_back(IDToString(bc_ins, method_id, <%=id_count%>)); 49% id_count += 1 50% end 51% end 52 break; 53% end 54 default: 55 break; 56 } 57 58 if (ins.IsCall()) { 59 // clearing excessive arguments if there are any 60 // if format has ID in it - recieve it. else instruction is indirect call and id = method_id 61 panda_file::File::EntityId id; 62 63 if (bc_ins.HasId(format, 0)) { 64 auto idx = bc_ins.GetId().AsIndex(); 65 id = file_->ResolveMethodIndex(method_id, idx); 66 } else { 67 id = method_id; 68 } 69 70 panda_file::MethodDataAccessor mda(*file_, id); 71 panda_file::ProtoDataAccessor pda(*file_, mda.GetProtoId()); 72 73 int overhead; 74 75 if (mda.IsStatic()) { 76 overhead = ins.regs.size() - pda.GetNumArgs(); 77 } else { 78 overhead = ins.regs.size() - pda.GetNumArgs() - 1; 79 } 80 if (overhead < 0 || overhead > static_cast<int>(ins.regs.size())) { 81 LOG(ERROR, DISASSEMBLER) 82 << "> error encountered in code of " << std::dec << method_id.GetOffset() << " (" 83 << "0x" << std::hex << method_id.GetOffset() << ") while disassembling call <" << ins.ToString("") 84 << ">. Invalid method id given or corrupted: calculated overhead (difference " 85 "between amount of registers specified by instruction format and amount of function's arguments) " 86 "exceeds number of registers specified in ISA or is lesser than 0!"; 87 return ins; 88 } 89 90 for (int i = 0; i < overhead; i++) { 91 ins.regs.pop_back(); 92 } 93 } 94 95 return ins; 96} 97 98} // namespace panda::disasm 99