1 /*
2 * Copyright (c) 2021 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 "runtime/include/cframe.h"
17 #include "runtime/include/runtime.h"
18 #include "runtime/include/stack_walker.h"
19
20 namespace panda {
21
IsNativeMethod() const22 bool CFrame::IsNativeMethod() const
23 {
24 return GetMethod()->IsNative();
25 }
26
SetVRegValue(const VRegInfo & vreg,uint64_t value,SlotType ** callee_stack)27 void CFrame::SetVRegValue(const VRegInfo &vreg, uint64_t value, SlotType **callee_stack)
28 {
29 auto location_value = static_cast<int>(vreg.GetValue());
30 switch (vreg.GetLocation()) {
31 case VRegInfo::Location::SLOT: {
32 SetValueToSlot(location_value, value);
33 if (!ArchTraits<ARCH>::IS_64_BITS && vreg.Has64BitValue()) {
34 SetValueToSlot(location_value - 1, value >> BITS_PER_UINT32);
35 }
36 break;
37 }
38 case VRegInfo::Location::REGISTER:
39 case VRegInfo::Location::FP_REGISTER: {
40 bool is_fp = vreg.GetLocation() == VRegInfo::Location::FP_REGISTER;
41 if ((GetCallerRegsMask(ARCH, is_fp) & (1U << vreg.GetValue())) != 0) {
42 CFrameLayout fl(ARCH, 0);
43 auto reg_num = location_value - GetFirstCallerReg(ARCH, is_fp);
44 reg_num = fl.GetCallerLastSlot(is_fp) - reg_num;
45 SetValueToSlot(reg_num, value);
46 if (!ArchTraits<ARCH>::IS_64_BITS && vreg.Has64BitValue()) {
47 SetValueToSlot(static_cast<int>(reg_num) - 1, value >> BITS_PER_UINT32);
48 }
49 break;
50 }
51 WriteCalleeSavedRegister(location_value, value, is_fp, callee_stack);
52 if constexpr (!ArchTraits<ARCH>::IS_64_BITS) { // NOLINT
53 if (vreg.Has64BitValue()) {
54 WriteCalleeSavedRegister(location_value + 1, value >> BITS_PER_UINT32, is_fp, callee_stack);
55 }
56 break;
57 }
58 break;
59 }
60 case VRegInfo::Location::CONSTANT:
61 ASSERT(false && "Modifying constants is not permitted"); // NOLINT(misc-static-assert)
62 break;
63 default:
64 UNREACHABLE();
65 }
66 }
67
Dump(std::ostream & os,uint32_t max_slot)68 void CFrame::Dump(std::ostream &os, uint32_t max_slot)
69 {
70 if (IsJni()) {
71 os << "JNI CFRAME: fp=" << fp_ << std::endl;
72 return;
73 }
74 auto spill_start_slot = GetCalleeRegsCount(ARCH, false) + GetCalleeRegsCount(ARCH, true) +
75 GetCallerRegsCount(ARCH, false) + GetCallerRegsCount(ARCH, true);
76 max_slot = max_slot > spill_start_slot ? (max_slot - spill_start_slot) : 0;
77
78 auto print_mem = [](std::ostream &stream, void *addr, std::string_view dscr, uintptr_t value) {
79 constexpr size_t WIDTH = 16;
80 stream << ' ' << addr << ": " << std::setw(WIDTH) << std::setfill(' ') << dscr << " 0x" << std::hex << value
81 << std::dec << std::endl;
82 };
83 os << "****************************************\n";
84 os << "* CFRAME: fp=" << fp_ << ", max_spill_slot=" << max_slot << '\n';
85 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
86 print_mem(os, fp_ - CFrameLayout::LrSlot::Start(), "lr", GetLr());
87 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
88 print_mem(os, fp_ - CFrameLayout::PrevFrameSlot::Start(), "prev", reinterpret_cast<uintptr_t>(GetPrevFrame()));
89 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
90 print_mem(os, fp_ - CFrameLayout::MethodSlot::Start(), "method", reinterpret_cast<uintptr_t>(GetMethod()));
91 PandaString dscr;
92 size_t slot = 0;
93 DumpCalleeRegs(os, print_mem, &dscr, &slot);
94 DumpCalleeFPRegs(os, print_mem, &dscr, &slot);
95 DumpCallerRegs(os, print_mem, &dscr, &slot);
96 DumpCallerFPRegs(os, print_mem, &dscr, &slot);
97 DumpLocals(os, print_mem, &dscr, &slot, max_slot);
98
99 os << "* CFRAME END\n";
100 os << "****************************************\n";
101 }
102
DumpCalleeRegs(std::ostream & os,MemPrinter print_mem,PandaString * dscr,size_t * slot)103 void CFrame::DumpCalleeRegs(std::ostream &os, MemPrinter print_mem, PandaString *dscr, size_t *slot)
104 {
105 os << " [Callee saved registers]\n";
106 for (auto i = panda::helpers::ToSigned(GetLastCalleeReg(ARCH, false));
107 i >= panda::helpers::ToSigned(GetFirstCalleeReg(ARCH, false)); i--, (*slot)++) {
108 *dscr = "x" + ToPandaString(i) + ":" + ToPandaString(*slot);
109 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
110 print_mem(os, fp_ - CFrameLayout::STACK_START_SLOT - *slot, *dscr, GetValueFromSlot(*slot));
111 }
112 }
113
DumpCalleeFPRegs(std::ostream & os,MemPrinter print_mem,PandaString * dscr,size_t * slot)114 void CFrame::DumpCalleeFPRegs(std::ostream &os, MemPrinter print_mem, PandaString *dscr, size_t *slot)
115 {
116 os << " [Callee saved FP registers]\n";
117 for (auto i = panda::helpers::ToSigned(GetLastCalleeReg(ARCH, true));
118 i >= panda::helpers::ToSigned(GetFirstCalleeReg(ARCH, true)); i--, (*slot)++) {
119 *dscr = "d" + ToPandaString(i) + ":" + ToPandaString(*slot);
120 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
121 print_mem(os, fp_ - CFrameLayout::STACK_START_SLOT - *slot, *dscr, GetValueFromSlot(*slot));
122 }
123 }
124
DumpCallerRegs(std::ostream & os,MemPrinter print_mem,PandaString * dscr,size_t * slot)125 void CFrame::DumpCallerRegs(std::ostream &os, MemPrinter print_mem, PandaString *dscr, size_t *slot)
126 {
127 os << " [Caller saved registers] " << GetLastCallerReg(ARCH, false) << " " << GetFirstCallerReg(ARCH, false)
128 << "\n";
129 for (auto i = panda::helpers::ToSigned(GetLastCallerReg(ARCH, false));
130 i >= panda::helpers::ToSigned(GetFirstCallerReg(ARCH, false)); i--, (*slot)++) {
131 *dscr = "x" + ToPandaString(i) + ":" + ToPandaString(*slot);
132 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
133 print_mem(os, fp_ - CFrameLayout::STACK_START_SLOT - *slot, *dscr, GetValueFromSlot(*slot));
134 }
135 }
136
DumpCallerFPRegs(std::ostream & os,MemPrinter print_mem,PandaString * dscr,size_t * slot)137 void CFrame::DumpCallerFPRegs(std::ostream &os, MemPrinter print_mem, PandaString *dscr, size_t *slot)
138 {
139 os << " [Caller saved FP registers]\n";
140 for (auto i = panda::helpers::ToSigned(GetLastCallerReg(ARCH, true));
141 i >= panda::helpers::ToSigned(GetFirstCallerReg(ARCH, true)); i--, (*slot)++) {
142 *dscr = "d" + ToPandaString(i) + ":" + ToPandaString(*slot);
143 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
144 print_mem(os, fp_ - CFrameLayout::STACK_START_SLOT - *slot, *dscr, GetValueFromSlot(*slot));
145 }
146 }
147
DumpLocals(std::ostream & os,MemPrinter print_mem,PandaString * dscr,size_t * slot,int32_t max_slot)148 void CFrame::DumpLocals(std::ostream &os, MemPrinter print_mem, PandaString *dscr, size_t *slot, int32_t max_slot)
149 {
150 os << " [Locals]\n";
151 for (auto i = 0; i <= max_slot; i++, (*slot)++) {
152 *dscr = "s" + ToPandaString(i) + ":" + ToPandaString(*slot);
153 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
154 print_mem(os, fp_ - CFrameLayout::STACK_START_SLOT - *slot, *dscr, GetValueFromSlot(*slot));
155 }
156 }
157
158 } // namespace panda
159