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