// Copyright 2018 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/memory_snapshot.h" #include #include "base/format_macros.h" #include "base/logging.h" #include "base/strings/stringprintf.h" #include "util/numeric/checked_range.h" namespace crashpad { namespace { bool DetermineMergedRangeImpl(bool log, const MemorySnapshot* a, const MemorySnapshot* b, CheckedRange* merged) { if (a->Size() == 0) { LOG_IF(ERROR, log) << base::StringPrintf( "invalid empty range at 0x%" PRIx64, a->Address()); return false; } if (b->Size() == 0) { LOG_IF(ERROR, log) << base::StringPrintf( "invalid empty range at 0x%" PRIx64, b->Address()); return false; } CheckedRange range_a(a->Address(), a->Size()); if (!range_a.IsValid()) { LOG_IF(ERROR, log) << base::StringPrintf("invalid range at 0x%" PRIx64 ", size %" PRIuS, range_a.base(), range_a.size()); return false; } CheckedRange range_b(b->Address(), b->Size()); if (!range_b.IsValid()) { LOG_IF(ERROR, log) << base::StringPrintf("invalid range at 0x%" PRIx64 ", size %" PRIuS, range_b.base(), range_b.size()); return false; } if (!range_a.OverlapsRange(range_b) && range_a.end() != range_b.base() && range_b.end() != range_a.base()) { LOG_IF(ERROR, log) << base::StringPrintf( "ranges not overlapping or abutting: (0x%" PRIx64 ", size %" PRIuS ") and (0x%" PRIx64 ", size %" PRIuS ")", range_a.base(), range_a.size(), range_b.base(), range_b.size()); return false; } if (merged) { uint64_t base = std::min(range_a.base(), range_b.base()); uint64_t end = std::max(range_a.end(), range_b.end()); size_t size = static_cast(end - base); merged->SetRange(base, size); } return true; } } // namespace bool LoggingDetermineMergedRange(const MemorySnapshot* a, const MemorySnapshot* b, CheckedRange* merged) { return DetermineMergedRangeImpl(true, a, b, merged); } bool DetermineMergedRange(const MemorySnapshot* a, const MemorySnapshot* b, CheckedRange* merged) { return DetermineMergedRangeImpl(false, a, b, merged); } } // namespace crashpad