DwarfOp.cpp revision 2fcf4cf13e9aefa8c312084af12ca2d712a6ead3
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 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 17#include <stdint.h> 18 19#include <deque> 20#include <string> 21#include <vector> 22 23#include <android-base/stringprintf.h> 24 25#include <unwindstack/DwarfError.h> 26#include <unwindstack/DwarfMemory.h> 27#include <unwindstack/Log.h> 28#include <unwindstack/Memory.h> 29#include <unwindstack/Regs.h> 30 31#include "DwarfOp.h" 32 33namespace unwindstack { 34 35template <typename AddressType> 36constexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256]; 37 38template <typename AddressType> 39bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end, uint8_t dwarf_version) { 40 uint32_t iterations = 0; 41 is_register_ = false; 42 stack_.clear(); 43 memory_->set_cur_offset(start); 44 while (memory_->cur_offset() < end) { 45 if (!Decode(dwarf_version)) { 46 return false; 47 } 48 // To protect against a branch that creates an infinite loop, 49 // terminate if the number of iterations gets too high. 50 if (iterations++ == 1000) { 51 last_error_.code = DWARF_ERROR_TOO_MANY_ITERATIONS; 52 return false; 53 } 54 } 55 return true; 56} 57 58template <typename AddressType> 59bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) { 60 last_error_.code = DWARF_ERROR_NONE; 61 if (!memory_->ReadBytes(&cur_op_, 1)) { 62 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 63 last_error_.address = memory_->cur_offset(); 64 return false; 65 } 66 67 const auto* op = &kCallbackTable[cur_op_]; 68 const auto handle_func = op->handle_func; 69 if (handle_func == nullptr) { 70 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; 71 return false; 72 } 73 74 // Check for an unsupported opcode. 75 if (dwarf_version < op->supported_version) { 76 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; 77 return false; 78 } 79 80 // Make sure that the required number of stack elements is available. 81 if (stack_.size() < op->num_required_stack_values) { 82 last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID; 83 return false; 84 } 85 86 operands_.clear(); 87 for (size_t i = 0; i < op->num_operands; i++) { 88 uint64_t value; 89 if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) { 90 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 91 last_error_.address = memory_->cur_offset(); 92 return false; 93 } 94 operands_.push_back(value); 95 } 96 return (this->*handle_func)(); 97} 98 99template <typename AddressType> 100void DwarfOp<AddressType>::GetLogInfo(uint64_t start, uint64_t end, 101 std::vector<std::string>* lines) { 102 memory_->set_cur_offset(start); 103 while (memory_->cur_offset() < end) { 104 uint8_t cur_op; 105 if (!memory_->ReadBytes(&cur_op, 1)) { 106 return; 107 } 108 109 std::string raw_string(android::base::StringPrintf("Raw Data: 0x%02x", cur_op)); 110 std::string log_string; 111 const auto* op = &kCallbackTable[cur_op]; 112 if (op->handle_func == nullptr) { 113 log_string = "Illegal"; 114 } else { 115 log_string = op->name; 116 uint64_t start_offset = memory_->cur_offset(); 117 for (size_t i = 0; i < op->num_operands; i++) { 118 uint64_t value; 119 if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) { 120 return; 121 } 122 log_string += ' ' + std::to_string(value); 123 } 124 uint64_t end_offset = memory_->cur_offset(); 125 126 memory_->set_cur_offset(start_offset); 127 for (size_t i = start_offset; i < end_offset; i++) { 128 uint8_t byte; 129 if (!memory_->ReadBytes(&byte, 1)) { 130 return; 131 } 132 raw_string += android::base::StringPrintf(" 0x%02x", byte); 133 } 134 memory_->set_cur_offset(end_offset); 135 } 136 lines->push_back(std::move(log_string)); 137 lines->push_back(std::move(raw_string)); 138 } 139} 140 141template <typename AddressType> 142bool DwarfOp<AddressType>::op_deref() { 143 // Read the address and dereference it. 144 AddressType addr = StackPop(); 145 AddressType value; 146 if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) { 147 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 148 last_error_.address = addr; 149 return false; 150 } 151 stack_.push_front(value); 152 return true; 153} 154 155template <typename AddressType> 156bool DwarfOp<AddressType>::op_deref_size() { 157 AddressType bytes_to_read = OperandAt(0); 158 if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) { 159 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; 160 return false; 161 } 162 // Read the address and dereference it. 163 AddressType addr = StackPop(); 164 AddressType value = 0; 165 if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) { 166 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 167 last_error_.address = addr; 168 return false; 169 } 170 stack_.push_front(value); 171 return true; 172} 173 174template <typename AddressType> 175bool DwarfOp<AddressType>::op_push() { 176 // Push all of the operands. 177 for (auto operand : operands_) { 178 stack_.push_front(operand); 179 } 180 return true; 181} 182 183template <typename AddressType> 184bool DwarfOp<AddressType>::op_dup() { 185 stack_.push_front(StackAt(0)); 186 return true; 187} 188 189template <typename AddressType> 190bool DwarfOp<AddressType>::op_drop() { 191 StackPop(); 192 return true; 193} 194 195template <typename AddressType> 196bool DwarfOp<AddressType>::op_over() { 197 stack_.push_front(StackAt(1)); 198 return true; 199} 200 201template <typename AddressType> 202bool DwarfOp<AddressType>::op_pick() { 203 AddressType index = OperandAt(0); 204 if (index > StackSize()) { 205 last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID; 206 return false; 207 } 208 stack_.push_front(StackAt(index)); 209 return true; 210} 211 212template <typename AddressType> 213bool DwarfOp<AddressType>::op_swap() { 214 AddressType old_value = stack_[0]; 215 stack_[0] = stack_[1]; 216 stack_[1] = old_value; 217 return true; 218} 219 220template <typename AddressType> 221bool DwarfOp<AddressType>::op_rot() { 222 AddressType top = stack_[0]; 223 stack_[0] = stack_[1]; 224 stack_[1] = stack_[2]; 225 stack_[2] = top; 226 return true; 227} 228 229template <typename AddressType> 230bool DwarfOp<AddressType>::op_abs() { 231 SignedType signed_value = static_cast<SignedType>(stack_[0]); 232 if (signed_value < 0) { 233 signed_value = -signed_value; 234 } 235 stack_[0] = static_cast<AddressType>(signed_value); 236 return true; 237} 238 239template <typename AddressType> 240bool DwarfOp<AddressType>::op_and() { 241 AddressType top = StackPop(); 242 stack_[0] &= top; 243 return true; 244} 245 246template <typename AddressType> 247bool DwarfOp<AddressType>::op_div() { 248 AddressType top = StackPop(); 249 if (top == 0) { 250 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; 251 return false; 252 } 253 SignedType signed_divisor = static_cast<SignedType>(top); 254 SignedType signed_dividend = static_cast<SignedType>(stack_[0]); 255 stack_[0] = static_cast<AddressType>(signed_dividend / signed_divisor); 256 return true; 257} 258 259template <typename AddressType> 260bool DwarfOp<AddressType>::op_minus() { 261 AddressType top = StackPop(); 262 stack_[0] -= top; 263 return true; 264} 265 266template <typename AddressType> 267bool DwarfOp<AddressType>::op_mod() { 268 AddressType top = StackPop(); 269 if (top == 0) { 270 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; 271 return false; 272 } 273 stack_[0] %= top; 274 return true; 275} 276 277template <typename AddressType> 278bool DwarfOp<AddressType>::op_mul() { 279 AddressType top = StackPop(); 280 stack_[0] *= top; 281 return true; 282} 283 284template <typename AddressType> 285bool DwarfOp<AddressType>::op_neg() { 286 SignedType signed_value = static_cast<SignedType>(stack_[0]); 287 stack_[0] = static_cast<AddressType>(-signed_value); 288 return true; 289} 290 291template <typename AddressType> 292bool DwarfOp<AddressType>::op_not() { 293 stack_[0] = ~stack_[0]; 294 return true; 295} 296 297template <typename AddressType> 298bool DwarfOp<AddressType>::op_or() { 299 AddressType top = StackPop(); 300 stack_[0] |= top; 301 return true; 302} 303 304template <typename AddressType> 305bool DwarfOp<AddressType>::op_plus() { 306 AddressType top = StackPop(); 307 stack_[0] += top; 308 return true; 309} 310 311template <typename AddressType> 312bool DwarfOp<AddressType>::op_plus_uconst() { 313 stack_[0] += OperandAt(0); 314 return true; 315} 316 317template <typename AddressType> 318bool DwarfOp<AddressType>::op_shl() { 319 AddressType top = StackPop(); 320 stack_[0] <<= top; 321 return true; 322} 323 324template <typename AddressType> 325bool DwarfOp<AddressType>::op_shr() { 326 AddressType top = StackPop(); 327 stack_[0] >>= top; 328 return true; 329} 330 331template <typename AddressType> 332bool DwarfOp<AddressType>::op_shra() { 333 AddressType top = StackPop(); 334 SignedType signed_value = static_cast<SignedType>(stack_[0]) >> top; 335 stack_[0] = static_cast<AddressType>(signed_value); 336 return true; 337} 338 339template <typename AddressType> 340bool DwarfOp<AddressType>::op_xor() { 341 AddressType top = StackPop(); 342 stack_[0] ^= top; 343 return true; 344} 345 346template <typename AddressType> 347bool DwarfOp<AddressType>::op_bra() { 348 // Requires one stack element. 349 AddressType top = StackPop(); 350 int16_t offset = static_cast<int16_t>(OperandAt(0)); 351 uint64_t cur_offset; 352 if (top != 0) { 353 cur_offset = memory_->cur_offset() + offset; 354 } else { 355 cur_offset = memory_->cur_offset() - offset; 356 } 357 memory_->set_cur_offset(cur_offset); 358 return true; 359} 360 361template <typename AddressType> 362bool DwarfOp<AddressType>::op_eq() { 363 AddressType top = StackPop(); 364 stack_[0] = bool_to_dwarf_bool(stack_[0] == top); 365 return true; 366} 367 368template <typename AddressType> 369bool DwarfOp<AddressType>::op_ge() { 370 AddressType top = StackPop(); 371 stack_[0] = bool_to_dwarf_bool(stack_[0] >= top); 372 return true; 373} 374 375template <typename AddressType> 376bool DwarfOp<AddressType>::op_gt() { 377 AddressType top = StackPop(); 378 stack_[0] = bool_to_dwarf_bool(stack_[0] > top); 379 return true; 380} 381 382template <typename AddressType> 383bool DwarfOp<AddressType>::op_le() { 384 AddressType top = StackPop(); 385 stack_[0] = bool_to_dwarf_bool(stack_[0] <= top); 386 return true; 387} 388 389template <typename AddressType> 390bool DwarfOp<AddressType>::op_lt() { 391 AddressType top = StackPop(); 392 stack_[0] = bool_to_dwarf_bool(stack_[0] < top); 393 return true; 394} 395 396template <typename AddressType> 397bool DwarfOp<AddressType>::op_ne() { 398 AddressType top = StackPop(); 399 stack_[0] = bool_to_dwarf_bool(stack_[0] != top); 400 return true; 401} 402 403template <typename AddressType> 404bool DwarfOp<AddressType>::op_skip() { 405 int16_t offset = static_cast<int16_t>(OperandAt(0)); 406 uint64_t cur_offset = memory_->cur_offset() + offset; 407 memory_->set_cur_offset(cur_offset); 408 return true; 409} 410 411template <typename AddressType> 412bool DwarfOp<AddressType>::op_lit() { 413 stack_.push_front(cur_op() - 0x30); 414 return true; 415} 416 417template <typename AddressType> 418bool DwarfOp<AddressType>::op_reg() { 419 is_register_ = true; 420 stack_.push_front(cur_op() - 0x50); 421 return true; 422} 423 424template <typename AddressType> 425bool DwarfOp<AddressType>::op_regx() { 426 is_register_ = true; 427 stack_.push_front(OperandAt(0)); 428 return true; 429} 430 431// It's not clear for breg/bregx, if this op should read the current 432// value of the register, or where we think that register is located. 433// For simplicity, the code will read the value before doing the unwind. 434template <typename AddressType> 435bool DwarfOp<AddressType>::op_breg() { 436 uint16_t reg = cur_op() - 0x70; 437 if (reg >= regs_->total_regs()) { 438 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; 439 return false; 440 } 441 stack_.push_front((*regs_)[reg] + OperandAt(0)); 442 return true; 443} 444 445template <typename AddressType> 446bool DwarfOp<AddressType>::op_bregx() { 447 AddressType reg = OperandAt(0); 448 if (reg >= regs_->total_regs()) { 449 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; 450 return false; 451 } 452 stack_.push_front((*regs_)[reg] + OperandAt(1)); 453 return true; 454} 455 456template <typename AddressType> 457bool DwarfOp<AddressType>::op_nop() { 458 return true; 459} 460 461template <typename AddressType> 462bool DwarfOp<AddressType>::op_not_implemented() { 463 last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED; 464 return false; 465} 466 467// Explicitly instantiate DwarfOp. 468template class DwarfOp<uint32_t>; 469template class DwarfOp<uint64_t>; 470 471} // namespace unwindstack 472