1 2 /* 3 * Copyright (c) 2023 Huawei Device Co., Ltd. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #ifndef DFX_DWARF_EXPRESSION_H 17 #define DFX_DWARF_EXPRESSION_H 18 19 #include <cinttypes> 20 #include <deque> 21 #include <type_traits> 22 #include <memory> 23 #include "dfx_errors.h" 24 #include "dfx_instr_statistic.h" 25 #include "dfx_memory.h" 26 #include "dfx_regs.h" 27 #include "dfx_regs_qut.h" 28 #include "dwarf_cfa_instructions.h" 29 30 namespace OHOS { 31 namespace HiviewDFX { 32 // DWARF expressions describe how to compute a value or specify a location. 33 // They 2 are expressed in terms of DWARF operations that operate on a stack of values 34 template <typename AddressType> 35 class DwarfOp { 36 using SignedType = typename std::make_signed<AddressType>::type; 37 using UnsignedType = typename std::make_unsigned<AddressType>::type; 38 39 public: DwarfOp(std::shared_ptr<DfxMemory> memory)40 DwarfOp(std::shared_ptr<DfxMemory> memory) : memory_(memory) {}; 41 virtual ~DwarfOp() = default; 42 43 AddressType Eval(DfxRegs& regs, AddressType initStackValue, AddressType startPtr); 44 45 protected: 46 bool Decode(DfxRegs& regs, uintptr_t& addr); 47 StackReset(AddressType initialStackValue)48 inline void StackReset(AddressType initialStackValue) 49 { 50 stack_.clear(); 51 stack_.push_front(initialStackValue); 52 }; 53 StackPush(AddressType value)54 inline void StackPush(AddressType value) 55 { 56 stack_.push_front(value); 57 } 58 StackPop()59 inline AddressType StackPop() 60 { 61 AddressType value = stack_.front(); 62 stack_.pop_front(); 63 return value; 64 } 65 StackAt(size_t index)66 inline AddressType StackAt(size_t index) { return stack_[index]; } StackSize()67 inline size_t StackSize() { return stack_.size(); } 68 69 /* DW_OP_addr DW_OP_constXs DW_OP_constXu */ 70 template <typename T> OpPush(T value)71 inline void OpPush(T value) 72 { 73 StackPush(static_cast<AddressType>(value)); 74 }; 75 76 /* DW_OP_deref */ OpDeref()77 inline void OpDeref() 78 { 79 auto addr = static_cast<uintptr_t>(StackPop()); 80 uintptr_t val; 81 memory_->ReadUptr(addr, &val); 82 StackPush(static_cast<AddressType>(val)); 83 }; 84 85 /* DW_OP_deref_size */ OpDerefSize(AddressType & exprPtr)86 void OpDerefSize(AddressType& exprPtr) 87 { 88 auto addr = static_cast<uintptr_t>(StackPop()); 89 AddressType value = 0; 90 uint8_t operand; 91 memory_->ReadU8(exprPtr, &operand, true); 92 switch (operand) { 93 case 1: { // 1 : read one byte length 94 uint8_t u8; 95 memory_->ReadU8(addr, &u8, true); 96 value = static_cast<AddressType>(u8); 97 } 98 break; 99 case 2: { // 2 : read two bytes length 100 uint16_t u16; 101 memory_->ReadU16(addr, &u16, true); 102 value = static_cast<AddressType>(u16); 103 } 104 break; 105 case 3: // 3 : read four bytes length 106 case 4: { // 4 : read four bytes length 107 uint32_t u32; 108 memory_->ReadU32(addr, &u32, true); 109 value = static_cast<AddressType>(u32); 110 } 111 break; 112 case 5: // 5 : read eight bytes length 113 case 6: // 6 : read eight bytes length 114 case 7: // 7 : read eight bytes length 115 case 8: { // 8 : read eight bytes length 116 uint64_t u64; 117 memory_->ReadU64(addr, &u64, true); 118 value = static_cast<AddressType>(u64); 119 } 120 break; 121 default: 122 break; 123 } 124 StackPush(static_cast<UnsignedType>(value)); 125 }; 126 127 /* DW_OP_dup */ OpDup()128 inline void OpDup() 129 { 130 StackPush(StackAt(0)); 131 }; 132 133 /* DW_OP_drop */ OpDrop()134 inline void OpDrop() 135 { 136 StackPop(); 137 }; 138 139 /* DW_OP_over */ OpOver()140 inline void OpOver() 141 { 142 StackPush(StackAt(1)); 143 }; 144 145 /* DW_OP_pick */ OpPick(AddressType & exprPtr)146 inline void OpPick(AddressType& exprPtr) 147 { 148 uint8_t reg; 149 memory_->ReadU8(exprPtr, ®, true); 150 if (reg > StackSize()) { 151 return; 152 } 153 AddressType value = StackAt(reg); 154 StackPush(value); 155 }; 156 157 /* DW_OP_swap */ OpSwap()158 inline void OpSwap() 159 { 160 AddressType oldValue = stack_[0]; 161 stack_[0] = stack_[1]; 162 stack_[1] = oldValue; 163 } 164 165 /* DW_OP_rot */ OpRot()166 inline void OpRot() 167 { 168 AddressType top = stack_[0]; 169 stack_[0] = stack_[1]; 170 stack_[1] = stack_[2]; // 2:the index of the array 171 stack_[2] = top; // 2:the index of the array 172 } 173 174 /* DW_OP_abs */ OpAbs()175 inline void OpAbs() 176 { 177 SignedType signedValue = static_cast<SignedType>(stack_[0]); 178 if (signedValue < 0) { 179 signedValue = -signedValue; 180 } 181 stack_[0] = static_cast<AddressType>(signedValue); 182 }; 183 184 /* DW_OP_and */ OpAnd()185 inline void OpAnd() 186 { 187 AddressType top = StackPop(); 188 stack_[0] &= top; 189 }; 190 191 /* DW_OP_div */ OpDiv()192 inline void OpDiv() 193 { 194 AddressType top = StackPop(); 195 if (top == 0) { 196 return; 197 } 198 SignedType signedDivisor = static_cast<SignedType>(top); 199 SignedType signedDividend = static_cast<SignedType>(stack_[0]); 200 stack_[0] = static_cast<AddressType>(signedDividend / signedDivisor); 201 }; 202 203 /* DW_OP_minus */ OpMinus()204 inline void OpMinus() 205 { 206 AddressType top = StackPop(); 207 stack_[0] -= top; 208 }; 209 210 /* DW_OP_mod */ OpMod()211 inline void OpMod() 212 { 213 AddressType top = StackPop(); 214 if (top == 0) { 215 return; 216 } 217 stack_[0] %= top; 218 }; 219 220 /* DW_OP_mul */ OpMul()221 inline void OpMul() 222 { 223 AddressType top = StackPop(); 224 stack_[0] *= top; 225 }; 226 OpNeg()227 inline void OpNeg() 228 { 229 SignedType signedValue = static_cast<SignedType>(stack_[0]); 230 stack_[0] = static_cast<AddressType>(-signedValue); 231 }; 232 OpNot()233 inline void OpNot() 234 { 235 stack_[0] = ~stack_[0]; 236 }; 237 OpOr()238 inline void OpOr() 239 { 240 AddressType top = StackPop(); 241 stack_[0] |= top; 242 }; 243 OpPlus()244 inline void OpPlus() 245 { 246 AddressType top = StackPop(); 247 stack_[0] += top; 248 }; 249 OpPlusULEBConst(AddressType & exprPtr)250 inline void OpPlusULEBConst(AddressType& exprPtr) 251 { 252 stack_[0] += memory_->ReadUleb128(exprPtr); 253 }; 254 OpShl()255 inline void OpShl() 256 { 257 AddressType top = StackPop(); 258 stack_[0] <<= top; 259 }; 260 OpShr()261 inline void OpShr() 262 { 263 AddressType top = StackPop(); 264 stack_[0] >>= top; 265 }; 266 OpShra()267 inline void OpShra() 268 { 269 AddressType top = StackPop(); 270 SignedType signedValue = static_cast<SignedType>(stack_[0]) >> top; 271 stack_[0] = static_cast<AddressType>(signedValue); 272 }; 273 OpXor()274 inline void OpXor() 275 { 276 AddressType top = StackPop(); 277 stack_[0] ^= top; 278 }; 279 OpSkip(AddressType & exprPtr)280 inline void OpSkip(AddressType& exprPtr) 281 { 282 int16_t offset; 283 memory_->ReadS16(exprPtr, &offset, true); 284 exprPtr = static_cast<AddressType>(exprPtr + offset); 285 }; 286 287 // DW_OP_bra OpBra(AddressType & exprPtr)288 inline void OpBra(AddressType& exprPtr) 289 { 290 AddressType top = StackPop(); 291 int16_t offset; 292 memory_->ReadS16(exprPtr, &offset, true); 293 if (top != 0) { 294 exprPtr = exprPtr + offset; 295 } 296 }; 297 OpEQ()298 inline void OpEQ() 299 { 300 AddressType top = StackPop(); 301 stack_[0] = ((stack_[0] == top) ? 1 : 0); 302 }; 303 OpGE()304 inline void OpGE() 305 { 306 AddressType top = StackPop(); 307 stack_[0] = ((stack_[0] >= top) ? 1 : 0); 308 }; 309 OpGT()310 inline void OpGT() 311 { 312 AddressType top = StackPop(); 313 stack_[0] = ((stack_[0] > top) ? 1 : 0); 314 }; 315 OpLE()316 inline void OpLE() 317 { 318 AddressType top = StackPop(); 319 stack_[0] = ((stack_[0] <= top) ? 1 : 0); 320 }; 321 OpLT()322 inline void OpLT() 323 { 324 AddressType top = StackPop(); 325 stack_[0] = ((stack_[0] < top) ? 1 : 0); 326 }; 327 OpNE()328 inline void OpNE() 329 { 330 AddressType top = StackPop(); 331 stack_[0] = ((stack_[0] != top) ? 1 : 0); 332 }; 333 334 // DW_OP_litXX OpLit(uint8_t opcode)335 inline void OpLit(uint8_t opcode) 336 { 337 stack_.push_front(opcode - DW_OP_lit0); 338 }; 339 340 // DW_OP_regXX OpReg(uint8_t opcode,DfxRegs & regs)341 inline void OpReg(uint8_t opcode, DfxRegs& regs) 342 { 343 auto reg = static_cast<UnsignedType>(opcode - DW_OP_reg0); 344 size_t qutIdx = 0; 345 if (!DfxRegsQut::IsQutReg(static_cast<uint16_t>(reg), qutIdx)) { 346 INSTR_STATISTIC(UnsupportedDwarfOp_Reg, reg, UNW_ERROR_UNSUPPORTED_QUT_REG); 347 return; 348 } 349 stack_.push_front(regs[reg]); 350 }; 351 352 // DW_OP_regx OpRegx(AddressType & exprPtr,DfxRegs & regs)353 inline void OpRegx(AddressType& exprPtr, DfxRegs& regs) 354 { 355 auto reg = static_cast<uint32_t>(memory_->ReadUleb128(exprPtr)); 356 size_t qutIdx = 0; 357 if (!DfxRegsQut::IsQutReg(static_cast<uint16_t>(reg), qutIdx)) { 358 INSTR_STATISTIC(UnsupportedDwarfOp_Regx, reg, UNW_ERROR_UNSUPPORTED_QUT_REG); 359 return; 360 } 361 stack_.push_front(regs[reg]); 362 }; 363 OpBReg(uint8_t opcode,AddressType & exprPtr,DfxRegs & regs)364 inline void OpBReg(uint8_t opcode, AddressType& exprPtr, DfxRegs& regs) 365 { 366 auto reg = static_cast<uint32_t>(opcode - DW_OP_breg0); 367 size_t qutIdx = 0; 368 if (!DfxRegsQut::IsQutReg(static_cast<uint16_t>(reg), qutIdx)) { 369 INSTR_STATISTIC(UnsupportedDwarfOp_Breg, reg, UNW_ERROR_UNSUPPORTED_QUT_REG); 370 return; 371 } 372 auto value = static_cast<SignedType>(memory_->ReadSleb128(exprPtr)); 373 value += static_cast<SignedType>(regs[reg]); 374 stack_.push_front(value); 375 }; 376 OpBRegx(AddressType & exprPtr,DfxRegs & regs)377 inline void OpBRegx(AddressType& exprPtr, DfxRegs& regs) 378 { 379 auto reg = static_cast<uint32_t>(memory_->ReadUleb128(exprPtr)); 380 size_t qutIdx = 0; 381 if (!DfxRegsQut::IsQutReg(static_cast<uint16_t>(reg), qutIdx)) { 382 INSTR_STATISTIC(UnsupportedDwarfOp_Bregx, reg, UNW_ERROR_UNSUPPORTED_QUT_REG); 383 return; 384 } 385 auto value = static_cast<SignedType>(memory_->ReadSleb128(exprPtr)); 386 value += static_cast<SignedType>(regs[reg]); 387 stack_.push_front(value); 388 }; 389 OpNop(uint8_t opcode)390 inline void OpNop(uint8_t opcode) 391 { 392 // log un-implemmented operate codes 393 }; 394 395 protected: 396 std::shared_ptr<DfxMemory> memory_; 397 std::deque<AddressType> stack_; 398 }; 399 } // nameapace HiviewDFX 400 } // nameapace OHOS 401 #endif