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 18 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 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 28 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 * 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 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 106 SectionLoadHistory::GetSectionLoadAddress(uint32_t stop_id, 107 const lldb::SectionSP §ion_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 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 125 bool SectionLoadHistory::SetSectionLoadAddress( 126 uint32_t stop_id, const lldb::SectionSP §ion_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 137 SectionLoadHistory::SetSectionUnloaded(uint32_t stop_id, 138 const lldb::SectionSP §ion_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 146 bool SectionLoadHistory::SetSectionUnloaded(uint32_t stop_id, 147 const lldb::SectionSP §ion_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 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