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