xref: /src/contrib/llvm-project/lldb/source/Expression/ObjectFileJIT.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1cfca06d7SDimitry Andric //===-- ObjectFileJIT.cpp -------------------------------------------------===//
20cac4ca3SEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60cac4ca3SEd Maste //
70cac4ca3SEd Maste //===----------------------------------------------------------------------===//
80cac4ca3SEd Maste 
90cac4ca3SEd Maste #include "llvm/ADT/StringRef.h"
100cac4ca3SEd Maste 
110cac4ca3SEd Maste #include "lldb/Core/Module.h"
120cac4ca3SEd Maste #include "lldb/Core/ModuleSpec.h"
130cac4ca3SEd Maste #include "lldb/Core/PluginManager.h"
140cac4ca3SEd Maste #include "lldb/Core/Section.h"
157fa27ce4SDimitry Andric #include "lldb/Expression/ObjectFileJIT.h"
160cac4ca3SEd Maste #include "lldb/Target/Process.h"
170cac4ca3SEd Maste #include "lldb/Target/SectionLoadList.h"
180cac4ca3SEd Maste #include "lldb/Target/Target.h"
19ef5d0b5eSDimitry Andric #include "lldb/Utility/ArchSpec.h"
2074a628f7SDimitry Andric #include "lldb/Utility/DataBuffer.h"
2174a628f7SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
2274a628f7SDimitry Andric #include "lldb/Utility/FileSpec.h"
237fa27ce4SDimitry Andric #include "lldb/Utility/FileSpecList.h"
2474a628f7SDimitry Andric #include "lldb/Utility/Log.h"
251b306c26SDimitry Andric #include "lldb/Utility/Timer.h"
2674a628f7SDimitry Andric #include "lldb/Utility/UUID.h"
270cac4ca3SEd Maste 
280cac4ca3SEd Maste using namespace lldb;
290cac4ca3SEd Maste using namespace lldb_private;
300cac4ca3SEd Maste 
31ead24645SDimitry Andric char ObjectFileJIT::ID;
32ead24645SDimitry Andric 
Initialize()3314f1b3e8SDimitry Andric void ObjectFileJIT::Initialize() {
340cac4ca3SEd Maste   PluginManager::RegisterPlugin(GetPluginNameStatic(),
3514f1b3e8SDimitry Andric                                 GetPluginDescriptionStatic(), CreateInstance,
3614f1b3e8SDimitry Andric                                 CreateMemoryInstance, GetModuleSpecifications);
370cac4ca3SEd Maste }
380cac4ca3SEd Maste 
Terminate()3914f1b3e8SDimitry Andric void ObjectFileJIT::Terminate() {
400cac4ca3SEd Maste   PluginManager::UnregisterPlugin(CreateInstance);
410cac4ca3SEd Maste }
420cac4ca3SEd Maste 
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)4314f1b3e8SDimitry Andric ObjectFile *ObjectFileJIT::CreateInstance(const lldb::ModuleSP &module_sp,
44145449b1SDimitry Andric                                           DataBufferSP data_sp,
450cac4ca3SEd Maste                                           lldb::offset_t data_offset,
460cac4ca3SEd Maste                                           const FileSpec *file,
470cac4ca3SEd Maste                                           lldb::offset_t file_offset,
4814f1b3e8SDimitry Andric                                           lldb::offset_t length) {
49f73363f1SDimitry Andric   // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from
50f73363f1SDimitry Andric   // a file
515f29bb8aSDimitry Andric   return nullptr;
520cac4ca3SEd Maste }
530cac4ca3SEd Maste 
CreateMemoryInstance(const lldb::ModuleSP & module_sp,WritableDataBufferSP data_sp,const ProcessSP & process_sp,lldb::addr_t header_addr)5414f1b3e8SDimitry Andric ObjectFile *ObjectFileJIT::CreateMemoryInstance(const lldb::ModuleSP &module_sp,
55145449b1SDimitry Andric                                                 WritableDataBufferSP data_sp,
560cac4ca3SEd Maste                                                 const ProcessSP &process_sp,
5714f1b3e8SDimitry Andric                                                 lldb::addr_t header_addr) {
58f73363f1SDimitry Andric   // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from
59f73363f1SDimitry Andric   // memory
605f29bb8aSDimitry Andric   return nullptr;
610cac4ca3SEd Maste }
620cac4ca3SEd Maste 
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)6314f1b3e8SDimitry Andric size_t ObjectFileJIT::GetModuleSpecifications(
6414f1b3e8SDimitry Andric     const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
6514f1b3e8SDimitry Andric     lldb::offset_t data_offset, lldb::offset_t file_offset,
6614f1b3e8SDimitry Andric     lldb::offset_t length, lldb_private::ModuleSpecList &specs) {
670cac4ca3SEd Maste   // JIT'ed object file can't be read from a file on disk
680cac4ca3SEd Maste   return 0;
690cac4ca3SEd Maste }
700cac4ca3SEd Maste 
ObjectFileJIT(const lldb::ModuleSP & module_sp,const ObjectFileJITDelegateSP & delegate_sp)710cac4ca3SEd Maste ObjectFileJIT::ObjectFileJIT(const lldb::ModuleSP &module_sp,
7214f1b3e8SDimitry Andric                              const ObjectFileJITDelegateSP &delegate_sp)
735f29bb8aSDimitry Andric     : ObjectFile(module_sp, nullptr, 0, 0, DataBufferSP(), 0), m_delegate_wp() {
7414f1b3e8SDimitry Andric   if (delegate_sp) {
750cac4ca3SEd Maste     m_delegate_wp = delegate_sp;
760cac4ca3SEd Maste     m_data.SetByteOrder(delegate_sp->GetByteOrder());
770cac4ca3SEd Maste     m_data.SetAddressByteSize(delegate_sp->GetAddressByteSize());
780cac4ca3SEd Maste   }
790cac4ca3SEd Maste }
800cac4ca3SEd Maste 
81344a3780SDimitry Andric ObjectFileJIT::~ObjectFileJIT() = default;
820cac4ca3SEd Maste 
ParseHeader()8314f1b3e8SDimitry Andric bool ObjectFileJIT::ParseHeader() {
840cac4ca3SEd Maste   // JIT code is never in a file, nor is it required to have any header
850cac4ca3SEd Maste   return false;
860cac4ca3SEd Maste }
870cac4ca3SEd Maste 
GetByteOrder() const8814f1b3e8SDimitry Andric ByteOrder ObjectFileJIT::GetByteOrder() const { return m_data.GetByteOrder(); }
890cac4ca3SEd Maste 
IsExecutable() const9014f1b3e8SDimitry Andric bool ObjectFileJIT::IsExecutable() const { return false; }
910cac4ca3SEd Maste 
GetAddressByteSize() const9214f1b3e8SDimitry Andric uint32_t ObjectFileJIT::GetAddressByteSize() const {
930cac4ca3SEd Maste   return m_data.GetAddressByteSize();
940cac4ca3SEd Maste }
950cac4ca3SEd Maste 
ParseSymtab(Symtab & symtab)96f65dcba8SDimitry Andric void ObjectFileJIT::ParseSymtab(Symtab &symtab) {
970cac4ca3SEd Maste   ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
980cac4ca3SEd Maste   if (delegate_sp)
99f65dcba8SDimitry Andric     delegate_sp->PopulateSymtab(this, symtab);
1000cac4ca3SEd Maste }
1010cac4ca3SEd Maste 
IsStripped()10214f1b3e8SDimitry Andric bool ObjectFileJIT::IsStripped() {
1030cac4ca3SEd Maste   return false; // JIT code that is in a module is never stripped
1040cac4ca3SEd Maste }
1050cac4ca3SEd Maste 
CreateSections(SectionList & unified_section_list)10614f1b3e8SDimitry Andric void ObjectFileJIT::CreateSections(SectionList &unified_section_list) {
1075f29bb8aSDimitry Andric   if (!m_sections_up) {
108cfca06d7SDimitry Andric     m_sections_up = std::make_unique<SectionList>();
1090cac4ca3SEd Maste     ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
11014f1b3e8SDimitry Andric     if (delegate_sp) {
1115f29bb8aSDimitry Andric       delegate_sp->PopulateSectionList(this, *m_sections_up);
1125f29bb8aSDimitry Andric       unified_section_list = *m_sections_up;
1130cac4ca3SEd Maste     }
1140cac4ca3SEd Maste   }
1150cac4ca3SEd Maste }
1160cac4ca3SEd Maste 
Dump(Stream * s)11714f1b3e8SDimitry Andric void ObjectFileJIT::Dump(Stream *s) {
1180cac4ca3SEd Maste   ModuleSP module_sp(GetModule());
11914f1b3e8SDimitry Andric   if (module_sp) {
120f3fbd1c0SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1210cac4ca3SEd Maste     s->Printf("%p: ", static_cast<void *>(this));
1220cac4ca3SEd Maste     s->Indent();
1230cac4ca3SEd Maste     s->PutCString("ObjectFileJIT");
1240cac4ca3SEd Maste 
12594994d37SDimitry Andric     if (ArchSpec arch = GetArchitecture())
1260cac4ca3SEd Maste       *s << ", arch = " << arch.GetArchitectureName();
1270cac4ca3SEd Maste 
1280cac4ca3SEd Maste     s->EOL();
1290cac4ca3SEd Maste 
1300cac4ca3SEd Maste     SectionList *sections = GetSectionList();
1310cac4ca3SEd Maste     if (sections)
132cfca06d7SDimitry Andric       sections->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true,
133cfca06d7SDimitry Andric                      UINT32_MAX);
1340cac4ca3SEd Maste 
1355f29bb8aSDimitry Andric     if (m_symtab_up)
1365f29bb8aSDimitry Andric       m_symtab_up->Dump(s, nullptr, eSortOrderNone);
1370cac4ca3SEd Maste   }
1380cac4ca3SEd Maste }
1390cac4ca3SEd Maste 
GetUUID()1405f29bb8aSDimitry Andric UUID ObjectFileJIT::GetUUID() {
1410cac4ca3SEd Maste   // TODO: maybe get from delegate, not needed for first pass
1425f29bb8aSDimitry Andric   return UUID();
1430cac4ca3SEd Maste }
1440cac4ca3SEd Maste 
GetDependentModules(FileSpecList & files)14514f1b3e8SDimitry Andric uint32_t ObjectFileJIT::GetDependentModules(FileSpecList &files) {
1460cac4ca3SEd Maste   // JIT modules don't have dependencies, but they could
1470cac4ca3SEd Maste   // if external functions are called and we know where they are
1480cac4ca3SEd Maste   files.Clear();
1490cac4ca3SEd Maste   return 0;
1500cac4ca3SEd Maste }
1510cac4ca3SEd Maste 
GetEntryPointAddress()15214f1b3e8SDimitry Andric lldb_private::Address ObjectFileJIT::GetEntryPointAddress() {
1530cac4ca3SEd Maste   return Address();
1540cac4ca3SEd Maste }
1550cac4ca3SEd Maste 
GetBaseAddress()15694994d37SDimitry Andric lldb_private::Address ObjectFileJIT::GetBaseAddress() { return Address(); }
1570cac4ca3SEd Maste 
CalculateType()15814f1b3e8SDimitry Andric ObjectFile::Type ObjectFileJIT::CalculateType() { return eTypeJIT; }
1590cac4ca3SEd Maste 
CalculateStrata()16014f1b3e8SDimitry Andric ObjectFile::Strata ObjectFileJIT::CalculateStrata() { return eStrataJIT; }
1610cac4ca3SEd Maste 
GetArchitecture()16294994d37SDimitry Andric ArchSpec ObjectFileJIT::GetArchitecture() {
16394994d37SDimitry Andric   if (ObjectFileJITDelegateSP delegate_sp = m_delegate_wp.lock())
16494994d37SDimitry Andric     return delegate_sp->GetArchitecture();
16594994d37SDimitry Andric   return ArchSpec();
1660cac4ca3SEd Maste }
1670cac4ca3SEd Maste 
SetLoadAddress(Target & target,lldb::addr_t value,bool value_is_offset)16814f1b3e8SDimitry Andric bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value,
16914f1b3e8SDimitry Andric                                    bool value_is_offset) {
1700cac4ca3SEd Maste   size_t num_loaded_sections = 0;
1710cac4ca3SEd Maste   SectionList *section_list = GetSectionList();
17214f1b3e8SDimitry Andric   if (section_list) {
1730cac4ca3SEd Maste     const size_t num_sections = section_list->GetSize();
1740cac4ca3SEd Maste     // "value" is an offset to apply to each top level segment
17514f1b3e8SDimitry Andric     for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
176f73363f1SDimitry Andric       // Iterate through the object file sections to find all of the sections
177f73363f1SDimitry Andric       // that size on disk (to avoid __PAGEZERO) and load them
1780cac4ca3SEd Maste       SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
17914f1b3e8SDimitry Andric       if (section_sp && section_sp->GetFileSize() > 0 &&
18094994d37SDimitry Andric           !section_sp->IsThreadSpecific()) {
18114f1b3e8SDimitry Andric         if (target.GetSectionLoadList().SetSectionLoadAddress(
18214f1b3e8SDimitry Andric                 section_sp, section_sp->GetFileAddress() + value))
1830cac4ca3SEd Maste           ++num_loaded_sections;
1840cac4ca3SEd Maste       }
1850cac4ca3SEd Maste     }
1860cac4ca3SEd Maste   }
1870cac4ca3SEd Maste   return num_loaded_sections > 0;
1880cac4ca3SEd Maste }
1890cac4ca3SEd Maste 
ReadSectionData(lldb_private::Section * section,lldb::offset_t section_offset,void * dst,size_t dst_len)190ef5d0b5eSDimitry Andric size_t ObjectFileJIT::ReadSectionData(lldb_private::Section *section,
19114f1b3e8SDimitry Andric                                       lldb::offset_t section_offset, void *dst,
192ef5d0b5eSDimitry Andric                                       size_t dst_len) {
1930cac4ca3SEd Maste   lldb::offset_t file_size = section->GetFileSize();
19414f1b3e8SDimitry Andric   if (section_offset < file_size) {
1950cac4ca3SEd Maste     size_t src_len = file_size - section_offset;
1960cac4ca3SEd Maste     if (src_len > dst_len)
1970cac4ca3SEd Maste       src_len = dst_len;
19814f1b3e8SDimitry Andric     const uint8_t *src =
19914f1b3e8SDimitry Andric         ((uint8_t *)(uintptr_t)section->GetFileOffset()) + section_offset;
2000cac4ca3SEd Maste 
2010cac4ca3SEd Maste     memcpy(dst, src, src_len);
2020cac4ca3SEd Maste     return src_len;
2030cac4ca3SEd Maste   }
2040cac4ca3SEd Maste   return 0;
2050cac4ca3SEd Maste }
2060cac4ca3SEd Maste 
2077fa27ce4SDimitry Andric size_t
ReadSectionData(lldb_private::Section * section,lldb_private::DataExtractor & section_data)2087fa27ce4SDimitry Andric ObjectFileJIT::ReadSectionData(lldb_private::Section *section,
209ef5d0b5eSDimitry Andric                                lldb_private::DataExtractor &section_data) {
21014f1b3e8SDimitry Andric   if (section->GetFileSize()) {
2110cac4ca3SEd Maste     const void *src = (void *)(uintptr_t)section->GetFileOffset();
2120cac4ca3SEd Maste 
2135f29bb8aSDimitry Andric     DataBufferSP data_sp =
2145f29bb8aSDimitry Andric         std::make_shared<DataBufferHeap>(src, section->GetFileSize());
2150cac4ca3SEd Maste     section_data.SetData(data_sp, 0, data_sp->GetByteSize());
2160cac4ca3SEd Maste     section_data.SetByteOrder(GetByteOrder());
2170cac4ca3SEd Maste     section_data.SetAddressByteSize(GetAddressByteSize());
2180cac4ca3SEd Maste     return section_data.GetByteSize();
2190cac4ca3SEd Maste   }
2200cac4ca3SEd Maste   section_data.Clear();
2210cac4ca3SEd Maste   return 0;
2220cac4ca3SEd Maste }
223