xref: /src/contrib/llvm-project/lldb/source/Core/AddressRange.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583) !
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 &section, 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