1/* 2 * Copyright (c) 2023-2024 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 "dfx_instructions.h" 17 18#include <algorithm> 19#include <cstdio> 20#include <cstdlib> 21 22#include "dfx_define.h" 23#include "dfx_errors.h" 24#include "dfx_log.h" 25#include "dfx_instr_statistic.h" 26#include "dfx_regs_qut.h" 27#include "dwarf_op.h" 28 29namespace OHOS { 30namespace HiviewDFX { 31namespace { 32#undef LOG_DOMAIN 33#undef LOG_TAG 34#define LOG_DOMAIN 0xD002D11 35#define LOG_TAG "DfxInstructions" 36} 37 38bool DfxInstructions::Flush(DfxRegs& regs, std::shared_ptr<DfxMemory> memory, uintptr_t cfa, RegLoc loc, uintptr_t& val) 39{ 40 if (memory == nullptr) { 41 return false; 42 } 43 uintptr_t location; 44 switch (loc.type) { 45 case REG_LOC_VAL_OFFSET: 46 val = cfa + static_cast<uintptr_t>(loc.val); 47 break; 48 case REG_LOC_MEM_OFFSET: 49 location = cfa + static_cast<uintptr_t>(loc.val); 50 memory->ReadUptr(location, &val); 51 break; 52 case REG_LOC_REGISTER: 53 location = static_cast<uintptr_t>(loc.val); 54 if (location >= regs.RegsSize()) { 55 DFXLOGE("Illegal register location"); 56 return false; 57 } 58 val = regs[location]; 59 break; 60 case REG_LOC_MEM_EXPRESSION: { 61 DwarfOp<uintptr_t> dwarfOp(memory); 62 location = dwarfOp.Eval(regs, cfa, loc.val); 63 memory->ReadUptr(location, &val); 64 break; 65 } 66 case REG_LOC_VAL_EXPRESSION: { 67 DwarfOp<uintptr_t> dwarfOp(memory); 68 val = dwarfOp.Eval(regs, cfa, loc.val); 69 break; 70 } 71 default: 72 DFXLOGE("Failed to save register."); 73 return false; 74 } 75 return true; 76} 77 78bool DfxInstructions::Apply(std::shared_ptr<DfxMemory> memory, DfxRegs& regs, RegLocState& rsState, uint16_t& errCode) 79{ 80 uintptr_t cfa = 0; 81 RegLoc cfaLoc; 82 if (rsState.cfaReg != 0) { 83 cfa = regs[rsState.cfaReg] + static_cast<uint32_t>(rsState.cfaRegOffset); 84 } else if (rsState.cfaExprPtr != 0) { 85 cfaLoc.type = REG_LOC_VAL_EXPRESSION; 86 cfaLoc.val = static_cast<intptr_t>(rsState.cfaExprPtr); 87 if (!Flush(regs, memory, 0, cfaLoc, cfa)) { 88 DFXLOGE("Failed to update cfa."); 89 return false; 90 } 91 } else { 92 DFXLOGE("no cfa info exist?"); 93 INSTR_STATISTIC(UnsupportedDefCfa, rsState.cfaReg, UNW_ERROR_NOT_SUPPORT); 94 return false; 95 } 96 DFXLOGU("Update cfa : %{public}" PRIx64 "", (uint64_t)cfa); 97 98 for (size_t i = 0; i < rsState.locs.size(); i++) { 99 if (rsState.locs[i].type != REG_LOC_UNUSED) { 100 size_t reg = DfxRegsQut::GetQutRegs()[i]; 101 if (Flush(regs, memory, cfa, rsState.locs[i], regs[reg])) { 102 DFXLOGU("Update reg[%{public}zu] : %{public}" PRIx64 "", reg, (uint64_t)regs[reg]); 103 } 104 } 105 } 106 107 regs.SetSp(cfa); 108 109 if (rsState.returnAddressUndefined) { 110 regs.SetPc(0); 111 errCode = UNW_ERROR_RETURN_ADDRESS_UNDEFINED; 112 return false; 113 } else { 114 if (rsState.returnAddressRegister >= REG_EH && rsState.returnAddressRegister < REG_LAST) { 115 DFXLOGU("returnAddressRegister: %{public}d", (int)rsState.returnAddressRegister); 116 regs.SetPc(regs[rsState.returnAddressRegister]); 117 } else { 118 DFXLOGE("returnAddressRegister: %{public}d error", (int)rsState.returnAddressRegister); 119 errCode = UNW_ERROR_ILLEGAL_VALUE; 120 return false; 121 } 122 } 123 if (rsState.returnAddressSame) { 124 errCode = UNW_ERROR_RETURN_ADDRESS_SAME; 125 return false; 126 } 127 128 return true; 129} 130} // namespace HiviewDFX 131} // namespace OHOS 132