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