xref: /src/contrib/llvm-project/lldb/source/Target/SectionLoadHistory.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1cfca06d7SDimitry Andric //===-- SectionLoadHistory.cpp --------------------------------------------===//
2866dcdacSEd 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
6866dcdacSEd Maste //
7866dcdacSEd Maste //===----------------------------------------------------------------------===//
8866dcdacSEd Maste 
9866dcdacSEd Maste #include "lldb/Target/SectionLoadHistory.h"
10866dcdacSEd Maste 
11866dcdacSEd Maste #include "lldb/Target/SectionLoadList.h"
1274a628f7SDimitry Andric #include "lldb/Utility/Stream.h"
13866dcdacSEd Maste 
14866dcdacSEd Maste using namespace lldb;
15866dcdacSEd Maste using namespace lldb_private;
16866dcdacSEd Maste 
IsEmpty() const1714f1b3e8SDimitry Andric bool SectionLoadHistory::IsEmpty() const {
18f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
19866dcdacSEd Maste   return m_stop_id_to_section_load_list.empty();
20866dcdacSEd Maste }
21866dcdacSEd Maste 
Clear()2214f1b3e8SDimitry Andric void SectionLoadHistory::Clear() {
23f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
24866dcdacSEd Maste   m_stop_id_to_section_load_list.clear();
25866dcdacSEd Maste }
26866dcdacSEd Maste 
GetLastStopID() const2714f1b3e8SDimitry Andric uint32_t SectionLoadHistory::GetLastStopID() const {
28f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
29866dcdacSEd Maste   if (m_stop_id_to_section_load_list.empty())
30866dcdacSEd Maste     return 0;
31866dcdacSEd Maste   else
32866dcdacSEd Maste     return m_stop_id_to_section_load_list.rbegin()->first;
33866dcdacSEd Maste }
34866dcdacSEd Maste 
35866dcdacSEd Maste SectionLoadList *
GetSectionLoadListForStopID(uint32_t stop_id,bool read_only)3614f1b3e8SDimitry Andric SectionLoadHistory::GetSectionLoadListForStopID(uint32_t stop_id,
3714f1b3e8SDimitry Andric                                                 bool read_only) {
3814f1b3e8SDimitry Andric   if (!m_stop_id_to_section_load_list.empty()) {
3914f1b3e8SDimitry Andric     if (read_only) {
4014f1b3e8SDimitry Andric       // The section load list is for reading data only so we don't need to
41f73363f1SDimitry Andric       // create a new SectionLoadList for the current stop ID, just return the
42f73363f1SDimitry Andric       // section load list for the stop ID that is equal to or less than the
43f73363f1SDimitry Andric       // current stop ID
4414f1b3e8SDimitry Andric       if (stop_id == eStopIDNow) {
45f73363f1SDimitry Andric         // If we are asking for the latest and greatest value, it is always at
46f73363f1SDimitry Andric         // the end of our list because that will be the highest stop ID.
4714f1b3e8SDimitry Andric         StopIDToSectionLoadList::reverse_iterator rpos =
4814f1b3e8SDimitry Andric             m_stop_id_to_section_load_list.rbegin();
49866dcdacSEd Maste         return rpos->second.get();
5014f1b3e8SDimitry Andric       } else {
5114f1b3e8SDimitry Andric         StopIDToSectionLoadList::iterator pos =
5214f1b3e8SDimitry Andric             m_stop_id_to_section_load_list.lower_bound(stop_id);
5314f1b3e8SDimitry Andric         if (pos != m_stop_id_to_section_load_list.end() &&
5414f1b3e8SDimitry Andric             pos->first == stop_id)
55866dcdacSEd Maste           return pos->second.get();
5614f1b3e8SDimitry Andric         else if (pos != m_stop_id_to_section_load_list.begin()) {
57866dcdacSEd Maste           --pos;
58866dcdacSEd Maste           return pos->second.get();
59866dcdacSEd Maste         }
60866dcdacSEd Maste       }
6114f1b3e8SDimitry Andric     } else {
6214f1b3e8SDimitry Andric       // You can only use "eStopIDNow" when reading from the section load
6314f1b3e8SDimitry Andric       // history
64866dcdacSEd Maste       assert(stop_id != eStopIDNow);
65866dcdacSEd Maste 
6614f1b3e8SDimitry Andric       // We are updating the section load list (not read only), so if the stop
67f73363f1SDimitry Andric       // ID passed in isn't the same as the last stop ID in our collection,
68f73363f1SDimitry Andric       // then create a new node using the current stop ID
6914f1b3e8SDimitry Andric       StopIDToSectionLoadList::iterator pos =
7014f1b3e8SDimitry Andric           m_stop_id_to_section_load_list.lower_bound(stop_id);
7114f1b3e8SDimitry Andric       if (pos != m_stop_id_to_section_load_list.end() &&
7214f1b3e8SDimitry Andric           pos->first == stop_id) {
73866dcdacSEd Maste         // We already have an entry for this value
74866dcdacSEd Maste         return pos->second.get();
75866dcdacSEd Maste       }
76866dcdacSEd Maste 
77866dcdacSEd Maste       // We must make a new section load list that is based on the last valid
78866dcdacSEd Maste       // section load list, so here we copy the last section load list and add
79866dcdacSEd Maste       // a new node for the current stop ID.
8014f1b3e8SDimitry Andric       StopIDToSectionLoadList::reverse_iterator rpos =
8114f1b3e8SDimitry Andric           m_stop_id_to_section_load_list.rbegin();
8214f1b3e8SDimitry Andric       SectionLoadListSP section_load_list_sp(
835f29bb8aSDimitry Andric           new SectionLoadList(*rpos->second));
84866dcdacSEd Maste       m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
85866dcdacSEd Maste       return section_load_list_sp.get();
86866dcdacSEd Maste     }
87866dcdacSEd Maste   }
880cac4ca3SEd Maste   SectionLoadListSP section_load_list_sp(new SectionLoadList());
890cac4ca3SEd Maste   if (stop_id == eStopIDNow)
900cac4ca3SEd Maste     stop_id = 0;
910cac4ca3SEd Maste   m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
920cac4ca3SEd Maste   return section_load_list_sp.get();
93866dcdacSEd Maste }
94866dcdacSEd Maste 
GetCurrentSectionLoadList()9514f1b3e8SDimitry Andric SectionLoadList &SectionLoadHistory::GetCurrentSectionLoadList() {
96866dcdacSEd Maste   const bool read_only = true;
97f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
9814f1b3e8SDimitry Andric   SectionLoadList *section_load_list =
9914f1b3e8SDimitry Andric       GetSectionLoadListForStopID(eStopIDNow, read_only);
1005f29bb8aSDimitry Andric   assert(section_load_list != nullptr);
101866dcdacSEd Maste   return *section_load_list;
102866dcdacSEd Maste }
103866dcdacSEd Maste 
104866dcdacSEd Maste addr_t
GetSectionLoadAddress(uint32_t stop_id,const lldb::SectionSP & section_sp)10514f1b3e8SDimitry Andric SectionLoadHistory::GetSectionLoadAddress(uint32_t stop_id,
10614f1b3e8SDimitry Andric                                           const lldb::SectionSP &section_sp) {
107f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
108866dcdacSEd Maste   const bool read_only = true;
10914f1b3e8SDimitry Andric   SectionLoadList *section_load_list =
11014f1b3e8SDimitry Andric       GetSectionLoadListForStopID(stop_id, read_only);
111866dcdacSEd Maste   return section_load_list->GetSectionLoadAddress(section_sp);
112866dcdacSEd Maste }
113866dcdacSEd Maste 
ResolveLoadAddress(uint32_t stop_id,addr_t load_addr,Address & so_addr)11414f1b3e8SDimitry Andric bool SectionLoadHistory::ResolveLoadAddress(uint32_t stop_id, addr_t load_addr,
11514f1b3e8SDimitry Andric                                             Address &so_addr) {
116866dcdacSEd Maste   // First find the top level section that this load address exists in
117f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
118866dcdacSEd Maste   const bool read_only = true;
11914f1b3e8SDimitry Andric   SectionLoadList *section_load_list =
12014f1b3e8SDimitry Andric       GetSectionLoadListForStopID(stop_id, read_only);
121866dcdacSEd Maste   return section_load_list->ResolveLoadAddress(load_addr, so_addr);
122866dcdacSEd Maste }
123866dcdacSEd Maste 
SetSectionLoadAddress(uint32_t stop_id,const lldb::SectionSP & section_sp,addr_t load_addr,bool warn_multiple)12414f1b3e8SDimitry Andric bool SectionLoadHistory::SetSectionLoadAddress(
12514f1b3e8SDimitry Andric     uint32_t stop_id, const lldb::SectionSP &section_sp, addr_t load_addr,
12614f1b3e8SDimitry Andric     bool warn_multiple) {
127f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
128866dcdacSEd Maste   const bool read_only = false;
12914f1b3e8SDimitry Andric   SectionLoadList *section_load_list =
13014f1b3e8SDimitry Andric       GetSectionLoadListForStopID(stop_id, read_only);
13114f1b3e8SDimitry Andric   return section_load_list->SetSectionLoadAddress(section_sp, load_addr,
13214f1b3e8SDimitry Andric                                                   warn_multiple);
133866dcdacSEd Maste }
134866dcdacSEd Maste 
135866dcdacSEd Maste size_t
SetSectionUnloaded(uint32_t stop_id,const lldb::SectionSP & section_sp)13614f1b3e8SDimitry Andric SectionLoadHistory::SetSectionUnloaded(uint32_t stop_id,
13714f1b3e8SDimitry Andric                                        const lldb::SectionSP &section_sp) {
138f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
139866dcdacSEd Maste   const bool read_only = false;
14014f1b3e8SDimitry Andric   SectionLoadList *section_load_list =
14114f1b3e8SDimitry Andric       GetSectionLoadListForStopID(stop_id, read_only);
142866dcdacSEd Maste   return section_load_list->SetSectionUnloaded(section_sp);
143866dcdacSEd Maste }
144866dcdacSEd Maste 
SetSectionUnloaded(uint32_t stop_id,const lldb::SectionSP & section_sp,addr_t load_addr)14514f1b3e8SDimitry Andric bool SectionLoadHistory::SetSectionUnloaded(uint32_t stop_id,
14614f1b3e8SDimitry Andric                                             const lldb::SectionSP &section_sp,
14714f1b3e8SDimitry Andric                                             addr_t load_addr) {
148f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
149866dcdacSEd Maste   const bool read_only = false;
15014f1b3e8SDimitry Andric   SectionLoadList *section_load_list =
15114f1b3e8SDimitry Andric       GetSectionLoadListForStopID(stop_id, read_only);
152866dcdacSEd Maste   return section_load_list->SetSectionUnloaded(section_sp, load_addr);
153866dcdacSEd Maste }
154866dcdacSEd Maste 
Dump(Stream & s,Target * target)15514f1b3e8SDimitry Andric void SectionLoadHistory::Dump(Stream &s, Target *target) {
156f3fbd1c0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_mutex);
15714f1b3e8SDimitry Andric   StopIDToSectionLoadList::iterator pos,
15814f1b3e8SDimitry Andric       end = m_stop_id_to_section_load_list.end();
15914f1b3e8SDimitry Andric   for (pos = m_stop_id_to_section_load_list.begin(); pos != end; ++pos) {
160866dcdacSEd Maste     s.Printf("StopID = %u:\n", pos->first);
161866dcdacSEd Maste     pos->second->Dump(s, target);
162866dcdacSEd Maste     s.EOL();
163866dcdacSEd Maste   }
164866dcdacSEd Maste }
165