xref: /freebsd-src/contrib/llvm-project/lldb/source/Expression/ObjectFileJIT.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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 &section_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