1 //===-- SectionLoadHistory.cpp ----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Target/SectionLoadHistory.h"
11 
12 #include "lldb/Target/SectionLoadList.h"
13 #include "lldb/Utility/Stream.h"
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 
IsEmpty() const18 bool SectionLoadHistory::IsEmpty() const {
19   std::lock_guard<std::recursive_mutex> guard(m_mutex);
20   return m_stop_id_to_section_load_list.empty();
21 }
22 
Clear()23 void SectionLoadHistory::Clear() {
24   std::lock_guard<std::recursive_mutex> guard(m_mutex);
25   m_stop_id_to_section_load_list.clear();
26 }
27 
GetLastStopID() const28 uint32_t SectionLoadHistory::GetLastStopID() const {
29   std::lock_guard<std::recursive_mutex> guard(m_mutex);
30   if (m_stop_id_to_section_load_list.empty())
31     return 0;
32   else
33     return m_stop_id_to_section_load_list.rbegin()->first;
34 }
35 
36 SectionLoadList *
GetSectionLoadListForStopID(uint32_t stop_id,bool read_only)37 SectionLoadHistory::GetSectionLoadListForStopID(uint32_t stop_id,
38                                                 bool read_only) {
39   if (!m_stop_id_to_section_load_list.empty()) {
40     if (read_only) {
41       // The section load list is for reading data only so we don't need to
42       // create a new SectionLoadList for the current stop ID, just return the
43       // section load list for the stop ID that is equal to or less than the
44       // current stop ID
45       if (stop_id == eStopIDNow) {
46         // If we are asking for the latest and greatest value, it is always at
47         // the end of our list because that will be the highest stop ID.
48         StopIDToSectionLoadList::reverse_iterator rpos =
49             m_stop_id_to_section_load_list.rbegin();
50         return rpos->second.get();
51       } else {
52         StopIDToSectionLoadList::iterator pos =
53             m_stop_id_to_section_load_list.lower_bound(stop_id);
54         if (pos != m_stop_id_to_section_load_list.end() &&
55             pos->first == stop_id)
56           return pos->second.get();
57         else if (pos != m_stop_id_to_section_load_list.begin()) {
58           --pos;
59           return pos->second.get();
60         }
61       }
62     } else {
63       // You can only use "eStopIDNow" when reading from the section load
64       // history
65       assert(stop_id != eStopIDNow);
66 
67       // We are updating the section load list (not read only), so if the stop
68       // ID passed in isn't the same as the last stop ID in our collection,
69       // then create a new node using the current stop ID
70       StopIDToSectionLoadList::iterator pos =
71           m_stop_id_to_section_load_list.lower_bound(stop_id);
72       if (pos != m_stop_id_to_section_load_list.end() &&
73           pos->first == stop_id) {
74         // We already have an entry for this value
75         return pos->second.get();
76       }
77 
78       // We must make a new section load list that is based on the last valid
79       // section load list, so here we copy the last section load list and add
80       // a new node for the current stop ID.
81       StopIDToSectionLoadList::reverse_iterator rpos =
82           m_stop_id_to_section_load_list.rbegin();
83       SectionLoadListSP section_load_list_sp(
84           new SectionLoadList(*rpos->second.get()));
85       m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
86       return section_load_list_sp.get();
87     }
88   }
89   SectionLoadListSP section_load_list_sp(new SectionLoadList());
90   if (stop_id == eStopIDNow)
91     stop_id = 0;
92   m_stop_id_to_section_load_list[stop_id] = section_load_list_sp;
93   return section_load_list_sp.get();
94 }
95 
GetCurrentSectionLoadList()96 SectionLoadList &SectionLoadHistory::GetCurrentSectionLoadList() {
97   const bool read_only = true;
98   std::lock_guard<std::recursive_mutex> guard(m_mutex);
99   SectionLoadList *section_load_list =
100       GetSectionLoadListForStopID(eStopIDNow, read_only);
101   assert(section_load_list != NULL);
102   return *section_load_list;
103 }
104 
105 addr_t
GetSectionLoadAddress(uint32_t stop_id,const lldb::SectionSP & section_sp)106 SectionLoadHistory::GetSectionLoadAddress(uint32_t stop_id,
107                                           const lldb::SectionSP &section_sp) {
108   std::lock_guard<std::recursive_mutex> guard(m_mutex);
109   const bool read_only = true;
110   SectionLoadList *section_load_list =
111       GetSectionLoadListForStopID(stop_id, read_only);
112   return section_load_list->GetSectionLoadAddress(section_sp);
113 }
114 
ResolveLoadAddress(uint32_t stop_id,addr_t load_addr,Address & so_addr)115 bool SectionLoadHistory::ResolveLoadAddress(uint32_t stop_id, addr_t load_addr,
116                                             Address &so_addr) {
117   // First find the top level section that this load address exists in
118   std::lock_guard<std::recursive_mutex> guard(m_mutex);
119   const bool read_only = true;
120   SectionLoadList *section_load_list =
121       GetSectionLoadListForStopID(stop_id, read_only);
122   return section_load_list->ResolveLoadAddress(load_addr, so_addr);
123 }
124 
SetSectionLoadAddress(uint32_t stop_id,const lldb::SectionSP & section_sp,addr_t load_addr,bool warn_multiple)125 bool SectionLoadHistory::SetSectionLoadAddress(
126     uint32_t stop_id, const lldb::SectionSP &section_sp, addr_t load_addr,
127     bool warn_multiple) {
128   std::lock_guard<std::recursive_mutex> guard(m_mutex);
129   const bool read_only = false;
130   SectionLoadList *section_load_list =
131       GetSectionLoadListForStopID(stop_id, read_only);
132   return section_load_list->SetSectionLoadAddress(section_sp, load_addr,
133                                                   warn_multiple);
134 }
135 
136 size_t
SetSectionUnloaded(uint32_t stop_id,const lldb::SectionSP & section_sp)137 SectionLoadHistory::SetSectionUnloaded(uint32_t stop_id,
138                                        const lldb::SectionSP &section_sp) {
139   std::lock_guard<std::recursive_mutex> guard(m_mutex);
140   const bool read_only = false;
141   SectionLoadList *section_load_list =
142       GetSectionLoadListForStopID(stop_id, read_only);
143   return section_load_list->SetSectionUnloaded(section_sp);
144 }
145 
SetSectionUnloaded(uint32_t stop_id,const lldb::SectionSP & section_sp,addr_t load_addr)146 bool SectionLoadHistory::SetSectionUnloaded(uint32_t stop_id,
147                                             const lldb::SectionSP &section_sp,
148                                             addr_t load_addr) {
149   std::lock_guard<std::recursive_mutex> guard(m_mutex);
150   const bool read_only = false;
151   SectionLoadList *section_load_list =
152       GetSectionLoadListForStopID(stop_id, read_only);
153   return section_load_list->SetSectionUnloaded(section_sp, load_addr);
154 }
155 
Dump(Stream & s,Target * target)156 void SectionLoadHistory::Dump(Stream &s, Target *target) {
157   std::lock_guard<std::recursive_mutex> guard(m_mutex);
158   StopIDToSectionLoadList::iterator pos,
159       end = m_stop_id_to_section_load_list.end();
160   for (pos = m_stop_id_to_section_load_list.begin(); pos != end; ++pos) {
161     s.Printf("StopID = %u:\n", pos->first);
162     pos->second->Dump(s, target);
163     s.EOL();
164   }
165 }
166