1723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris/* 2723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * Copyright (C) 2016 The Android Open Source Project 3723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * 4723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * Licensed under the Apache License, Version 2.0 (the "License"); 5723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * you may not use this file except in compliance with the License. 6723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * You may obtain a copy of the License at 7723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * 8723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * http://www.apache.org/licenses/LICENSE-2.0 9723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * 10723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * Unless required by applicable law or agreed to in writing, software 11723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * distributed under the License is distributed on an "AS IS" BASIS, 12723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * See the License for the specific language governing permissions and 14723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris * limitations under the License. 15723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris */ 16723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 17723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include <stdint.h> 18723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 19723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include <deque> 20723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include <string> 21723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 22723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include <android-base/stringprintf.h> 23723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 24d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Log.h> 2553914165e4a19e4a320cf3394e4fabff4e89d7c6Christopher Ferris#include <unwindstack/MachineArm.h> 26d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris#include <unwindstack/Memory.h> 27d06001d6e07b14b865f3294fff82d2571ed7cb2cChristopher Ferris#include <unwindstack/RegsArm.h> 28d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 29723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris#include "ArmExidx.h" 309416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris#include "Check.h" 31d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 32d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferrisnamespace unwindstack { 33723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 34723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisvoid ArmExidx::LogRawData() { 35723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string log_str("Raw Data:"); 36723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris for (const uint8_t data : data_) { 37723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log_str += android::base::StringPrintf(" 0x%02x", data); 38723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 39723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, log_str.c_str()); 40723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 41723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 42723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisbool ArmExidx::ExtractEntryData(uint32_t entry_offset) { 43723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.clear(); 44723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_NONE; 45723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 46723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (entry_offset & 1) { 47723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // The offset needs to be at least two byte aligned. 48723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_INVALID_ALIGNMENT; 49723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 50723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 51723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 52723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Each entry is a 32 bit prel31 offset followed by 32 bits 53723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // of unwind information. If bit 31 of the unwind data is zero, 54723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // then this is a prel31 offset to the start of the unwind data. 55723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // If the unwind data is 1, then this is a cant unwind entry. 56723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Otherwise, this data is the compact form of the unwind information. 57723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint32_t data; 58723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!elf_memory_->Read32(entry_offset + 4, &data)) { 59723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_READ_FAILED; 602fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris status_address_ = entry_offset + 4; 61723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 62723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 63723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (data == 1) { 64723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // This is a CANT UNWIND entry. 65723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_NO_UNWIND; 66723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 67723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "Raw Data: 0x00 0x00 0x00 0x01"); 68723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "[cantunwind]"); 69723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 70723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 71723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 72723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 73723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (data & (1UL << 31)) { 74723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // This is a compact table entry. 75723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if ((data >> 24) & 0xf) { 76723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // This is a non-zero index, this code doesn't support 77723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // other formats. 78723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_INVALID_PERSONALITY; 79723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 80723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 81723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back((data >> 16) & 0xff); 82723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back((data >> 8) & 0xff); 83723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t last_op = data & 0xff; 84723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back(last_op); 85723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (last_op != ARM_OP_FINISH) { 86723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // If this didn't end with a finish op, add one. 87723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back(ARM_OP_FINISH); 88723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 89723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 90723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris LogRawData(); 91723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 92723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 93723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 94723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 95723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Get the address of the ops. 96723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Sign extend the data value if necessary. 97723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris int32_t signed_data = static_cast<int32_t>(data << 1) >> 1; 98723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint32_t addr = (entry_offset + 4) + signed_data; 99723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!elf_memory_->Read32(addr, &data)) { 100723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_READ_FAILED; 1012fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris status_address_ = addr; 102723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 103723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 104723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 105723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris size_t num_table_words; 106723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (data & (1UL << 31)) { 107723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Compact model. 108723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris switch ((data >> 24) & 0xf) { 109723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 0: 110723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris num_table_words = 0; 111723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back((data >> 16) & 0xff); 112723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris break; 113723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 1: 114723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 2: 115723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris num_table_words = (data >> 16) & 0xff; 116723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris addr += 4; 117723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris break; 118723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris default: 119723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Only a personality of 0, 1, 2 is valid. 120723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_INVALID_PERSONALITY; 121723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 122723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 123723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back((data >> 8) & 0xff); 124723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back(data & 0xff); 125723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } else { 126723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Generic model. 127723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 128723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Skip the personality routine data, it doesn't contain any data 129723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // needed to decode the unwind information. 130723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris addr += 4; 131723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!elf_memory_->Read32(addr, &data)) { 132723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_READ_FAILED; 1332fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris status_address_ = addr; 134723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 135723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 136723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris num_table_words = (data >> 24) & 0xff; 137723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back((data >> 16) & 0xff); 138723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back((data >> 8) & 0xff); 139723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back(data & 0xff); 140723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris addr += 4; 141723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 142723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 143723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (num_table_words > 5) { 144723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_MALFORMED; 145723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 146723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 147723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 148723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris for (size_t i = 0; i < num_table_words; i++) { 149723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!elf_memory_->Read32(addr, &data)) { 150723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_READ_FAILED; 1512fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris status_address_ = addr; 152723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 153723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 154723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back((data >> 24) & 0xff); 155723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back((data >> 16) & 0xff); 156723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back((data >> 8) & 0xff); 157723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back(data & 0xff); 158723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris addr += 4; 159723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 160723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 161723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (data_.back() != ARM_OP_FINISH) { 162723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // If this didn't end with a finish op, add one. 163723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.push_back(ARM_OP_FINISH); 164723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 165723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 166723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 167723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris LogRawData(); 168723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 169723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 170723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 171723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 172723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::GetByte(uint8_t* byte) { 173723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (data_.empty()) { 174723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_TRUNCATED; 175723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 176723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 177723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris *byte = data_.front(); 178723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris data_.pop_front(); 179723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 180723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 181723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 182723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) { 1839416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris CHECK((byte >> 4) == 0x8); 184723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 185723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint16_t registers = (byte & 0xf) << 8; 186723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!GetByte(&byte)) { 187723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 188723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 189723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 190723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris registers |= byte; 191723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (registers == 0) { 192723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10000000 00000000: Refuse to unwind 193723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 194723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "Refuse to unwind"); 195723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 196723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_NO_UNWIND; 197723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 198723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 199723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 1000iiii iiiiiiii: Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} 200723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 201723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris bool add_comma = false; 202723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string msg = "pop {"; 203723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris for (size_t i = 0; i < 12; i++) { 204723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (registers & (1 << i)) { 205723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (add_comma) { 206723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += ", "; 207723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 208723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += android::base::StringPrintf("r%zu", i + 4); 209723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris add_comma = true; 210723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 211723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 212723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s}", msg.c_str()); 213723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 214723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 215723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 216723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 217723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 218723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris registers <<= 4; 219723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris for (size_t reg = 4; reg < 16; reg++) { 220723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (registers & (1 << reg)) { 221723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) { 222723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_READ_FAILED; 2232fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris status_address_ = cfa_; 224723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 225723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 226723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += 4; 227723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 228723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 2293958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 230723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // If the sp register is modified, change the cfa value. 231723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (registers & (1 << ARM_REG_SP)) { 232723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ = (*regs_)[ARM_REG_SP]; 233723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 2343958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris 2353958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris // Indicate if the pc register was set. 2363958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris if (registers & (1 << ARM_REG_PC)) { 2373958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris pc_set_ = true; 2383958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris } 239723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 240723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 241723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 242723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_01(uint8_t byte) { 2439416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris CHECK((byte >> 4) == 0x9); 244723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 245723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t bits = byte & 0xf; 246723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (bits == 13 || bits == 15) { 247723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10011101: Reserved as prefix for ARM register to register moves 248723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves 249723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 250723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "[Reserved]"); 251723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 252723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_RESERVED; 253723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 254723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 255723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15) 256723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 257723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "vsp = r%d", bits); 258723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 259723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 260723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 261723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 262723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // It is impossible for bits to be larger than the total number of 263723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // arm registers, so don't bother checking if bits is a valid register. 264723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ = (*regs_)[bits]; 265723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 266723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 267723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 268723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_10(uint8_t byte) { 2699416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris CHECK((byte >> 4) == 0xa); 270723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 271723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10100nnn: Pop r4-r[4+nnn] 272723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10101nnn: Pop r4-r[4+nnn], r14 273723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 274723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string msg = "pop {r4"; 275723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t end_reg = byte & 0x7; 276723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (end_reg) { 277723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += android::base::StringPrintf("-r%d", 4 + end_reg); 278723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 279723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (byte & 0x8) { 280723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s, r14}", msg.c_str()); 281723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } else { 282723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s}", msg.c_str()); 283723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 284723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 285723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 286723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 287723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 288723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 289723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris for (size_t i = 4; i <= 4 + (byte & 0x7); i++) { 290723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!process_memory_->Read32(cfa_, &(*regs_)[i])) { 291723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_READ_FAILED; 2922fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris status_address_ = cfa_; 293723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 294723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 295723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += 4; 296723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 297723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (byte & 0x8) { 298723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!process_memory_->Read32(cfa_, &(*regs_)[ARM_REG_R14])) { 299723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_READ_FAILED; 3002fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris status_address_ = cfa_; 301723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 302723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 303723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += 4; 304723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 305723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 306723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 307723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 308723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_0000() { 309723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10110000: Finish 310723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 311723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "finish"); 312723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 313723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_FINISH; 314723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 315723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 316723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 317723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_FINISH; 318723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 319723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 320723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 321723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_0001() { 322723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t byte; 323723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!GetByte(&byte)) { 324723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 325723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 326723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 327723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (byte == 0) { 328723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10110001 00000000: Spare 329723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 330723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "Spare"); 331723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 332723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_SPARE; 333723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 334723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 335723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (byte >> 4) { 336723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10110001 xxxxyyyy: Spare (xxxx != 0000) 337723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 338723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "Spare"); 339723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 340723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_SPARE; 341723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 342723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 343723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 344723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10110001 0000iiii: Pop integer registers under mask {r3, r2, r1, r0} 345723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 346723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris bool add_comma = false; 347723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string msg = "pop {"; 348723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris for (size_t i = 0; i < 4; i++) { 349723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (byte & (1 << i)) { 350723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (add_comma) { 351723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += ", "; 352723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 353723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += android::base::StringPrintf("r%zu", i); 354723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris add_comma = true; 355723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 356723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 357723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s}", msg.c_str()); 358723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 359723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 360723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 361723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 362723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 363723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris for (size_t reg = 0; reg < 4; reg++) { 364723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (byte & (1 << reg)) { 365723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) { 366723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_READ_FAILED; 3672fcf4cf13e9aefa8c312084af12ca2d712a6ead3Christopher Ferris status_address_ = cfa_; 368723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 369723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 370723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += 4; 371723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 372723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 373723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 374723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 375723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 376723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_0010() { 377723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2) 378723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint32_t result = 0; 379723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint32_t shift = 0; 380723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t byte; 381723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris do { 382723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!GetByte(&byte)) { 383723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 384723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 385723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 386723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris result |= (byte & 0x7f) << shift; 387723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris shift += 7; 388723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } while (byte & 0x80); 389723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris result <<= 2; 390723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 391723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "vsp = vsp + %d", 0x204 + result); 392723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 393723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 394723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 395723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 396723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += 0x204 + result; 397723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 398723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 399723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 400723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_0011() { 401723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by FSTMFDX 402723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t byte; 403723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!GetByte(&byte)) { 404723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 405723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 406723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 407723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 408723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t start_reg = byte >> 4; 409723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string msg = android::base::StringPrintf("pop {d%d", start_reg); 410723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t end_reg = start_reg + (byte & 0xf); 411723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (end_reg) { 412723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += android::base::StringPrintf("-d%d", end_reg); 413723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 414723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s}", msg.c_str()); 415723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 416723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 417723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 418723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 419723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += (byte & 0xf) * 8 + 12; 420723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 421723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 422723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 423723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_01nn() { 424723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 101101nn: Spare 425723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 426723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "Spare"); 427723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 428723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_SPARE; 429723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 430723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 431723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 432723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10_11_1nnn(uint8_t byte) { 4339416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris CHECK((byte & ~0x07) == 0xb8); 434723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 435723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 10111nnn: Pop VFP double-precision registers D[8]-D[8+nnn] by FSTMFDX 436723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 437723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string msg = "pop {d8"; 438723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t last_reg = (byte & 0x7); 439723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (last_reg) { 440723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += android::base::StringPrintf("-d%d", last_reg + 8); 441723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 442723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s}", msg.c_str()); 443723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 444723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 445723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 446723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 447723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Only update the cfa. 448723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += (byte & 0x7) * 8 + 12; 449723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 450723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 451723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 452723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_10(uint8_t byte) { 4539416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris CHECK((byte >> 6) == 0x2); 454723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 455723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris switch ((byte >> 4) & 0x3) { 456723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 0: 457723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_10_00(byte); 458723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 1: 459723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_10_01(byte); 460723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 2: 461723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_10_10(byte); 462723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris default: 463723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris switch (byte & 0xf) { 464723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 0: 465723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_10_11_0000(); 466723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 1: 467723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_10_11_0001(); 468723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 2: 469723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_10_11_0010(); 470723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 3: 471723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_10_11_0011(); 472723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris default: 473723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (byte & 0x8) { 474723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_10_11_1nnn(byte); 475723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } else { 476723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_10_11_01nn(); 477723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 478723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 479723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 480723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 481723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 482723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_11_000(uint8_t byte) { 4839416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris CHECK((byte & ~0x07) == 0xc0); 484723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 485723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t bits = byte & 0x7; 486723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (bits == 6) { 487723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!GetByte(&byte)) { 488723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 489723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 490723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 491723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] 492723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 493723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t start_reg = byte >> 4; 494723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string msg = android::base::StringPrintf("pop {wR%d", start_reg); 495723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t end_reg = byte & 0xf; 496723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (end_reg) { 497723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += android::base::StringPrintf("-wR%d", start_reg + end_reg); 498723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 499723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s}", msg.c_str()); 500723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 501723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 502723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 503723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 504723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Only update the cfa. 505723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += (byte & 0xf) * 8 + 8; 506723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } else if (bits == 7) { 507723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!GetByte(&byte)) { 508723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 509723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 510723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 511723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (byte == 0) { 512723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 11000111 00000000: Spare 513723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 514723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "Spare"); 515723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 516723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_SPARE; 517723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 518723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } else if ((byte >> 4) == 0) { 519723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 11000111 0000iiii: Intel Wireless MMX pop wCGR registers {wCGR0,1,2,3} 520723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 521723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris bool add_comma = false; 522723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string msg = "pop {"; 523723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris for (size_t i = 0; i < 4; i++) { 524723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (byte & (1 << i)) { 525723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (add_comma) { 526723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += ", "; 527723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 528723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += android::base::StringPrintf("wCGR%zu", i); 529723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris add_comma = true; 530723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 531723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 532723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s}", msg.c_str()); 533723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 534723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Only update the cfa. 535723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += __builtin_popcount(byte) * 4; 536723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } else { 537723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 11000111 xxxxyyyy: Spare (xxxx != 0000) 538723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 539723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "Spare"); 540723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 541723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_SPARE; 542723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 543723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 544723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } else { 545723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7) 546723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 547723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string msg = "pop {wR10"; 548723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t nnn = byte & 0x7; 549723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (nnn) { 550723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += android::base::StringPrintf("-wR%d", 10 + nnn); 551723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 552723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s}", msg.c_str()); 553723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 554723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 555723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 556723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 557723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Only update the cfa. 558723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += (byte & 0x7) * 8 + 8; 559723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 560723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 561723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 562723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 563723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_11_001(uint8_t byte) { 5649416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris CHECK((byte & ~0x07) == 0xc8); 565723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 566723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t bits = byte & 0x7; 567723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (bits == 0) { 568723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 11001000 sssscccc: Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] by VPUSH 569723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!GetByte(&byte)) { 570723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 571723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 572723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 573723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 574723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t start_reg = byte >> 4; 575723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string msg = android::base::StringPrintf("pop {d%d", 16 + start_reg); 576723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t end_reg = byte & 0xf; 577723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (end_reg) { 578723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += android::base::StringPrintf("-d%d", 16 + start_reg + end_reg); 579723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 580723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s}", msg.c_str()); 581723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 582723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 583723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 584723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 585723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Only update the cfa. 586723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += (byte & 0xf) * 8 + 8; 587723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } else if (bits == 1) { 588723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 11001001 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by VPUSH 589723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!GetByte(&byte)) { 590723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 591723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 592723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 593723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 594723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t start_reg = byte >> 4; 595723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string msg = android::base::StringPrintf("pop {d%d", start_reg); 596723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t end_reg = byte & 0xf; 597723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (end_reg) { 598723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += android::base::StringPrintf("-d%d", start_reg + end_reg); 599723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 600723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s}", msg.c_str()); 601723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 602723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 603723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 604723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 605723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // Only update the cfa. 606723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += (byte & 0xf) * 8 + 8; 607723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } else { 608723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 11001yyy: Spare (yyy != 000, 001) 609723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 610723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "Spare"); 611723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 612723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_SPARE; 613723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 614723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 615723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 616723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 617723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 618723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_11_010(uint8_t byte) { 6199416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris CHECK((byte & ~0x07) == 0xd0); 620723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 621723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH 622723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 623723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris std::string msg = "pop {d8"; 624723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t end_reg = byte & 0x7; 625723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (end_reg) { 626723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris msg += android::base::StringPrintf("-d%d", 8 + end_reg); 627723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 628723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "%s}", msg.c_str()); 629723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 630723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 631723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 632723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 633723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += (byte & 0x7) * 8 + 8; 634723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 635723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 636723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 637723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisinline bool ArmExidx::DecodePrefix_11(uint8_t byte) { 6389416703f5b37cde61fe8f3e3572b84b21e06ea81Christopher Ferris CHECK((byte >> 6) == 0x3); 639723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 640723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris switch ((byte >> 3) & 0x7) { 641723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 0: 642723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_11_000(byte); 643723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 1: 644723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_11_001(byte); 645723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 2: 646723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_11_010(byte); 647723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris default: 648723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 11xxxyyy: Spare (xxx != 000, 001, 010) 649723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 650723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "Spare"); 651723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 652723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_SPARE; 653723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 654723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 655723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 656723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 657723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisbool ArmExidx::Decode() { 658723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris status_ = ARM_STATUS_NONE; 659723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris uint8_t byte; 660723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (!GetByte(&byte)) { 661723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return false; 662723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 663723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 664723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris switch (byte >> 6) { 665723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 0: 666723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 00xxxxxx: vsp = vsp + (xxxxxxx << 2) + 4 667723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 668723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "vsp = vsp + %d", ((byte & 0x3f) << 2) + 4); 669723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 670723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris break; 671723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 672723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 673723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ += ((byte & 0x3f) << 2) + 4; 674723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris break; 675723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 1: 676723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris // 01xxxxxx: vsp = vsp - (xxxxxxx << 2) + 4 677723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_) { 678723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris log(log_indent_, "vsp = vsp - %d", ((byte & 0x3f) << 2) + 4); 679723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris if (log_skip_execution_) { 680723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris break; 681723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 682723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 683723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris cfa_ -= ((byte & 0x3f) << 2) + 4; 684723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris break; 685723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris case 2: 686723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_10(byte); 687723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris default: 688723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return DecodePrefix_11(byte); 689723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris } 690723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return true; 691723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 692723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris 693723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferrisbool ArmExidx::Eval() { 6943958f8060ac0adccd977c0fab7a53d45f3fce58dChristopher Ferris pc_set_ = false; 695723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris while (Decode()); 696723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris return status_ == ARM_STATUS_FINISH; 697723cf9b6e61744f7a20a807e67ab50adb9db5d42Christopher Ferris} 698d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris 699d226a5140989f509a0ed3e2723f05d5fc93ce8dfChristopher Ferris} // namespace unwindstack 700