xref: /llvm-project/lldb/source/Target/CoreFileMemoryRanges.cpp (revision 96b7c64b8a874584a9dad44bb8901904c14701c0)
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