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