15ffd83dbSDimitry Andric //===-- ObjectFile.cpp ----------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 100b57cec5SDimitry Andric #include "lldb/Core/Module.h" 110b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h" 120b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h" 130b57cec5SDimitry Andric #include "lldb/Core/Section.h" 149dba64beSDimitry Andric #include "lldb/Symbol/CallFrameInfo.h" 150b57cec5SDimitry Andric #include "lldb/Symbol/ObjectContainer.h" 160b57cec5SDimitry Andric #include "lldb/Symbol/SymbolFile.h" 170b57cec5SDimitry Andric #include "lldb/Target/Process.h" 180b57cec5SDimitry Andric #include "lldb/Target/SectionLoadList.h" 190b57cec5SDimitry Andric #include "lldb/Target/Target.h" 200b57cec5SDimitry Andric #include "lldb/Utility/DataBuffer.h" 210b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 2281ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 230b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 240b57cec5SDimitry Andric #include "lldb/Utility/Timer.h" 250b57cec5SDimitry Andric #include "lldb/lldb-private.h" 260b57cec5SDimitry Andric 270eae32dcSDimitry Andric #include "llvm/Support/DJB.h" 280eae32dcSDimitry Andric 290b57cec5SDimitry Andric using namespace lldb; 300b57cec5SDimitry Andric using namespace lldb_private; 310b57cec5SDimitry Andric 329dba64beSDimitry Andric char ObjectFile::ID; 3381ad6265SDimitry Andric size_t ObjectFile::g_initial_bytes_to_read = 512; 349dba64beSDimitry Andric 35e8d8bef9SDimitry Andric static ObjectFileSP 36e8d8bef9SDimitry Andric CreateObjectFromContainer(const lldb::ModuleSP &module_sp, const FileSpec *file, 37e8d8bef9SDimitry Andric lldb::offset_t file_offset, lldb::offset_t file_size, 3881ad6265SDimitry Andric DataBufferSP data_sp, lldb::offset_t &data_offset) { 39e8d8bef9SDimitry Andric ObjectContainerCreateInstance callback; 40e8d8bef9SDimitry Andric for (uint32_t idx = 0; 41e8d8bef9SDimitry Andric (callback = PluginManager::GetObjectContainerCreateCallbackAtIndex( 42e8d8bef9SDimitry Andric idx)) != nullptr; 43e8d8bef9SDimitry Andric ++idx) { 44e8d8bef9SDimitry Andric std::unique_ptr<ObjectContainer> object_container_up(callback( 45e8d8bef9SDimitry Andric module_sp, data_sp, data_offset, file, file_offset, file_size)); 46e8d8bef9SDimitry Andric if (object_container_up) 47e8d8bef9SDimitry Andric return object_container_up->GetObjectFile(file); 48e8d8bef9SDimitry Andric } 49e8d8bef9SDimitry Andric return {}; 50e8d8bef9SDimitry Andric } 51e8d8bef9SDimitry Andric 520b57cec5SDimitry Andric ObjectFileSP 530b57cec5SDimitry Andric ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file, 540b57cec5SDimitry Andric lldb::offset_t file_offset, lldb::offset_t file_size, 550b57cec5SDimitry Andric DataBufferSP &data_sp, lldb::offset_t &data_offset) { 56e8d8bef9SDimitry Andric LLDB_SCOPED_TIMERF( 570b57cec5SDimitry Andric "ObjectFile::FindPlugin (module = %s, file = %p, file_offset = " 580b57cec5SDimitry Andric "0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")", 590b57cec5SDimitry Andric module_sp->GetFileSpec().GetPath().c_str(), 600b57cec5SDimitry Andric static_cast<const void *>(file), static_cast<uint64_t>(file_offset), 610b57cec5SDimitry Andric static_cast<uint64_t>(file_size)); 62e8d8bef9SDimitry Andric 63e8d8bef9SDimitry Andric if (!module_sp) 64e8d8bef9SDimitry Andric return {}; 65e8d8bef9SDimitry Andric 66e8d8bef9SDimitry Andric if (!file) 67e8d8bef9SDimitry Andric return {}; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric if (!data_sp) { 705ffd83dbSDimitry Andric const bool file_exists = FileSystem::Instance().Exists(*file); 710b57cec5SDimitry Andric // We have an object name which most likely means we have a .o file in 720b57cec5SDimitry Andric // a static archive (.a file). Try and see if we have a cached archive 730b57cec5SDimitry Andric // first without reading any data first 740b57cec5SDimitry Andric if (file_exists && module_sp->GetObjectName()) { 75e8d8bef9SDimitry Andric ObjectFileSP object_file_sp = CreateObjectFromContainer( 76e8d8bef9SDimitry Andric module_sp, file, file_offset, file_size, data_sp, data_offset); 77e8d8bef9SDimitry Andric if (object_file_sp) 780b57cec5SDimitry Andric return object_file_sp; 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric // Ok, we didn't find any containers that have a named object, now lets 810b57cec5SDimitry Andric // read the first 512 bytes from the file so the object file and object 820b57cec5SDimitry Andric // container plug-ins can use these bytes to see if they can parse this 830b57cec5SDimitry Andric // file. 840b57cec5SDimitry Andric if (file_size > 0) { 8581ad6265SDimitry Andric data_sp = FileSystem::Instance().CreateDataBuffer( 8681ad6265SDimitry Andric file->GetPath(), g_initial_bytes_to_read, file_offset); 870b57cec5SDimitry Andric data_offset = 0; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric if (!data_sp || data_sp->GetByteSize() == 0) { 920b57cec5SDimitry Andric // Check for archive file with format "/path/to/archive.a(object.o)" 939dba64beSDimitry Andric llvm::SmallString<256> path_with_object; 949dba64beSDimitry Andric module_sp->GetFileSpec().GetPath(path_with_object); 950b57cec5SDimitry Andric 96e8d8bef9SDimitry Andric FileSpec archive_file; 970b57cec5SDimitry Andric ConstString archive_object; 980b57cec5SDimitry Andric const bool must_exist = true; 99e8d8bef9SDimitry Andric if (ObjectFile::SplitArchivePathWithObject(path_with_object, archive_file, 100e8d8bef9SDimitry Andric archive_object, must_exist)) { 1010b57cec5SDimitry Andric file_size = FileSystem::Instance().GetByteSize(archive_file); 1020b57cec5SDimitry Andric if (file_size > 0) { 1030b57cec5SDimitry Andric file = &archive_file; 1040b57cec5SDimitry Andric module_sp->SetFileSpecAndObjectName(archive_file, archive_object); 1050b57cec5SDimitry Andric // Check if this is a object container by iterating through all 1060b57cec5SDimitry Andric // object container plugin instances and then trying to get an 1070b57cec5SDimitry Andric // object file from the container plugins since we had a name. 1080b57cec5SDimitry Andric // Also, don't read 1090b57cec5SDimitry Andric // ANY data in case there is data cached in the container plug-ins 1100b57cec5SDimitry Andric // (like BSD archives caching the contained objects within an 1110b57cec5SDimitry Andric // file). 112e8d8bef9SDimitry Andric ObjectFileSP object_file_sp = CreateObjectFromContainer( 113e8d8bef9SDimitry Andric module_sp, file, file_offset, file_size, data_sp, data_offset); 114e8d8bef9SDimitry Andric if (object_file_sp) 1150b57cec5SDimitry Andric return object_file_sp; 1160b57cec5SDimitry Andric // We failed to find any cached object files in the container plug- 1170b57cec5SDimitry Andric // ins, so lets read the first 512 bytes and try again below... 1180b57cec5SDimitry Andric data_sp = FileSystem::Instance().CreateDataBuffer( 11981ad6265SDimitry Andric archive_file.GetPath(), g_initial_bytes_to_read, file_offset); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric if (data_sp && data_sp->GetByteSize() > 0) { 1250b57cec5SDimitry Andric // Check if this is a normal object file by iterating through all 1260b57cec5SDimitry Andric // object file plugin instances. 127e8d8bef9SDimitry Andric ObjectFileCreateInstance callback; 1280b57cec5SDimitry Andric for (uint32_t idx = 0; 129e8d8bef9SDimitry Andric (callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != 1300b57cec5SDimitry Andric nullptr; 1310b57cec5SDimitry Andric ++idx) { 132e8d8bef9SDimitry Andric ObjectFileSP object_file_sp(callback(module_sp, data_sp, data_offset, 133e8d8bef9SDimitry Andric file, file_offset, file_size)); 1340b57cec5SDimitry Andric if (object_file_sp.get()) 1350b57cec5SDimitry Andric return object_file_sp; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric // Check if this is a object container by iterating through all object 1390b57cec5SDimitry Andric // container plugin instances and then trying to get an object file 1400b57cec5SDimitry Andric // from the container. 141e8d8bef9SDimitry Andric ObjectFileSP object_file_sp = CreateObjectFromContainer( 142e8d8bef9SDimitry Andric module_sp, file, file_offset, file_size, data_sp, data_offset); 143e8d8bef9SDimitry Andric if (object_file_sp) 1440b57cec5SDimitry Andric return object_file_sp; 1450b57cec5SDimitry Andric } 146e8d8bef9SDimitry Andric 1470b57cec5SDimitry Andric // We didn't find it, so clear our shared pointer in case it contains 1480b57cec5SDimitry Andric // anything and return an empty shared pointer 149e8d8bef9SDimitry Andric return {}; 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric ObjectFileSP ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, 1530b57cec5SDimitry Andric const ProcessSP &process_sp, 1540b57cec5SDimitry Andric lldb::addr_t header_addr, 15581ad6265SDimitry Andric WritableDataBufferSP data_sp) { 1560b57cec5SDimitry Andric ObjectFileSP object_file_sp; 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric if (module_sp) { 159e8d8bef9SDimitry Andric LLDB_SCOPED_TIMERF("ObjectFile::FindPlugin (module = " 1600b57cec5SDimitry Andric "%s, process = %p, header_addr = " 1610b57cec5SDimitry Andric "0x%" PRIx64 ")", 1620b57cec5SDimitry Andric module_sp->GetFileSpec().GetPath().c_str(), 1630b57cec5SDimitry Andric static_cast<void *>(process_sp.get()), header_addr); 1640b57cec5SDimitry Andric uint32_t idx; 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric // Check if this is a normal object file by iterating through all object 1670b57cec5SDimitry Andric // file plugin instances. 1680b57cec5SDimitry Andric ObjectFileCreateMemoryInstance create_callback; 1690b57cec5SDimitry Andric for (idx = 0; 1700b57cec5SDimitry Andric (create_callback = 1710b57cec5SDimitry Andric PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(idx)) != 1720b57cec5SDimitry Andric nullptr; 1730b57cec5SDimitry Andric ++idx) { 1740b57cec5SDimitry Andric object_file_sp.reset( 1750b57cec5SDimitry Andric create_callback(module_sp, data_sp, process_sp, header_addr)); 1760b57cec5SDimitry Andric if (object_file_sp.get()) 1770b57cec5SDimitry Andric return object_file_sp; 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric // We didn't find it, so clear our shared pointer in case it contains 1820b57cec5SDimitry Andric // anything and return an empty shared pointer 1830b57cec5SDimitry Andric object_file_sp.reset(); 1840b57cec5SDimitry Andric return object_file_sp; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 187*0fca6ea1SDimitry Andric bool ObjectFile::IsObjectFile(lldb_private::FileSpec file_spec) { 188*0fca6ea1SDimitry Andric DataBufferSP data_sp; 189*0fca6ea1SDimitry Andric offset_t data_offset = 0; 190*0fca6ea1SDimitry Andric ModuleSP module_sp = std::make_shared<Module>(file_spec); 191*0fca6ea1SDimitry Andric return static_cast<bool>(ObjectFile::FindPlugin( 192*0fca6ea1SDimitry Andric module_sp, &file_spec, 0, FileSystem::Instance().GetByteSize(file_spec), 193*0fca6ea1SDimitry Andric data_sp, data_offset)); 194*0fca6ea1SDimitry Andric } 195*0fca6ea1SDimitry Andric 1960b57cec5SDimitry Andric size_t ObjectFile::GetModuleSpecifications(const FileSpec &file, 1970b57cec5SDimitry Andric lldb::offset_t file_offset, 1980b57cec5SDimitry Andric lldb::offset_t file_size, 1995ffd83dbSDimitry Andric ModuleSpecList &specs, 2005ffd83dbSDimitry Andric DataBufferSP data_sp) { 2015ffd83dbSDimitry Andric if (!data_sp) 20281ad6265SDimitry Andric data_sp = FileSystem::Instance().CreateDataBuffer( 20381ad6265SDimitry Andric file.GetPath(), g_initial_bytes_to_read, file_offset); 2040b57cec5SDimitry Andric if (data_sp) { 2050b57cec5SDimitry Andric if (file_size == 0) { 2060b57cec5SDimitry Andric const lldb::offset_t actual_file_size = 2070b57cec5SDimitry Andric FileSystem::Instance().GetByteSize(file); 2080b57cec5SDimitry Andric if (actual_file_size > file_offset) 2090b57cec5SDimitry Andric file_size = actual_file_size - file_offset; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric return ObjectFile::GetModuleSpecifications(file, // file spec 2120b57cec5SDimitry Andric data_sp, // data bytes 2130b57cec5SDimitry Andric 0, // data offset 2140b57cec5SDimitry Andric file_offset, // file offset 2150b57cec5SDimitry Andric file_size, // file length 2160b57cec5SDimitry Andric specs); 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric return 0; 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric size_t ObjectFile::GetModuleSpecifications( 2220b57cec5SDimitry Andric const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, 2230b57cec5SDimitry Andric lldb::offset_t data_offset, lldb::offset_t file_offset, 2240b57cec5SDimitry Andric lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) { 2250b57cec5SDimitry Andric const size_t initial_count = specs.GetSize(); 2260b57cec5SDimitry Andric ObjectFileGetModuleSpecifications callback; 2270b57cec5SDimitry Andric uint32_t i; 2280b57cec5SDimitry Andric // Try the ObjectFile plug-ins 2290b57cec5SDimitry Andric for (i = 0; 2300b57cec5SDimitry Andric (callback = 2310b57cec5SDimitry Andric PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex( 2320b57cec5SDimitry Andric i)) != nullptr; 2330b57cec5SDimitry Andric ++i) { 2340b57cec5SDimitry Andric if (callback(file, data_sp, data_offset, file_offset, file_size, specs) > 0) 2350b57cec5SDimitry Andric return specs.GetSize() - initial_count; 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric // Try the ObjectContainer plug-ins 2390b57cec5SDimitry Andric for (i = 0; 2400b57cec5SDimitry Andric (callback = PluginManager:: 2410b57cec5SDimitry Andric GetObjectContainerGetModuleSpecificationsCallbackAtIndex(i)) != 2420b57cec5SDimitry Andric nullptr; 2430b57cec5SDimitry Andric ++i) { 2440b57cec5SDimitry Andric if (callback(file, data_sp, data_offset, file_offset, file_size, specs) > 0) 2450b57cec5SDimitry Andric return specs.GetSize() - initial_count; 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric return 0; 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp, 2510b57cec5SDimitry Andric const FileSpec *file_spec_ptr, 2520b57cec5SDimitry Andric lldb::offset_t file_offset, lldb::offset_t length, 25381ad6265SDimitry Andric lldb::DataBufferSP data_sp, lldb::offset_t data_offset) 2540b57cec5SDimitry Andric : ModuleChild(module_sp), 2550b57cec5SDimitry Andric m_file(), // This file could be different from the original module's file 2560b57cec5SDimitry Andric m_type(eTypeInvalid), m_strata(eStrataInvalid), 2570b57cec5SDimitry Andric m_file_offset(file_offset), m_length(length), m_data(), m_process_wp(), 2580b57cec5SDimitry Andric m_memory_addr(LLDB_INVALID_ADDRESS), m_sections_up(), m_symtab_up(), 2594824e7fdSDimitry Andric m_symtab_once_up(new llvm::once_flag()) { 2600b57cec5SDimitry Andric if (file_spec_ptr) 2610b57cec5SDimitry Andric m_file = *file_spec_ptr; 2620b57cec5SDimitry Andric if (data_sp) 2630b57cec5SDimitry Andric m_data.SetData(data_sp, data_offset, length); 26481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Object); 2659dba64beSDimitry Andric LLDB_LOGF(log, 2669dba64beSDimitry Andric "%p ObjectFile::ObjectFile() module = %p (%s), file = %s, " 2670b57cec5SDimitry Andric "file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64, 2680b57cec5SDimitry Andric static_cast<void *>(this), static_cast<void *>(module_sp.get()), 2690b57cec5SDimitry Andric module_sp->GetSpecificationDescription().c_str(), 2700b57cec5SDimitry Andric m_file ? m_file.GetPath().c_str() : "<NULL>", m_file_offset, 2710b57cec5SDimitry Andric m_length); 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp, 2750b57cec5SDimitry Andric const ProcessSP &process_sp, lldb::addr_t header_addr, 27681ad6265SDimitry Andric DataBufferSP header_data_sp) 2770b57cec5SDimitry Andric : ModuleChild(module_sp), m_file(), m_type(eTypeInvalid), 2780b57cec5SDimitry Andric m_strata(eStrataInvalid), m_file_offset(0), m_length(0), m_data(), 2790b57cec5SDimitry Andric m_process_wp(process_sp), m_memory_addr(header_addr), m_sections_up(), 2804824e7fdSDimitry Andric m_symtab_up(), m_symtab_once_up(new llvm::once_flag()) { 2810b57cec5SDimitry Andric if (header_data_sp) 2820b57cec5SDimitry Andric m_data.SetData(header_data_sp, 0, header_data_sp->GetByteSize()); 28381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Object); 2849dba64beSDimitry Andric LLDB_LOGF(log, 2859dba64beSDimitry Andric "%p ObjectFile::ObjectFile() module = %p (%s), process = %p, " 2860b57cec5SDimitry Andric "header_addr = 0x%" PRIx64, 2870b57cec5SDimitry Andric static_cast<void *>(this), static_cast<void *>(module_sp.get()), 2880b57cec5SDimitry Andric module_sp->GetSpecificationDescription().c_str(), 2890b57cec5SDimitry Andric static_cast<void *>(process_sp.get()), m_memory_addr); 2900b57cec5SDimitry Andric } 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric ObjectFile::~ObjectFile() { 29381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Object); 2949dba64beSDimitry Andric LLDB_LOGF(log, "%p ObjectFile::~ObjectFile ()\n", static_cast<void *>(this)); 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric bool ObjectFile::SetModulesArchitecture(const ArchSpec &new_arch) { 2980b57cec5SDimitry Andric ModuleSP module_sp(GetModule()); 2990b57cec5SDimitry Andric if (module_sp) 3000b57cec5SDimitry Andric return module_sp->SetArchitecture(new_arch); 3010b57cec5SDimitry Andric return false; 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric AddressClass ObjectFile::GetAddressClass(addr_t file_addr) { 3050b57cec5SDimitry Andric Symtab *symtab = GetSymtab(); 3060b57cec5SDimitry Andric if (symtab) { 3070b57cec5SDimitry Andric Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr); 3080b57cec5SDimitry Andric if (symbol) { 3090b57cec5SDimitry Andric if (symbol->ValueIsAddress()) { 3100b57cec5SDimitry Andric const SectionSP section_sp(symbol->GetAddressRef().GetSection()); 3110b57cec5SDimitry Andric if (section_sp) { 3120b57cec5SDimitry Andric const SectionType section_type = section_sp->GetType(); 3130b57cec5SDimitry Andric switch (section_type) { 3140b57cec5SDimitry Andric case eSectionTypeInvalid: 3150b57cec5SDimitry Andric return AddressClass::eUnknown; 3160b57cec5SDimitry Andric case eSectionTypeCode: 3170b57cec5SDimitry Andric return AddressClass::eCode; 3180b57cec5SDimitry Andric case eSectionTypeContainer: 3190b57cec5SDimitry Andric return AddressClass::eUnknown; 3200b57cec5SDimitry Andric case eSectionTypeData: 3210b57cec5SDimitry Andric case eSectionTypeDataCString: 3220b57cec5SDimitry Andric case eSectionTypeDataCStringPointers: 3230b57cec5SDimitry Andric case eSectionTypeDataSymbolAddress: 3240b57cec5SDimitry Andric case eSectionTypeData4: 3250b57cec5SDimitry Andric case eSectionTypeData8: 3260b57cec5SDimitry Andric case eSectionTypeData16: 3270b57cec5SDimitry Andric case eSectionTypeDataPointers: 3280b57cec5SDimitry Andric case eSectionTypeZeroFill: 3290b57cec5SDimitry Andric case eSectionTypeDataObjCMessageRefs: 3300b57cec5SDimitry Andric case eSectionTypeDataObjCCFStrings: 3310b57cec5SDimitry Andric case eSectionTypeGoSymtab: 3320b57cec5SDimitry Andric return AddressClass::eData; 3330b57cec5SDimitry Andric case eSectionTypeDebug: 3340b57cec5SDimitry Andric case eSectionTypeDWARFDebugAbbrev: 3350b57cec5SDimitry Andric case eSectionTypeDWARFDebugAbbrevDwo: 3360b57cec5SDimitry Andric case eSectionTypeDWARFDebugAddr: 3370b57cec5SDimitry Andric case eSectionTypeDWARFDebugAranges: 3380b57cec5SDimitry Andric case eSectionTypeDWARFDebugCuIndex: 3390b57cec5SDimitry Andric case eSectionTypeDWARFDebugFrame: 3400b57cec5SDimitry Andric case eSectionTypeDWARFDebugInfo: 3410b57cec5SDimitry Andric case eSectionTypeDWARFDebugInfoDwo: 3420b57cec5SDimitry Andric case eSectionTypeDWARFDebugLine: 3430b57cec5SDimitry Andric case eSectionTypeDWARFDebugLineStr: 3440b57cec5SDimitry Andric case eSectionTypeDWARFDebugLoc: 345480093f4SDimitry Andric case eSectionTypeDWARFDebugLocDwo: 3460b57cec5SDimitry Andric case eSectionTypeDWARFDebugLocLists: 347480093f4SDimitry Andric case eSectionTypeDWARFDebugLocListsDwo: 3480b57cec5SDimitry Andric case eSectionTypeDWARFDebugMacInfo: 3490b57cec5SDimitry Andric case eSectionTypeDWARFDebugMacro: 3500b57cec5SDimitry Andric case eSectionTypeDWARFDebugNames: 3510b57cec5SDimitry Andric case eSectionTypeDWARFDebugPubNames: 3520b57cec5SDimitry Andric case eSectionTypeDWARFDebugPubTypes: 3530b57cec5SDimitry Andric case eSectionTypeDWARFDebugRanges: 3540b57cec5SDimitry Andric case eSectionTypeDWARFDebugRngLists: 355480093f4SDimitry Andric case eSectionTypeDWARFDebugRngListsDwo: 3560b57cec5SDimitry Andric case eSectionTypeDWARFDebugStr: 3570b57cec5SDimitry Andric case eSectionTypeDWARFDebugStrDwo: 3580b57cec5SDimitry Andric case eSectionTypeDWARFDebugStrOffsets: 3590b57cec5SDimitry Andric case eSectionTypeDWARFDebugStrOffsetsDwo: 3605ffd83dbSDimitry Andric case eSectionTypeDWARFDebugTuIndex: 3610b57cec5SDimitry Andric case eSectionTypeDWARFDebugTypes: 3620b57cec5SDimitry Andric case eSectionTypeDWARFDebugTypesDwo: 3630b57cec5SDimitry Andric case eSectionTypeDWARFAppleNames: 3640b57cec5SDimitry Andric case eSectionTypeDWARFAppleTypes: 3650b57cec5SDimitry Andric case eSectionTypeDWARFAppleNamespaces: 3660b57cec5SDimitry Andric case eSectionTypeDWARFAppleObjC: 3670b57cec5SDimitry Andric case eSectionTypeDWARFGNUDebugAltLink: 36806c3fb27SDimitry Andric case eSectionTypeCTF: 3695f757f3fSDimitry Andric case eSectionTypeSwiftModules: 3700b57cec5SDimitry Andric return AddressClass::eDebug; 3710b57cec5SDimitry Andric case eSectionTypeEHFrame: 3720b57cec5SDimitry Andric case eSectionTypeARMexidx: 3730b57cec5SDimitry Andric case eSectionTypeARMextab: 3740b57cec5SDimitry Andric case eSectionTypeCompactUnwind: 3750b57cec5SDimitry Andric return AddressClass::eRuntime; 3760b57cec5SDimitry Andric case eSectionTypeELFSymbolTable: 3770b57cec5SDimitry Andric case eSectionTypeELFDynamicSymbols: 3780b57cec5SDimitry Andric case eSectionTypeELFRelocationEntries: 3790b57cec5SDimitry Andric case eSectionTypeELFDynamicLinkInfo: 3800b57cec5SDimitry Andric case eSectionTypeOther: 3810b57cec5SDimitry Andric return AddressClass::eUnknown; 3820b57cec5SDimitry Andric case eSectionTypeAbsoluteAddress: 3830b57cec5SDimitry Andric // In case of absolute sections decide the address class based on 3840b57cec5SDimitry Andric // the symbol type because the section type isn't specify if it is 3850b57cec5SDimitry Andric // a code or a data section. 3860b57cec5SDimitry Andric break; 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric } 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric const SymbolType symbol_type = symbol->GetType(); 3920b57cec5SDimitry Andric switch (symbol_type) { 3930b57cec5SDimitry Andric case eSymbolTypeAny: 3940b57cec5SDimitry Andric return AddressClass::eUnknown; 3950b57cec5SDimitry Andric case eSymbolTypeAbsolute: 3960b57cec5SDimitry Andric return AddressClass::eUnknown; 3970b57cec5SDimitry Andric case eSymbolTypeCode: 3980b57cec5SDimitry Andric return AddressClass::eCode; 3990b57cec5SDimitry Andric case eSymbolTypeTrampoline: 4000b57cec5SDimitry Andric return AddressClass::eCode; 4010b57cec5SDimitry Andric case eSymbolTypeResolver: 4020b57cec5SDimitry Andric return AddressClass::eCode; 4030b57cec5SDimitry Andric case eSymbolTypeData: 4040b57cec5SDimitry Andric return AddressClass::eData; 4050b57cec5SDimitry Andric case eSymbolTypeRuntime: 4060b57cec5SDimitry Andric return AddressClass::eRuntime; 4070b57cec5SDimitry Andric case eSymbolTypeException: 4080b57cec5SDimitry Andric return AddressClass::eRuntime; 4090b57cec5SDimitry Andric case eSymbolTypeSourceFile: 4100b57cec5SDimitry Andric return AddressClass::eDebug; 4110b57cec5SDimitry Andric case eSymbolTypeHeaderFile: 4120b57cec5SDimitry Andric return AddressClass::eDebug; 4130b57cec5SDimitry Andric case eSymbolTypeObjectFile: 4140b57cec5SDimitry Andric return AddressClass::eDebug; 4150b57cec5SDimitry Andric case eSymbolTypeCommonBlock: 4160b57cec5SDimitry Andric return AddressClass::eDebug; 4170b57cec5SDimitry Andric case eSymbolTypeBlock: 4180b57cec5SDimitry Andric return AddressClass::eDebug; 4190b57cec5SDimitry Andric case eSymbolTypeLocal: 4200b57cec5SDimitry Andric return AddressClass::eData; 4210b57cec5SDimitry Andric case eSymbolTypeParam: 4220b57cec5SDimitry Andric return AddressClass::eData; 4230b57cec5SDimitry Andric case eSymbolTypeVariable: 4240b57cec5SDimitry Andric return AddressClass::eData; 4250b57cec5SDimitry Andric case eSymbolTypeVariableType: 4260b57cec5SDimitry Andric return AddressClass::eDebug; 4270b57cec5SDimitry Andric case eSymbolTypeLineEntry: 4280b57cec5SDimitry Andric return AddressClass::eDebug; 4290b57cec5SDimitry Andric case eSymbolTypeLineHeader: 4300b57cec5SDimitry Andric return AddressClass::eDebug; 4310b57cec5SDimitry Andric case eSymbolTypeScopeBegin: 4320b57cec5SDimitry Andric return AddressClass::eDebug; 4330b57cec5SDimitry Andric case eSymbolTypeScopeEnd: 4340b57cec5SDimitry Andric return AddressClass::eDebug; 4350b57cec5SDimitry Andric case eSymbolTypeAdditional: 4360b57cec5SDimitry Andric return AddressClass::eUnknown; 4370b57cec5SDimitry Andric case eSymbolTypeCompiler: 4380b57cec5SDimitry Andric return AddressClass::eDebug; 4390b57cec5SDimitry Andric case eSymbolTypeInstrumentation: 4400b57cec5SDimitry Andric return AddressClass::eDebug; 4410b57cec5SDimitry Andric case eSymbolTypeUndefined: 4420b57cec5SDimitry Andric return AddressClass::eUnknown; 4430b57cec5SDimitry Andric case eSymbolTypeObjCClass: 4440b57cec5SDimitry Andric return AddressClass::eRuntime; 4450b57cec5SDimitry Andric case eSymbolTypeObjCMetaClass: 4460b57cec5SDimitry Andric return AddressClass::eRuntime; 4470b57cec5SDimitry Andric case eSymbolTypeObjCIVar: 4480b57cec5SDimitry Andric return AddressClass::eRuntime; 4490b57cec5SDimitry Andric case eSymbolTypeReExported: 4500b57cec5SDimitry Andric return AddressClass::eRuntime; 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric return AddressClass::eUnknown; 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric DataBufferSP ObjectFile::ReadMemory(const ProcessSP &process_sp, 4580b57cec5SDimitry Andric lldb::addr_t addr, size_t byte_size) { 4590b57cec5SDimitry Andric DataBufferSP data_sp; 4600b57cec5SDimitry Andric if (process_sp) { 4610b57cec5SDimitry Andric std::unique_ptr<DataBufferHeap> data_up(new DataBufferHeap(byte_size, 0)); 4620b57cec5SDimitry Andric Status error; 4630b57cec5SDimitry Andric const size_t bytes_read = process_sp->ReadMemory( 4640b57cec5SDimitry Andric addr, data_up->GetBytes(), data_up->GetByteSize(), error); 4650b57cec5SDimitry Andric if (bytes_read == byte_size) 4660b57cec5SDimitry Andric data_sp.reset(data_up.release()); 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric return data_sp; 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric size_t ObjectFile::GetData(lldb::offset_t offset, size_t length, 4720b57cec5SDimitry Andric DataExtractor &data) const { 4730b57cec5SDimitry Andric // The entire file has already been mmap'ed into m_data, so just copy from 4740b57cec5SDimitry Andric // there as the back mmap buffer will be shared with shared pointers. 4750b57cec5SDimitry Andric return data.SetData(m_data, offset, length); 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric size_t ObjectFile::CopyData(lldb::offset_t offset, size_t length, 4790b57cec5SDimitry Andric void *dst) const { 4800b57cec5SDimitry Andric // The entire file has already been mmap'ed into m_data, so just copy from 4810b57cec5SDimitry Andric // there Note that the data remains in target byte order. 4820b57cec5SDimitry Andric return m_data.CopyData(offset, length, dst); 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric size_t ObjectFile::ReadSectionData(Section *section, 4860b57cec5SDimitry Andric lldb::offset_t section_offset, void *dst, 4870b57cec5SDimitry Andric size_t dst_len) { 4880b57cec5SDimitry Andric assert(section); 4890b57cec5SDimitry Andric section_offset *= section->GetTargetByteSize(); 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric // If some other objectfile owns this data, pass this to them. 4920b57cec5SDimitry Andric if (section->GetObjectFile() != this) 4930b57cec5SDimitry Andric return section->GetObjectFile()->ReadSectionData(section, section_offset, 4940b57cec5SDimitry Andric dst, dst_len); 4950b57cec5SDimitry Andric 496e8d8bef9SDimitry Andric if (!section->IsRelocated()) 497e8d8bef9SDimitry Andric RelocateSection(section); 498e8d8bef9SDimitry Andric 4990b57cec5SDimitry Andric if (IsInMemory()) { 5000b57cec5SDimitry Andric ProcessSP process_sp(m_process_wp.lock()); 5010b57cec5SDimitry Andric if (process_sp) { 5020b57cec5SDimitry Andric Status error; 5030b57cec5SDimitry Andric const addr_t base_load_addr = 5040b57cec5SDimitry Andric section->GetLoadBaseAddress(&process_sp->GetTarget()); 5050b57cec5SDimitry Andric if (base_load_addr != LLDB_INVALID_ADDRESS) 5060b57cec5SDimitry Andric return process_sp->ReadMemory(base_load_addr + section_offset, dst, 5070b57cec5SDimitry Andric dst_len, error); 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric } else { 5100b57cec5SDimitry Andric const lldb::offset_t section_file_size = section->GetFileSize(); 5110b57cec5SDimitry Andric if (section_offset < section_file_size) { 5120b57cec5SDimitry Andric const size_t section_bytes_left = section_file_size - section_offset; 5130b57cec5SDimitry Andric size_t section_dst_len = dst_len; 5140b57cec5SDimitry Andric if (section_dst_len > section_bytes_left) 5150b57cec5SDimitry Andric section_dst_len = section_bytes_left; 5160b57cec5SDimitry Andric return CopyData(section->GetFileOffset() + section_offset, 5170b57cec5SDimitry Andric section_dst_len, dst); 5180b57cec5SDimitry Andric } else { 5190b57cec5SDimitry Andric if (section->GetType() == eSectionTypeZeroFill) { 5200b57cec5SDimitry Andric const uint64_t section_size = section->GetByteSize(); 5210b57cec5SDimitry Andric const uint64_t section_bytes_left = section_size - section_offset; 5220b57cec5SDimitry Andric uint64_t section_dst_len = dst_len; 5230b57cec5SDimitry Andric if (section_dst_len > section_bytes_left) 5240b57cec5SDimitry Andric section_dst_len = section_bytes_left; 5250b57cec5SDimitry Andric memset(dst, 0, section_dst_len); 5260b57cec5SDimitry Andric return section_dst_len; 5270b57cec5SDimitry Andric } 5280b57cec5SDimitry Andric } 5290b57cec5SDimitry Andric } 5300b57cec5SDimitry Andric return 0; 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric // Get the section data the file on disk 5340b57cec5SDimitry Andric size_t ObjectFile::ReadSectionData(Section *section, 5350b57cec5SDimitry Andric DataExtractor §ion_data) { 5360b57cec5SDimitry Andric // If some other objectfile owns this data, pass this to them. 5370b57cec5SDimitry Andric if (section->GetObjectFile() != this) 5380b57cec5SDimitry Andric return section->GetObjectFile()->ReadSectionData(section, section_data); 5390b57cec5SDimitry Andric 540e8d8bef9SDimitry Andric if (!section->IsRelocated()) 541e8d8bef9SDimitry Andric RelocateSection(section); 542e8d8bef9SDimitry Andric 5430b57cec5SDimitry Andric if (IsInMemory()) { 5440b57cec5SDimitry Andric ProcessSP process_sp(m_process_wp.lock()); 5450b57cec5SDimitry Andric if (process_sp) { 5460b57cec5SDimitry Andric const addr_t base_load_addr = 5470b57cec5SDimitry Andric section->GetLoadBaseAddress(&process_sp->GetTarget()); 5480b57cec5SDimitry Andric if (base_load_addr != LLDB_INVALID_ADDRESS) { 5490b57cec5SDimitry Andric DataBufferSP data_sp( 5500b57cec5SDimitry Andric ReadMemory(process_sp, base_load_addr, section->GetByteSize())); 5510b57cec5SDimitry Andric if (data_sp) { 5520b57cec5SDimitry Andric section_data.SetData(data_sp, 0, data_sp->GetByteSize()); 5530b57cec5SDimitry Andric section_data.SetByteOrder(process_sp->GetByteOrder()); 5540b57cec5SDimitry Andric section_data.SetAddressByteSize(process_sp->GetAddressByteSize()); 5550b57cec5SDimitry Andric return section_data.GetByteSize(); 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric } 559e8d8bef9SDimitry Andric } 560e8d8bef9SDimitry Andric 5610b57cec5SDimitry Andric // The object file now contains a full mmap'ed copy of the object file 5620b57cec5SDimitry Andric // data, so just use this 5635f757f3fSDimitry Andric return GetData(section->GetFileOffset(), GetSectionDataSize(section), 5640b57cec5SDimitry Andric section_data); 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric 5679dba64beSDimitry Andric bool ObjectFile::SplitArchivePathWithObject(llvm::StringRef path_with_object, 5680b57cec5SDimitry Andric FileSpec &archive_file, 5690b57cec5SDimitry Andric ConstString &archive_object, 5700b57cec5SDimitry Andric bool must_exist) { 5719dba64beSDimitry Andric size_t len = path_with_object.size(); 5729dba64beSDimitry Andric if (len < 2 || path_with_object.back() != ')') 5730b57cec5SDimitry Andric return false; 5749dba64beSDimitry Andric llvm::StringRef archive = path_with_object.substr(0, path_with_object.rfind('(')); 5759dba64beSDimitry Andric if (archive.empty()) 5769dba64beSDimitry Andric return false; 5779dba64beSDimitry Andric llvm::StringRef object = path_with_object.substr(archive.size() + 1).drop_back(); 5789dba64beSDimitry Andric archive_file.SetFile(archive, FileSpec::Style::native); 5799dba64beSDimitry Andric if (must_exist && !FileSystem::Instance().Exists(archive_file)) 5809dba64beSDimitry Andric return false; 5819dba64beSDimitry Andric archive_object.SetString(object); 5829dba64beSDimitry Andric return true; 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric void ObjectFile::ClearSymtab() { 5860b57cec5SDimitry Andric ModuleSP module_sp(GetModule()); 5870b57cec5SDimitry Andric if (module_sp) { 58881ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Object); 5899dba64beSDimitry Andric LLDB_LOGF(log, "%p ObjectFile::ClearSymtab () symtab = %p", 5900b57cec5SDimitry Andric static_cast<void *>(this), 5910b57cec5SDimitry Andric static_cast<void *>(m_symtab_up.get())); 5924824e7fdSDimitry Andric // Since we need to clear the symbol table, we need a new llvm::once_flag 5934824e7fdSDimitry Andric // instance so we can safely create another symbol table 5944824e7fdSDimitry Andric m_symtab_once_up.reset(new llvm::once_flag()); 5950b57cec5SDimitry Andric m_symtab_up.reset(); 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric SectionList *ObjectFile::GetSectionList(bool update_module_section_list) { 6000b57cec5SDimitry Andric if (m_sections_up == nullptr) { 6010b57cec5SDimitry Andric if (update_module_section_list) { 6020b57cec5SDimitry Andric ModuleSP module_sp(GetModule()); 6030b57cec5SDimitry Andric if (module_sp) { 6040b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); 6050b57cec5SDimitry Andric CreateSections(*module_sp->GetUnifiedSectionList()); 6060b57cec5SDimitry Andric } 6070b57cec5SDimitry Andric } else { 6080b57cec5SDimitry Andric SectionList unified_section_list; 6090b57cec5SDimitry Andric CreateSections(unified_section_list); 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric return m_sections_up.get(); 6130b57cec5SDimitry Andric } 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric lldb::SymbolType 6160b57cec5SDimitry Andric ObjectFile::GetSymbolTypeFromName(llvm::StringRef name, 6170b57cec5SDimitry Andric lldb::SymbolType symbol_type_hint) { 6180b57cec5SDimitry Andric if (!name.empty()) { 6195f757f3fSDimitry Andric if (name.starts_with("_OBJC_")) { 6200b57cec5SDimitry Andric // ObjC 6215f757f3fSDimitry Andric if (name.starts_with("_OBJC_CLASS_$_")) 6220b57cec5SDimitry Andric return lldb::eSymbolTypeObjCClass; 6235f757f3fSDimitry Andric if (name.starts_with("_OBJC_METACLASS_$_")) 6240b57cec5SDimitry Andric return lldb::eSymbolTypeObjCMetaClass; 6255f757f3fSDimitry Andric if (name.starts_with("_OBJC_IVAR_$_")) 6260b57cec5SDimitry Andric return lldb::eSymbolTypeObjCIVar; 6275f757f3fSDimitry Andric } else if (name.starts_with(".objc_class_name_")) { 6280b57cec5SDimitry Andric // ObjC v1 6290b57cec5SDimitry Andric return lldb::eSymbolTypeObjCClass; 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric return symbol_type_hint; 6330b57cec5SDimitry Andric } 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric std::vector<ObjectFile::LoadableData> 6360b57cec5SDimitry Andric ObjectFile::GetLoadableData(Target &target) { 6370b57cec5SDimitry Andric std::vector<LoadableData> loadables; 6380b57cec5SDimitry Andric SectionList *section_list = GetSectionList(); 6390b57cec5SDimitry Andric if (!section_list) 6400b57cec5SDimitry Andric return loadables; 6410b57cec5SDimitry Andric // Create a list of loadable data from loadable sections 6420b57cec5SDimitry Andric size_t section_count = section_list->GetNumSections(0); 6430b57cec5SDimitry Andric for (size_t i = 0; i < section_count; ++i) { 6440b57cec5SDimitry Andric LoadableData loadable; 6450b57cec5SDimitry Andric SectionSP section_sp = section_list->GetSectionAtIndex(i); 6460b57cec5SDimitry Andric loadable.Dest = 6470b57cec5SDimitry Andric target.GetSectionLoadList().GetSectionLoadAddress(section_sp); 6480b57cec5SDimitry Andric if (loadable.Dest == LLDB_INVALID_ADDRESS) 6490b57cec5SDimitry Andric continue; 6500b57cec5SDimitry Andric // We can skip sections like bss 6510b57cec5SDimitry Andric if (section_sp->GetFileSize() == 0) 6520b57cec5SDimitry Andric continue; 6530b57cec5SDimitry Andric DataExtractor section_data; 6540b57cec5SDimitry Andric section_sp->GetSectionData(section_data); 6550b57cec5SDimitry Andric loadable.Contents = llvm::ArrayRef<uint8_t>(section_data.GetDataStart(), 6560b57cec5SDimitry Andric section_data.GetByteSize()); 6570b57cec5SDimitry Andric loadables.push_back(loadable); 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric return loadables; 6600b57cec5SDimitry Andric } 6610b57cec5SDimitry Andric 6629dba64beSDimitry Andric std::unique_ptr<CallFrameInfo> ObjectFile::CreateCallFrameInfo() { 6639dba64beSDimitry Andric return {}; 6649dba64beSDimitry Andric } 6659dba64beSDimitry Andric 6660b57cec5SDimitry Andric void ObjectFile::RelocateSection(lldb_private::Section *section) 6670b57cec5SDimitry Andric { 6680b57cec5SDimitry Andric } 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric DataBufferSP ObjectFile::MapFileData(const FileSpec &file, uint64_t Size, 6710b57cec5SDimitry Andric uint64_t Offset) { 6720b57cec5SDimitry Andric return FileSystem::Instance().CreateDataBuffer(file.GetPath(), Size, Offset); 6730b57cec5SDimitry Andric } 6740b57cec5SDimitry Andric 6750b57cec5SDimitry Andric void llvm::format_provider<ObjectFile::Type>::format( 6760b57cec5SDimitry Andric const ObjectFile::Type &type, raw_ostream &OS, StringRef Style) { 6770b57cec5SDimitry Andric switch (type) { 6780b57cec5SDimitry Andric case ObjectFile::eTypeInvalid: 6790b57cec5SDimitry Andric OS << "invalid"; 6800b57cec5SDimitry Andric break; 6810b57cec5SDimitry Andric case ObjectFile::eTypeCoreFile: 6820b57cec5SDimitry Andric OS << "core file"; 6830b57cec5SDimitry Andric break; 6840b57cec5SDimitry Andric case ObjectFile::eTypeExecutable: 6850b57cec5SDimitry Andric OS << "executable"; 6860b57cec5SDimitry Andric break; 6870b57cec5SDimitry Andric case ObjectFile::eTypeDebugInfo: 6880b57cec5SDimitry Andric OS << "debug info"; 6890b57cec5SDimitry Andric break; 6900b57cec5SDimitry Andric case ObjectFile::eTypeDynamicLinker: 6910b57cec5SDimitry Andric OS << "dynamic linker"; 6920b57cec5SDimitry Andric break; 6930b57cec5SDimitry Andric case ObjectFile::eTypeObjectFile: 6940b57cec5SDimitry Andric OS << "object file"; 6950b57cec5SDimitry Andric break; 6960b57cec5SDimitry Andric case ObjectFile::eTypeSharedLibrary: 6970b57cec5SDimitry Andric OS << "shared library"; 6980b57cec5SDimitry Andric break; 6990b57cec5SDimitry Andric case ObjectFile::eTypeStubLibrary: 7000b57cec5SDimitry Andric OS << "stub library"; 7010b57cec5SDimitry Andric break; 7020b57cec5SDimitry Andric case ObjectFile::eTypeJIT: 7030b57cec5SDimitry Andric OS << "jit"; 7040b57cec5SDimitry Andric break; 7050b57cec5SDimitry Andric case ObjectFile::eTypeUnknown: 7060b57cec5SDimitry Andric OS << "unknown"; 7070b57cec5SDimitry Andric break; 7080b57cec5SDimitry Andric } 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric void llvm::format_provider<ObjectFile::Strata>::format( 7120b57cec5SDimitry Andric const ObjectFile::Strata &strata, raw_ostream &OS, StringRef Style) { 7130b57cec5SDimitry Andric switch (strata) { 7140b57cec5SDimitry Andric case ObjectFile::eStrataInvalid: 7150b57cec5SDimitry Andric OS << "invalid"; 7160b57cec5SDimitry Andric break; 7170b57cec5SDimitry Andric case ObjectFile::eStrataUnknown: 7180b57cec5SDimitry Andric OS << "unknown"; 7190b57cec5SDimitry Andric break; 7200b57cec5SDimitry Andric case ObjectFile::eStrataUser: 7210b57cec5SDimitry Andric OS << "user"; 7220b57cec5SDimitry Andric break; 7230b57cec5SDimitry Andric case ObjectFile::eStrataKernel: 7240b57cec5SDimitry Andric OS << "kernel"; 7250b57cec5SDimitry Andric break; 7260b57cec5SDimitry Andric case ObjectFile::eStrataRawImage: 7270b57cec5SDimitry Andric OS << "raw image"; 7280b57cec5SDimitry Andric break; 7290b57cec5SDimitry Andric case ObjectFile::eStrataJIT: 7300b57cec5SDimitry Andric OS << "jit"; 7310b57cec5SDimitry Andric break; 7320b57cec5SDimitry Andric } 7330b57cec5SDimitry Andric } 7344824e7fdSDimitry Andric 7354824e7fdSDimitry Andric 7364824e7fdSDimitry Andric Symtab *ObjectFile::GetSymtab() { 7374824e7fdSDimitry Andric ModuleSP module_sp(GetModule()); 7384824e7fdSDimitry Andric if (module_sp) { 7394824e7fdSDimitry Andric // We can't take the module lock in ObjectFile::GetSymtab() or we can 7404824e7fdSDimitry Andric // deadlock in DWARF indexing when any file asks for the symbol table from 7414824e7fdSDimitry Andric // an object file. This currently happens in the preloading of symbols in 7424824e7fdSDimitry Andric // SymbolFileDWARF::PreloadSymbols() because the main thread will take the 7434824e7fdSDimitry Andric // module lock, and then threads will be spun up to index the DWARF and 7444824e7fdSDimitry Andric // any of those threads might end up trying to relocate items in the DWARF 7454824e7fdSDimitry Andric // sections which causes ObjectFile::GetSectionData(...) to relocate section 7464824e7fdSDimitry Andric // data which requires the symbol table. 7474824e7fdSDimitry Andric // 7484824e7fdSDimitry Andric // So to work around this, we create the symbol table one time using 7494824e7fdSDimitry Andric // llvm::once_flag, lock it, and then set the unique pointer. Any other 7504824e7fdSDimitry Andric // thread that gets ahold of the symbol table before parsing is done, will 7514824e7fdSDimitry Andric // not be able to access the symbol table contents since all APIs in Symtab 7524824e7fdSDimitry Andric // are protected by a mutex in the Symtab object itself. 7534824e7fdSDimitry Andric llvm::call_once(*m_symtab_once_up, [&]() { 7544824e7fdSDimitry Andric Symtab *symtab = new Symtab(this); 7554824e7fdSDimitry Andric std::lock_guard<std::recursive_mutex> symtab_guard(symtab->GetMutex()); 7564824e7fdSDimitry Andric m_symtab_up.reset(symtab); 7570eae32dcSDimitry Andric if (!m_symtab_up->LoadFromCache()) { 7580eae32dcSDimitry Andric ElapsedTime elapsed(module_sp->GetSymtabParseTime()); 7594824e7fdSDimitry Andric ParseSymtab(*m_symtab_up); 7604824e7fdSDimitry Andric m_symtab_up->Finalize(); 7610eae32dcSDimitry Andric } 7624824e7fdSDimitry Andric }); 7634824e7fdSDimitry Andric } 7644824e7fdSDimitry Andric return m_symtab_up.get(); 7654824e7fdSDimitry Andric } 7660eae32dcSDimitry Andric 7670eae32dcSDimitry Andric uint32_t ObjectFile::GetCacheHash() { 7680eae32dcSDimitry Andric if (m_cache_hash) 7690eae32dcSDimitry Andric return *m_cache_hash; 7700eae32dcSDimitry Andric StreamString strm; 7710eae32dcSDimitry Andric strm.Format("{0}-{1}-{2}", m_file, GetType(), GetStrata()); 7720eae32dcSDimitry Andric m_cache_hash = llvm::djbHash(strm.GetString()); 7730eae32dcSDimitry Andric return *m_cache_hash; 7740eae32dcSDimitry Andric } 77506c3fb27SDimitry Andric 77606c3fb27SDimitry Andric namespace llvm { 77706c3fb27SDimitry Andric namespace json { 77806c3fb27SDimitry Andric 77906c3fb27SDimitry Andric bool fromJSON(const llvm::json::Value &value, 78006c3fb27SDimitry Andric lldb_private::ObjectFile::Type &type, llvm::json::Path path) { 78106c3fb27SDimitry Andric if (auto str = value.getAsString()) { 78206c3fb27SDimitry Andric type = llvm::StringSwitch<ObjectFile::Type>(*str) 78306c3fb27SDimitry Andric .Case("corefile", ObjectFile::eTypeCoreFile) 78406c3fb27SDimitry Andric .Case("executable", ObjectFile::eTypeExecutable) 78506c3fb27SDimitry Andric .Case("debuginfo", ObjectFile::eTypeDebugInfo) 78606c3fb27SDimitry Andric .Case("dynamiclinker", ObjectFile::eTypeDynamicLinker) 78706c3fb27SDimitry Andric .Case("objectfile", ObjectFile::eTypeObjectFile) 78806c3fb27SDimitry Andric .Case("sharedlibrary", ObjectFile::eTypeSharedLibrary) 78906c3fb27SDimitry Andric .Case("stublibrary", ObjectFile::eTypeStubLibrary) 79006c3fb27SDimitry Andric .Case("jit", ObjectFile::eTypeJIT) 79106c3fb27SDimitry Andric .Case("unknown", ObjectFile::eTypeUnknown) 79206c3fb27SDimitry Andric .Default(ObjectFile::eTypeInvalid); 79306c3fb27SDimitry Andric 79406c3fb27SDimitry Andric if (type == ObjectFile::eTypeInvalid) { 79506c3fb27SDimitry Andric path.report("invalid object type"); 79606c3fb27SDimitry Andric return false; 79706c3fb27SDimitry Andric } 79806c3fb27SDimitry Andric 79906c3fb27SDimitry Andric return true; 80006c3fb27SDimitry Andric } 80106c3fb27SDimitry Andric path.report("expected string"); 80206c3fb27SDimitry Andric return false; 80306c3fb27SDimitry Andric } 80406c3fb27SDimitry Andric } // namespace json 80506c3fb27SDimitry Andric } // namespace llvm 806