upload android base code part6
This commit is contained in:
parent
421e214c7d
commit
4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions
316
android/system/core/libunwindstack/DwarfDebugFrame.cpp
Normal file
316
android/system/core/libunwindstack/DwarfDebugFrame.cpp
Normal file
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <unwindstack/DwarfStructs.h>
|
||||
#include <unwindstack/Memory.h>
|
||||
|
||||
#include "DwarfDebugFrame.h"
|
||||
#include "DwarfEncoding.h"
|
||||
#include "DwarfError.h"
|
||||
|
||||
namespace unwindstack {
|
||||
|
||||
template <typename AddressType>
|
||||
bool DwarfDebugFrame<AddressType>::Init(uint64_t offset, uint64_t size) {
|
||||
offset_ = offset;
|
||||
end_offset_ = offset + size;
|
||||
|
||||
memory_.clear_func_offset();
|
||||
memory_.clear_text_offset();
|
||||
memory_.set_data_offset(offset);
|
||||
memory_.set_cur_offset(offset);
|
||||
|
||||
return CreateSortedFdeList();
|
||||
}
|
||||
|
||||
template <typename AddressType>
|
||||
bool DwarfDebugFrame<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) {
|
||||
uint8_t version;
|
||||
if (!memory_.ReadBytes(&version, 1)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
// Read the augmentation string.
|
||||
std::vector<char> aug_string;
|
||||
char aug_value;
|
||||
bool get_encoding = false;
|
||||
do {
|
||||
if (!memory_.ReadBytes(&aug_value, 1)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
if (aug_value == 'R') {
|
||||
get_encoding = true;
|
||||
}
|
||||
aug_string.push_back(aug_value);
|
||||
} while (aug_value != '\0');
|
||||
|
||||
if (version == 4) {
|
||||
// Skip the Address Size field.
|
||||
memory_.set_cur_offset(memory_.cur_offset() + 1);
|
||||
|
||||
// Read the segment size.
|
||||
if (!memory_.ReadBytes(segment_size, 1)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
*segment_size = 0;
|
||||
}
|
||||
|
||||
if (aug_string[0] != 'z' || !get_encoding) {
|
||||
// No encoding
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip code alignment factor
|
||||
uint8_t value;
|
||||
do {
|
||||
if (!memory_.ReadBytes(&value, 1)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
} while (value & 0x80);
|
||||
|
||||
// Skip data alignment factor
|
||||
do {
|
||||
if (!memory_.ReadBytes(&value, 1)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
} while (value & 0x80);
|
||||
|
||||
if (version == 1) {
|
||||
// Skip return address register.
|
||||
memory_.set_cur_offset(memory_.cur_offset() + 1);
|
||||
} else {
|
||||
// Skip return address register.
|
||||
do {
|
||||
if (!memory_.ReadBytes(&value, 1)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
} while (value & 0x80);
|
||||
}
|
||||
|
||||
// Skip the augmentation length.
|
||||
do {
|
||||
if (!memory_.ReadBytes(&value, 1)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
} while (value & 0x80);
|
||||
|
||||
for (size_t i = 1; i < aug_string.size(); i++) {
|
||||
if (aug_string[i] == 'R') {
|
||||
if (!memory_.ReadBytes(encoding, 1)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
// Got the encoding, that's all we are looking for.
|
||||
return true;
|
||||
} else if (aug_string[i] == 'L') {
|
||||
memory_.set_cur_offset(memory_.cur_offset() + 1);
|
||||
} else if (aug_string[i] == 'P') {
|
||||
uint8_t encoding;
|
||||
if (!memory_.ReadBytes(&encoding, 1)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
uint64_t value;
|
||||
if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It should be impossible to get here.
|
||||
abort();
|
||||
}
|
||||
|
||||
template <typename AddressType>
|
||||
bool DwarfDebugFrame<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size,
|
||||
uint8_t encoding) {
|
||||
if (segment_size != 0) {
|
||||
memory_.set_cur_offset(memory_.cur_offset() + 1);
|
||||
}
|
||||
|
||||
uint64_t start;
|
||||
if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t length;
|
||||
if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
if (length != 0) {
|
||||
fdes_.emplace_back(entry_offset, start, length);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename AddressType>
|
||||
bool DwarfDebugFrame<AddressType>::CreateSortedFdeList() {
|
||||
memory_.set_cur_offset(offset_);
|
||||
|
||||
// Loop through all of the entries and read just enough to create
|
||||
// a sorted list of pcs.
|
||||
// This code assumes that first comes the cie, then the fdes that
|
||||
// it applies to.
|
||||
uint64_t cie_offset = 0;
|
||||
uint8_t address_encoding;
|
||||
uint8_t segment_size;
|
||||
while (memory_.cur_offset() < end_offset_) {
|
||||
uint64_t cur_entry_offset = memory_.cur_offset();
|
||||
|
||||
// Figure out the entry length and type.
|
||||
uint32_t value32;
|
||||
if (!memory_.ReadBytes(&value32, sizeof(value32))) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t next_entry_offset;
|
||||
if (value32 == static_cast<uint32_t>(-1)) {
|
||||
uint64_t value64;
|
||||
if (!memory_.ReadBytes(&value64, sizeof(value64))) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
next_entry_offset = memory_.cur_offset() + value64;
|
||||
|
||||
// Read the Cie Id of a Cie or the pointer of the Fde.
|
||||
if (!memory_.ReadBytes(&value64, sizeof(value64))) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value64 == static_cast<uint64_t>(-1)) {
|
||||
// Cie 64 bit
|
||||
address_encoding = DW_EH_PE_sdata8;
|
||||
if (!GetCieInfo(&segment_size, &address_encoding)) {
|
||||
return false;
|
||||
}
|
||||
cie_offset = cur_entry_offset;
|
||||
} else {
|
||||
if (offset_ + value64 != cie_offset) {
|
||||
// This means that this Fde is not following the Cie.
|
||||
last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fde 64 bit
|
||||
if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
next_entry_offset = memory_.cur_offset() + value32;
|
||||
|
||||
// Read the Cie Id of a Cie or the pointer of the Fde.
|
||||
if (!memory_.ReadBytes(&value32, sizeof(value32))) {
|
||||
last_error_ = DWARF_ERROR_MEMORY_INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value32 == static_cast<uint32_t>(-1)) {
|
||||
// Cie 32 bit
|
||||
address_encoding = DW_EH_PE_sdata4;
|
||||
if (!GetCieInfo(&segment_size, &address_encoding)) {
|
||||
return false;
|
||||
}
|
||||
cie_offset = cur_entry_offset;
|
||||
} else {
|
||||
if (offset_ + value32 != cie_offset) {
|
||||
// This means that this Fde is not following the Cie.
|
||||
last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fde 32 bit
|
||||
if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (next_entry_offset < memory_.cur_offset()) {
|
||||
// This indicates some kind of corruption, or malformed section data.
|
||||
last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
|
||||
return false;
|
||||
}
|
||||
memory_.set_cur_offset(next_entry_offset);
|
||||
}
|
||||
|
||||
// Sort the entries.
|
||||
std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) {
|
||||
if (a.start == b.start) return a.end < b.end;
|
||||
return a.start < b.start;
|
||||
});
|
||||
|
||||
fde_count_ = fdes_.size();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename AddressType>
|
||||
bool DwarfDebugFrame<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) {
|
||||
if (fde_count_ == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t first = 0;
|
||||
size_t last = fde_count_;
|
||||
while (first < last) {
|
||||
size_t current = (first + last) / 2;
|
||||
const FdeInfo* info = &fdes_[current];
|
||||
if (pc >= info->start && pc <= info->end) {
|
||||
*fde_offset = info->offset;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pc < info->start) {
|
||||
last = current;
|
||||
} else {
|
||||
first = current + 1;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename AddressType>
|
||||
const DwarfFde* DwarfDebugFrame<AddressType>::GetFdeFromIndex(size_t index) {
|
||||
if (index >= fdes_.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return this->GetFdeFromOffset(fdes_[index].offset);
|
||||
}
|
||||
|
||||
// Explicitly instantiate DwarfDebugFrame.
|
||||
template class DwarfDebugFrame<uint32_t>;
|
||||
template class DwarfDebugFrame<uint64_t>;
|
||||
|
||||
} // namespace unwindstack
|
Loading…
Add table
Add a link
Reference in a new issue