1 //===-- CoreFileMemoryRanges.cpp --------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Target/CoreFileMemoryRanges.h" 10 11 using namespace lldb; 12 using namespace lldb_private; 13 14 using Entry = CoreFileMemoryRanges::Entry; 15 16 static bool Overlaps(const Entry *region_one, const Entry *region_two) { 17 return !(region_one->GetRangeEnd() < region_two->GetRangeBase() || 18 region_two->GetRangeEnd() < region_one->GetRangeBase()); 19 } 20 21 static bool IntersectHelper(const Entry *region_one, const Entry *region_two) { 22 return region_one->GetRangeBase() == region_two->GetRangeEnd() || 23 region_one->GetRangeEnd() == region_two->GetRangeBase(); 24 } 25 26 static bool OnlyIntersects(const Entry *region_one, const Entry *region_two) { 27 return IntersectHelper(region_one, region_two) || 28 IntersectHelper(region_two, region_one); 29 } 30 31 static bool PermissionsMatch(const Entry *region_one, const Entry *region_two) { 32 return region_one->data.lldb_permissions == region_two->data.lldb_permissions; 33 } 34 35 // This assumes any overlapping ranges will share the same permissions 36 // and that adjacent ranges could have different permissions. 37 Status CoreFileMemoryRanges::FinalizeCoreFileSaveRanges() { 38 Status error; 39 this->Sort(); 40 for (size_t i = this->GetSize() - 1; i > 0; i--) { 41 auto region_one = this->GetMutableEntryAtIndex(i); 42 auto region_two = this->GetMutableEntryAtIndex(i - 1); 43 if (Overlaps(region_one, region_two)) { 44 // It's okay for interesecting regions to have different permissions but 45 // if they overlap we fail because we don't know what to do with them. 46 if (!PermissionsMatch(region_one, region_two)) { 47 // Permissions mismatch and it's not a simple intersection. 48 if (!OnlyIntersects(region_one, region_two)) { 49 error = Status::FromErrorStringWithFormatv( 50 "Memory region at {0}::{1} has different permssions than " 51 "overlapping region at {2}::{3}", 52 region_one->GetRangeBase(), region_one->GetRangeEnd(), 53 region_two->GetRangeBase(), region_two->GetRangeEnd()); 54 return error; 55 } 56 // Simple intersection, we can just not merge these. 57 else 58 continue; 59 } 60 const addr_t base = 61 std::min(region_one->GetRangeBase(), region_two->GetRangeBase()); 62 const addr_t byte_size = 63 std::max(region_one->GetRangeEnd(), region_two->GetRangeEnd()) - base; 64 65 region_two->SetRangeBase(base); 66 region_two->SetByteSize(byte_size); 67 68 // Because this is a range data vector, the entry has a base as well 69 // as the data contained in the entry. So we have to update both. 70 // And llvm::AddressRange isn't mutable so we have to create a new one. 71 llvm::AddressRange range(base, base + byte_size); 72 const CoreFileMemoryRange core_range = { 73 range, region_two->data.lldb_permissions}; 74 region_two->data = core_range; 75 // Erase is delete from [Inclusive, exclusive index). 76 if (!this->Erase(i, i + 1)) { 77 error = Status::FromErrorStringWithFormat( 78 "Core file memory ranges mutated outside of " 79 "CalculateCoreFileSaveRanges"); 80 return error; 81 } 82 } 83 } 84 85 return error; 86 } 87