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