// Copyright 2017 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 "minidump/minidump_annotation_writer.h" #include #include "base/check_op.h" #include "base/logging.h" #include "util/file/file_writer.h" #include "util/numeric/safe_assignment.h" namespace crashpad { MinidumpAnnotationWriter::MinidumpAnnotationWriter() = default; MinidumpAnnotationWriter::~MinidumpAnnotationWriter() = default; void MinidumpAnnotationWriter::InitializeFromSnapshot( const AnnotationSnapshot& snapshot) { DCHECK_EQ(state(), kStateMutable); name_.SetUTF8(snapshot.name); annotation_.type = snapshot.type; annotation_.reserved = 0; value_.set_data(snapshot.value); } void MinidumpAnnotationWriter::InitializeWithData( const std::string& name, uint16_t type, const std::vector& data) { DCHECK_EQ(state(), kStateMutable); name_.SetUTF8(name); annotation_.type = type; annotation_.reserved = 0; value_.set_data(data); } bool MinidumpAnnotationWriter::Freeze() { DCHECK_EQ(state(), kStateMutable); if (!MinidumpWritable::Freeze()) { return false; } name_.RegisterRVA(&annotation_.name); value_.RegisterRVA(&annotation_.value); return true; } size_t MinidumpAnnotationWriter::SizeOfObject() { DCHECK_GE(state(), kStateFrozen); // This object is written by the MinidumpAnnotationListWriter, and its // children write themselves. return 0; } std::vector MinidumpAnnotationWriter::Children() { DCHECK_GE(state(), kStateFrozen); return {&name_, &value_}; } bool MinidumpAnnotationWriter::WriteObject(FileWriterInterface* file_writer) { DCHECK_EQ(state(), kStateWritable); // This object is written by the MinidumpAnnotationListWriter, and its // children write themselves. return true; } MinidumpAnnotationListWriter::MinidumpAnnotationListWriter() : minidump_list_(new MinidumpAnnotationList()) {} MinidumpAnnotationListWriter::~MinidumpAnnotationListWriter() = default; void MinidumpAnnotationListWriter::InitializeFromList( const std::vector& list) { DCHECK_EQ(state(), kStateMutable); for (const auto& annotation : list) { auto writer = std::make_unique(); writer->InitializeFromSnapshot(annotation); AddObject(std::move(writer)); } } void MinidumpAnnotationListWriter::AddObject( std::unique_ptr annotation_writer) { DCHECK_EQ(state(), kStateMutable); objects_.push_back(std::move(annotation_writer)); } bool MinidumpAnnotationListWriter::IsUseful() const { return !objects_.empty(); } bool MinidumpAnnotationListWriter::Freeze() { DCHECK_EQ(state(), kStateMutable); if (!MinidumpWritable::Freeze()) { return false; } if (!AssignIfInRange(&minidump_list_->count, objects_.size())) { LOG(ERROR) << "annotation list size " << objects_.size() << " is out of range"; return false; } return true; } size_t MinidumpAnnotationListWriter::SizeOfObject() { DCHECK_GE(state(), kStateFrozen); return sizeof(*minidump_list_) + sizeof(MinidumpAnnotation) * objects_.size(); } std::vector MinidumpAnnotationListWriter::Children() { DCHECK_GE(state(), kStateFrozen); std::vector children(objects_.size()); for (size_t i = 0; i < objects_.size(); ++i) { children[i] = objects_[i].get(); } return children; } bool MinidumpAnnotationListWriter::WriteObject( FileWriterInterface* file_writer) { DCHECK_EQ(state(), kStateWritable); std::vector iov; iov.reserve(1 + objects_.size()); iov.emplace_back( WritableIoVec{minidump_list_.get(), sizeof(*minidump_list_)}); for (const auto& object : objects_) { iov.emplace_back(WritableIoVec{object->minidump_annotation(), sizeof(MinidumpAnnotation)}); } return file_writer->WriteIoVec(&iov); } } // namespace crashpad