1cfca06d7SDimitry Andric //===-- AddressRange.cpp --------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "lldb/Core/AddressRange.h"
10f034231aSEd Maste #include "lldb/Core/Module.h"
11344a3780SDimitry Andric #include "lldb/Core/Section.h"
12f034231aSEd Maste #include "lldb/Target/Target.h"
1394994d37SDimitry Andric #include "lldb/Utility/ConstString.h"
1494994d37SDimitry Andric #include "lldb/Utility/FileSpec.h"
1574a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
1694994d37SDimitry Andric #include "lldb/lldb-defines.h"
17ac9a064cSDimitry Andric #include "lldb/lldb-types.h"
1874a628f7SDimitry Andric
1994994d37SDimitry Andric #include "llvm/Support/Compiler.h"
2074a628f7SDimitry Andric
2194994d37SDimitry Andric #include <memory>
2274a628f7SDimitry Andric
23344a3780SDimitry Andric #include <cinttypes>
2474a628f7SDimitry Andric
2574a628f7SDimitry Andric namespace lldb_private {
2674a628f7SDimitry Andric class SectionList;
2774a628f7SDimitry Andric }
28f034231aSEd Maste
29f034231aSEd Maste using namespace lldb;
30f034231aSEd Maste using namespace lldb_private;
31f034231aSEd Maste
AddressRange()32344a3780SDimitry Andric AddressRange::AddressRange() : m_base_addr() {}
33f034231aSEd Maste
AddressRange(addr_t file_addr,addr_t byte_size,const SectionList * section_list)3414f1b3e8SDimitry Andric AddressRange::AddressRange(addr_t file_addr, addr_t byte_size,
3514f1b3e8SDimitry Andric const SectionList *section_list)
3614f1b3e8SDimitry Andric : m_base_addr(file_addr, section_list), m_byte_size(byte_size) {}
37f034231aSEd Maste
AddressRange(const lldb::SectionSP & section,addr_t offset,addr_t byte_size)3814f1b3e8SDimitry Andric AddressRange::AddressRange(const lldb::SectionSP §ion, addr_t offset,
3914f1b3e8SDimitry Andric addr_t byte_size)
4014f1b3e8SDimitry Andric : m_base_addr(section, offset), m_byte_size(byte_size) {}
41f034231aSEd Maste
AddressRange(const Address & so_addr,addr_t byte_size)4214f1b3e8SDimitry Andric AddressRange::AddressRange(const Address &so_addr, addr_t byte_size)
4314f1b3e8SDimitry Andric : m_base_addr(so_addr), m_byte_size(byte_size) {}
44f034231aSEd Maste
45344a3780SDimitry Andric AddressRange::~AddressRange() = default;
46f034231aSEd Maste
Contains(const Address & addr) const47344a3780SDimitry Andric bool AddressRange::Contains(const Address &addr) const {
48344a3780SDimitry Andric SectionSP range_sect_sp = GetBaseAddress().GetSection();
49344a3780SDimitry Andric SectionSP addr_sect_sp = addr.GetSection();
50344a3780SDimitry Andric if (range_sect_sp) {
51344a3780SDimitry Andric if (!addr_sect_sp ||
52344a3780SDimitry Andric range_sect_sp->GetModule() != addr_sect_sp->GetModule())
53344a3780SDimitry Andric return false; // Modules do not match.
54344a3780SDimitry Andric } else if (addr_sect_sp) {
55344a3780SDimitry Andric return false; // Range has no module but "addr" does because addr has a
56344a3780SDimitry Andric // section
57344a3780SDimitry Andric }
58344a3780SDimitry Andric // Either the modules match, or both have no module, so it is ok to compare
59344a3780SDimitry Andric // the file addresses in this case only.
60344a3780SDimitry Andric return ContainsFileAddress(addr);
61344a3780SDimitry Andric }
62344a3780SDimitry Andric
ContainsFileAddress(const Address & addr) const6314f1b3e8SDimitry Andric bool AddressRange::ContainsFileAddress(const Address &addr) const {
64f034231aSEd Maste if (addr.GetSection() == m_base_addr.GetSection())
65f034231aSEd Maste return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize();
66f034231aSEd Maste addr_t file_base_addr = GetBaseAddress().GetFileAddress();
67f034231aSEd Maste if (file_base_addr == LLDB_INVALID_ADDRESS)
68f034231aSEd Maste return false;
69f034231aSEd Maste
70f034231aSEd Maste addr_t file_addr = addr.GetFileAddress();
71f034231aSEd Maste if (file_addr == LLDB_INVALID_ADDRESS)
72f034231aSEd Maste return false;
73f034231aSEd Maste
74f034231aSEd Maste if (file_base_addr <= file_addr)
75f034231aSEd Maste return (file_addr - file_base_addr) < GetByteSize();
76f034231aSEd Maste
77f034231aSEd Maste return false;
78f034231aSEd Maste }
79f034231aSEd Maste
ContainsFileAddress(addr_t file_addr) const8014f1b3e8SDimitry Andric bool AddressRange::ContainsFileAddress(addr_t file_addr) const {
81f034231aSEd Maste if (file_addr == LLDB_INVALID_ADDRESS)
82f034231aSEd Maste return false;
83f034231aSEd Maste
84f034231aSEd Maste addr_t file_base_addr = GetBaseAddress().GetFileAddress();
85f034231aSEd Maste if (file_base_addr == LLDB_INVALID_ADDRESS)
86f034231aSEd Maste return false;
87f034231aSEd Maste
88f034231aSEd Maste if (file_base_addr <= file_addr)
89f034231aSEd Maste return (file_addr - file_base_addr) < GetByteSize();
90f034231aSEd Maste
91f034231aSEd Maste return false;
92f034231aSEd Maste }
93f034231aSEd Maste
ContainsLoadAddress(const Address & addr,Target * target) const9414f1b3e8SDimitry Andric bool AddressRange::ContainsLoadAddress(const Address &addr,
9514f1b3e8SDimitry Andric Target *target) const {
96f034231aSEd Maste if (addr.GetSection() == m_base_addr.GetSection())
97f034231aSEd Maste return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize();
98f034231aSEd Maste addr_t load_base_addr = GetBaseAddress().GetLoadAddress(target);
99f034231aSEd Maste if (load_base_addr == LLDB_INVALID_ADDRESS)
100f034231aSEd Maste return false;
101f034231aSEd Maste
102f034231aSEd Maste addr_t load_addr = addr.GetLoadAddress(target);
103f034231aSEd Maste if (load_addr == LLDB_INVALID_ADDRESS)
104f034231aSEd Maste return false;
105f034231aSEd Maste
106f034231aSEd Maste if (load_base_addr <= load_addr)
107f034231aSEd Maste return (load_addr - load_base_addr) < GetByteSize();
108f034231aSEd Maste
109f034231aSEd Maste return false;
110f034231aSEd Maste }
111f034231aSEd Maste
ContainsLoadAddress(addr_t load_addr,Target * target) const11214f1b3e8SDimitry Andric bool AddressRange::ContainsLoadAddress(addr_t load_addr, Target *target) const {
113f034231aSEd Maste if (load_addr == LLDB_INVALID_ADDRESS)
114f034231aSEd Maste return false;
115f034231aSEd Maste
116f034231aSEd Maste addr_t load_base_addr = GetBaseAddress().GetLoadAddress(target);
117f034231aSEd Maste if (load_base_addr == LLDB_INVALID_ADDRESS)
118f034231aSEd Maste return false;
119f034231aSEd Maste
120f034231aSEd Maste if (load_base_addr <= load_addr)
121f034231aSEd Maste return (load_addr - load_base_addr) < GetByteSize();
122f034231aSEd Maste
123f034231aSEd Maste return false;
124f034231aSEd Maste }
125f034231aSEd Maste
Extend(const AddressRange & rhs_range)1265f29bb8aSDimitry Andric bool AddressRange::Extend(const AddressRange &rhs_range) {
1275f29bb8aSDimitry Andric addr_t lhs_end_addr = GetBaseAddress().GetFileAddress() + GetByteSize();
1285f29bb8aSDimitry Andric addr_t rhs_base_addr = rhs_range.GetBaseAddress().GetFileAddress();
1295f29bb8aSDimitry Andric
1305f29bb8aSDimitry Andric if (!ContainsFileAddress(rhs_range.GetBaseAddress()) &&
1315f29bb8aSDimitry Andric lhs_end_addr != rhs_base_addr)
1325f29bb8aSDimitry Andric // The ranges don't intersect at all on the right side of this range.
1335f29bb8aSDimitry Andric return false;
1345f29bb8aSDimitry Andric
1355f29bb8aSDimitry Andric addr_t rhs_end_addr = rhs_base_addr + rhs_range.GetByteSize();
1365f29bb8aSDimitry Andric if (lhs_end_addr >= rhs_end_addr)
1375f29bb8aSDimitry Andric // The rhs range totally overlaps this one, nothing to add.
1385f29bb8aSDimitry Andric return false;
1395f29bb8aSDimitry Andric
1405f29bb8aSDimitry Andric m_byte_size += rhs_end_addr - lhs_end_addr;
1415f29bb8aSDimitry Andric return true;
1425f29bb8aSDimitry Andric }
1435f29bb8aSDimitry Andric
Clear()14414f1b3e8SDimitry Andric void AddressRange::Clear() {
145f034231aSEd Maste m_base_addr.Clear();
146f034231aSEd Maste m_byte_size = 0;
147f034231aSEd Maste }
148f034231aSEd Maste
IsValid() const149ac9a064cSDimitry Andric bool AddressRange::IsValid() const {
150ac9a064cSDimitry Andric return m_base_addr.IsValid() && (m_byte_size > 0);
151ac9a064cSDimitry Andric }
152ac9a064cSDimitry Andric
Dump(Stream * s,Target * target,Address::DumpStyle style,Address::DumpStyle fallback_style) const15314f1b3e8SDimitry Andric bool AddressRange::Dump(Stream *s, Target *target, Address::DumpStyle style,
15414f1b3e8SDimitry Andric Address::DumpStyle fallback_style) const {
155f034231aSEd Maste addr_t vmaddr = LLDB_INVALID_ADDRESS;
156f034231aSEd Maste int addr_size = sizeof(addr_t);
157f034231aSEd Maste if (target)
158f034231aSEd Maste addr_size = target->GetArchitecture().GetAddressByteSize();
159f034231aSEd Maste
160f034231aSEd Maste bool show_module = false;
16114f1b3e8SDimitry Andric switch (style) {
162f034231aSEd Maste default:
163f034231aSEd Maste break;
164f034231aSEd Maste case Address::DumpStyleSectionNameOffset:
165f034231aSEd Maste case Address::DumpStyleSectionPointerOffset:
166f034231aSEd Maste s->PutChar('[');
167f034231aSEd Maste m_base_addr.Dump(s, target, style, fallback_style);
168f034231aSEd Maste s->PutChar('-');
169706b4fc4SDimitry Andric DumpAddress(s->AsRawOstream(), m_base_addr.GetOffset() + GetByteSize(),
170706b4fc4SDimitry Andric addr_size);
171f034231aSEd Maste s->PutChar(')');
172f034231aSEd Maste return true;
173f034231aSEd Maste break;
174f034231aSEd Maste
175f034231aSEd Maste case Address::DumpStyleModuleWithFileAddress:
176f034231aSEd Maste show_module = true;
177e3b55780SDimitry Andric [[fallthrough]];
178f034231aSEd Maste case Address::DumpStyleFileAddress:
179f034231aSEd Maste vmaddr = m_base_addr.GetFileAddress();
180f034231aSEd Maste break;
181f034231aSEd Maste
182f034231aSEd Maste case Address::DumpStyleLoadAddress:
183f034231aSEd Maste vmaddr = m_base_addr.GetLoadAddress(target);
184f034231aSEd Maste break;
185f034231aSEd Maste }
186f034231aSEd Maste
18714f1b3e8SDimitry Andric if (vmaddr != LLDB_INVALID_ADDRESS) {
18814f1b3e8SDimitry Andric if (show_module) {
189f034231aSEd Maste ModuleSP module_sp(GetBaseAddress().GetModule());
190f034231aSEd Maste if (module_sp)
19114f1b3e8SDimitry Andric s->Printf("%s", module_sp->GetFileSpec().GetFilename().AsCString(
19214f1b3e8SDimitry Andric "<Unknown>"));
193f034231aSEd Maste }
194706b4fc4SDimitry Andric DumpAddressRange(s->AsRawOstream(), vmaddr, vmaddr + GetByteSize(),
195706b4fc4SDimitry Andric addr_size);
196f034231aSEd Maste return true;
19714f1b3e8SDimitry Andric } else if (fallback_style != Address::DumpStyleInvalid) {
198f034231aSEd Maste return Dump(s, target, fallback_style, Address::DumpStyleInvalid);
199f034231aSEd Maste }
200f034231aSEd Maste
201f034231aSEd Maste return false;
202f034231aSEd Maste }
203f034231aSEd Maste
DumpDebug(Stream * s) const20414f1b3e8SDimitry Andric void AddressRange::DumpDebug(Stream *s) const {
20514f1b3e8SDimitry Andric s->Printf("%p: AddressRange section = %p, offset = 0x%16.16" PRIx64
20614f1b3e8SDimitry Andric ", byte_size = 0x%16.16" PRIx64 "\n",
2070cac4ca3SEd Maste static_cast<const void *>(this),
2080cac4ca3SEd Maste static_cast<void *>(m_base_addr.GetSection().get()),
2090cac4ca3SEd Maste m_base_addr.GetOffset(), GetByteSize());
210f034231aSEd Maste }
211ac9a064cSDimitry Andric
GetDescription(Stream * s,Target * target) const212ac9a064cSDimitry Andric bool AddressRange::GetDescription(Stream *s, Target *target) const {
213ac9a064cSDimitry Andric addr_t start_addr = m_base_addr.GetLoadAddress(target);
214ac9a064cSDimitry Andric if (start_addr != LLDB_INVALID_ADDRESS) {
215ac9a064cSDimitry Andric // We have a valid target and the address was resolved, or we have a base
216ac9a064cSDimitry Andric // address with no section. Just print out a raw address range: [<addr>,
217ac9a064cSDimitry Andric // <addr>)
218ac9a064cSDimitry Andric s->Printf("[0x%" PRIx64 "-0x%" PRIx64 ")", start_addr,
219ac9a064cSDimitry Andric start_addr + GetByteSize());
220ac9a064cSDimitry Andric return true;
221ac9a064cSDimitry Andric }
222ac9a064cSDimitry Andric
223ac9a064cSDimitry Andric // Either no target or the address wasn't resolved, print as
224ac9a064cSDimitry Andric // <module>[<file-addr>-<file-addr>)
225ac9a064cSDimitry Andric const char *file_name = "";
226ac9a064cSDimitry Andric const auto section_sp = m_base_addr.GetSection();
227ac9a064cSDimitry Andric if (section_sp) {
228ac9a064cSDimitry Andric if (const auto object_file = section_sp->GetObjectFile())
229ac9a064cSDimitry Andric file_name = object_file->GetFileSpec().GetFilename().AsCString();
230ac9a064cSDimitry Andric }
231ac9a064cSDimitry Andric start_addr = m_base_addr.GetFileAddress();
232ac9a064cSDimitry Andric const addr_t end_addr = (start_addr == LLDB_INVALID_ADDRESS)
233ac9a064cSDimitry Andric ? LLDB_INVALID_ADDRESS
234ac9a064cSDimitry Andric : start_addr + GetByteSize();
235ac9a064cSDimitry Andric s->Printf("%s[0x%" PRIx64 "-0x%" PRIx64 ")", file_name, start_addr, end_addr);
236ac9a064cSDimitry Andric return true;
237ac9a064cSDimitry Andric }
238ac9a064cSDimitry Andric
operator ==(const AddressRange & rhs)239ac9a064cSDimitry Andric bool AddressRange::operator==(const AddressRange &rhs) {
240ac9a064cSDimitry Andric if (!IsValid() || !rhs.IsValid())
241ac9a064cSDimitry Andric return false;
242ac9a064cSDimitry Andric return m_base_addr == rhs.GetBaseAddress() &&
243ac9a064cSDimitry Andric m_byte_size == rhs.GetByteSize();
244ac9a064cSDimitry Andric }
245ac9a064cSDimitry Andric
operator !=(const AddressRange & rhs)246ac9a064cSDimitry Andric bool AddressRange::operator!=(const AddressRange &rhs) {
247ac9a064cSDimitry Andric return !(*this == rhs);
248ac9a064cSDimitry Andric }
249