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 0x%16.16" PRIx64 110 " maps to more than one section: %s.%s and %s.%s", 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 m_addr_to_sect[load_addr] = section; 121 return true; // Changed 122 123 } else { 124 if (log) { 125 LLDB_LOGF( 126 log, 127 "SectionLoadList::%s (section = %p (%s), load_addr = 0x%16.16" PRIx64 128 ") error: module has been deleted", 129 __FUNCTION__, static_cast<void *>(section.get()), 130 section->GetName().AsCString(), load_addr); 131 } 132 } 133 return false; 134 } 135 136 size_t SectionLoadList::SetSectionUnloaded(const lldb::SectionSP §ion_sp) { 137 size_t unload_count = 0; 138 139 if (section_sp) { 140 Log *log = GetLog(LLDBLog::DynamicLoader); 141 142 if (log && log->GetVerbose()) { 143 ModuleSP module_sp = section_sp->GetModule(); 144 std::string module_name("<Unknown>"); 145 if (module_sp) { 146 const FileSpec &module_file_spec( 147 section_sp->GetModule()->GetFileSpec()); 148 module_name = module_file_spec.GetPath(); 149 } 150 LLDB_LOGF(log, "SectionLoadList::%s (section = %p (%s.%s))", __FUNCTION__, 151 static_cast<void *>(section_sp.get()), module_name.c_str(), 152 section_sp->GetName().AsCString()); 153 } 154 155 std::lock_guard<std::recursive_mutex> guard(m_mutex); 156 157 sect_to_addr_collection::iterator sta_pos = 158 m_sect_to_addr.find(section_sp.get()); 159 if (sta_pos != m_sect_to_addr.end()) { 160 ++unload_count; 161 addr_t load_addr = sta_pos->second; 162 m_sect_to_addr.erase(sta_pos); 163 164 addr_to_sect_collection::iterator ats_pos = 165 m_addr_to_sect.find(load_addr); 166 if (ats_pos != m_addr_to_sect.end()) 167 m_addr_to_sect.erase(ats_pos); 168 } 169 } 170 return unload_count; 171 } 172 173 bool SectionLoadList::SetSectionUnloaded(const lldb::SectionSP §ion_sp, 174 addr_t load_addr) { 175 Log *log = GetLog(LLDBLog::DynamicLoader); 176 177 if (log && log->GetVerbose()) { 178 ModuleSP module_sp = section_sp->GetModule(); 179 std::string module_name("<Unknown>"); 180 if (module_sp) { 181 const FileSpec &module_file_spec(section_sp->GetModule()->GetFileSpec()); 182 module_name = module_file_spec.GetPath(); 183 } 184 LLDB_LOGF( 185 log, 186 "SectionLoadList::%s (section = %p (%s.%s), load_addr = 0x%16.16" PRIx64 187 ")", 188 __FUNCTION__, static_cast<void *>(section_sp.get()), 189 module_name.c_str(), section_sp->GetName().AsCString(), load_addr); 190 } 191 bool erased = false; 192 std::lock_guard<std::recursive_mutex> guard(m_mutex); 193 sect_to_addr_collection::iterator sta_pos = 194 m_sect_to_addr.find(section_sp.get()); 195 if (sta_pos != m_sect_to_addr.end()) { 196 erased = true; 197 m_sect_to_addr.erase(sta_pos); 198 } 199 200 addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr); 201 if (ats_pos != m_addr_to_sect.end()) { 202 erased = true; 203 m_addr_to_sect.erase(ats_pos); 204 } 205 206 return erased; 207 } 208 209 bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, Address &so_addr, 210 bool allow_section_end) const { 211 // First find the top level section that this load address exists in 212 std::lock_guard<std::recursive_mutex> guard(m_mutex); 213 if (!m_addr_to_sect.empty()) { 214 addr_to_sect_collection::const_iterator pos = 215 m_addr_to_sect.lower_bound(load_addr); 216 if (pos != m_addr_to_sect.end()) { 217 if (load_addr != pos->first && pos != m_addr_to_sect.begin()) 218 --pos; 219 const addr_t pos_load_addr = pos->first; 220 if (load_addr >= pos_load_addr) { 221 addr_t offset = load_addr - pos_load_addr; 222 if (offset < pos->second->GetByteSize() + (allow_section_end ? 1 : 0)) { 223 // We have found the top level section, now we need to find the 224 // deepest child section. 225 return pos->second->ResolveContainedAddress(offset, so_addr, 226 allow_section_end); 227 } 228 } 229 } else { 230 // There are no entries that have an address that is >= load_addr, so we 231 // need to check the last entry on our collection. 232 addr_to_sect_collection::const_reverse_iterator rpos = 233 m_addr_to_sect.rbegin(); 234 if (load_addr >= rpos->first) { 235 addr_t offset = load_addr - rpos->first; 236 if (offset < 237 rpos->second->GetByteSize() + (allow_section_end ? 1 : 0)) { 238 // We have found the top level section, now we need to find the 239 // deepest child section. 240 return rpos->second->ResolveContainedAddress(offset, so_addr, 241 allow_section_end); 242 } 243 } 244 } 245 } 246 so_addr.Clear(); 247 return false; 248 } 249 250 void SectionLoadList::Dump(Stream &s, Target *target) { 251 std::lock_guard<std::recursive_mutex> guard(m_mutex); 252 addr_to_sect_collection::const_iterator pos, end; 253 for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end; 254 ++pos) { 255 s.Printf("addr = 0x%16.16" PRIx64 ", section = %p: ", pos->first, 256 static_cast<void *>(pos->second.get())); 257 pos->second->Dump(s.AsRawOstream(), s.GetIndentLevel(), target, 0); 258 } 259 } 260