1dda28197Spatrick //===-- ObjectFile.cpp ----------------------------------------------------===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9061da546Spatrick #include "lldb/Symbol/ObjectFile.h" 10061da546Spatrick #include "lldb/Core/Module.h" 11061da546Spatrick #include "lldb/Core/ModuleSpec.h" 12061da546Spatrick #include "lldb/Core/PluginManager.h" 13061da546Spatrick #include "lldb/Core/Section.h" 14061da546Spatrick #include "lldb/Symbol/CallFrameInfo.h" 15061da546Spatrick #include "lldb/Symbol/ObjectContainer.h" 16061da546Spatrick #include "lldb/Symbol/SymbolFile.h" 17061da546Spatrick #include "lldb/Target/Process.h" 18061da546Spatrick #include "lldb/Target/SectionLoadList.h" 19061da546Spatrick #include "lldb/Target/Target.h" 20061da546Spatrick #include "lldb/Utility/DataBuffer.h" 21061da546Spatrick #include "lldb/Utility/DataBufferHeap.h" 22061da546Spatrick #include "lldb/Utility/Log.h" 23061da546Spatrick #include "lldb/Utility/Timer.h" 24061da546Spatrick #include "lldb/lldb-private.h" 25061da546Spatrick 26061da546Spatrick using namespace lldb; 27061da546Spatrick using namespace lldb_private; 28061da546Spatrick 29061da546Spatrick char ObjectFile::ID; 30061da546Spatrick 31*be691f3bSpatrick static ObjectFileSP 32*be691f3bSpatrick CreateObjectFromContainer(const lldb::ModuleSP &module_sp, const FileSpec *file, 33*be691f3bSpatrick lldb::offset_t file_offset, lldb::offset_t file_size, 34*be691f3bSpatrick DataBufferSP &data_sp, lldb::offset_t &data_offset) { 35*be691f3bSpatrick ObjectContainerCreateInstance callback; 36*be691f3bSpatrick for (uint32_t idx = 0; 37*be691f3bSpatrick (callback = PluginManager::GetObjectContainerCreateCallbackAtIndex( 38*be691f3bSpatrick idx)) != nullptr; 39*be691f3bSpatrick ++idx) { 40*be691f3bSpatrick std::unique_ptr<ObjectContainer> object_container_up(callback( 41*be691f3bSpatrick module_sp, data_sp, data_offset, file, file_offset, file_size)); 42*be691f3bSpatrick if (object_container_up) 43*be691f3bSpatrick return object_container_up->GetObjectFile(file); 44*be691f3bSpatrick } 45*be691f3bSpatrick return {}; 46*be691f3bSpatrick } 47*be691f3bSpatrick 48061da546Spatrick ObjectFileSP 49061da546Spatrick ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file, 50061da546Spatrick lldb::offset_t file_offset, lldb::offset_t file_size, 51061da546Spatrick DataBufferSP &data_sp, lldb::offset_t &data_offset) { 52*be691f3bSpatrick LLDB_SCOPED_TIMERF( 53061da546Spatrick "ObjectFile::FindPlugin (module = %s, file = %p, file_offset = " 54061da546Spatrick "0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")", 55061da546Spatrick module_sp->GetFileSpec().GetPath().c_str(), 56061da546Spatrick static_cast<const void *>(file), static_cast<uint64_t>(file_offset), 57061da546Spatrick static_cast<uint64_t>(file_size)); 58*be691f3bSpatrick 59*be691f3bSpatrick if (!module_sp) 60*be691f3bSpatrick return {}; 61*be691f3bSpatrick 62*be691f3bSpatrick if (!file) 63*be691f3bSpatrick return {}; 64061da546Spatrick 65061da546Spatrick if (!data_sp) { 66dda28197Spatrick const bool file_exists = FileSystem::Instance().Exists(*file); 67061da546Spatrick // We have an object name which most likely means we have a .o file in 68061da546Spatrick // a static archive (.a file). Try and see if we have a cached archive 69061da546Spatrick // first without reading any data first 70061da546Spatrick if (file_exists && module_sp->GetObjectName()) { 71*be691f3bSpatrick ObjectFileSP object_file_sp = CreateObjectFromContainer( 72*be691f3bSpatrick module_sp, file, file_offset, file_size, data_sp, data_offset); 73*be691f3bSpatrick if (object_file_sp) 74061da546Spatrick return object_file_sp; 75061da546Spatrick } 76061da546Spatrick // Ok, we didn't find any containers that have a named object, now lets 77061da546Spatrick // read the first 512 bytes from the file so the object file and object 78061da546Spatrick // container plug-ins can use these bytes to see if they can parse this 79061da546Spatrick // file. 80061da546Spatrick if (file_size > 0) { 81*be691f3bSpatrick data_sp = FileSystem::Instance().CreateDataBuffer(file->GetPath(), 512, 82*be691f3bSpatrick file_offset); 83061da546Spatrick data_offset = 0; 84061da546Spatrick } 85061da546Spatrick } 86061da546Spatrick 87061da546Spatrick if (!data_sp || data_sp->GetByteSize() == 0) { 88061da546Spatrick // Check for archive file with format "/path/to/archive.a(object.o)" 89061da546Spatrick llvm::SmallString<256> path_with_object; 90061da546Spatrick module_sp->GetFileSpec().GetPath(path_with_object); 91061da546Spatrick 92*be691f3bSpatrick FileSpec archive_file; 93061da546Spatrick ConstString archive_object; 94061da546Spatrick const bool must_exist = true; 95*be691f3bSpatrick if (ObjectFile::SplitArchivePathWithObject(path_with_object, archive_file, 96*be691f3bSpatrick archive_object, must_exist)) { 97061da546Spatrick file_size = FileSystem::Instance().GetByteSize(archive_file); 98061da546Spatrick if (file_size > 0) { 99061da546Spatrick file = &archive_file; 100061da546Spatrick module_sp->SetFileSpecAndObjectName(archive_file, archive_object); 101061da546Spatrick // Check if this is a object container by iterating through all 102061da546Spatrick // object container plugin instances and then trying to get an 103061da546Spatrick // object file from the container plugins since we had a name. 104061da546Spatrick // Also, don't read 105061da546Spatrick // ANY data in case there is data cached in the container plug-ins 106061da546Spatrick // (like BSD archives caching the contained objects within an 107061da546Spatrick // file). 108*be691f3bSpatrick ObjectFileSP object_file_sp = CreateObjectFromContainer( 109*be691f3bSpatrick module_sp, file, file_offset, file_size, data_sp, data_offset); 110*be691f3bSpatrick if (object_file_sp) 111061da546Spatrick return object_file_sp; 112061da546Spatrick // We failed to find any cached object files in the container plug- 113061da546Spatrick // ins, so lets read the first 512 bytes and try again below... 114061da546Spatrick data_sp = FileSystem::Instance().CreateDataBuffer( 115061da546Spatrick archive_file.GetPath(), 512, file_offset); 116061da546Spatrick } 117061da546Spatrick } 118061da546Spatrick } 119061da546Spatrick 120061da546Spatrick if (data_sp && data_sp->GetByteSize() > 0) { 121061da546Spatrick // Check if this is a normal object file by iterating through all 122061da546Spatrick // object file plugin instances. 123*be691f3bSpatrick ObjectFileCreateInstance callback; 124061da546Spatrick for (uint32_t idx = 0; 125*be691f3bSpatrick (callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != 126061da546Spatrick nullptr; 127061da546Spatrick ++idx) { 128*be691f3bSpatrick ObjectFileSP object_file_sp(callback(module_sp, data_sp, data_offset, 129*be691f3bSpatrick file, file_offset, file_size)); 130061da546Spatrick if (object_file_sp.get()) 131061da546Spatrick return object_file_sp; 132061da546Spatrick } 133061da546Spatrick 134061da546Spatrick // Check if this is a object container by iterating through all object 135061da546Spatrick // container plugin instances and then trying to get an object file 136061da546Spatrick // from the container. 137*be691f3bSpatrick ObjectFileSP object_file_sp = CreateObjectFromContainer( 138*be691f3bSpatrick module_sp, file, file_offset, file_size, data_sp, data_offset); 139*be691f3bSpatrick if (object_file_sp) 140061da546Spatrick return object_file_sp; 141061da546Spatrick } 142*be691f3bSpatrick 143061da546Spatrick // We didn't find it, so clear our shared pointer in case it contains 144061da546Spatrick // anything and return an empty shared pointer 145*be691f3bSpatrick return {}; 146061da546Spatrick } 147061da546Spatrick 148061da546Spatrick ObjectFileSP ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, 149061da546Spatrick const ProcessSP &process_sp, 150061da546Spatrick lldb::addr_t header_addr, 151061da546Spatrick DataBufferSP &data_sp) { 152061da546Spatrick ObjectFileSP object_file_sp; 153061da546Spatrick 154061da546Spatrick if (module_sp) { 155*be691f3bSpatrick LLDB_SCOPED_TIMERF("ObjectFile::FindPlugin (module = " 156061da546Spatrick "%s, process = %p, header_addr = " 157061da546Spatrick "0x%" PRIx64 ")", 158061da546Spatrick module_sp->GetFileSpec().GetPath().c_str(), 159061da546Spatrick static_cast<void *>(process_sp.get()), header_addr); 160061da546Spatrick uint32_t idx; 161061da546Spatrick 162061da546Spatrick // Check if this is a normal object file by iterating through all object 163061da546Spatrick // file plugin instances. 164061da546Spatrick ObjectFileCreateMemoryInstance create_callback; 165061da546Spatrick for (idx = 0; 166061da546Spatrick (create_callback = 167061da546Spatrick PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(idx)) != 168061da546Spatrick nullptr; 169061da546Spatrick ++idx) { 170061da546Spatrick object_file_sp.reset( 171061da546Spatrick create_callback(module_sp, data_sp, process_sp, header_addr)); 172061da546Spatrick if (object_file_sp.get()) 173061da546Spatrick return object_file_sp; 174061da546Spatrick } 175061da546Spatrick } 176061da546Spatrick 177061da546Spatrick // We didn't find it, so clear our shared pointer in case it contains 178061da546Spatrick // anything and return an empty shared pointer 179061da546Spatrick object_file_sp.reset(); 180061da546Spatrick return object_file_sp; 181061da546Spatrick } 182061da546Spatrick 183061da546Spatrick size_t ObjectFile::GetModuleSpecifications(const FileSpec &file, 184061da546Spatrick lldb::offset_t file_offset, 185061da546Spatrick lldb::offset_t file_size, 186dda28197Spatrick ModuleSpecList &specs, 187dda28197Spatrick DataBufferSP data_sp) { 188dda28197Spatrick if (!data_sp) 189dda28197Spatrick data_sp = FileSystem::Instance().CreateDataBuffer(file.GetPath(), 512, 190dda28197Spatrick file_offset); 191061da546Spatrick if (data_sp) { 192061da546Spatrick if (file_size == 0) { 193061da546Spatrick const lldb::offset_t actual_file_size = 194061da546Spatrick FileSystem::Instance().GetByteSize(file); 195061da546Spatrick if (actual_file_size > file_offset) 196061da546Spatrick file_size = actual_file_size - file_offset; 197061da546Spatrick } 198061da546Spatrick return ObjectFile::GetModuleSpecifications(file, // file spec 199061da546Spatrick data_sp, // data bytes 200061da546Spatrick 0, // data offset 201061da546Spatrick file_offset, // file offset 202061da546Spatrick file_size, // file length 203061da546Spatrick specs); 204061da546Spatrick } 205061da546Spatrick return 0; 206061da546Spatrick } 207061da546Spatrick 208061da546Spatrick size_t ObjectFile::GetModuleSpecifications( 209061da546Spatrick const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, 210061da546Spatrick lldb::offset_t data_offset, lldb::offset_t file_offset, 211061da546Spatrick lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) { 212061da546Spatrick const size_t initial_count = specs.GetSize(); 213061da546Spatrick ObjectFileGetModuleSpecifications callback; 214061da546Spatrick uint32_t i; 215061da546Spatrick // Try the ObjectFile plug-ins 216061da546Spatrick for (i = 0; 217061da546Spatrick (callback = 218061da546Spatrick PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex( 219061da546Spatrick i)) != nullptr; 220061da546Spatrick ++i) { 221061da546Spatrick if (callback(file, data_sp, data_offset, file_offset, file_size, specs) > 0) 222061da546Spatrick return specs.GetSize() - initial_count; 223061da546Spatrick } 224061da546Spatrick 225061da546Spatrick // Try the ObjectContainer plug-ins 226061da546Spatrick for (i = 0; 227061da546Spatrick (callback = PluginManager:: 228061da546Spatrick GetObjectContainerGetModuleSpecificationsCallbackAtIndex(i)) != 229061da546Spatrick nullptr; 230061da546Spatrick ++i) { 231061da546Spatrick if (callback(file, data_sp, data_offset, file_offset, file_size, specs) > 0) 232061da546Spatrick return specs.GetSize() - initial_count; 233061da546Spatrick } 234061da546Spatrick return 0; 235061da546Spatrick } 236061da546Spatrick 237061da546Spatrick ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp, 238061da546Spatrick const FileSpec *file_spec_ptr, 239061da546Spatrick lldb::offset_t file_offset, lldb::offset_t length, 240061da546Spatrick const lldb::DataBufferSP &data_sp, 241061da546Spatrick lldb::offset_t data_offset) 242061da546Spatrick : ModuleChild(module_sp), 243061da546Spatrick m_file(), // This file could be different from the original module's file 244061da546Spatrick m_type(eTypeInvalid), m_strata(eStrataInvalid), 245061da546Spatrick m_file_offset(file_offset), m_length(length), m_data(), m_process_wp(), 246061da546Spatrick m_memory_addr(LLDB_INVALID_ADDRESS), m_sections_up(), m_symtab_up(), 247061da546Spatrick m_synthetic_symbol_idx(0) { 248061da546Spatrick if (file_spec_ptr) 249061da546Spatrick m_file = *file_spec_ptr; 250061da546Spatrick if (data_sp) 251061da546Spatrick m_data.SetData(data_sp, data_offset, length); 252061da546Spatrick Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); 253061da546Spatrick LLDB_LOGF(log, 254061da546Spatrick "%p ObjectFile::ObjectFile() module = %p (%s), file = %s, " 255061da546Spatrick "file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64, 256061da546Spatrick static_cast<void *>(this), static_cast<void *>(module_sp.get()), 257061da546Spatrick module_sp->GetSpecificationDescription().c_str(), 258061da546Spatrick m_file ? m_file.GetPath().c_str() : "<NULL>", m_file_offset, 259061da546Spatrick m_length); 260061da546Spatrick } 261061da546Spatrick 262061da546Spatrick ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp, 263061da546Spatrick const ProcessSP &process_sp, lldb::addr_t header_addr, 264061da546Spatrick DataBufferSP &header_data_sp) 265061da546Spatrick : ModuleChild(module_sp), m_file(), m_type(eTypeInvalid), 266061da546Spatrick m_strata(eStrataInvalid), m_file_offset(0), m_length(0), m_data(), 267061da546Spatrick m_process_wp(process_sp), m_memory_addr(header_addr), m_sections_up(), 268061da546Spatrick m_symtab_up(), m_synthetic_symbol_idx(0) { 269061da546Spatrick if (header_data_sp) 270061da546Spatrick m_data.SetData(header_data_sp, 0, header_data_sp->GetByteSize()); 271061da546Spatrick Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); 272061da546Spatrick LLDB_LOGF(log, 273061da546Spatrick "%p ObjectFile::ObjectFile() module = %p (%s), process = %p, " 274061da546Spatrick "header_addr = 0x%" PRIx64, 275061da546Spatrick static_cast<void *>(this), static_cast<void *>(module_sp.get()), 276061da546Spatrick module_sp->GetSpecificationDescription().c_str(), 277061da546Spatrick static_cast<void *>(process_sp.get()), m_memory_addr); 278061da546Spatrick } 279061da546Spatrick 280061da546Spatrick ObjectFile::~ObjectFile() { 281061da546Spatrick Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); 282061da546Spatrick LLDB_LOGF(log, "%p ObjectFile::~ObjectFile ()\n", static_cast<void *>(this)); 283061da546Spatrick } 284061da546Spatrick 285061da546Spatrick bool ObjectFile::SetModulesArchitecture(const ArchSpec &new_arch) { 286061da546Spatrick ModuleSP module_sp(GetModule()); 287061da546Spatrick if (module_sp) 288061da546Spatrick return module_sp->SetArchitecture(new_arch); 289061da546Spatrick return false; 290061da546Spatrick } 291061da546Spatrick 292061da546Spatrick AddressClass ObjectFile::GetAddressClass(addr_t file_addr) { 293061da546Spatrick Symtab *symtab = GetSymtab(); 294061da546Spatrick if (symtab) { 295061da546Spatrick Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr); 296061da546Spatrick if (symbol) { 297061da546Spatrick if (symbol->ValueIsAddress()) { 298061da546Spatrick const SectionSP section_sp(symbol->GetAddressRef().GetSection()); 299061da546Spatrick if (section_sp) { 300061da546Spatrick const SectionType section_type = section_sp->GetType(); 301061da546Spatrick switch (section_type) { 302061da546Spatrick case eSectionTypeInvalid: 303061da546Spatrick return AddressClass::eUnknown; 304061da546Spatrick case eSectionTypeCode: 305061da546Spatrick return AddressClass::eCode; 306061da546Spatrick case eSectionTypeContainer: 307061da546Spatrick return AddressClass::eUnknown; 308061da546Spatrick case eSectionTypeData: 309061da546Spatrick case eSectionTypeDataCString: 310061da546Spatrick case eSectionTypeDataCStringPointers: 311061da546Spatrick case eSectionTypeDataSymbolAddress: 312061da546Spatrick case eSectionTypeData4: 313061da546Spatrick case eSectionTypeData8: 314061da546Spatrick case eSectionTypeData16: 315061da546Spatrick case eSectionTypeDataPointers: 316061da546Spatrick case eSectionTypeZeroFill: 317061da546Spatrick case eSectionTypeDataObjCMessageRefs: 318061da546Spatrick case eSectionTypeDataObjCCFStrings: 319061da546Spatrick case eSectionTypeGoSymtab: 320061da546Spatrick return AddressClass::eData; 321061da546Spatrick case eSectionTypeDebug: 322061da546Spatrick case eSectionTypeDWARFDebugAbbrev: 323061da546Spatrick case eSectionTypeDWARFDebugAbbrevDwo: 324061da546Spatrick case eSectionTypeDWARFDebugAddr: 325061da546Spatrick case eSectionTypeDWARFDebugAranges: 326061da546Spatrick case eSectionTypeDWARFDebugCuIndex: 327061da546Spatrick case eSectionTypeDWARFDebugFrame: 328061da546Spatrick case eSectionTypeDWARFDebugInfo: 329061da546Spatrick case eSectionTypeDWARFDebugInfoDwo: 330061da546Spatrick case eSectionTypeDWARFDebugLine: 331061da546Spatrick case eSectionTypeDWARFDebugLineStr: 332061da546Spatrick case eSectionTypeDWARFDebugLoc: 333061da546Spatrick case eSectionTypeDWARFDebugLocDwo: 334061da546Spatrick case eSectionTypeDWARFDebugLocLists: 335061da546Spatrick case eSectionTypeDWARFDebugLocListsDwo: 336061da546Spatrick case eSectionTypeDWARFDebugMacInfo: 337061da546Spatrick case eSectionTypeDWARFDebugMacro: 338061da546Spatrick case eSectionTypeDWARFDebugNames: 339061da546Spatrick case eSectionTypeDWARFDebugPubNames: 340061da546Spatrick case eSectionTypeDWARFDebugPubTypes: 341061da546Spatrick case eSectionTypeDWARFDebugRanges: 342061da546Spatrick case eSectionTypeDWARFDebugRngLists: 343061da546Spatrick case eSectionTypeDWARFDebugRngListsDwo: 344061da546Spatrick case eSectionTypeDWARFDebugStr: 345061da546Spatrick case eSectionTypeDWARFDebugStrDwo: 346061da546Spatrick case eSectionTypeDWARFDebugStrOffsets: 347061da546Spatrick case eSectionTypeDWARFDebugStrOffsetsDwo: 348dda28197Spatrick case eSectionTypeDWARFDebugTuIndex: 349061da546Spatrick case eSectionTypeDWARFDebugTypes: 350061da546Spatrick case eSectionTypeDWARFDebugTypesDwo: 351061da546Spatrick case eSectionTypeDWARFAppleNames: 352061da546Spatrick case eSectionTypeDWARFAppleTypes: 353061da546Spatrick case eSectionTypeDWARFAppleNamespaces: 354061da546Spatrick case eSectionTypeDWARFAppleObjC: 355061da546Spatrick case eSectionTypeDWARFGNUDebugAltLink: 356061da546Spatrick return AddressClass::eDebug; 357061da546Spatrick case eSectionTypeEHFrame: 358061da546Spatrick case eSectionTypeARMexidx: 359061da546Spatrick case eSectionTypeARMextab: 360061da546Spatrick case eSectionTypeCompactUnwind: 361061da546Spatrick return AddressClass::eRuntime; 362061da546Spatrick case eSectionTypeELFSymbolTable: 363061da546Spatrick case eSectionTypeELFDynamicSymbols: 364061da546Spatrick case eSectionTypeELFRelocationEntries: 365061da546Spatrick case eSectionTypeELFDynamicLinkInfo: 366061da546Spatrick case eSectionTypeOther: 367061da546Spatrick return AddressClass::eUnknown; 368061da546Spatrick case eSectionTypeAbsoluteAddress: 369061da546Spatrick // In case of absolute sections decide the address class based on 370061da546Spatrick // the symbol type because the section type isn't specify if it is 371061da546Spatrick // a code or a data section. 372061da546Spatrick break; 373061da546Spatrick } 374061da546Spatrick } 375061da546Spatrick } 376061da546Spatrick 377061da546Spatrick const SymbolType symbol_type = symbol->GetType(); 378061da546Spatrick switch (symbol_type) { 379061da546Spatrick case eSymbolTypeAny: 380061da546Spatrick return AddressClass::eUnknown; 381061da546Spatrick case eSymbolTypeAbsolute: 382061da546Spatrick return AddressClass::eUnknown; 383061da546Spatrick case eSymbolTypeCode: 384061da546Spatrick return AddressClass::eCode; 385061da546Spatrick case eSymbolTypeTrampoline: 386061da546Spatrick return AddressClass::eCode; 387061da546Spatrick case eSymbolTypeResolver: 388061da546Spatrick return AddressClass::eCode; 389061da546Spatrick case eSymbolTypeData: 390061da546Spatrick return AddressClass::eData; 391061da546Spatrick case eSymbolTypeRuntime: 392061da546Spatrick return AddressClass::eRuntime; 393061da546Spatrick case eSymbolTypeException: 394061da546Spatrick return AddressClass::eRuntime; 395061da546Spatrick case eSymbolTypeSourceFile: 396061da546Spatrick return AddressClass::eDebug; 397061da546Spatrick case eSymbolTypeHeaderFile: 398061da546Spatrick return AddressClass::eDebug; 399061da546Spatrick case eSymbolTypeObjectFile: 400061da546Spatrick return AddressClass::eDebug; 401061da546Spatrick case eSymbolTypeCommonBlock: 402061da546Spatrick return AddressClass::eDebug; 403061da546Spatrick case eSymbolTypeBlock: 404061da546Spatrick return AddressClass::eDebug; 405061da546Spatrick case eSymbolTypeLocal: 406061da546Spatrick return AddressClass::eData; 407061da546Spatrick case eSymbolTypeParam: 408061da546Spatrick return AddressClass::eData; 409061da546Spatrick case eSymbolTypeVariable: 410061da546Spatrick return AddressClass::eData; 411061da546Spatrick case eSymbolTypeVariableType: 412061da546Spatrick return AddressClass::eDebug; 413061da546Spatrick case eSymbolTypeLineEntry: 414061da546Spatrick return AddressClass::eDebug; 415061da546Spatrick case eSymbolTypeLineHeader: 416061da546Spatrick return AddressClass::eDebug; 417061da546Spatrick case eSymbolTypeScopeBegin: 418061da546Spatrick return AddressClass::eDebug; 419061da546Spatrick case eSymbolTypeScopeEnd: 420061da546Spatrick return AddressClass::eDebug; 421061da546Spatrick case eSymbolTypeAdditional: 422061da546Spatrick return AddressClass::eUnknown; 423061da546Spatrick case eSymbolTypeCompiler: 424061da546Spatrick return AddressClass::eDebug; 425061da546Spatrick case eSymbolTypeInstrumentation: 426061da546Spatrick return AddressClass::eDebug; 427061da546Spatrick case eSymbolTypeUndefined: 428061da546Spatrick return AddressClass::eUnknown; 429061da546Spatrick case eSymbolTypeObjCClass: 430061da546Spatrick return AddressClass::eRuntime; 431061da546Spatrick case eSymbolTypeObjCMetaClass: 432061da546Spatrick return AddressClass::eRuntime; 433061da546Spatrick case eSymbolTypeObjCIVar: 434061da546Spatrick return AddressClass::eRuntime; 435061da546Spatrick case eSymbolTypeReExported: 436061da546Spatrick return AddressClass::eRuntime; 437061da546Spatrick } 438061da546Spatrick } 439061da546Spatrick } 440061da546Spatrick return AddressClass::eUnknown; 441061da546Spatrick } 442061da546Spatrick 443061da546Spatrick DataBufferSP ObjectFile::ReadMemory(const ProcessSP &process_sp, 444061da546Spatrick lldb::addr_t addr, size_t byte_size) { 445061da546Spatrick DataBufferSP data_sp; 446061da546Spatrick if (process_sp) { 447061da546Spatrick std::unique_ptr<DataBufferHeap> data_up(new DataBufferHeap(byte_size, 0)); 448061da546Spatrick Status error; 449061da546Spatrick const size_t bytes_read = process_sp->ReadMemory( 450061da546Spatrick addr, data_up->GetBytes(), data_up->GetByteSize(), error); 451061da546Spatrick if (bytes_read == byte_size) 452061da546Spatrick data_sp.reset(data_up.release()); 453061da546Spatrick } 454061da546Spatrick return data_sp; 455061da546Spatrick } 456061da546Spatrick 457061da546Spatrick size_t ObjectFile::GetData(lldb::offset_t offset, size_t length, 458061da546Spatrick DataExtractor &data) const { 459061da546Spatrick // The entire file has already been mmap'ed into m_data, so just copy from 460061da546Spatrick // there as the back mmap buffer will be shared with shared pointers. 461061da546Spatrick return data.SetData(m_data, offset, length); 462061da546Spatrick } 463061da546Spatrick 464061da546Spatrick size_t ObjectFile::CopyData(lldb::offset_t offset, size_t length, 465061da546Spatrick void *dst) const { 466061da546Spatrick // The entire file has already been mmap'ed into m_data, so just copy from 467061da546Spatrick // there Note that the data remains in target byte order. 468061da546Spatrick return m_data.CopyData(offset, length, dst); 469061da546Spatrick } 470061da546Spatrick 471061da546Spatrick size_t ObjectFile::ReadSectionData(Section *section, 472061da546Spatrick lldb::offset_t section_offset, void *dst, 473061da546Spatrick size_t dst_len) { 474061da546Spatrick assert(section); 475061da546Spatrick section_offset *= section->GetTargetByteSize(); 476061da546Spatrick 477061da546Spatrick // If some other objectfile owns this data, pass this to them. 478061da546Spatrick if (section->GetObjectFile() != this) 479061da546Spatrick return section->GetObjectFile()->ReadSectionData(section, section_offset, 480061da546Spatrick dst, dst_len); 481061da546Spatrick 482*be691f3bSpatrick if (!section->IsRelocated()) 483*be691f3bSpatrick RelocateSection(section); 484*be691f3bSpatrick 485061da546Spatrick if (IsInMemory()) { 486061da546Spatrick ProcessSP process_sp(m_process_wp.lock()); 487061da546Spatrick if (process_sp) { 488061da546Spatrick Status error; 489061da546Spatrick const addr_t base_load_addr = 490061da546Spatrick section->GetLoadBaseAddress(&process_sp->GetTarget()); 491061da546Spatrick if (base_load_addr != LLDB_INVALID_ADDRESS) 492061da546Spatrick return process_sp->ReadMemory(base_load_addr + section_offset, dst, 493061da546Spatrick dst_len, error); 494061da546Spatrick } 495061da546Spatrick } else { 496061da546Spatrick const lldb::offset_t section_file_size = section->GetFileSize(); 497061da546Spatrick if (section_offset < section_file_size) { 498061da546Spatrick const size_t section_bytes_left = section_file_size - section_offset; 499061da546Spatrick size_t section_dst_len = dst_len; 500061da546Spatrick if (section_dst_len > section_bytes_left) 501061da546Spatrick section_dst_len = section_bytes_left; 502061da546Spatrick return CopyData(section->GetFileOffset() + section_offset, 503061da546Spatrick section_dst_len, dst); 504061da546Spatrick } else { 505061da546Spatrick if (section->GetType() == eSectionTypeZeroFill) { 506061da546Spatrick const uint64_t section_size = section->GetByteSize(); 507061da546Spatrick const uint64_t section_bytes_left = section_size - section_offset; 508061da546Spatrick uint64_t section_dst_len = dst_len; 509061da546Spatrick if (section_dst_len > section_bytes_left) 510061da546Spatrick section_dst_len = section_bytes_left; 511061da546Spatrick memset(dst, 0, section_dst_len); 512061da546Spatrick return section_dst_len; 513061da546Spatrick } 514061da546Spatrick } 515061da546Spatrick } 516061da546Spatrick return 0; 517061da546Spatrick } 518061da546Spatrick 519061da546Spatrick // Get the section data the file on disk 520061da546Spatrick size_t ObjectFile::ReadSectionData(Section *section, 521061da546Spatrick DataExtractor §ion_data) { 522061da546Spatrick // If some other objectfile owns this data, pass this to them. 523061da546Spatrick if (section->GetObjectFile() != this) 524061da546Spatrick return section->GetObjectFile()->ReadSectionData(section, section_data); 525061da546Spatrick 526*be691f3bSpatrick if (!section->IsRelocated()) 527*be691f3bSpatrick RelocateSection(section); 528*be691f3bSpatrick 529061da546Spatrick if (IsInMemory()) { 530061da546Spatrick ProcessSP process_sp(m_process_wp.lock()); 531061da546Spatrick if (process_sp) { 532061da546Spatrick const addr_t base_load_addr = 533061da546Spatrick section->GetLoadBaseAddress(&process_sp->GetTarget()); 534061da546Spatrick if (base_load_addr != LLDB_INVALID_ADDRESS) { 535061da546Spatrick DataBufferSP data_sp( 536061da546Spatrick ReadMemory(process_sp, base_load_addr, section->GetByteSize())); 537061da546Spatrick if (data_sp) { 538061da546Spatrick section_data.SetData(data_sp, 0, data_sp->GetByteSize()); 539061da546Spatrick section_data.SetByteOrder(process_sp->GetByteOrder()); 540061da546Spatrick section_data.SetAddressByteSize(process_sp->GetAddressByteSize()); 541061da546Spatrick return section_data.GetByteSize(); 542061da546Spatrick } 543061da546Spatrick } 544061da546Spatrick } 545*be691f3bSpatrick } 546*be691f3bSpatrick 547061da546Spatrick // The object file now contains a full mmap'ed copy of the object file 548061da546Spatrick // data, so just use this 549061da546Spatrick return GetData(section->GetFileOffset(), section->GetFileSize(), 550061da546Spatrick section_data); 551061da546Spatrick } 552061da546Spatrick 553061da546Spatrick bool ObjectFile::SplitArchivePathWithObject(llvm::StringRef path_with_object, 554061da546Spatrick FileSpec &archive_file, 555061da546Spatrick ConstString &archive_object, 556061da546Spatrick bool must_exist) { 557061da546Spatrick size_t len = path_with_object.size(); 558061da546Spatrick if (len < 2 || path_with_object.back() != ')') 559061da546Spatrick return false; 560061da546Spatrick llvm::StringRef archive = path_with_object.substr(0, path_with_object.rfind('(')); 561061da546Spatrick if (archive.empty()) 562061da546Spatrick return false; 563061da546Spatrick llvm::StringRef object = path_with_object.substr(archive.size() + 1).drop_back(); 564061da546Spatrick archive_file.SetFile(archive, FileSpec::Style::native); 565061da546Spatrick if (must_exist && !FileSystem::Instance().Exists(archive_file)) 566061da546Spatrick return false; 567061da546Spatrick archive_object.SetString(object); 568061da546Spatrick return true; 569061da546Spatrick } 570061da546Spatrick 571061da546Spatrick void ObjectFile::ClearSymtab() { 572061da546Spatrick ModuleSP module_sp(GetModule()); 573061da546Spatrick if (module_sp) { 574061da546Spatrick std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); 575061da546Spatrick Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); 576061da546Spatrick LLDB_LOGF(log, "%p ObjectFile::ClearSymtab () symtab = %p", 577061da546Spatrick static_cast<void *>(this), 578061da546Spatrick static_cast<void *>(m_symtab_up.get())); 579061da546Spatrick m_symtab_up.reset(); 580061da546Spatrick } 581061da546Spatrick } 582061da546Spatrick 583061da546Spatrick SectionList *ObjectFile::GetSectionList(bool update_module_section_list) { 584061da546Spatrick if (m_sections_up == nullptr) { 585061da546Spatrick if (update_module_section_list) { 586061da546Spatrick ModuleSP module_sp(GetModule()); 587061da546Spatrick if (module_sp) { 588061da546Spatrick std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); 589061da546Spatrick CreateSections(*module_sp->GetUnifiedSectionList()); 590061da546Spatrick } 591061da546Spatrick } else { 592061da546Spatrick SectionList unified_section_list; 593061da546Spatrick CreateSections(unified_section_list); 594061da546Spatrick } 595061da546Spatrick } 596061da546Spatrick return m_sections_up.get(); 597061da546Spatrick } 598061da546Spatrick 599061da546Spatrick lldb::SymbolType 600061da546Spatrick ObjectFile::GetSymbolTypeFromName(llvm::StringRef name, 601061da546Spatrick lldb::SymbolType symbol_type_hint) { 602061da546Spatrick if (!name.empty()) { 603061da546Spatrick if (name.startswith("_OBJC_")) { 604061da546Spatrick // ObjC 605061da546Spatrick if (name.startswith("_OBJC_CLASS_$_")) 606061da546Spatrick return lldb::eSymbolTypeObjCClass; 607061da546Spatrick if (name.startswith("_OBJC_METACLASS_$_")) 608061da546Spatrick return lldb::eSymbolTypeObjCMetaClass; 609061da546Spatrick if (name.startswith("_OBJC_IVAR_$_")) 610061da546Spatrick return lldb::eSymbolTypeObjCIVar; 611061da546Spatrick } else if (name.startswith(".objc_class_name_")) { 612061da546Spatrick // ObjC v1 613061da546Spatrick return lldb::eSymbolTypeObjCClass; 614061da546Spatrick } 615061da546Spatrick } 616061da546Spatrick return symbol_type_hint; 617061da546Spatrick } 618061da546Spatrick 619061da546Spatrick std::vector<ObjectFile::LoadableData> 620061da546Spatrick ObjectFile::GetLoadableData(Target &target) { 621061da546Spatrick std::vector<LoadableData> loadables; 622061da546Spatrick SectionList *section_list = GetSectionList(); 623061da546Spatrick if (!section_list) 624061da546Spatrick return loadables; 625061da546Spatrick // Create a list of loadable data from loadable sections 626061da546Spatrick size_t section_count = section_list->GetNumSections(0); 627061da546Spatrick for (size_t i = 0; i < section_count; ++i) { 628061da546Spatrick LoadableData loadable; 629061da546Spatrick SectionSP section_sp = section_list->GetSectionAtIndex(i); 630061da546Spatrick loadable.Dest = 631061da546Spatrick target.GetSectionLoadList().GetSectionLoadAddress(section_sp); 632061da546Spatrick if (loadable.Dest == LLDB_INVALID_ADDRESS) 633061da546Spatrick continue; 634061da546Spatrick // We can skip sections like bss 635061da546Spatrick if (section_sp->GetFileSize() == 0) 636061da546Spatrick continue; 637061da546Spatrick DataExtractor section_data; 638061da546Spatrick section_sp->GetSectionData(section_data); 639061da546Spatrick loadable.Contents = llvm::ArrayRef<uint8_t>(section_data.GetDataStart(), 640061da546Spatrick section_data.GetByteSize()); 641061da546Spatrick loadables.push_back(loadable); 642061da546Spatrick } 643061da546Spatrick return loadables; 644061da546Spatrick } 645061da546Spatrick 646061da546Spatrick std::unique_ptr<CallFrameInfo> ObjectFile::CreateCallFrameInfo() { 647061da546Spatrick return {}; 648061da546Spatrick } 649061da546Spatrick 650061da546Spatrick void ObjectFile::RelocateSection(lldb_private::Section *section) 651061da546Spatrick { 652061da546Spatrick } 653061da546Spatrick 654061da546Spatrick DataBufferSP ObjectFile::MapFileData(const FileSpec &file, uint64_t Size, 655061da546Spatrick uint64_t Offset) { 656061da546Spatrick return FileSystem::Instance().CreateDataBuffer(file.GetPath(), Size, Offset); 657061da546Spatrick } 658061da546Spatrick 659061da546Spatrick void llvm::format_provider<ObjectFile::Type>::format( 660061da546Spatrick const ObjectFile::Type &type, raw_ostream &OS, StringRef Style) { 661061da546Spatrick switch (type) { 662061da546Spatrick case ObjectFile::eTypeInvalid: 663061da546Spatrick OS << "invalid"; 664061da546Spatrick break; 665061da546Spatrick case ObjectFile::eTypeCoreFile: 666061da546Spatrick OS << "core file"; 667061da546Spatrick break; 668061da546Spatrick case ObjectFile::eTypeExecutable: 669061da546Spatrick OS << "executable"; 670061da546Spatrick break; 671061da546Spatrick case ObjectFile::eTypeDebugInfo: 672061da546Spatrick OS << "debug info"; 673061da546Spatrick break; 674061da546Spatrick case ObjectFile::eTypeDynamicLinker: 675061da546Spatrick OS << "dynamic linker"; 676061da546Spatrick break; 677061da546Spatrick case ObjectFile::eTypeObjectFile: 678061da546Spatrick OS << "object file"; 679061da546Spatrick break; 680061da546Spatrick case ObjectFile::eTypeSharedLibrary: 681061da546Spatrick OS << "shared library"; 682061da546Spatrick break; 683061da546Spatrick case ObjectFile::eTypeStubLibrary: 684061da546Spatrick OS << "stub library"; 685061da546Spatrick break; 686061da546Spatrick case ObjectFile::eTypeJIT: 687061da546Spatrick OS << "jit"; 688061da546Spatrick break; 689061da546Spatrick case ObjectFile::eTypeUnknown: 690061da546Spatrick OS << "unknown"; 691061da546Spatrick break; 692061da546Spatrick } 693061da546Spatrick } 694061da546Spatrick 695061da546Spatrick void llvm::format_provider<ObjectFile::Strata>::format( 696061da546Spatrick const ObjectFile::Strata &strata, raw_ostream &OS, StringRef Style) { 697061da546Spatrick switch (strata) { 698061da546Spatrick case ObjectFile::eStrataInvalid: 699061da546Spatrick OS << "invalid"; 700061da546Spatrick break; 701061da546Spatrick case ObjectFile::eStrataUnknown: 702061da546Spatrick OS << "unknown"; 703061da546Spatrick break; 704061da546Spatrick case ObjectFile::eStrataUser: 705061da546Spatrick OS << "user"; 706061da546Spatrick break; 707061da546Spatrick case ObjectFile::eStrataKernel: 708061da546Spatrick OS << "kernel"; 709061da546Spatrick break; 710061da546Spatrick case ObjectFile::eStrataRawImage: 711061da546Spatrick OS << "raw image"; 712061da546Spatrick break; 713061da546Spatrick case ObjectFile::eStrataJIT: 714061da546Spatrick OS << "jit"; 715061da546Spatrick break; 716061da546Spatrick } 717061da546Spatrick } 718