brintos

brintos / llvm-project-archived public Read only

0
0
Text · 32.0 KiB · 6f5348c Raw
852 lines · cpp
1//===-- ObjectFile.cpp ----------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Symbol/ObjectFile.h"10#include "lldb/Core/Module.h"11#include "lldb/Core/ModuleSpec.h"12#include "lldb/Core/PluginManager.h"13#include "lldb/Core/Section.h"14#include "lldb/Symbol/CallFrameInfo.h"15#include "lldb/Symbol/ObjectContainer.h"16#include "lldb/Symbol/SymbolFile.h"17#include "lldb/Target/Process.h"18#include "lldb/Target/SectionLoadList.h"19#include "lldb/Target/Target.h"20#include "lldb/Utility/DataBuffer.h"21#include "lldb/Utility/DataBufferHeap.h"22#include "lldb/Utility/LLDBLog.h"23#include "lldb/Utility/Log.h"24#include "lldb/Utility/Timer.h"25#include "lldb/lldb-private.h"26 27#include "llvm/Support/DJB.h"28 29using namespace lldb;30using namespace lldb_private;31 32char ObjectFile::ID;33size_t ObjectFile::g_initial_bytes_to_read = 512;34 35static ObjectFileSP36CreateObjectFromContainer(const lldb::ModuleSP &module_sp, const FileSpec *file,37                          lldb::offset_t file_offset, lldb::offset_t file_size,38                          DataBufferSP data_sp, lldb::offset_t &data_offset) {39  ObjectContainerCreateInstance callback;40  for (uint32_t idx = 0;41       (callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(42            idx)) != nullptr;43       ++idx) {44    std::unique_ptr<ObjectContainer> object_container_up(callback(45        module_sp, data_sp, data_offset, file, file_offset, file_size));46    if (object_container_up)47      return object_container_up->GetObjectFile(file);48  }49  return {};50}51 52ObjectFileSP53ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,54                       lldb::offset_t file_offset, lldb::offset_t file_size,55                       DataBufferSP &data_sp, lldb::offset_t &data_offset) {56  LLDB_SCOPED_TIMERF(57      "ObjectFile::FindPlugin (module = %s, file = %p, file_offset = "58      "0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")",59      module_sp->GetFileSpec().GetPath().c_str(),60      static_cast<const void *>(file), static_cast<uint64_t>(file_offset),61      static_cast<uint64_t>(file_size));62 63  if (!module_sp)64    return {};65 66  if (!file)67    return {};68 69  if (!data_sp) {70    const bool file_exists = FileSystem::Instance().Exists(*file);71    // We have an object name which most likely means we have a .o file in72    // a static archive (.a file). Try and see if we have a cached archive73    // first without reading any data first74    if (file_exists && module_sp->GetObjectName()) {75      ObjectFileSP object_file_sp = CreateObjectFromContainer(76          module_sp, file, file_offset, file_size, data_sp, data_offset);77      if (object_file_sp)78        return object_file_sp;79    }80    // Ok, we didn't find any containers that have a named object, now lets81    // read the first 512 bytes from the file so the object file and object82    // container plug-ins can use these bytes to see if they can parse this83    // file.84    if (file_size > 0) {85      data_sp = FileSystem::Instance().CreateDataBuffer(86          file->GetPath(), g_initial_bytes_to_read, file_offset);87      data_offset = 0;88    }89  }90 91  if (!data_sp || data_sp->GetByteSize() == 0) {92    // Check for archive file with format "/path/to/archive.a(object.o)"93    llvm::SmallString<256> path_with_object;94    module_sp->GetFileSpec().GetPath(path_with_object);95 96    FileSpec archive_file;97    ConstString archive_object;98    const bool must_exist = true;99    if (ObjectFile::SplitArchivePathWithObject(path_with_object, archive_file,100                                               archive_object, must_exist)) {101      file_size = FileSystem::Instance().GetByteSize(archive_file);102      if (file_size > 0) {103        file = &archive_file;104        module_sp->SetFileSpecAndObjectName(archive_file, archive_object);105        // Check if this is a object container by iterating through all106        // object container plugin instances and then trying to get an107        // object file from the container plugins since we had a name.108        // Also, don't read109        // ANY data in case there is data cached in the container plug-ins110        // (like BSD archives caching the contained objects within an111        // file).112        ObjectFileSP object_file_sp = CreateObjectFromContainer(113            module_sp, file, file_offset, file_size, data_sp, data_offset);114        if (object_file_sp)115          return object_file_sp;116        // We failed to find any cached object files in the container plug-117        // ins, so lets read the first 512 bytes and try again below...118        data_sp = FileSystem::Instance().CreateDataBuffer(119            archive_file.GetPath(), g_initial_bytes_to_read, file_offset);120      }121    }122  }123 124  if (data_sp && data_sp->GetByteSize() > 0) {125    // Check if this is a normal object file by iterating through all126    // object file plugin instances.127    ObjectFileCreateInstance callback;128    for (uint32_t idx = 0;129         (callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) !=130         nullptr;131         ++idx) {132      ObjectFileSP object_file_sp(callback(module_sp, data_sp, data_offset,133                                           file, file_offset, file_size));134      if (object_file_sp.get())135        return object_file_sp;136    }137 138    // Check if this is a object container by iterating through all object139    // container plugin instances and then trying to get an object file140    // from the container.141    ObjectFileSP object_file_sp = CreateObjectFromContainer(142        module_sp, file, file_offset, file_size, data_sp, data_offset);143    if (object_file_sp)144      return object_file_sp;145  }146 147  // We didn't find it, so clear our shared pointer in case it contains148  // anything and return an empty shared pointer149  return {};150}151 152ObjectFileSP ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp,153                                    const ProcessSP &process_sp,154                                    lldb::addr_t header_addr,155                                    WritableDataBufferSP data_sp) {156  ObjectFileSP object_file_sp;157 158  if (module_sp) {159    LLDB_SCOPED_TIMERF("ObjectFile::FindPlugin (module = "160                       "%s, process = %p, header_addr = "161                       "0x%" PRIx64 ")",162                       module_sp->GetFileSpec().GetPath().c_str(),163                       static_cast<void *>(process_sp.get()), header_addr);164    uint32_t idx;165 166    // Check if this is a normal object file by iterating through all object167    // file plugin instances.168    ObjectFileCreateMemoryInstance create_callback;169    for (idx = 0;170         (create_callback =171              PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(idx)) !=172         nullptr;173         ++idx) {174      object_file_sp.reset(175          create_callback(module_sp, data_sp, process_sp, header_addr));176      if (object_file_sp.get())177        return object_file_sp;178    }179  }180 181  // We didn't find it, so clear our shared pointer in case it contains182  // anything and return an empty shared pointer183  object_file_sp.reset();184  return object_file_sp;185}186 187bool ObjectFile::IsObjectFile(lldb_private::FileSpec file_spec) {188  DataBufferSP data_sp;189  offset_t data_offset = 0;190  ModuleSP module_sp = std::make_shared<Module>(file_spec);191  return static_cast<bool>(ObjectFile::FindPlugin(192      module_sp, &file_spec, 0, FileSystem::Instance().GetByteSize(file_spec),193      data_sp, data_offset));194}195 196size_t ObjectFile::GetModuleSpecifications(const FileSpec &file,197                                           lldb::offset_t file_offset,198                                           lldb::offset_t file_size,199                                           ModuleSpecList &specs,200                                           DataBufferSP data_sp) {201  if (!data_sp)202    data_sp = FileSystem::Instance().CreateDataBuffer(203        file.GetPath(), g_initial_bytes_to_read, file_offset);204  if (data_sp) {205    if (file_size == 0) {206      const lldb::offset_t actual_file_size =207          FileSystem::Instance().GetByteSize(file);208      if (actual_file_size > file_offset)209        file_size = actual_file_size - file_offset;210    }211    return ObjectFile::GetModuleSpecifications(file,        // file spec212                                               data_sp,     // data bytes213                                               0,           // data offset214                                               file_offset, // file offset215                                               file_size,   // file length216                                               specs);217  }218  return 0;219}220 221size_t ObjectFile::GetModuleSpecifications(222    const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,223    lldb::offset_t data_offset, lldb::offset_t file_offset,224    lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) {225  const size_t initial_count = specs.GetSize();226  ObjectFileGetModuleSpecifications callback;227  uint32_t i;228  // Try the ObjectFile plug-ins229  for (i = 0;230       (callback =231            PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex(232                i)) != nullptr;233       ++i) {234    if (callback(file, data_sp, data_offset, file_offset, file_size, specs) > 0)235      return specs.GetSize() - initial_count;236  }237 238  // Try the ObjectContainer plug-ins239  for (i = 0;240       (callback = PluginManager::241            GetObjectContainerGetModuleSpecificationsCallbackAtIndex(i)) !=242       nullptr;243       ++i) {244    if (callback(file, data_sp, data_offset, file_offset, file_size, specs) > 0)245      return specs.GetSize() - initial_count;246  }247  return 0;248}249 250ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp,251                       const FileSpec *file_spec_ptr,252                       lldb::offset_t file_offset, lldb::offset_t length,253                       lldb::DataBufferSP data_sp, lldb::offset_t data_offset)254    : ModuleChild(module_sp),255      m_file(), // This file could be different from the original module's file256      m_type(eTypeInvalid), m_strata(eStrataInvalid),257      m_file_offset(file_offset), m_length(length), m_data(), m_process_wp(),258      m_memory_addr(LLDB_INVALID_ADDRESS), m_sections_up(), m_symtab_up(),259      m_symtab_once_up(new llvm::once_flag()) {260  if (file_spec_ptr)261    m_file = *file_spec_ptr;262  if (data_sp)263    m_data.SetData(data_sp, data_offset, length);264  Log *log = GetLog(LLDBLog::Object);265  LLDB_LOGF(log,266            "%p ObjectFile::ObjectFile() module = %p (%s), file = %s, "267            "file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64,268            static_cast<void *>(this), static_cast<void *>(module_sp.get()),269            module_sp->GetSpecificationDescription().c_str(),270            m_file ? m_file.GetPath().c_str() : "<NULL>", m_file_offset,271            m_length);272}273 274ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp,275                       const ProcessSP &process_sp, lldb::addr_t header_addr,276                       DataBufferSP header_data_sp)277    : ModuleChild(module_sp), m_file(), m_type(eTypeInvalid),278      m_strata(eStrataInvalid), m_file_offset(0), m_length(0), m_data(),279      m_process_wp(process_sp), m_memory_addr(header_addr), m_sections_up(),280      m_symtab_up(), m_symtab_once_up(new llvm::once_flag()) {281  if (header_data_sp)282    m_data.SetData(header_data_sp, 0, header_data_sp->GetByteSize());283  Log *log = GetLog(LLDBLog::Object);284  LLDB_LOGF(log,285            "%p ObjectFile::ObjectFile() module = %p (%s), process = %p, "286            "header_addr = 0x%" PRIx64,287            static_cast<void *>(this), static_cast<void *>(module_sp.get()),288            module_sp->GetSpecificationDescription().c_str(),289            static_cast<void *>(process_sp.get()), m_memory_addr);290}291 292ObjectFile::~ObjectFile() {293  Log *log = GetLog(LLDBLog::Object);294  LLDB_LOGF(log, "%p ObjectFile::~ObjectFile ()\n", static_cast<void *>(this));295}296 297bool ObjectFile::SetModulesArchitecture(const ArchSpec &new_arch) {298  ModuleSP module_sp(GetModule());299  if (module_sp)300    return module_sp->SetArchitecture(new_arch);301  return false;302}303 304AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {305  Symtab *symtab = GetSymtab();306  if (symtab) {307    Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr);308    if (symbol) {309      if (symbol->ValueIsAddress()) {310        const SectionSP section_sp(symbol->GetAddressRef().GetSection());311        if (section_sp) {312          const SectionType section_type = section_sp->GetType();313          switch (section_type) {314          case eSectionTypeInvalid:315            return AddressClass::eUnknown;316          case eSectionTypeCode:317            return AddressClass::eCode;318          case eSectionTypeContainer:319            return AddressClass::eUnknown;320          case eSectionTypeData:321          case eSectionTypeDataCString:322          case eSectionTypeDataCStringPointers:323          case eSectionTypeDataSymbolAddress:324          case eSectionTypeData4:325          case eSectionTypeData8:326          case eSectionTypeData16:327          case eSectionTypeDataPointers:328          case eSectionTypeZeroFill:329          case eSectionTypeDataObjCMessageRefs:330          case eSectionTypeDataObjCCFStrings:331          case eSectionTypeGoSymtab:332            return AddressClass::eData;333          case eSectionTypeDebug:334          case eSectionTypeDWARFDebugAbbrev:335          case eSectionTypeDWARFDebugAbbrevDwo:336          case eSectionTypeDWARFDebugAddr:337          case eSectionTypeDWARFDebugAranges:338          case eSectionTypeDWARFDebugCuIndex:339          case eSectionTypeDWARFDebugFrame:340          case eSectionTypeDWARFDebugInfo:341          case eSectionTypeDWARFDebugInfoDwo:342          case eSectionTypeDWARFDebugLine:343          case eSectionTypeDWARFDebugLineStr:344          case eSectionTypeDWARFDebugLoc:345          case eSectionTypeDWARFDebugLocDwo:346          case eSectionTypeDWARFDebugLocLists:347          case eSectionTypeDWARFDebugLocListsDwo:348          case eSectionTypeDWARFDebugMacInfo:349          case eSectionTypeDWARFDebugMacro:350          case eSectionTypeDWARFDebugNames:351          case eSectionTypeDWARFDebugPubNames:352          case eSectionTypeDWARFDebugPubTypes:353          case eSectionTypeDWARFDebugRanges:354          case eSectionTypeDWARFDebugRngLists:355          case eSectionTypeDWARFDebugRngListsDwo:356          case eSectionTypeDWARFDebugStr:357          case eSectionTypeDWARFDebugStrDwo:358          case eSectionTypeDWARFDebugStrOffsets:359          case eSectionTypeDWARFDebugStrOffsetsDwo:360          case eSectionTypeDWARFDebugTuIndex:361          case eSectionTypeDWARFDebugTypes:362          case eSectionTypeDWARFDebugTypesDwo:363          case eSectionTypeDWARFAppleNames:364          case eSectionTypeDWARFAppleTypes:365          case eSectionTypeDWARFAppleNamespaces:366          case eSectionTypeDWARFAppleObjC:367          case eSectionTypeDWARFGNUDebugAltLink:368          case eSectionTypeCTF:369          case eSectionTypeLLDBFormatters:370          case eSectionTypeLLDBTypeSummaries:371          case eSectionTypeSwiftModules:372            return AddressClass::eDebug;373          case eSectionTypeEHFrame:374          case eSectionTypeARMexidx:375          case eSectionTypeARMextab:376          case eSectionTypeCompactUnwind:377            return AddressClass::eRuntime;378          case eSectionTypeELFSymbolTable:379          case eSectionTypeELFDynamicSymbols:380          case eSectionTypeELFRelocationEntries:381          case eSectionTypeELFDynamicLinkInfo:382          case eSectionTypeWasmName:383          case eSectionTypeOther:384            return AddressClass::eUnknown;385          case eSectionTypeAbsoluteAddress:386            // In case of absolute sections decide the address class based on387            // the symbol type because the section type isn't specify if it is388            // a code or a data section.389            break;390          }391        }392      }393 394      const SymbolType symbol_type = symbol->GetType();395      switch (symbol_type) {396      case eSymbolTypeAny:397        return AddressClass::eUnknown;398      case eSymbolTypeAbsolute:399        return AddressClass::eUnknown;400      case eSymbolTypeCode:401        return AddressClass::eCode;402      case eSymbolTypeTrampoline:403        return AddressClass::eCode;404      case eSymbolTypeResolver:405        return AddressClass::eCode;406      case eSymbolTypeData:407        return AddressClass::eData;408      case eSymbolTypeRuntime:409        return AddressClass::eRuntime;410      case eSymbolTypeException:411        return AddressClass::eRuntime;412      case eSymbolTypeSourceFile:413        return AddressClass::eDebug;414      case eSymbolTypeHeaderFile:415        return AddressClass::eDebug;416      case eSymbolTypeObjectFile:417        return AddressClass::eDebug;418      case eSymbolTypeCommonBlock:419        return AddressClass::eDebug;420      case eSymbolTypeBlock:421        return AddressClass::eDebug;422      case eSymbolTypeLocal:423        return AddressClass::eData;424      case eSymbolTypeParam:425        return AddressClass::eData;426      case eSymbolTypeVariable:427        return AddressClass::eData;428      case eSymbolTypeVariableType:429        return AddressClass::eDebug;430      case eSymbolTypeLineEntry:431        return AddressClass::eDebug;432      case eSymbolTypeLineHeader:433        return AddressClass::eDebug;434      case eSymbolTypeScopeBegin:435        return AddressClass::eDebug;436      case eSymbolTypeScopeEnd:437        return AddressClass::eDebug;438      case eSymbolTypeAdditional:439        return AddressClass::eUnknown;440      case eSymbolTypeCompiler:441        return AddressClass::eDebug;442      case eSymbolTypeInstrumentation:443        return AddressClass::eDebug;444      case eSymbolTypeUndefined:445        return AddressClass::eUnknown;446      case eSymbolTypeObjCClass:447        return AddressClass::eRuntime;448      case eSymbolTypeObjCMetaClass:449        return AddressClass::eRuntime;450      case eSymbolTypeObjCIVar:451        return AddressClass::eRuntime;452      case eSymbolTypeReExported:453        return AddressClass::eRuntime;454      }455    }456  }457  return AddressClass::eUnknown;458}459 460WritableDataBufferSP ObjectFile::ReadMemory(const ProcessSP &process_sp,461                                            lldb::addr_t addr,462                                            size_t byte_size) {463  WritableDataBufferSP data_sp;464  if (process_sp) {465    std::unique_ptr<DataBufferHeap> data_up(new DataBufferHeap(byte_size, 0));466    Status error;467    const size_t bytes_read = process_sp->ReadMemory(468        addr, data_up->GetBytes(), data_up->GetByteSize(), error);469    if (bytes_read == byte_size)470      data_sp.reset(data_up.release());471  }472  return data_sp;473}474 475size_t ObjectFile::GetData(lldb::offset_t offset, size_t length,476                           DataExtractor &data) const {477  // The entire file has already been mmap'ed into m_data, so just copy from478  // there as the back mmap buffer will be shared with shared pointers.479  return data.SetData(m_data, offset, length);480}481 482size_t ObjectFile::CopyData(lldb::offset_t offset, size_t length,483                            void *dst) const {484  // The entire file has already been mmap'ed into m_data, so just copy from485  // there Note that the data remains in target byte order.486  return m_data.CopyData(offset, length, dst);487}488 489size_t ObjectFile::ReadSectionData(Section *section,490                                   lldb::offset_t section_offset, void *dst,491                                   size_t dst_len) {492  assert(section);493  section_offset *= section->GetTargetByteSize();494 495  // If some other objectfile owns this data, pass this to them.496  if (section->GetObjectFile() != this)497    return section->GetObjectFile()->ReadSectionData(section, section_offset,498                                                     dst, dst_len);499 500  if (!section->IsRelocated())501    RelocateSection(section);502 503  if (IsInMemory()) {504    ProcessSP process_sp(m_process_wp.lock());505    if (process_sp) {506      Status error;507      const addr_t base_load_addr =508          section->GetLoadBaseAddress(&process_sp->GetTarget());509      if (base_load_addr != LLDB_INVALID_ADDRESS)510        return process_sp->ReadMemory(base_load_addr + section_offset, dst,511                                      dst_len, error);512    }513  } else {514    const lldb::offset_t section_file_size = section->GetFileSize();515    if (section_offset < section_file_size) {516      const size_t section_bytes_left = section_file_size - section_offset;517      size_t section_dst_len = dst_len;518      if (section_dst_len > section_bytes_left)519        section_dst_len = section_bytes_left;520      return CopyData(section->GetFileOffset() + section_offset,521                      section_dst_len, dst);522    } else {523      if (section->GetType() == eSectionTypeZeroFill) {524        const uint64_t section_size = section->GetByteSize();525        const uint64_t section_bytes_left = section_size - section_offset;526        uint64_t section_dst_len = dst_len;527        if (section_dst_len > section_bytes_left)528          section_dst_len = section_bytes_left;529        memset(dst, 0, section_dst_len);530        return section_dst_len;531      }532    }533  }534  return 0;535}536 537// Get the section data the file on disk538size_t ObjectFile::ReadSectionData(Section *section,539                                   DataExtractor &section_data) {540  // If some other objectfile owns this data, pass this to them.541  if (section->GetObjectFile() != this)542    return section->GetObjectFile()->ReadSectionData(section, section_data);543 544  if (!section->IsRelocated())545    RelocateSection(section);546 547  if (IsInMemory()) {548    ProcessSP process_sp(m_process_wp.lock());549    if (process_sp) {550      const addr_t base_load_addr =551          section->GetLoadBaseAddress(&process_sp->GetTarget());552      if (base_load_addr != LLDB_INVALID_ADDRESS) {553        DataBufferSP data_sp(554            ReadMemory(process_sp, base_load_addr, section->GetByteSize()));555        if (data_sp) {556          section_data.SetData(data_sp, 0, data_sp->GetByteSize());557          section_data.SetByteOrder(process_sp->GetByteOrder());558          section_data.SetAddressByteSize(process_sp->GetAddressByteSize());559          return section_data.GetByteSize();560        }561      }562    }563  }564 565  // The object file now contains a full mmap'ed copy of the object file566  // data, so just use this567  return GetData(section->GetFileOffset(), GetSectionDataSize(section),568                 section_data);569}570 571bool ObjectFile::SplitArchivePathWithObject(llvm::StringRef path_with_object,572                                            FileSpec &archive_file,573                                            ConstString &archive_object,574                                            bool must_exist) {575  size_t len = path_with_object.size();576  if (len < 2 || path_with_object.back() != ')')577    return false;578  llvm::StringRef archive = path_with_object.substr(0, path_with_object.rfind('('));579  if (archive.empty())580    return false;581  llvm::StringRef object = path_with_object.substr(archive.size() + 1).drop_back();582  archive_file.SetFile(archive, FileSpec::Style::native);583  if (must_exist && !FileSystem::Instance().Exists(archive_file))584    return false;585  archive_object.SetString(object);586  return true;587}588 589void ObjectFile::ClearSymtab() {590  ModuleSP module_sp(GetModule());591  if (module_sp) {592    Log *log = GetLog(LLDBLog::Object);593    LLDB_LOGF(log, "%p ObjectFile::ClearSymtab () symtab = %p",594              static_cast<void *>(this),595              static_cast<void *>(m_symtab_up.get()));596    // Since we need to clear the symbol table, we need a new llvm::once_flag597    // instance so we can safely create another symbol table598    m_symtab_once_up.reset(new llvm::once_flag());599    m_symtab_up.reset();600  }601}602 603SectionList *ObjectFile::GetSectionList(bool update_module_section_list) {604  if (m_sections_up == nullptr) {605    if (update_module_section_list) {606      ModuleSP module_sp(GetModule());607      if (module_sp) {608        std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());609        CreateSections(*module_sp->GetUnifiedSectionList());610      }611    } else {612      SectionList unified_section_list;613      CreateSections(unified_section_list);614    }615  }616  return m_sections_up.get();617}618 619lldb::SymbolType620ObjectFile::GetSymbolTypeFromName(llvm::StringRef name,621                                  lldb::SymbolType symbol_type_hint) {622  if (!name.empty()) {623    if (name.starts_with("_OBJC_")) {624      // ObjC625      if (name.starts_with("_OBJC_CLASS_$_"))626        return lldb::eSymbolTypeObjCClass;627      if (name.starts_with("_OBJC_METACLASS_$_"))628        return lldb::eSymbolTypeObjCMetaClass;629      if (name.starts_with("_OBJC_IVAR_$_"))630        return lldb::eSymbolTypeObjCIVar;631    } else if (name.starts_with(".objc_class_name_")) {632      // ObjC v1633      return lldb::eSymbolTypeObjCClass;634    }635  }636  return symbol_type_hint;637}638 639lldb::SectionType640ObjectFile::GetDWARFSectionTypeFromName(llvm::StringRef name) {641  return llvm::StringSwitch<SectionType>(name)642      .Case("abbrev", eSectionTypeDWARFDebugAbbrev)643      .Case("abbrev.dwo", eSectionTypeDWARFDebugAbbrevDwo)644      .Case("addr", eSectionTypeDWARFDebugAddr)645      .Case("aranges", eSectionTypeDWARFDebugAranges)646      .Case("cu_index", eSectionTypeDWARFDebugCuIndex)647      .Case("frame", eSectionTypeDWARFDebugFrame)648      .Case("info", eSectionTypeDWARFDebugInfo)649      .Case("info.dwo", eSectionTypeDWARFDebugInfoDwo)650      .Cases({"line", "line.dwo"}, eSectionTypeDWARFDebugLine)651      .Cases({"line_str", "line_str.dwo"}, eSectionTypeDWARFDebugLineStr)652      .Case("loc", eSectionTypeDWARFDebugLoc)653      .Case("loc.dwo", eSectionTypeDWARFDebugLocDwo)654      .Case("loclists", eSectionTypeDWARFDebugLocLists)655      .Case("loclists.dwo", eSectionTypeDWARFDebugLocListsDwo)656      .Case("macinfo", eSectionTypeDWARFDebugMacInfo)657      .Cases({"macro", "macro.dwo"}, eSectionTypeDWARFDebugMacro)658      .Case("names", eSectionTypeDWARFDebugNames)659      .Case("pubnames", eSectionTypeDWARFDebugPubNames)660      .Case("pubtypes", eSectionTypeDWARFDebugPubTypes)661      .Case("ranges", eSectionTypeDWARFDebugRanges)662      .Case("rnglists", eSectionTypeDWARFDebugRngLists)663      .Case("rnglists.dwo", eSectionTypeDWARFDebugRngListsDwo)664      .Case("str", eSectionTypeDWARFDebugStr)665      .Case("str.dwo", eSectionTypeDWARFDebugStrDwo)666      .Cases({"str_offsets", "str_offs"}, eSectionTypeDWARFDebugStrOffsets)667      .Case("str_offsets.dwo", eSectionTypeDWARFDebugStrOffsetsDwo)668      .Case("tu_index", eSectionTypeDWARFDebugTuIndex)669      .Case("types", eSectionTypeDWARFDebugTypes)670      .Case("types.dwo", eSectionTypeDWARFDebugTypesDwo)671      .Default(eSectionTypeOther);672}673 674std::vector<ObjectFile::LoadableData>675ObjectFile::GetLoadableData(Target &target) {676  std::vector<LoadableData> loadables;677  SectionList *section_list = GetSectionList();678  if (!section_list)679    return loadables;680  // Create a list of loadable data from loadable sections681  size_t section_count = section_list->GetNumSections(0);682  for (size_t i = 0; i < section_count; ++i) {683    LoadableData loadable;684    SectionSP section_sp = section_list->GetSectionAtIndex(i);685    loadable.Dest = target.GetSectionLoadAddress(section_sp);686    if (loadable.Dest == LLDB_INVALID_ADDRESS)687      continue;688    // We can skip sections like bss689    if (section_sp->GetFileSize() == 0)690      continue;691    DataExtractor section_data;692    section_sp->GetSectionData(section_data);693    loadable.Contents = llvm::ArrayRef<uint8_t>(section_data.GetDataStart(),694                                                section_data.GetByteSize());695    loadables.push_back(loadable);696  }697  return loadables;698}699 700std::unique_ptr<CallFrameInfo> ObjectFile::CreateCallFrameInfo() {701  return {};702}703 704void ObjectFile::RelocateSection(lldb_private::Section *section)705{706}707 708DataBufferSP ObjectFile::MapFileData(const FileSpec &file, uint64_t Size,709                                     uint64_t Offset) {710  return FileSystem::Instance().CreateDataBuffer(file.GetPath(), Size, Offset);711}712 713void llvm::format_provider<ObjectFile::Type>::format(714    const ObjectFile::Type &type, raw_ostream &OS, StringRef Style) {715  switch (type) {716  case ObjectFile::eTypeInvalid:717    OS << "invalid";718    break;719  case ObjectFile::eTypeCoreFile:720    OS << "core file";721    break;722  case ObjectFile::eTypeExecutable:723    OS << "executable";724    break;725  case ObjectFile::eTypeDebugInfo:726    OS << "debug info";727    break;728  case ObjectFile::eTypeDynamicLinker:729    OS << "dynamic linker";730    break;731  case ObjectFile::eTypeObjectFile:732    OS << "object file";733    break;734  case ObjectFile::eTypeSharedLibrary:735    OS << "shared library";736    break;737  case ObjectFile::eTypeStubLibrary:738    OS << "stub library";739    break;740  case ObjectFile::eTypeJIT:741    OS << "jit";742    break;743  case ObjectFile::eTypeUnknown:744    OS << "unknown";745    break;746  }747}748 749void llvm::format_provider<ObjectFile::Strata>::format(750    const ObjectFile::Strata &strata, raw_ostream &OS, StringRef Style) {751  switch (strata) {752  case ObjectFile::eStrataInvalid:753    OS << "invalid";754    break;755  case ObjectFile::eStrataUnknown:756    OS << "unknown";757    break;758  case ObjectFile::eStrataUser:759    OS << "user";760    break;761  case ObjectFile::eStrataKernel:762    OS << "kernel";763    break;764  case ObjectFile::eStrataRawImage:765    OS << "raw image";766    break;767  case ObjectFile::eStrataJIT:768    OS << "jit";769    break;770  }771}772 773Symtab *ObjectFile::GetSymtab(bool can_create) {774  ModuleSP module_sp(GetModule());775  if (module_sp && can_create) {776    // We can't take the module lock in ObjectFile::GetSymtab() or we can777    // deadlock in DWARF indexing when any file asks for the symbol table from778    // an object file. This currently happens in the preloading of symbols in779    // SymbolFileDWARF::PreloadSymbols() because the main thread will take the780    // module lock, and then threads will be spun up to index the DWARF and781    // any of those threads might end up trying to relocate items in the DWARF782    // sections which causes ObjectFile::GetSectionData(...) to relocate section783    // data which requires the symbol table.784    //785    // So to work around this, we create the symbol table one time using786    // llvm::once_flag, lock it, and then set the unique pointer. Any other787    // thread that gets ahold of the symbol table before parsing is done, will788    // not be able to access the symbol table contents since all APIs in Symtab789    // are protected by a mutex in the Symtab object itself.790    llvm::call_once(*m_symtab_once_up, [&]() {791      Symtab *symtab = new Symtab(this);792      std::lock_guard<std::recursive_mutex> symtab_guard(symtab->GetMutex());793      m_symtab_up.reset(symtab);794      if (!m_symtab_up->LoadFromCache()) {795        ElapsedTime elapsed(module_sp->GetSymtabParseTime());796        ParseSymtab(*m_symtab_up);797        m_symtab_up->Finalize();798      }799    });800  }801  return m_symtab_up.get();802}803 804uint32_t ObjectFile::GetCacheHash() {805  if (m_cache_hash)806    return *m_cache_hash;807  StreamString strm;808  strm.Format("{0}-{1}-{2}", m_file, GetType(), GetStrata());809  m_cache_hash = llvm::djbHash(strm.GetString());810  return *m_cache_hash;811}812 813std::string ObjectFile::GetObjectName() const {814  if (ModuleSP module_sp = GetModule())815    if (ConstString object_name = module_sp->GetObjectName())816      return llvm::formatv("{0}({1})", GetFileSpec().GetFilename().GetString(),817                           object_name.GetString())818          .str();819  return GetFileSpec().GetFilename().GetString();820}821 822namespace llvm {823namespace json {824 825bool fromJSON(const llvm::json::Value &value,826              lldb_private::ObjectFile::Type &type, llvm::json::Path path) {827  if (auto str = value.getAsString()) {828    type = llvm::StringSwitch<ObjectFile::Type>(*str)829               .Case("corefile", ObjectFile::eTypeCoreFile)830               .Case("executable", ObjectFile::eTypeExecutable)831               .Case("debuginfo", ObjectFile::eTypeDebugInfo)832               .Case("dynamiclinker", ObjectFile::eTypeDynamicLinker)833               .Case("objectfile", ObjectFile::eTypeObjectFile)834               .Case("sharedlibrary", ObjectFile::eTypeSharedLibrary)835               .Case("stublibrary", ObjectFile::eTypeStubLibrary)836               .Case("jit", ObjectFile::eTypeJIT)837               .Case("unknown", ObjectFile::eTypeUnknown)838               .Default(ObjectFile::eTypeInvalid);839 840    if (type == ObjectFile::eTypeInvalid) {841      path.report("invalid object type");842      return false;843    }844 845    return true;846  }847  path.report("expected string");848  return false;849}850} // namespace json851} // namespace llvm852