• 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#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