1 //===-- SectionLoadList.cpp -----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Target/SectionLoadList.h" 10 11 #include "lldb/Core/Module.h" 12 #include "lldb/Core/Section.h" 13 #include "lldb/Symbol/Block.h" 14 #include "lldb/Symbol/Symbol.h" 15 #include "lldb/Symbol/SymbolContext.h" 16 #include "lldb/Utility/LLDBLog.h" 17 #include "lldb/Utility/Log.h" 18 #include "lldb/Utility/Stream.h" 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 SectionLoadList::SectionLoadList(const SectionLoadList &rhs) 24 : m_addr_to_sect(), m_sect_to_addr(), m_mutex() { 25 std::lock_guard<std::recursive_mutex> guard(rhs.m_mutex); 26 m_addr_to_sect = rhs.m_addr_to_sect; 27 m_sect_to_addr = rhs.m_sect_to_addr; 28 } 29 30 void SectionLoadList::operator=(const SectionLoadList &rhs) { 31 std::lock(m_mutex, rhs.m_mutex); 32 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock); 33 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex, std::adopt_lock); 34 m_addr_to_sect = rhs.m_addr_to_sect; 35 m_sect_to_addr = rhs.m_sect_to_addr; 36 } 37 38 bool SectionLoadList::IsEmpty() const { 39 std::lock_guard<std::recursive_mutex> guard(m_mutex); 40 return m_addr_to_sect.empty(); 41 } 42 43 void SectionLoadList::Clear() { 44 std::lock_guard<std::recursive_mutex> guard(m_mutex); 45 m_addr_to_sect.clear(); 46 m_sect_to_addr.clear(); 47 } 48 49 addr_t 50 SectionLoadList::GetSectionLoadAddress(const lldb::SectionSP §ion) const { 51 // TODO: add support for the same section having multiple load addresses 52 addr_t section_load_addr = LLDB_INVALID_ADDRESS; 53 if (section) { 54 std::lock_guard<std::recursive_mutex> guard(m_mutex); 55 sect_to_addr_collection::const_iterator pos = 56 m_sect_to_addr.find(section.get()); 57 58 if (pos != m_sect_to_addr.end()) 59 section_load_addr = pos->second; 60 } 61 return section_load_addr; 62 } 63 64 bool SectionLoadList::SetSectionLoadAddress(const lldb::SectionSP §ion, 65 addr_t load_addr, 66 bool warn_multiple) { 67 Log *log = GetLog(LLDBLog::DynamicLoader); 68 ModuleSP module_sp(section->GetModule()); 69 70 if (module_sp) { 71 LLDB_LOGV(log, "(section = {0} ({1}.{2}), load_addr = {3:x}) module = {4}", 72 section.get(), module_sp->GetFileSpec(), section->GetName(), 73 load_addr, module_sp.get()); 74 75 if (section->GetByteSize() == 0) 76 return false; // No change 77 78 // Fill in the section -> load_addr map 79 std::lock_guard<std::recursive_mutex> guard(m_mutex); 80 sect_to_addr_collection::iterator sta_pos = 81 m_sect_to_addr.find(section.get()); 82 if (sta_pos != m_sect_to_addr.end()) { 83 if (load_addr == sta_pos->second) 84 return false; // No change... 85 else 86 sta_pos->second = load_addr; 87 } else 88 m_sect_to_addr[section.get()] = load_addr; 89 90 // Fill in the load_addr -> section map 91 addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr); 92 if (ats_pos != m_addr_to_sect.end()) { 93 // Some sections are ok to overlap, and for others we should warn. When 94 // we have multiple load addresses that correspond to a section, we will 95 // always attribute the section to the be last section that claims it 96 // exists at that address. Sometimes it is ok for more that one section 97 // to be loaded at a specific load address, and other times it isn't. The 98 // "warn_multiple" parameter tells us if we should warn in this case or 99 // not. The DynamicLoader plug-in subclasses should know which sections 100 // should warn and which shouldn't (darwin shared cache modules all 101 // shared the same "__LINKEDIT" sections, so the dynamic loader can pass 102 // false for "warn_multiple"). 103 if (warn_multiple && section != ats_pos->second) { 104 ModuleSP module_sp(section->GetModule()); 105 if (module_sp) { 106 ModuleSP curr_module_sp(ats_pos->second->GetModule()); 107 if (curr_module_sp) { 108 module_sp->ReportWarning( 109 "address {0:x16} maps to more than one section: {1}.{2} and " 110 "{3}.{4}", 111 load_addr, module_sp->GetFileSpec().GetFilename().GetCString(), 112 section->GetName().GetCString(), 113 curr_module_sp->GetFileSpec().GetFilename().GetCString(), 114 ats_pos->second->GetName().GetCString()); 115 } 116 } 117 } 118 ats_pos->second = section; 119 } else { 120 // Remove the old address->section entry, if 121 // there is one. 122 for (const auto &entry : m_addr_to_sect) { 123 if (entry.second == section) { 124 const auto &it_pos = m_addr_to_sect.find(entry.first); 125 m_addr_to_sect.erase(it_pos); 126 break; 127 } 128 } 129 m_addr_to_sect[load_addr] = section; 130 } 131 return true; // Changed 132 133 } else { 134 if (log) { 135 LLDB_LOGF( 136 log, 137 "SectionLoadList::%s (section = %p (%s), load_addr = 0x%16.16" PRIx64 138 ") error: module has been deleted", 139 __FUNCTION__, static_cast<void *>(section.get()), 140 section->GetName().AsCString(), load_addr); 141 } 142 } 143 return false; 144 } 145 146 size_t SectionLoadList::SetSectionUnloaded(const lldb::SectionSP §ion_sp) { 147 size_t unload_count = 0; 148 149 if (section_sp) { 150 Log *log = GetLog(LLDBLog::DynamicLoader); 151 152 if (log && log->GetVerbose()) { 153 ModuleSP module_sp = section_sp->GetModule(); 154 std::string module_name("<Unknown>"); 155 if (module_sp) { 156 const FileSpec &module_file_spec( 157 section_sp->GetModule()->GetFileSpec()); 158 module_name = module_file_spec.GetPath(); 159 } 160 LLDB_LOGF(log, "SectionLoadList::%s (section = %p (%s.%s))", __FUNCTION__, 161 static_cast<void *>(section_sp.get()), module_name.c_str(), 162 section_sp->GetName().AsCString()); 163 } 164 165 std::lock_guard<std::recursive_mutex> guard(m_mutex); 166 167 sect_to_addr_collection::iterator sta_pos = 168 m_sect_to_addr.find(section_sp.get()); 169 if (sta_pos != m_sect_to_addr.end()) { 170 ++unload_count; 171 addr_t load_addr = sta_pos->second; 172 m_sect_to_addr.erase(sta_pos); 173 174 addr_to_sect_collection::iterator ats_pos = 175 m_addr_to_sect.find(load_addr); 176 if (ats_pos != m_addr_to_sect.end()) 177 m_addr_to_sect.erase(ats_pos); 178 } 179 } 180 return unload_count; 181 } 182 183 bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP §ion_sp, 184 addr_t load_addr) { 185 Log *log = GetLog(LLDBLog::DynamicLoader); 186 187 if (log && log->GetVerbose()) { 188 ModuleSP module_sp = section_sp->GetModule(); 189 std::string module_name("<Unknown>"); 190 if (module_sp) { 191 const FileSpec &module_file_spec(section_sp->GetModule()->GetFileSpec()); 192 module_name = module_file_spec.GetPath(); 193 } 194 LLDB_LOGF( 195 log, 196 "SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64 197 ")", 198 __FUNCTION__, static_cast<void *>(section_sp.get()), 199 module_name.c_str(), section_sp->GetName().AsCString(), load_addr); 200 } 201 bool erased = false; 202 std::lock_guard<std::recursive_mutex> guard(m_mutex); 203 sect_to_addr_collection::iterator sta_pos = 204 m_sect_to_addr.find(section_sp.get()); 205 if (sta_pos != m_sect_to_addr.end()) { 206 erased = true; 207 m_sect_to_addr.erase(sta_pos); 208 } 209 210 addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr); 211 if (ats_pos != m_addr_to_sect.end()) { 212 erased = true; 213 m_addr_to_sect.erase(ats_pos); 214 } 215 216 return erased; 217 } 218 219 bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, Address &so_addr, 220 bool allow_section_end) const { 221 // First find the top level section that this load address exists in 222 std::lock_guard<std::recursive_mutex> guard(m_mutex); 223 if (!m_addr_to_sect.empty()) { 224 addr_to_sect_collection::const_iterator pos = 225 m_addr_to_sect.lower_bound(load_addr); 226 if (pos != m_addr_to_sect.end()) { 227 if (load_addr != pos->first && pos != m_addr_to_sect.begin()) 228 --pos; 229 const addr_t pos_load_addr = pos->first; 230 if (load_addr >= pos_load_addr) { 231 addr_t offset = load_addr - pos_load_addr; 232 if (offset < pos->second->GetByteSize() + (allow_section_end ? 1 : 0)) { 233 // We have found the top level section, now we need to find the 234 // deepest child section. 235 return pos->second->ResolveContainedAddress(offset, so_addr, 236 allow_section_end); 237 } 238 } 239 } else { 240 // There are no entries that have an address that is >= load_addr, so we 241 // need to check the last entry on our collection. 242 addr_to_sect_collection::const_reverse_iterator rpos = 243 m_addr_to_sect.rbegin(); 244 if (load_addr >= rpos->first) { 245 addr_t offset = load_addr - rpos->first; 246 if (offset < 247 rpos->second->GetByteSize() + (allow_section_end ? 1 : 0)) { 248 // We have found the top level section, now we need to find the 249 // deepest child section. 250 return rpos->second->ResolveContainedAddress(offset, so_addr, 251 allow_section_end); 252 } 253 } 254 } 255 } 256 so_addr.Clear(); 257 return false; 258 } 259 260 void SectionLoadList::Dump(Stream &s, Target *target) { 261 std::lock_guard<std::recursive_mutex> guard(m_mutex); 262 addr_to_sect_collection::const_iterator pos, end; 263 for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end; 264 ++pos) { 265 s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ", pos->first, 266 static_cast<void *>(pos->second.get())); 267 pos->second->Dump(s.AsRawOstream(), s.GetIndentLevel(), target, 0); 268 } 269 } 270