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