15ffd83dbSDimitry Andric //===-- ObjectFileJIT.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 "llvm/ADT/StringRef.h"
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "ObjectFileJIT.h"
120b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
130b57cec5SDimitry Andric #include "lldb/Core/FileSpecList.h"
140b57cec5SDimitry Andric #include "lldb/Core/Module.h"
150b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h"
160b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
170b57cec5SDimitry Andric #include "lldb/Core/Section.h"
180b57cec5SDimitry Andric #include "lldb/Core/StreamFile.h"
190b57cec5SDimitry Andric #include "lldb/Host/Host.h"
200b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
210b57cec5SDimitry Andric #include "lldb/Target/Platform.h"
220b57cec5SDimitry Andric #include "lldb/Target/Process.h"
230b57cec5SDimitry Andric #include "lldb/Target/SectionLoadList.h"
240b57cec5SDimitry Andric #include "lldb/Target/Target.h"
250b57cec5SDimitry Andric #include "lldb/Utility/ArchSpec.h"
260b57cec5SDimitry Andric #include "lldb/Utility/DataBuffer.h"
270b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
280b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h"
290b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
300b57cec5SDimitry Andric #include "lldb/Utility/RangeMap.h"
310b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
320b57cec5SDimitry Andric #include "lldb/Utility/Timer.h"
330b57cec5SDimitry Andric #include "lldb/Utility/UUID.h"
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric #ifndef __APPLE__
360b57cec5SDimitry Andric #include "Utility/UuidCompatibility.h"
370b57cec5SDimitry Andric #endif
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric using namespace lldb;
400b57cec5SDimitry Andric using namespace lldb_private;
410b57cec5SDimitry Andric
425ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(ObjectFileJIT)
435ffd83dbSDimitry Andric
449dba64beSDimitry Andric char ObjectFileJIT::ID;
459dba64beSDimitry Andric
Initialize()460b57cec5SDimitry Andric void ObjectFileJIT::Initialize() {
470b57cec5SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(),
480b57cec5SDimitry Andric GetPluginDescriptionStatic(), CreateInstance,
490b57cec5SDimitry Andric CreateMemoryInstance, GetModuleSpecifications);
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric
Terminate()520b57cec5SDimitry Andric void ObjectFileJIT::Terminate() {
530b57cec5SDimitry Andric PluginManager::UnregisterPlugin(CreateInstance);
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric
GetPluginNameStatic()560b57cec5SDimitry Andric lldb_private::ConstString ObjectFileJIT::GetPluginNameStatic() {
570b57cec5SDimitry Andric static ConstString g_name("jit");
580b57cec5SDimitry Andric return g_name;
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric
GetPluginDescriptionStatic()610b57cec5SDimitry Andric const char *ObjectFileJIT::GetPluginDescriptionStatic() {
620b57cec5SDimitry Andric return "JIT code object file";
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric
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)650b57cec5SDimitry Andric ObjectFile *ObjectFileJIT::CreateInstance(const lldb::ModuleSP &module_sp,
660b57cec5SDimitry Andric DataBufferSP &data_sp,
670b57cec5SDimitry Andric lldb::offset_t data_offset,
680b57cec5SDimitry Andric const FileSpec *file,
690b57cec5SDimitry Andric lldb::offset_t file_offset,
700b57cec5SDimitry Andric lldb::offset_t length) {
710b57cec5SDimitry Andric // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from
720b57cec5SDimitry Andric // a file
730b57cec5SDimitry Andric return nullptr;
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric
CreateMemoryInstance(const lldb::ModuleSP & module_sp,DataBufferSP & data_sp,const ProcessSP & process_sp,lldb::addr_t header_addr)760b57cec5SDimitry Andric ObjectFile *ObjectFileJIT::CreateMemoryInstance(const lldb::ModuleSP &module_sp,
770b57cec5SDimitry Andric DataBufferSP &data_sp,
780b57cec5SDimitry Andric const ProcessSP &process_sp,
790b57cec5SDimitry Andric lldb::addr_t header_addr) {
800b57cec5SDimitry Andric // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from
810b57cec5SDimitry Andric // memory
820b57cec5SDimitry Andric return nullptr;
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric
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)850b57cec5SDimitry Andric size_t ObjectFileJIT::GetModuleSpecifications(
860b57cec5SDimitry Andric const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
870b57cec5SDimitry Andric lldb::offset_t data_offset, lldb::offset_t file_offset,
880b57cec5SDimitry Andric lldb::offset_t length, lldb_private::ModuleSpecList &specs) {
890b57cec5SDimitry Andric // JIT'ed object file can't be read from a file on disk
900b57cec5SDimitry Andric return 0;
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric
ObjectFileJIT(const lldb::ModuleSP & module_sp,const ObjectFileJITDelegateSP & delegate_sp)930b57cec5SDimitry Andric ObjectFileJIT::ObjectFileJIT(const lldb::ModuleSP &module_sp,
940b57cec5SDimitry Andric const ObjectFileJITDelegateSP &delegate_sp)
950b57cec5SDimitry Andric : ObjectFile(module_sp, nullptr, 0, 0, DataBufferSP(), 0), m_delegate_wp() {
960b57cec5SDimitry Andric if (delegate_sp) {
970b57cec5SDimitry Andric m_delegate_wp = delegate_sp;
980b57cec5SDimitry Andric m_data.SetByteOrder(delegate_sp->GetByteOrder());
990b57cec5SDimitry Andric m_data.SetAddressByteSize(delegate_sp->GetAddressByteSize());
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric
103*5f7ddb14SDimitry Andric ObjectFileJIT::~ObjectFileJIT() = default;
1040b57cec5SDimitry Andric
ParseHeader()1050b57cec5SDimitry Andric bool ObjectFileJIT::ParseHeader() {
1060b57cec5SDimitry Andric // JIT code is never in a file, nor is it required to have any header
1070b57cec5SDimitry Andric return false;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
GetByteOrder() const1100b57cec5SDimitry Andric ByteOrder ObjectFileJIT::GetByteOrder() const { return m_data.GetByteOrder(); }
1110b57cec5SDimitry Andric
IsExecutable() const1120b57cec5SDimitry Andric bool ObjectFileJIT::IsExecutable() const { return false; }
1130b57cec5SDimitry Andric
GetAddressByteSize() const1140b57cec5SDimitry Andric uint32_t ObjectFileJIT::GetAddressByteSize() const {
1150b57cec5SDimitry Andric return m_data.GetAddressByteSize();
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric
GetSymtab()1180b57cec5SDimitry Andric Symtab *ObjectFileJIT::GetSymtab() {
1190b57cec5SDimitry Andric ModuleSP module_sp(GetModule());
1200b57cec5SDimitry Andric if (module_sp) {
1210b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1220b57cec5SDimitry Andric if (m_symtab_up == nullptr) {
1235ffd83dbSDimitry Andric m_symtab_up = std::make_unique<Symtab>(this);
1240b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> symtab_guard(
1250b57cec5SDimitry Andric m_symtab_up->GetMutex());
1260b57cec5SDimitry Andric ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
1270b57cec5SDimitry Andric if (delegate_sp)
1280b57cec5SDimitry Andric delegate_sp->PopulateSymtab(this, *m_symtab_up);
1290b57cec5SDimitry Andric // TODO: get symbols from delegate
1300b57cec5SDimitry Andric m_symtab_up->Finalize();
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric return m_symtab_up.get();
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric
IsStripped()1360b57cec5SDimitry Andric bool ObjectFileJIT::IsStripped() {
1370b57cec5SDimitry Andric return false; // JIT code that is in a module is never stripped
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric
CreateSections(SectionList & unified_section_list)1400b57cec5SDimitry Andric void ObjectFileJIT::CreateSections(SectionList &unified_section_list) {
1410b57cec5SDimitry Andric if (!m_sections_up) {
1425ffd83dbSDimitry Andric m_sections_up = std::make_unique<SectionList>();
1430b57cec5SDimitry Andric ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
1440b57cec5SDimitry Andric if (delegate_sp) {
1450b57cec5SDimitry Andric delegate_sp->PopulateSectionList(this, *m_sections_up);
1460b57cec5SDimitry Andric unified_section_list = *m_sections_up;
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric
Dump(Stream * s)1510b57cec5SDimitry Andric void ObjectFileJIT::Dump(Stream *s) {
1520b57cec5SDimitry Andric ModuleSP module_sp(GetModule());
1530b57cec5SDimitry Andric if (module_sp) {
1540b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1550b57cec5SDimitry Andric s->Printf("%p: ", static_cast<void *>(this));
1560b57cec5SDimitry Andric s->Indent();
1570b57cec5SDimitry Andric s->PutCString("ObjectFileJIT");
1580b57cec5SDimitry Andric
1590b57cec5SDimitry Andric if (ArchSpec arch = GetArchitecture())
1600b57cec5SDimitry Andric *s << ", arch = " << arch.GetArchitectureName();
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric s->EOL();
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric SectionList *sections = GetSectionList();
1650b57cec5SDimitry Andric if (sections)
1665ffd83dbSDimitry Andric sections->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true,
1675ffd83dbSDimitry Andric UINT32_MAX);
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric if (m_symtab_up)
1700b57cec5SDimitry Andric m_symtab_up->Dump(s, nullptr, eSortOrderNone);
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric
GetUUID()1740b57cec5SDimitry Andric UUID ObjectFileJIT::GetUUID() {
1750b57cec5SDimitry Andric // TODO: maybe get from delegate, not needed for first pass
1760b57cec5SDimitry Andric return UUID();
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric
GetDependentModules(FileSpecList & files)1790b57cec5SDimitry Andric uint32_t ObjectFileJIT::GetDependentModules(FileSpecList &files) {
1800b57cec5SDimitry Andric // JIT modules don't have dependencies, but they could
1810b57cec5SDimitry Andric // if external functions are called and we know where they are
1820b57cec5SDimitry Andric files.Clear();
1830b57cec5SDimitry Andric return 0;
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric
GetEntryPointAddress()1860b57cec5SDimitry Andric lldb_private::Address ObjectFileJIT::GetEntryPointAddress() {
1870b57cec5SDimitry Andric return Address();
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric
GetBaseAddress()1900b57cec5SDimitry Andric lldb_private::Address ObjectFileJIT::GetBaseAddress() { return Address(); }
1910b57cec5SDimitry Andric
CalculateType()1920b57cec5SDimitry Andric ObjectFile::Type ObjectFileJIT::CalculateType() { return eTypeJIT; }
1930b57cec5SDimitry Andric
CalculateStrata()1940b57cec5SDimitry Andric ObjectFile::Strata ObjectFileJIT::CalculateStrata() { return eStrataJIT; }
1950b57cec5SDimitry Andric
GetArchitecture()1960b57cec5SDimitry Andric ArchSpec ObjectFileJIT::GetArchitecture() {
1970b57cec5SDimitry Andric if (ObjectFileJITDelegateSP delegate_sp = m_delegate_wp.lock())
1980b57cec5SDimitry Andric return delegate_sp->GetArchitecture();
1990b57cec5SDimitry Andric return ArchSpec();
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric // PluginInterface protocol
GetPluginName()2030b57cec5SDimitry Andric lldb_private::ConstString ObjectFileJIT::GetPluginName() {
2040b57cec5SDimitry Andric return GetPluginNameStatic();
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric
GetPluginVersion()2070b57cec5SDimitry Andric uint32_t ObjectFileJIT::GetPluginVersion() { return 1; }
2080b57cec5SDimitry Andric
SetLoadAddress(Target & target,lldb::addr_t value,bool value_is_offset)2090b57cec5SDimitry Andric bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value,
2100b57cec5SDimitry Andric bool value_is_offset) {
2110b57cec5SDimitry Andric size_t num_loaded_sections = 0;
2120b57cec5SDimitry Andric SectionList *section_list = GetSectionList();
2130b57cec5SDimitry Andric if (section_list) {
2140b57cec5SDimitry Andric const size_t num_sections = section_list->GetSize();
2150b57cec5SDimitry Andric // "value" is an offset to apply to each top level segment
2160b57cec5SDimitry Andric for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
2170b57cec5SDimitry Andric // Iterate through the object file sections to find all of the sections
2180b57cec5SDimitry Andric // that size on disk (to avoid __PAGEZERO) and load them
2190b57cec5SDimitry Andric SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
2200b57cec5SDimitry Andric if (section_sp && section_sp->GetFileSize() > 0 &&
2210b57cec5SDimitry Andric !section_sp->IsThreadSpecific()) {
2220b57cec5SDimitry Andric if (target.GetSectionLoadList().SetSectionLoadAddress(
2230b57cec5SDimitry Andric section_sp, section_sp->GetFileAddress() + value))
2240b57cec5SDimitry Andric ++num_loaded_sections;
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric return num_loaded_sections > 0;
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric
ReadSectionData(lldb_private::Section * section,lldb::offset_t section_offset,void * dst,size_t dst_len)2310b57cec5SDimitry Andric size_t ObjectFileJIT::ReadSectionData(lldb_private::Section *section,
2320b57cec5SDimitry Andric lldb::offset_t section_offset, void *dst,
2330b57cec5SDimitry Andric size_t dst_len) {
2340b57cec5SDimitry Andric lldb::offset_t file_size = section->GetFileSize();
2350b57cec5SDimitry Andric if (section_offset < file_size) {
2360b57cec5SDimitry Andric size_t src_len = file_size - section_offset;
2370b57cec5SDimitry Andric if (src_len > dst_len)
2380b57cec5SDimitry Andric src_len = dst_len;
2390b57cec5SDimitry Andric const uint8_t *src =
2400b57cec5SDimitry Andric ((uint8_t *)(uintptr_t)section->GetFileOffset()) + section_offset;
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric memcpy(dst, src, src_len);
2430b57cec5SDimitry Andric return src_len;
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric return 0;
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric
ReadSectionData(lldb_private::Section * section,lldb_private::DataExtractor & section_data)2480b57cec5SDimitry Andric size_t ObjectFileJIT::ReadSectionData(
2490b57cec5SDimitry Andric lldb_private::Section *section,
2500b57cec5SDimitry Andric lldb_private::DataExtractor §ion_data) {
2510b57cec5SDimitry Andric if (section->GetFileSize()) {
2520b57cec5SDimitry Andric const void *src = (void *)(uintptr_t)section->GetFileOffset();
2530b57cec5SDimitry Andric
2540b57cec5SDimitry Andric DataBufferSP data_sp =
2550b57cec5SDimitry Andric std::make_shared<DataBufferHeap>(src, section->GetFileSize());
2560b57cec5SDimitry Andric section_data.SetData(data_sp, 0, data_sp->GetByteSize());
2570b57cec5SDimitry Andric section_data.SetByteOrder(GetByteOrder());
2580b57cec5SDimitry Andric section_data.SetAddressByteSize(GetAddressByteSize());
2590b57cec5SDimitry Andric return section_data.GetByteSize();
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric section_data.Clear();
2620b57cec5SDimitry Andric return 0;
2630b57cec5SDimitry Andric }
264