diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp')
| -rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp | 248 | 
1 files changed, 248 insertions, 0 deletions
| diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp new file mode 100644 index 000000000000..bec0099517c8 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp @@ -0,0 +1,248 @@ +//===-- ObjectFileJIT.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringRef.h" + +#include "ObjectFileJIT.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/FileSpecList.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RangeMap.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/Timer.h" +#include "lldb/Utility/UUID.h" + +#ifndef __APPLE__ +#include "Utility/UuidCompatibility.h" +#endif + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(ObjectFileJIT) + +char ObjectFileJIT::ID; + +void ObjectFileJIT::Initialize() { +  PluginManager::RegisterPlugin(GetPluginNameStatic(), +                                GetPluginDescriptionStatic(), CreateInstance, +                                CreateMemoryInstance, GetModuleSpecifications); +} + +void ObjectFileJIT::Terminate() { +  PluginManager::UnregisterPlugin(CreateInstance); +} + +ObjectFile *ObjectFileJIT::CreateInstance(const lldb::ModuleSP &module_sp, +                                          DataBufferSP &data_sp, +                                          lldb::offset_t data_offset, +                                          const FileSpec *file, +                                          lldb::offset_t file_offset, +                                          lldb::offset_t length) { +  // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from +  // a file +  return nullptr; +} + +ObjectFile *ObjectFileJIT::CreateMemoryInstance(const lldb::ModuleSP &module_sp, +                                                DataBufferSP &data_sp, +                                                const ProcessSP &process_sp, +                                                lldb::addr_t header_addr) { +  // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from +  // memory +  return nullptr; +} + +size_t ObjectFileJIT::GetModuleSpecifications( +    const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, +    lldb::offset_t data_offset, lldb::offset_t file_offset, +    lldb::offset_t length, lldb_private::ModuleSpecList &specs) { +  // JIT'ed object file can't be read from a file on disk +  return 0; +} + +ObjectFileJIT::ObjectFileJIT(const lldb::ModuleSP &module_sp, +                             const ObjectFileJITDelegateSP &delegate_sp) +    : ObjectFile(module_sp, nullptr, 0, 0, DataBufferSP(), 0), m_delegate_wp() { +  if (delegate_sp) { +    m_delegate_wp = delegate_sp; +    m_data.SetByteOrder(delegate_sp->GetByteOrder()); +    m_data.SetAddressByteSize(delegate_sp->GetAddressByteSize()); +  } +} + +ObjectFileJIT::~ObjectFileJIT() = default; + +bool ObjectFileJIT::ParseHeader() { +  // JIT code is never in a file, nor is it required to have any header +  return false; +} + +ByteOrder ObjectFileJIT::GetByteOrder() const { return m_data.GetByteOrder(); } + +bool ObjectFileJIT::IsExecutable() const { return false; } + +uint32_t ObjectFileJIT::GetAddressByteSize() const { +  return m_data.GetAddressByteSize(); +} + +Symtab *ObjectFileJIT::GetSymtab() { +  ModuleSP module_sp(GetModule()); +  if (module_sp) { +    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); +    if (m_symtab_up == nullptr) { +      ElapsedTime elapsed(module_sp->GetSymtabParseTime()); +      m_symtab_up = std::make_unique<Symtab>(this); +      std::lock_guard<std::recursive_mutex> symtab_guard( +          m_symtab_up->GetMutex()); +      ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock()); +      if (delegate_sp) +        delegate_sp->PopulateSymtab(this, *m_symtab_up); +      // TODO: get symbols from delegate +      m_symtab_up->Finalize(); +    } +  } +  return m_symtab_up.get(); +} + +bool ObjectFileJIT::IsStripped() { +  return false; // JIT code that is in a module is never stripped +} + +void ObjectFileJIT::CreateSections(SectionList &unified_section_list) { +  if (!m_sections_up) { +    m_sections_up = std::make_unique<SectionList>(); +    ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock()); +    if (delegate_sp) { +      delegate_sp->PopulateSectionList(this, *m_sections_up); +      unified_section_list = *m_sections_up; +    } +  } +} + +void ObjectFileJIT::Dump(Stream *s) { +  ModuleSP module_sp(GetModule()); +  if (module_sp) { +    std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); +    s->Printf("%p: ", static_cast<void *>(this)); +    s->Indent(); +    s->PutCString("ObjectFileJIT"); + +    if (ArchSpec arch = GetArchitecture()) +      *s << ", arch = " << arch.GetArchitectureName(); + +    s->EOL(); + +    SectionList *sections = GetSectionList(); +    if (sections) +      sections->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true, +                     UINT32_MAX); + +    if (m_symtab_up) +      m_symtab_up->Dump(s, nullptr, eSortOrderNone); +  } +} + +UUID ObjectFileJIT::GetUUID() { +  // TODO: maybe get from delegate, not needed for first pass +  return UUID(); +} + +uint32_t ObjectFileJIT::GetDependentModules(FileSpecList &files) { +  // JIT modules don't have dependencies, but they could +  // if external functions are called and we know where they are +  files.Clear(); +  return 0; +} + +lldb_private::Address ObjectFileJIT::GetEntryPointAddress() { +  return Address(); +} + +lldb_private::Address ObjectFileJIT::GetBaseAddress() { return Address(); } + +ObjectFile::Type ObjectFileJIT::CalculateType() { return eTypeJIT; } + +ObjectFile::Strata ObjectFileJIT::CalculateStrata() { return eStrataJIT; } + +ArchSpec ObjectFileJIT::GetArchitecture() { +  if (ObjectFileJITDelegateSP delegate_sp = m_delegate_wp.lock()) +    return delegate_sp->GetArchitecture(); +  return ArchSpec(); +} + +bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value, +                                   bool value_is_offset) { +  size_t num_loaded_sections = 0; +  SectionList *section_list = GetSectionList(); +  if (section_list) { +    const size_t num_sections = section_list->GetSize(); +    // "value" is an offset to apply to each top level segment +    for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) { +      // Iterate through the object file sections to find all of the sections +      // that size on disk (to avoid __PAGEZERO) and load them +      SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); +      if (section_sp && section_sp->GetFileSize() > 0 && +          !section_sp->IsThreadSpecific()) { +        if (target.GetSectionLoadList().SetSectionLoadAddress( +                section_sp, section_sp->GetFileAddress() + value)) +          ++num_loaded_sections; +      } +    } +  } +  return num_loaded_sections > 0; +} + +size_t ObjectFileJIT::ReadSectionData(lldb_private::Section *section, +                                      lldb::offset_t section_offset, void *dst, +                                      size_t dst_len) { +  lldb::offset_t file_size = section->GetFileSize(); +  if (section_offset < file_size) { +    size_t src_len = file_size - section_offset; +    if (src_len > dst_len) +      src_len = dst_len; +    const uint8_t *src = +        ((uint8_t *)(uintptr_t)section->GetFileOffset()) + section_offset; + +    memcpy(dst, src, src_len); +    return src_len; +  } +  return 0; +} + +size_t ObjectFileJIT::ReadSectionData( +    lldb_private::Section *section, +    lldb_private::DataExtractor §ion_data) { +  if (section->GetFileSize()) { +    const void *src = (void *)(uintptr_t)section->GetFileOffset(); + +    DataBufferSP data_sp = +        std::make_shared<DataBufferHeap>(src, section->GetFileSize()); +    section_data.SetData(data_sp, 0, data_sp->GetByteSize()); +    section_data.SetByteOrder(GetByteOrder()); +    section_data.SetAddressByteSize(GetAddressByteSize()); +    return section_data.GetByteSize(); +  } +  section_data.Clear(); +  return 0; +} | 
