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