1*06c3fb27SDimitry Andric //===-- ObjectFileJIT.cpp -------------------------------------------------===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric 9*06c3fb27SDimitry Andric #include "llvm/ADT/StringRef.h" 10*06c3fb27SDimitry Andric 11*06c3fb27SDimitry Andric #include "lldb/Core/Module.h" 12*06c3fb27SDimitry Andric #include "lldb/Core/ModuleSpec.h" 13*06c3fb27SDimitry Andric #include "lldb/Core/PluginManager.h" 14*06c3fb27SDimitry Andric #include "lldb/Core/Section.h" 15*06c3fb27SDimitry Andric #include "lldb/Expression/ObjectFileJIT.h" 16*06c3fb27SDimitry Andric #include "lldb/Target/Process.h" 17*06c3fb27SDimitry Andric #include "lldb/Target/SectionLoadList.h" 18*06c3fb27SDimitry Andric #include "lldb/Target/Target.h" 19*06c3fb27SDimitry Andric #include "lldb/Utility/ArchSpec.h" 20*06c3fb27SDimitry Andric #include "lldb/Utility/DataBuffer.h" 21*06c3fb27SDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 22*06c3fb27SDimitry Andric #include "lldb/Utility/FileSpec.h" 23*06c3fb27SDimitry Andric #include "lldb/Utility/FileSpecList.h" 24*06c3fb27SDimitry Andric #include "lldb/Utility/Log.h" 25*06c3fb27SDimitry Andric #include "lldb/Utility/Timer.h" 26*06c3fb27SDimitry Andric #include "lldb/Utility/UUID.h" 27*06c3fb27SDimitry Andric 28*06c3fb27SDimitry Andric #ifndef __APPLE__ 29*06c3fb27SDimitry Andric #include "Utility/UuidCompatibility.h" 30*06c3fb27SDimitry Andric #endif 31*06c3fb27SDimitry Andric 32*06c3fb27SDimitry Andric using namespace lldb; 33*06c3fb27SDimitry Andric using namespace lldb_private; 34*06c3fb27SDimitry Andric 35*06c3fb27SDimitry Andric char ObjectFileJIT::ID; 36*06c3fb27SDimitry Andric 37*06c3fb27SDimitry Andric void ObjectFileJIT::Initialize() { 38*06c3fb27SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 39*06c3fb27SDimitry Andric GetPluginDescriptionStatic(), CreateInstance, 40*06c3fb27SDimitry Andric CreateMemoryInstance, GetModuleSpecifications); 41*06c3fb27SDimitry Andric } 42*06c3fb27SDimitry Andric 43*06c3fb27SDimitry Andric void ObjectFileJIT::Terminate() { 44*06c3fb27SDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 45*06c3fb27SDimitry Andric } 46*06c3fb27SDimitry Andric 47*06c3fb27SDimitry Andric ObjectFile *ObjectFileJIT::CreateInstance(const lldb::ModuleSP &module_sp, 48*06c3fb27SDimitry Andric DataBufferSP data_sp, 49*06c3fb27SDimitry Andric lldb::offset_t data_offset, 50*06c3fb27SDimitry Andric const FileSpec *file, 51*06c3fb27SDimitry Andric lldb::offset_t file_offset, 52*06c3fb27SDimitry Andric lldb::offset_t length) { 53*06c3fb27SDimitry Andric // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from 54*06c3fb27SDimitry Andric // a file 55*06c3fb27SDimitry Andric return nullptr; 56*06c3fb27SDimitry Andric } 57*06c3fb27SDimitry Andric 58*06c3fb27SDimitry Andric ObjectFile *ObjectFileJIT::CreateMemoryInstance(const lldb::ModuleSP &module_sp, 59*06c3fb27SDimitry Andric WritableDataBufferSP data_sp, 60*06c3fb27SDimitry Andric const ProcessSP &process_sp, 61*06c3fb27SDimitry Andric lldb::addr_t header_addr) { 62*06c3fb27SDimitry Andric // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from 63*06c3fb27SDimitry Andric // memory 64*06c3fb27SDimitry Andric return nullptr; 65*06c3fb27SDimitry Andric } 66*06c3fb27SDimitry Andric 67*06c3fb27SDimitry Andric size_t ObjectFileJIT::GetModuleSpecifications( 68*06c3fb27SDimitry Andric const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, 69*06c3fb27SDimitry Andric lldb::offset_t data_offset, lldb::offset_t file_offset, 70*06c3fb27SDimitry Andric lldb::offset_t length, lldb_private::ModuleSpecList &specs) { 71*06c3fb27SDimitry Andric // JIT'ed object file can't be read from a file on disk 72*06c3fb27SDimitry Andric return 0; 73*06c3fb27SDimitry Andric } 74*06c3fb27SDimitry Andric 75*06c3fb27SDimitry Andric ObjectFileJIT::ObjectFileJIT(const lldb::ModuleSP &module_sp, 76*06c3fb27SDimitry Andric const ObjectFileJITDelegateSP &delegate_sp) 77*06c3fb27SDimitry Andric : ObjectFile(module_sp, nullptr, 0, 0, DataBufferSP(), 0), m_delegate_wp() { 78*06c3fb27SDimitry Andric if (delegate_sp) { 79*06c3fb27SDimitry Andric m_delegate_wp = delegate_sp; 80*06c3fb27SDimitry Andric m_data.SetByteOrder(delegate_sp->GetByteOrder()); 81*06c3fb27SDimitry Andric m_data.SetAddressByteSize(delegate_sp->GetAddressByteSize()); 82*06c3fb27SDimitry Andric } 83*06c3fb27SDimitry Andric } 84*06c3fb27SDimitry Andric 85*06c3fb27SDimitry Andric ObjectFileJIT::~ObjectFileJIT() = default; 86*06c3fb27SDimitry Andric 87*06c3fb27SDimitry Andric bool ObjectFileJIT::ParseHeader() { 88*06c3fb27SDimitry Andric // JIT code is never in a file, nor is it required to have any header 89*06c3fb27SDimitry Andric return false; 90*06c3fb27SDimitry Andric } 91*06c3fb27SDimitry Andric 92*06c3fb27SDimitry Andric ByteOrder ObjectFileJIT::GetByteOrder() const { return m_data.GetByteOrder(); } 93*06c3fb27SDimitry Andric 94*06c3fb27SDimitry Andric bool ObjectFileJIT::IsExecutable() const { return false; } 95*06c3fb27SDimitry Andric 96*06c3fb27SDimitry Andric uint32_t ObjectFileJIT::GetAddressByteSize() const { 97*06c3fb27SDimitry Andric return m_data.GetAddressByteSize(); 98*06c3fb27SDimitry Andric } 99*06c3fb27SDimitry Andric 100*06c3fb27SDimitry Andric void ObjectFileJIT::ParseSymtab(Symtab &symtab) { 101*06c3fb27SDimitry Andric ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock()); 102*06c3fb27SDimitry Andric if (delegate_sp) 103*06c3fb27SDimitry Andric delegate_sp->PopulateSymtab(this, symtab); 104*06c3fb27SDimitry Andric } 105*06c3fb27SDimitry Andric 106*06c3fb27SDimitry Andric bool ObjectFileJIT::IsStripped() { 107*06c3fb27SDimitry Andric return false; // JIT code that is in a module is never stripped 108*06c3fb27SDimitry Andric } 109*06c3fb27SDimitry Andric 110*06c3fb27SDimitry Andric void ObjectFileJIT::CreateSections(SectionList &unified_section_list) { 111*06c3fb27SDimitry Andric if (!m_sections_up) { 112*06c3fb27SDimitry Andric m_sections_up = std::make_unique<SectionList>(); 113*06c3fb27SDimitry Andric ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock()); 114*06c3fb27SDimitry Andric if (delegate_sp) { 115*06c3fb27SDimitry Andric delegate_sp->PopulateSectionList(this, *m_sections_up); 116*06c3fb27SDimitry Andric unified_section_list = *m_sections_up; 117*06c3fb27SDimitry Andric } 118*06c3fb27SDimitry Andric } 119*06c3fb27SDimitry Andric } 120*06c3fb27SDimitry Andric 121*06c3fb27SDimitry Andric void ObjectFileJIT::Dump(Stream *s) { 122*06c3fb27SDimitry Andric ModuleSP module_sp(GetModule()); 123*06c3fb27SDimitry Andric if (module_sp) { 124*06c3fb27SDimitry Andric std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); 125*06c3fb27SDimitry Andric s->Printf("%p: ", static_cast<void *>(this)); 126*06c3fb27SDimitry Andric s->Indent(); 127*06c3fb27SDimitry Andric s->PutCString("ObjectFileJIT"); 128*06c3fb27SDimitry Andric 129*06c3fb27SDimitry Andric if (ArchSpec arch = GetArchitecture()) 130*06c3fb27SDimitry Andric *s << ", arch = " << arch.GetArchitectureName(); 131*06c3fb27SDimitry Andric 132*06c3fb27SDimitry Andric s->EOL(); 133*06c3fb27SDimitry Andric 134*06c3fb27SDimitry Andric SectionList *sections = GetSectionList(); 135*06c3fb27SDimitry Andric if (sections) 136*06c3fb27SDimitry Andric sections->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true, 137*06c3fb27SDimitry Andric UINT32_MAX); 138*06c3fb27SDimitry Andric 139*06c3fb27SDimitry Andric if (m_symtab_up) 140*06c3fb27SDimitry Andric m_symtab_up->Dump(s, nullptr, eSortOrderNone); 141*06c3fb27SDimitry Andric } 142*06c3fb27SDimitry Andric } 143*06c3fb27SDimitry Andric 144*06c3fb27SDimitry Andric UUID ObjectFileJIT::GetUUID() { 145*06c3fb27SDimitry Andric // TODO: maybe get from delegate, not needed for first pass 146*06c3fb27SDimitry Andric return UUID(); 147*06c3fb27SDimitry Andric } 148*06c3fb27SDimitry Andric 149*06c3fb27SDimitry Andric uint32_t ObjectFileJIT::GetDependentModules(FileSpecList &files) { 150*06c3fb27SDimitry Andric // JIT modules don't have dependencies, but they could 151*06c3fb27SDimitry Andric // if external functions are called and we know where they are 152*06c3fb27SDimitry Andric files.Clear(); 153*06c3fb27SDimitry Andric return 0; 154*06c3fb27SDimitry Andric } 155*06c3fb27SDimitry Andric 156*06c3fb27SDimitry Andric lldb_private::Address ObjectFileJIT::GetEntryPointAddress() { 157*06c3fb27SDimitry Andric return Address(); 158*06c3fb27SDimitry Andric } 159*06c3fb27SDimitry Andric 160*06c3fb27SDimitry Andric lldb_private::Address ObjectFileJIT::GetBaseAddress() { return Address(); } 161*06c3fb27SDimitry Andric 162*06c3fb27SDimitry Andric ObjectFile::Type ObjectFileJIT::CalculateType() { return eTypeJIT; } 163*06c3fb27SDimitry Andric 164*06c3fb27SDimitry Andric ObjectFile::Strata ObjectFileJIT::CalculateStrata() { return eStrataJIT; } 165*06c3fb27SDimitry Andric 166*06c3fb27SDimitry Andric ArchSpec ObjectFileJIT::GetArchitecture() { 167*06c3fb27SDimitry Andric if (ObjectFileJITDelegateSP delegate_sp = m_delegate_wp.lock()) 168*06c3fb27SDimitry Andric return delegate_sp->GetArchitecture(); 169*06c3fb27SDimitry Andric return ArchSpec(); 170*06c3fb27SDimitry Andric } 171*06c3fb27SDimitry Andric 172*06c3fb27SDimitry Andric bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value, 173*06c3fb27SDimitry Andric bool value_is_offset) { 174*06c3fb27SDimitry Andric size_t num_loaded_sections = 0; 175*06c3fb27SDimitry Andric SectionList *section_list = GetSectionList(); 176*06c3fb27SDimitry Andric if (section_list) { 177*06c3fb27SDimitry Andric const size_t num_sections = section_list->GetSize(); 178*06c3fb27SDimitry Andric // "value" is an offset to apply to each top level segment 179*06c3fb27SDimitry Andric for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) { 180*06c3fb27SDimitry Andric // Iterate through the object file sections to find all of the sections 181*06c3fb27SDimitry Andric // that size on disk (to avoid __PAGEZERO) and load them 182*06c3fb27SDimitry Andric SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); 183*06c3fb27SDimitry Andric if (section_sp && section_sp->GetFileSize() > 0 && 184*06c3fb27SDimitry Andric !section_sp->IsThreadSpecific()) { 185*06c3fb27SDimitry Andric if (target.GetSectionLoadList().SetSectionLoadAddress( 186*06c3fb27SDimitry Andric section_sp, section_sp->GetFileAddress() + value)) 187*06c3fb27SDimitry Andric ++num_loaded_sections; 188*06c3fb27SDimitry Andric } 189*06c3fb27SDimitry Andric } 190*06c3fb27SDimitry Andric } 191*06c3fb27SDimitry Andric return num_loaded_sections > 0; 192*06c3fb27SDimitry Andric } 193*06c3fb27SDimitry Andric 194*06c3fb27SDimitry Andric size_t ObjectFileJIT::ReadSectionData(lldb_private::Section *section, 195*06c3fb27SDimitry Andric lldb::offset_t section_offset, void *dst, 196*06c3fb27SDimitry Andric size_t dst_len) { 197*06c3fb27SDimitry Andric lldb::offset_t file_size = section->GetFileSize(); 198*06c3fb27SDimitry Andric if (section_offset < file_size) { 199*06c3fb27SDimitry Andric size_t src_len = file_size - section_offset; 200*06c3fb27SDimitry Andric if (src_len > dst_len) 201*06c3fb27SDimitry Andric src_len = dst_len; 202*06c3fb27SDimitry Andric const uint8_t *src = 203*06c3fb27SDimitry Andric ((uint8_t *)(uintptr_t)section->GetFileOffset()) + section_offset; 204*06c3fb27SDimitry Andric 205*06c3fb27SDimitry Andric memcpy(dst, src, src_len); 206*06c3fb27SDimitry Andric return src_len; 207*06c3fb27SDimitry Andric } 208*06c3fb27SDimitry Andric return 0; 209*06c3fb27SDimitry Andric } 210*06c3fb27SDimitry Andric 211*06c3fb27SDimitry Andric size_t 212*06c3fb27SDimitry Andric ObjectFileJIT::ReadSectionData(lldb_private::Section *section, 213*06c3fb27SDimitry Andric lldb_private::DataExtractor §ion_data) { 214*06c3fb27SDimitry Andric if (section->GetFileSize()) { 215*06c3fb27SDimitry Andric const void *src = (void *)(uintptr_t)section->GetFileOffset(); 216*06c3fb27SDimitry Andric 217*06c3fb27SDimitry Andric DataBufferSP data_sp = 218*06c3fb27SDimitry Andric std::make_shared<DataBufferHeap>(src, section->GetFileSize()); 219*06c3fb27SDimitry Andric section_data.SetData(data_sp, 0, data_sp->GetByteSize()); 220*06c3fb27SDimitry Andric section_data.SetByteOrder(GetByteOrder()); 221*06c3fb27SDimitry Andric section_data.SetAddressByteSize(GetAddressByteSize()); 222*06c3fb27SDimitry Andric return section_data.GetByteSize(); 223*06c3fb27SDimitry Andric } 224*06c3fb27SDimitry Andric section_data.Clear(); 225*06c3fb27SDimitry Andric return 0; 226*06c3fb27SDimitry Andric } 227