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 §ion_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