ObjectFile.cpp revision c9b798c06458466c818efc6b385f538a22fae022
1//===-- ObjectFile.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/lldb-private.h" 11#include "lldb/lldb-private-log.h" 12#include "lldb/Core/DataBuffer.h" 13#include "lldb/Core/DataBufferHeap.h" 14#include "lldb/Core/Log.h" 15#include "lldb/Core/Module.h" 16#include "lldb/Core/PluginManager.h" 17#include "lldb/Core/RegularExpression.h" 18#include "lldb/Core/Section.h" 19#include "lldb/Core/Timer.h" 20#include "lldb/Symbol/ObjectFile.h" 21#include "lldb/Symbol/ObjectContainer.h" 22#include "lldb/Symbol/SymbolFile.h" 23#include "lldb/Target/Process.h" 24#include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h" 25 26using namespace lldb; 27using namespace lldb_private; 28 29ObjectFileSP 30ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp, const FileSpec* file, addr_t file_offset, addr_t file_size, DataBufferSP &file_data_sp) 31{ 32 ObjectFileSP object_file_sp; 33 34 if (module_sp) 35 { 36 Timer scoped_timer (__PRETTY_FUNCTION__, 37 "ObjectFile::FindPlugin (module = %s/%s, file = %p, file_offset = 0x%8.8llx, file_size = 0x%8.8llx)", 38 module_sp->GetFileSpec().GetDirectory().AsCString(), 39 module_sp->GetFileSpec().GetFilename().AsCString(), 40 file, (uint64_t) file_offset, (uint64_t) file_size); 41 if (file) 42 { 43 // Memory map the entire file contents 44 if (!file_data_sp && file_size > 0) 45 { 46 assert (file_offset == 0); 47 file_data_sp = file->MemoryMapFileContents(file_offset, file_size); 48 } 49 50 if (!file_data_sp || file_data_sp->GetByteSize() == 0) 51 { 52 // Check for archive file with format "/path/to/archive.a(object.o)" 53 char path_with_object[PATH_MAX*2]; 54 module_sp->GetFileSpec().GetPath(path_with_object, sizeof(path_with_object)); 55 56 FileSpec archive_file; 57 ConstString archive_object; 58 if (ObjectFile::SplitArchivePathWithObject (path_with_object, archive_file, archive_object)) 59 { 60 file_size = archive_file.GetByteSize(); 61 if (file_size > 0) 62 { 63 module_sp->SetFileSpecAndObjectName (archive_file, archive_object); 64 file_data_sp = archive_file.MemoryMapFileContents(file_offset, file_size); 65 } 66 } 67 } 68 69 if (file_data_sp && file_data_sp->GetByteSize() > 0) 70 { 71 uint32_t idx; 72 73 // Check if this is a normal object file by iterating through 74 // all object file plugin instances. 75 ObjectFileCreateInstance create_object_file_callback; 76 for (idx = 0; (create_object_file_callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != NULL; ++idx) 77 { 78 object_file_sp.reset (create_object_file_callback(module_sp, file_data_sp, file, file_offset, file_size)); 79 if (object_file_sp.get()) 80 return object_file_sp; 81 } 82 83 // Check if this is a object container by iterating through 84 // all object container plugin instances and then trying to get 85 // an object file from the container. 86 ObjectContainerCreateInstance create_object_container_callback; 87 for (idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != NULL; ++idx) 88 { 89 std::auto_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module_sp, file_data_sp, file, file_offset, file_size)); 90 91 if (object_container_ap.get()) 92 object_file_sp = object_container_ap->GetObjectFile(file); 93 94 if (object_file_sp.get()) 95 return object_file_sp; 96 } 97 } 98 } 99 } 100 // We didn't find it, so clear our shared pointer in case it 101 // contains anything and return an empty shared pointer 102 object_file_sp.reset(); 103 return object_file_sp; 104} 105 106ObjectFileSP 107ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp, 108 const ProcessSP &process_sp, 109 lldb::addr_t header_addr, 110 DataBufferSP &file_data_sp) 111{ 112 ObjectFileSP object_file_sp; 113 114 if (module_sp) 115 { 116 Timer scoped_timer (__PRETTY_FUNCTION__, 117 "ObjectFile::FindPlugin (module = %s/%s, process = %p, header_addr = 0x%llx)", 118 module_sp->GetFileSpec().GetDirectory().AsCString(), 119 module_sp->GetFileSpec().GetFilename().AsCString(), 120 process_sp.get(), header_addr); 121 uint32_t idx; 122 123 // Check if this is a normal object file by iterating through 124 // all object file plugin instances. 125 ObjectFileCreateMemoryInstance create_callback; 126 for (idx = 0; (create_callback = PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(idx)) != NULL; ++idx) 127 { 128 object_file_sp.reset (create_callback(module_sp, file_data_sp, process_sp, header_addr)); 129 if (object_file_sp.get()) 130 return object_file_sp; 131 } 132 133 } 134 // We didn't find it, so clear our shared pointer in case it 135 // contains anything and return an empty shared pointer 136 object_file_sp.reset(); 137 return object_file_sp; 138} 139 140ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, 141 const FileSpec *file_spec_ptr, 142 addr_t file_offset, 143 addr_t file_size, 144 DataBufferSP& file_data_sp) : 145 ModuleChild (module_sp), 146 m_file (), // This file could be different from the original module's file 147 m_type (eTypeInvalid), 148 m_strata (eStrataInvalid), 149 m_offset (file_offset), 150 m_length (file_size), 151 m_data (), 152 m_unwind_table (*this), 153 m_process_wp(), 154 m_memory_addr (LLDB_INVALID_ADDRESS) 155{ 156 if (file_spec_ptr) 157 m_file = *file_spec_ptr; 158 if (file_data_sp) 159 m_data.SetData (file_data_sp, file_offset, file_size); 160 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 161 if (log) 162 { 163 if (m_file) 164 { 165 log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = %s/%s, offset = 0x%8.8llx, size = %llu\n", 166 this, 167 module_sp->GetFileSpec().GetDirectory().AsCString(), 168 module_sp->GetFileSpec().GetFilename().AsCString(), 169 m_file.GetDirectory().AsCString(), 170 m_file.GetFilename().AsCString(), 171 m_offset, 172 m_length); 173 } 174 else 175 { 176 log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, file = <NULL>, offset = 0x%8.8llx, size = %llu\n", 177 this, 178 module_sp->GetFileSpec().GetDirectory().AsCString(), 179 module_sp->GetFileSpec().GetFilename().AsCString(), 180 m_offset, 181 m_length); 182 } 183 } 184} 185 186 187ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, 188 const ProcessSP &process_sp, 189 lldb::addr_t header_addr, 190 DataBufferSP& header_data_sp) : 191 ModuleChild (module_sp), 192 m_file (), 193 m_type (eTypeInvalid), 194 m_strata (eStrataInvalid), 195 m_offset (header_addr), 196 m_length (0), 197 m_data (), 198 m_unwind_table (*this), 199 m_process_wp (process_sp), 200 m_memory_addr (header_addr) 201{ 202 if (header_data_sp) 203 m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize()); 204 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 205 if (log) 206 { 207 log->Printf ("%p ObjectFile::ObjectFile () module = %s/%s, process = %p, header_addr = 0x%llx\n", 208 this, 209 module_sp->GetFileSpec().GetDirectory().AsCString(), 210 module_sp->GetFileSpec().GetFilename().AsCString(), 211 process_sp.get(), 212 m_offset); 213 } 214} 215 216 217ObjectFile::~ObjectFile() 218{ 219 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 220 if (log) 221 log->Printf ("%p ObjectFile::~ObjectFile ()\n", this); 222} 223 224bool 225ObjectFile::SetModulesArchitecture (const ArchSpec &new_arch) 226{ 227 ModuleSP module_sp (GetModule()); 228 if (module_sp) 229 return module_sp->SetArchitecture (new_arch); 230 return false; 231} 232 233AddressClass 234ObjectFile::GetAddressClass (addr_t file_addr) 235{ 236 Symtab *symtab = GetSymtab(); 237 if (symtab) 238 { 239 Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr); 240 if (symbol) 241 { 242 if (symbol->ValueIsAddress()) 243 { 244 const SectionSP section_sp (symbol->GetAddress().GetSection()); 245 if (section_sp) 246 { 247 const SectionType section_type = section_sp->GetType(); 248 switch (section_type) 249 { 250 case eSectionTypeInvalid: return eAddressClassUnknown; 251 case eSectionTypeCode: return eAddressClassCode; 252 case eSectionTypeContainer: return eAddressClassUnknown; 253 case eSectionTypeData: 254 case eSectionTypeDataCString: 255 case eSectionTypeDataCStringPointers: 256 case eSectionTypeDataSymbolAddress: 257 case eSectionTypeData4: 258 case eSectionTypeData8: 259 case eSectionTypeData16: 260 case eSectionTypeDataPointers: 261 case eSectionTypeZeroFill: 262 case eSectionTypeDataObjCMessageRefs: 263 case eSectionTypeDataObjCCFStrings: 264 return eAddressClassData; 265 case eSectionTypeDebug: 266 case eSectionTypeDWARFDebugAbbrev: 267 case eSectionTypeDWARFDebugAranges: 268 case eSectionTypeDWARFDebugFrame: 269 case eSectionTypeDWARFDebugInfo: 270 case eSectionTypeDWARFDebugLine: 271 case eSectionTypeDWARFDebugLoc: 272 case eSectionTypeDWARFDebugMacInfo: 273 case eSectionTypeDWARFDebugPubNames: 274 case eSectionTypeDWARFDebugPubTypes: 275 case eSectionTypeDWARFDebugRanges: 276 case eSectionTypeDWARFDebugStr: 277 case eSectionTypeDWARFAppleNames: 278 case eSectionTypeDWARFAppleTypes: 279 case eSectionTypeDWARFAppleNamespaces: 280 case eSectionTypeDWARFAppleObjC: 281 return eAddressClassDebug; 282 case eSectionTypeEHFrame: return eAddressClassRuntime; 283 case eSectionTypeOther: return eAddressClassUnknown; 284 } 285 } 286 } 287 288 const SymbolType symbol_type = symbol->GetType(); 289 switch (symbol_type) 290 { 291 case eSymbolTypeAny: return eAddressClassUnknown; 292 case eSymbolTypeAbsolute: return eAddressClassUnknown; 293 case eSymbolTypeCode: return eAddressClassCode; 294 case eSymbolTypeTrampoline: return eAddressClassCode; 295 case eSymbolTypeData: return eAddressClassData; 296 case eSymbolTypeRuntime: return eAddressClassRuntime; 297 case eSymbolTypeException: return eAddressClassRuntime; 298 case eSymbolTypeSourceFile: return eAddressClassDebug; 299 case eSymbolTypeHeaderFile: return eAddressClassDebug; 300 case eSymbolTypeObjectFile: return eAddressClassDebug; 301 case eSymbolTypeCommonBlock: return eAddressClassDebug; 302 case eSymbolTypeBlock: return eAddressClassDebug; 303 case eSymbolTypeLocal: return eAddressClassData; 304 case eSymbolTypeParam: return eAddressClassData; 305 case eSymbolTypeVariable: return eAddressClassData; 306 case eSymbolTypeVariableType: return eAddressClassDebug; 307 case eSymbolTypeLineEntry: return eAddressClassDebug; 308 case eSymbolTypeLineHeader: return eAddressClassDebug; 309 case eSymbolTypeScopeBegin: return eAddressClassDebug; 310 case eSymbolTypeScopeEnd: return eAddressClassDebug; 311 case eSymbolTypeAdditional: return eAddressClassUnknown; 312 case eSymbolTypeCompiler: return eAddressClassDebug; 313 case eSymbolTypeInstrumentation:return eAddressClassDebug; 314 case eSymbolTypeUndefined: return eAddressClassUnknown; 315 case eSymbolTypeObjCClass: return eAddressClassRuntime; 316 case eSymbolTypeObjCMetaClass: return eAddressClassRuntime; 317 case eSymbolTypeObjCIVar: return eAddressClassRuntime; 318 } 319 } 320 } 321 return eAddressClassUnknown; 322} 323 324DataBufferSP 325ObjectFile::ReadMemory (const ProcessSP &process_sp, lldb::addr_t addr, size_t byte_size) 326{ 327 DataBufferSP data_sp; 328 if (process_sp) 329 { 330 std::auto_ptr<DataBufferHeap> data_ap (new DataBufferHeap (byte_size, 0)); 331 Error error; 332 const size_t bytes_read = process_sp->ReadMemory (addr, 333 data_ap->GetBytes(), 334 data_ap->GetByteSize(), 335 error); 336 if (bytes_read == byte_size) 337 data_sp.reset (data_ap.release()); 338 } 339 return data_sp; 340} 341 342size_t 343ObjectFile::GetData (off_t offset, size_t length, DataExtractor &data) const 344{ 345 // The entire file has already been mmap'ed into m_data, so just copy from there 346 // as the back mmap buffer will be shared with shared pointers. 347 return data.SetData (m_data, offset, length); 348} 349 350size_t 351ObjectFile::CopyData (off_t offset, size_t length, void *dst) const 352{ 353 // The entire file has already been mmap'ed into m_data, so just copy from there 354 return m_data.CopyByteOrderedData (offset, length, dst, length, lldb::endian::InlHostByteOrder()); 355} 356 357 358size_t 359ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void *dst, size_t dst_len) const 360{ 361 if (IsInMemory()) 362 { 363 ProcessSP process_sp (m_process_wp.lock()); 364 if (process_sp) 365 { 366 Error error; 367 return process_sp->ReadMemory (section->GetLoadBaseAddress (&process_sp->GetTarget()) + section_offset, dst, dst_len, error); 368 } 369 } 370 else 371 { 372 const uint64_t section_file_size = section->GetFileSize(); 373 if (section_offset < section_file_size) 374 { 375 const uint64_t section_bytes_left = section_file_size - section_offset; 376 uint64_t section_dst_len = dst_len; 377 if (section_dst_len > section_bytes_left) 378 section_dst_len = section_bytes_left; 379 return CopyData (section->GetFileOffset() + section_offset, section_dst_len, dst); 380 } 381 } 382 return 0; 383} 384 385//---------------------------------------------------------------------- 386// Get the section data the file on disk 387//---------------------------------------------------------------------- 388size_t 389ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const 390{ 391 if (IsInMemory()) 392 { 393 ProcessSP process_sp (m_process_wp.lock()); 394 if (process_sp) 395 { 396 DataBufferSP data_sp (ReadMemory (process_sp, section->GetLoadBaseAddress (&process_sp->GetTarget()), section->GetByteSize())); 397 if (data_sp) 398 { 399 section_data.SetData (data_sp, 0, data_sp->GetByteSize()); 400 section_data.SetByteOrder (process_sp->GetByteOrder()); 401 section_data.SetAddressByteSize (process_sp->GetAddressByteSize()); 402 return section_data.GetByteSize(); 403 } 404 } 405 } 406 else 407 { 408 // The object file now contains a full mmap'ed copy of the object file data, so just use this 409 return MemoryMapSectionData (section, section_data); 410 } 411 section_data.Clear(); 412 return 0; 413} 414 415size_t 416ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section_data) const 417{ 418 if (IsInMemory()) 419 { 420 return ReadSectionData (section, section_data); 421 } 422 else 423 { 424 // The object file now contains a full mmap'ed copy of the object file data, so just use this 425 return GetData(section->GetFileOffset(), section->GetFileSize(), section_data); 426 } 427 section_data.Clear(); 428 return 0; 429} 430 431 432bool 433ObjectFile::SplitArchivePathWithObject (const char *path_with_object, FileSpec &archive_file, ConstString &archive_object) 434{ 435 RegularExpression g_object_regex("(.*)\\(([^\\)]+)\\)$"); 436 if (g_object_regex.Execute (path_with_object, 2)) 437 { 438 std::string path; 439 std::string obj; 440 if (g_object_regex.GetMatchAtIndex (path_with_object, 1, path) && 441 g_object_regex.GetMatchAtIndex (path_with_object, 2, obj)) 442 { 443 archive_file.SetFile (path.c_str(), false); 444 archive_object.SetCString(obj.c_str()); 445 return true; 446 } 447 } 448 return false; 449} 450 451