mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +08:00
6a9e2e6003
This CL rolls mini_chromium to pick up the move of a bunch of files to base/apple, and makes changes to adjust. Bug: chromium:1444927 Change-Id: Ib692e2a1628e2c0c8228795eaecdb7f35b1c09fa Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/4786387 Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Avi Drissman <avi@chromium.org>
254 lines
8.6 KiB
C++
254 lines
8.6 KiB
C++
// Copyright 2020 The Crashpad Authors
|
|
//
|
|
// 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 "snapshot/ios/thread_snapshot_ios_intermediate_dump.h"
|
|
|
|
#include "base/apple/mach_logging.h"
|
|
#include "snapshot/ios/intermediate_dump_reader_util.h"
|
|
#include "snapshot/mac/cpu_context_mac.h"
|
|
#include "util/ios/ios_intermediate_dump_data.h"
|
|
#include "util/ios/ios_intermediate_dump_list.h"
|
|
#include "util/ios/ios_intermediate_dump_map.h"
|
|
|
|
#include <vector>
|
|
|
|
namespace {
|
|
|
|
std::vector<uint8_t> GenerateStackMemoryFromFrames(const uint64_t* frames,
|
|
const size_t frame_count) {
|
|
std::vector<uint8_t> stack_memory;
|
|
if (frame_count < 2) {
|
|
return stack_memory;
|
|
}
|
|
size_t pointer_size = sizeof(uintptr_t);
|
|
size_t frame_record_size = 2 * pointer_size;
|
|
size_t stack_size = frame_record_size * (frame_count - 1) + pointer_size;
|
|
stack_memory.resize(stack_size);
|
|
uintptr_t sp = stack_size - pointer_size;
|
|
uintptr_t fp = 0;
|
|
uintptr_t lr = 0;
|
|
for (size_t current_frame = frame_count - 1; current_frame > 0;
|
|
--current_frame) {
|
|
memcpy(&stack_memory[0] + sp, &lr, sizeof(lr));
|
|
sp -= pointer_size;
|
|
memcpy(&stack_memory[0] + sp, &fp, sizeof(fp));
|
|
fp = sp;
|
|
sp -= pointer_size;
|
|
lr = frames[current_frame];
|
|
}
|
|
|
|
if (sp != 0) {
|
|
LOG(ERROR) << "kExpectedFinalSp should be 0, is " << sp;
|
|
}
|
|
if (fp != sizeof(uintptr_t)) {
|
|
LOG(ERROR) << "kExpectedFinalFp should be sizeof(uintptr_t), is " << fp;
|
|
}
|
|
if (lr != frames[1]) {
|
|
LOG(ERROR) << "lr should be " << frames[1] << ", is " << lr;
|
|
}
|
|
return stack_memory;
|
|
}
|
|
|
|
} // namespace
|
|
namespace crashpad {
|
|
namespace internal {
|
|
|
|
using Key = IntermediateDumpKey;
|
|
|
|
ThreadSnapshotIOSIntermediateDump::ThreadSnapshotIOSIntermediateDump()
|
|
: ThreadSnapshot(),
|
|
#if defined(ARCH_CPU_X86_64)
|
|
context_x86_64_(),
|
|
#elif defined(ARCH_CPU_ARM64)
|
|
context_arm64_(),
|
|
#endif
|
|
context_(),
|
|
stack_(),
|
|
thread_name_(),
|
|
thread_id_(0),
|
|
thread_specific_data_address_(0),
|
|
suspend_count_(0),
|
|
priority_(0),
|
|
initialized_() {
|
|
#if defined(ARCH_CPU_X86_64)
|
|
context_.architecture = kCPUArchitectureX86_64;
|
|
context_.x86_64 = &context_x86_64_;
|
|
#elif defined(ARCH_CPU_ARM64)
|
|
context_.architecture = kCPUArchitectureARM64;
|
|
context_.arm64 = &context_arm64_;
|
|
#endif
|
|
}
|
|
|
|
ThreadSnapshotIOSIntermediateDump::~ThreadSnapshotIOSIntermediateDump() {}
|
|
|
|
bool ThreadSnapshotIOSIntermediateDump::Initialize(
|
|
const IOSIntermediateDumpMap* thread_data) {
|
|
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
|
|
|
GetDataValueFromMap(thread_data, Key::kSuspendCount, &suspend_count_);
|
|
GetDataValueFromMap(thread_data, Key::kPriority, &priority_);
|
|
GetDataValueFromMap(thread_data, Key::kThreadID, &thread_id_);
|
|
GetDataValueFromMap(
|
|
thread_data, Key::kThreadDataAddress, &thread_specific_data_address_);
|
|
GetDataStringFromMap(thread_data, Key::kThreadName, &thread_name_);
|
|
|
|
#if defined(ARCH_CPU_X86_64)
|
|
typedef x86_thread_state64_t thread_state_type;
|
|
typedef x86_float_state64_t float_state_type;
|
|
typedef x86_debug_state64_t debug_state_type;
|
|
#elif defined(ARCH_CPU_ARM64)
|
|
typedef arm_thread_state64_t thread_state_type;
|
|
typedef arm_neon_state64_t float_state_type;
|
|
typedef arm_debug_state64_t debug_state_type;
|
|
#endif
|
|
|
|
thread_state_type thread_state;
|
|
float_state_type float_state;
|
|
debug_state_type debug_state;
|
|
|
|
const IOSIntermediateDumpData* nsexception_frames =
|
|
thread_data->GetAsData(Key::kThreadUncaughtNSExceptionFrames);
|
|
const IOSIntermediateDumpData* thread_stack_data_dump =
|
|
thread_data->GetAsData(Key::kStackRegionData);
|
|
if (nsexception_frames && thread_stack_data_dump) {
|
|
LOG(ERROR) << "Unexpected thread with kStackRegionData and "
|
|
<< "kThreadUncaughtNSExceptionFrames, using kStackRegionData";
|
|
}
|
|
if (thread_stack_data_dump) {
|
|
vm_address_t stack_region_address;
|
|
GetDataValueFromMap(
|
|
thread_data, Key::kStackRegionAddress, &stack_region_address);
|
|
|
|
const std::vector<uint8_t>& bytes = thread_stack_data_dump->bytes();
|
|
const vm_address_t stack_region_data =
|
|
reinterpret_cast<const vm_address_t>(bytes.data());
|
|
vm_size_t stack_region_size = bytes.size();
|
|
stack_.Initialize(
|
|
stack_region_address, stack_region_data, stack_region_size);
|
|
} else if (nsexception_frames) {
|
|
const std::vector<uint8_t>& bytes = nsexception_frames->bytes();
|
|
const uint64_t* frames = reinterpret_cast<const uint64_t*>(bytes.data());
|
|
size_t frame_count = bytes.size() / sizeof(uint64_t);
|
|
exception_stack_memory_ =
|
|
GenerateStackMemoryFromFrames(frames, frame_count);
|
|
vm_address_t stack_memory_addr =
|
|
!exception_stack_memory_.empty()
|
|
? reinterpret_cast<vm_address_t>(&exception_stack_memory_[0])
|
|
: 0;
|
|
stack_.Initialize(0, stack_memory_addr, exception_stack_memory_.size());
|
|
} else {
|
|
stack_.Initialize(0, 0, 0);
|
|
}
|
|
|
|
if (GetDataValueFromMap(thread_data, Key::kThreadState, &thread_state) &&
|
|
GetDataValueFromMap(thread_data, Key::kFloatState, &float_state) &&
|
|
GetDataValueFromMap(thread_data, Key::kDebugState, &debug_state)) {
|
|
#if defined(ARCH_CPU_X86_64)
|
|
InitializeCPUContextX86_64(&context_x86_64_,
|
|
THREAD_STATE_NONE,
|
|
nullptr,
|
|
0,
|
|
&thread_state,
|
|
&float_state,
|
|
&debug_state);
|
|
#elif defined(ARCH_CPU_ARM64)
|
|
InitializeCPUContextARM64(&context_arm64_,
|
|
THREAD_STATE_NONE,
|
|
nullptr,
|
|
0,
|
|
&thread_state,
|
|
&float_state,
|
|
&debug_state);
|
|
|
|
#else
|
|
#error Port to your CPU architecture
|
|
#endif
|
|
}
|
|
const IOSIntermediateDumpList* thread_context_memory_regions =
|
|
GetListFromMap(thread_data, Key::kThreadContextMemoryRegions);
|
|
if (thread_context_memory_regions) {
|
|
for (auto& region : *thread_context_memory_regions) {
|
|
vm_address_t address;
|
|
const IOSIntermediateDumpData* region_data =
|
|
region->GetAsData(Key::kThreadContextMemoryRegionData);
|
|
if (!region_data)
|
|
continue;
|
|
if (GetDataValueFromMap(
|
|
region.get(), Key::kThreadContextMemoryRegionAddress, &address)) {
|
|
const std::vector<uint8_t>& bytes = region_data->bytes();
|
|
vm_size_t data_size = bytes.size();
|
|
if (data_size == 0)
|
|
continue;
|
|
|
|
const vm_address_t data =
|
|
reinterpret_cast<const vm_address_t>(bytes.data());
|
|
|
|
auto memory =
|
|
std::make_unique<internal::MemorySnapshotIOSIntermediateDump>();
|
|
memory->Initialize(address, data, data_size);
|
|
extra_memory_.push_back(std::move(memory));
|
|
}
|
|
}
|
|
}
|
|
|
|
INITIALIZATION_STATE_SET_VALID(initialized_);
|
|
return true;
|
|
}
|
|
const CPUContext* ThreadSnapshotIOSIntermediateDump::Context() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return &context_;
|
|
}
|
|
|
|
const MemorySnapshot* ThreadSnapshotIOSIntermediateDump::Stack() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return &stack_;
|
|
}
|
|
|
|
uint64_t ThreadSnapshotIOSIntermediateDump::ThreadID() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return thread_id_;
|
|
}
|
|
|
|
std::string ThreadSnapshotIOSIntermediateDump::ThreadName() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return thread_name_;
|
|
}
|
|
|
|
int ThreadSnapshotIOSIntermediateDump::SuspendCount() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return suspend_count_;
|
|
}
|
|
|
|
int ThreadSnapshotIOSIntermediateDump::Priority() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return priority_;
|
|
}
|
|
|
|
uint64_t ThreadSnapshotIOSIntermediateDump::ThreadSpecificDataAddress() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return thread_specific_data_address_;
|
|
}
|
|
|
|
std::vector<const MemorySnapshot*>
|
|
ThreadSnapshotIOSIntermediateDump::ExtraMemory() const {
|
|
std::vector<const MemorySnapshot*> extra_memory;
|
|
for (const auto& memory : extra_memory_) {
|
|
extra_memory.push_back(memory.get());
|
|
}
|
|
return extra_memory;
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace crashpad
|