180814287SRaphael Isemann //===-- AddressRange.cpp --------------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
930fdc8d8SChris Lattner #include "lldb/Core/AddressRange.h"
10c9800667SGreg Clayton #include "lldb/Core/Module.h"
11ade59d53SWalter Erquinigo #include "lldb/Core/Section.h"
12f5e56de0SGreg Clayton #include "lldb/Target/Target.h"
13672d2c12SJonas Devlieghere #include "lldb/Utility/ConstString.h"
14672d2c12SJonas Devlieghere #include "lldb/Utility/FileSpec.h"
15bf9a7730SZachary Turner #include "lldb/Utility/Stream.h"
16672d2c12SJonas Devlieghere #include "lldb/lldb-defines.h"
172f3df613SZachary Turner 
18672d2c12SJonas Devlieghere #include "llvm/Support/Compiler.h"
192f3df613SZachary Turner 
20672d2c12SJonas Devlieghere #include <memory>
212f3df613SZachary Turner 
2276e47d48SRaphael Isemann #include <cinttypes>
232f3df613SZachary Turner 
242f3df613SZachary Turner namespace lldb_private {
252f3df613SZachary Turner class SectionList;
262f3df613SZachary Turner }
2730fdc8d8SChris Lattner 
2830fdc8d8SChris Lattner using namespace lldb;
2930fdc8d8SChris Lattner using namespace lldb_private;
3030fdc8d8SChris Lattner 
AddressRange()319494c510SJonas Devlieghere AddressRange::AddressRange() : m_base_addr() {}
3230fdc8d8SChris Lattner 
AddressRange(addr_t file_addr,addr_t byte_size,const SectionList * section_list)33b9c1b51eSKate Stone AddressRange::AddressRange(addr_t file_addr, addr_t byte_size,
34b9c1b51eSKate Stone                            const SectionList *section_list)
35b9c1b51eSKate Stone     : m_base_addr(file_addr, section_list), m_byte_size(byte_size) {}
3630fdc8d8SChris Lattner 
AddressRange(const lldb::SectionSP & section,addr_t offset,addr_t byte_size)37b9c1b51eSKate Stone AddressRange::AddressRange(const lldb::SectionSP &section, addr_t offset,
38b9c1b51eSKate Stone                            addr_t byte_size)
39b9c1b51eSKate Stone     : m_base_addr(section, offset), m_byte_size(byte_size) {}
4030fdc8d8SChris Lattner 
AddressRange(const Address & so_addr,addr_t byte_size)41b9c1b51eSKate Stone AddressRange::AddressRange(const Address &so_addr, addr_t byte_size)
42b9c1b51eSKate Stone     : m_base_addr(so_addr), m_byte_size(byte_size) {}
4330fdc8d8SChris Lattner 
44*fd2433e1SJonas Devlieghere AddressRange::~AddressRange() = default;
4530fdc8d8SChris Lattner 
Contains(const Address & addr) const46ade59d53SWalter Erquinigo bool AddressRange::Contains(const Address &addr) const {
47ade59d53SWalter Erquinigo   SectionSP range_sect_sp = GetBaseAddress().GetSection();
48ade59d53SWalter Erquinigo   SectionSP addr_sect_sp = addr.GetSection();
49ade59d53SWalter Erquinigo   if (range_sect_sp) {
50ade59d53SWalter Erquinigo     if (!addr_sect_sp ||
51ade59d53SWalter Erquinigo         range_sect_sp->GetModule() != addr_sect_sp->GetModule())
52ade59d53SWalter Erquinigo       return false; // Modules do not match.
53ade59d53SWalter Erquinigo   } else if (addr_sect_sp) {
54ade59d53SWalter Erquinigo     return false; // Range has no module but "addr" does because addr has a
55ade59d53SWalter Erquinigo                   // section
56ade59d53SWalter Erquinigo   }
57ade59d53SWalter Erquinigo   // Either the modules match, or both have no module, so it is ok to compare
58ade59d53SWalter Erquinigo   // the file addresses in this case only.
59ade59d53SWalter Erquinigo   return ContainsFileAddress(addr);
60ade59d53SWalter Erquinigo }
61ade59d53SWalter Erquinigo 
ContainsFileAddress(const Address & addr) const62b9c1b51eSKate Stone bool AddressRange::ContainsFileAddress(const Address &addr) const {
6330fdc8d8SChris Lattner   if (addr.GetSection() == m_base_addr.GetSection())
6430fdc8d8SChris Lattner     return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize();
6530fdc8d8SChris Lattner   addr_t file_base_addr = GetBaseAddress().GetFileAddress();
6630fdc8d8SChris Lattner   if (file_base_addr == LLDB_INVALID_ADDRESS)
6730fdc8d8SChris Lattner     return false;
6830fdc8d8SChris Lattner 
6930fdc8d8SChris Lattner   addr_t file_addr = addr.GetFileAddress();
7030fdc8d8SChris Lattner   if (file_addr == LLDB_INVALID_ADDRESS)
7130fdc8d8SChris Lattner     return false;
7230fdc8d8SChris Lattner 
7330fdc8d8SChris Lattner   if (file_base_addr <= file_addr)
7430fdc8d8SChris Lattner     return (file_addr - file_base_addr) < GetByteSize();
7530fdc8d8SChris Lattner 
7630fdc8d8SChris Lattner   return false;
7730fdc8d8SChris Lattner }
7830fdc8d8SChris Lattner 
ContainsFileAddress(addr_t file_addr) const79b9c1b51eSKate Stone bool AddressRange::ContainsFileAddress(addr_t file_addr) const {
8030fdc8d8SChris Lattner   if (file_addr == LLDB_INVALID_ADDRESS)
8130fdc8d8SChris Lattner     return false;
8230fdc8d8SChris Lattner 
8330fdc8d8SChris Lattner   addr_t file_base_addr = GetBaseAddress().GetFileAddress();
8430fdc8d8SChris Lattner   if (file_base_addr == LLDB_INVALID_ADDRESS)
8530fdc8d8SChris Lattner     return false;
8630fdc8d8SChris Lattner 
8730fdc8d8SChris Lattner   if (file_base_addr <= file_addr)
8830fdc8d8SChris Lattner     return (file_addr - file_base_addr) < GetByteSize();
8930fdc8d8SChris Lattner 
9030fdc8d8SChris Lattner   return false;
9130fdc8d8SChris Lattner }
9230fdc8d8SChris Lattner 
ContainsLoadAddress(const Address & addr,Target * target) const93b9c1b51eSKate Stone bool AddressRange::ContainsLoadAddress(const Address &addr,
94b9c1b51eSKate Stone                                        Target *target) const {
9530fdc8d8SChris Lattner   if (addr.GetSection() == m_base_addr.GetSection())
9630fdc8d8SChris Lattner     return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize();
97f5e56de0SGreg Clayton   addr_t load_base_addr = GetBaseAddress().GetLoadAddress(target);
9830fdc8d8SChris Lattner   if (load_base_addr == LLDB_INVALID_ADDRESS)
9930fdc8d8SChris Lattner     return false;
10030fdc8d8SChris Lattner 
101f5e56de0SGreg Clayton   addr_t load_addr = addr.GetLoadAddress(target);
10230fdc8d8SChris Lattner   if (load_addr == LLDB_INVALID_ADDRESS)
10330fdc8d8SChris Lattner     return false;
10430fdc8d8SChris Lattner 
10530fdc8d8SChris Lattner   if (load_base_addr <= load_addr)
10630fdc8d8SChris Lattner     return (load_addr - load_base_addr) < GetByteSize();
10730fdc8d8SChris Lattner 
10830fdc8d8SChris Lattner   return false;
10930fdc8d8SChris Lattner }
11030fdc8d8SChris Lattner 
ContainsLoadAddress(addr_t load_addr,Target * target) const111b9c1b51eSKate Stone bool AddressRange::ContainsLoadAddress(addr_t load_addr, Target *target) const {
11230fdc8d8SChris Lattner   if (load_addr == LLDB_INVALID_ADDRESS)
11330fdc8d8SChris Lattner     return false;
11430fdc8d8SChris Lattner 
115f5e56de0SGreg Clayton   addr_t load_base_addr = GetBaseAddress().GetLoadAddress(target);
11630fdc8d8SChris Lattner   if (load_base_addr == LLDB_INVALID_ADDRESS)
11730fdc8d8SChris Lattner     return false;
11830fdc8d8SChris Lattner 
11930fdc8d8SChris Lattner   if (load_base_addr <= load_addr)
12030fdc8d8SChris Lattner     return (load_addr - load_base_addr) < GetByteSize();
12130fdc8d8SChris Lattner 
12230fdc8d8SChris Lattner   return false;
12330fdc8d8SChris Lattner }
12430fdc8d8SChris Lattner 
Extend(const AddressRange & rhs_range)1258a777920SGreg Clayton bool AddressRange::Extend(const AddressRange &rhs_range) {
1268a777920SGreg Clayton   addr_t lhs_end_addr = GetBaseAddress().GetFileAddress() + GetByteSize();
1278a777920SGreg Clayton   addr_t rhs_base_addr = rhs_range.GetBaseAddress().GetFileAddress();
1288a777920SGreg Clayton 
1298a777920SGreg Clayton   if (!ContainsFileAddress(rhs_range.GetBaseAddress()) &&
1308a777920SGreg Clayton       lhs_end_addr != rhs_base_addr)
1318a777920SGreg Clayton     // The ranges don't intersect at all on the right side of this range.
1328a777920SGreg Clayton     return false;
1338a777920SGreg Clayton 
1348a777920SGreg Clayton   addr_t rhs_end_addr = rhs_base_addr + rhs_range.GetByteSize();
1358a777920SGreg Clayton   if (lhs_end_addr >= rhs_end_addr)
1368a777920SGreg Clayton     // The rhs range totally overlaps this one, nothing to add.
1378a777920SGreg Clayton     return false;
1388a777920SGreg Clayton 
1398a777920SGreg Clayton   m_byte_size += rhs_end_addr - lhs_end_addr;
1408a777920SGreg Clayton   return true;
1418a777920SGreg Clayton }
1428a777920SGreg Clayton 
Clear()143b9c1b51eSKate Stone void AddressRange::Clear() {
14430fdc8d8SChris Lattner   m_base_addr.Clear();
14530fdc8d8SChris Lattner   m_byte_size = 0;
14630fdc8d8SChris Lattner }
14730fdc8d8SChris Lattner 
Dump(Stream * s,Target * target,Address::DumpStyle style,Address::DumpStyle fallback_style) const148b9c1b51eSKate Stone bool AddressRange::Dump(Stream *s, Target *target, Address::DumpStyle style,
149b9c1b51eSKate Stone                         Address::DumpStyle fallback_style) const {
15030fdc8d8SChris Lattner   addr_t vmaddr = LLDB_INVALID_ADDRESS;
15130fdc8d8SChris Lattner   int addr_size = sizeof(addr_t);
152514487e8SGreg Clayton   if (target)
153514487e8SGreg Clayton     addr_size = target->GetArchitecture().GetAddressByteSize();
15430fdc8d8SChris Lattner 
155c9800667SGreg Clayton   bool show_module = false;
156b9c1b51eSKate Stone   switch (style) {
157c982c768SGreg Clayton   default:
158c982c768SGreg Clayton     break;
15930fdc8d8SChris Lattner   case Address::DumpStyleSectionNameOffset:
16030fdc8d8SChris Lattner   case Address::DumpStyleSectionPointerOffset:
16130fdc8d8SChris Lattner     s->PutChar('[');
162f5e56de0SGreg Clayton     m_base_addr.Dump(s, target, style, fallback_style);
16330fdc8d8SChris Lattner     s->PutChar('-');
1641462f5a4SRaphael Isemann     DumpAddress(s->AsRawOstream(), m_base_addr.GetOffset() + GetByteSize(),
1651462f5a4SRaphael Isemann                 addr_size);
16630fdc8d8SChris Lattner     s->PutChar(')');
16730fdc8d8SChris Lattner     return true;
16830fdc8d8SChris Lattner     break;
16930fdc8d8SChris Lattner 
170c9800667SGreg Clayton   case Address::DumpStyleModuleWithFileAddress:
171c9800667SGreg Clayton     show_module = true;
17262e0681aSJason Molenda     LLVM_FALLTHROUGH;
17330fdc8d8SChris Lattner   case Address::DumpStyleFileAddress:
17430fdc8d8SChris Lattner     vmaddr = m_base_addr.GetFileAddress();
17530fdc8d8SChris Lattner     break;
17630fdc8d8SChris Lattner 
17730fdc8d8SChris Lattner   case Address::DumpStyleLoadAddress:
178f5e56de0SGreg Clayton     vmaddr = m_base_addr.GetLoadAddress(target);
17930fdc8d8SChris Lattner     break;
18030fdc8d8SChris Lattner   }
18130fdc8d8SChris Lattner 
182b9c1b51eSKate Stone   if (vmaddr != LLDB_INVALID_ADDRESS) {
183b9c1b51eSKate Stone     if (show_module) {
184e72dfb32SGreg Clayton       ModuleSP module_sp(GetBaseAddress().GetModule());
185e72dfb32SGreg Clayton       if (module_sp)
186b9c1b51eSKate Stone         s->Printf("%s", module_sp->GetFileSpec().GetFilename().AsCString(
187b9c1b51eSKate Stone                             "<Unknown>"));
188c9800667SGreg Clayton     }
1891462f5a4SRaphael Isemann     DumpAddressRange(s->AsRawOstream(), vmaddr, vmaddr + GetByteSize(),
1901462f5a4SRaphael Isemann                      addr_size);
19130fdc8d8SChris Lattner     return true;
192b9c1b51eSKate Stone   } else if (fallback_style != Address::DumpStyleInvalid) {
193f5e56de0SGreg Clayton     return Dump(s, target, fallback_style, Address::DumpStyleInvalid);
194c9800667SGreg Clayton   }
19530fdc8d8SChris Lattner 
19630fdc8d8SChris Lattner   return false;
19730fdc8d8SChris Lattner }
19830fdc8d8SChris Lattner 
DumpDebug(Stream * s) const199b9c1b51eSKate Stone void AddressRange::DumpDebug(Stream *s) const {
200b9c1b51eSKate Stone   s->Printf("%p: AddressRange section = %p, offset = 0x%16.16" PRIx64
201b9c1b51eSKate Stone             ", byte_size = 0x%16.16" PRIx64 "\n",
202324a1036SSaleem Abdulrasool             static_cast<const void *>(this),
203324a1036SSaleem Abdulrasool             static_cast<void *>(m_base_addr.GetSection().get()),
204324a1036SSaleem Abdulrasool             m_base_addr.GetOffset(), GetByteSize());
20530fdc8d8SChris Lattner }
206