Skip to content

Commit 2de488f

Browse files
committed
Implement parsing of metadata generated by the JIT.
TypeSystemSwiftTyperef requires metadata to be registered for it to be able to do its work. This registers metadata generated by the JIT, which are types declared in LLDB itself (including the REPL and playgrounds).
1 parent 87dcd8c commit 2de488f

File tree

11 files changed

+189
-82
lines changed

11 files changed

+189
-82
lines changed

lldb/include/lldb/Core/JITSection.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//===-- JITSection.h --------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_CORE_JIT_SECTION_H
10+
#define LLDB_CORE_JIT_SECTION_H
11+
12+
#include "Section.h"
13+
14+
namespace lldb_private {
15+
16+
/// A JIT-compiled section. This type of section may contain JIT specific data
17+
/// at the end of its buffer when compared to a regular section.
18+
class JITSection : public Section {
19+
public:
20+
JITSection(const lldb::ModuleSP &module_sp, ObjectFile *obj_file,
21+
lldb::user_id_t sect_id, ConstString name,
22+
lldb::SectionType sect_type, lldb::addr_t file_vm_addr,
23+
lldb::addr_t vm_size, lldb::offset_t file_offset,
24+
lldb::offset_t file_size, uint32_t log2align, uint32_t flags,
25+
size_t non_jit_size, uint32_t target_byte_size = 1)
26+
: Section(module_sp, obj_file, sect_id, name, sect_type, file_vm_addr,
27+
vm_size, file_offset, file_size, log2align, flags,
28+
target_byte_size),
29+
m_non_jit_size(non_jit_size) {}
30+
31+
JITSection(const lldb::SectionSP &parent_section_sp,
32+
const lldb::ModuleSP &module_sp, ObjectFile *obj_file,
33+
lldb::user_id_t sect_id, ConstString name,
34+
lldb::SectionType sect_type, lldb::addr_t file_vm_addr,
35+
lldb::addr_t vm_size, lldb::offset_t file_offset,
36+
lldb::offset_t file_size, uint32_t log2align, uint32_t flags,
37+
size_t non_jit_size, uint32_t target_byte_size = 1)
38+
: Section(parent_section_sp, module_sp, obj_file, sect_id, name,
39+
sect_type, file_vm_addr, vm_size, file_offset, file_size,
40+
log2align, flags, target_byte_size),
41+
m_non_jit_size(non_jit_size) {}
42+
43+
// LLVM RTTI support
44+
static char ID;
45+
virtual bool isA(const void *ClassID) const {
46+
return ClassID == &ID || Section::isA(ClassID);
47+
}
48+
static bool classof(const Section *obj) { return obj->isA(&ID); }
49+
50+
/// Returns the section size discounting the jit specific data.
51+
size_t getNonJitSize() const { return m_non_jit_size; }
52+
53+
private:
54+
size_t m_non_jit_size = 0;
55+
};
56+
} // namespace lldb_private
57+
58+
#endif // LLDB_CORE_JIT_SECTION_H

lldb/include/lldb/Core/Section.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,12 @@ class Section : public std::enable_shared_from_this<Section>,
117117
lldb::offset_t file_size, uint32_t log2align, uint32_t flags,
118118
uint32_t target_byte_size = 1);
119119

120-
~Section();
120+
virtual ~Section();
121+
122+
// LLVM RTTI support
123+
static char ID;
124+
virtual bool isA(const void *ClassID) const { return ClassID == &ID; }
125+
static bool classof(const Section *obj) { return obj->isA(&ID); }
121126

122127
static int Compare(const Section &a, const Section &b);
123128

lldb/include/lldb/Expression/IRExecutionUnit.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
1919
#include "llvm/IR/Module.h"
20+
#include "llvm/ADT/StringMap.h"
2021

2122
#include "lldb/Expression/IRMemoryMap.h"
2223
#include "lldb/Symbol/ObjectFile.h"
@@ -409,6 +410,8 @@ class IRExecutionUnit : public std::enable_shared_from_this<IRExecutionUnit>,
409410
///< defining no functions using that variable, would do this.) If this
410411
///< is true, any allocations need to be committed immediately -- no
411412
///< opportunity for relocation.
413+
414+
llvm::StringMap<uint64_t> m_section_size_map;
412415
};
413416

414417
} // namespace lldb_private

lldb/source/Core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ add_lldb_library(lldbCore
3939
Highlighter.cpp
4040
IOHandler.cpp
4141
IOHandlerCursesGUI.cpp
42+
JITSection.cpp
4243
Mangled.cpp
4344
Module.cpp
4445
ModuleChild.cpp

lldb/source/Core/JITSection.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//===-- JITSection.cpp ----------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
10+
#include "lldb/Core/JITSection.h"
11+
12+
namespace lldb_private {
13+
char JITSection::ID;
14+
}

lldb/source/Core/Section.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class DataExtractor;
2525
using namespace lldb;
2626
using namespace lldb_private;
2727

28+
char Section::ID;
29+
2830
const char *Section::GetTypeAsCString() const {
2931
switch (m_type) {
3032
case eSectionTypeInvalid:

lldb/source/Expression/IRExecutionUnit.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "llvm/ADT/ScopeExit.h"
910
#include "llvm/ExecutionEngine/ExecutionEngine.h"
11+
#include "llvm/ExecutionEngine/JITEventListener.h"
1012
#include "llvm/ExecutionEngine/ObjectCache.h"
1113
#include "llvm/IR/Constants.h"
1214
#include "llvm/IR/LLVMContext.h"
@@ -16,6 +18,7 @@
1618

1719
#include "lldb/Core/Debugger.h"
1820
#include "lldb/Core/Disassembler.h"
21+
#include "lldb/Core/JITSection.h"
1922
#include "lldb/Core/Module.h"
2023
#include "lldb/Core/Section.h"
2124
#include "lldb/Expression/IRExecutionUnit.h"
@@ -336,6 +339,30 @@ void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr,
336339
m_execution_engine_up->setObjectCache(m_object_cache_up.get());
337340
}
338341

342+
/// Record the size of the sections discounting the extra space used
343+
/// by the JIT. This is a hack and should be removed when we switch
344+
/// from MCJIT to ORCJIT.
345+
struct JitSectionSizeRecorder : public llvm::JITEventListener {
346+
llvm::StringMap<uint64_t> &m_section_size_map;
347+
JitSectionSizeRecorder(llvm::StringMap<uint64_t> &section_size_map) :
348+
m_section_size_map(section_size_map) {}
349+
350+
void notifyObjectLoaded(ObjectKey K, const llvm::object::ObjectFile &Obj,
351+
const llvm::RuntimeDyld::LoadedObjectInfo &L) override {
352+
for (llvm::object::SectionRef section: Obj.sections()) {
353+
auto name = section.getName();
354+
if (name)
355+
m_section_size_map.insert({name.get(), section.getSize()});
356+
}
357+
358+
}
359+
};
360+
361+
JitSectionSizeRecorder size_recorder(m_section_size_map);
362+
m_execution_engine_up->RegisterJITEventListener(&size_recorder);
363+
auto on_exit = llvm::make_scope_exit(
364+
[&]() { m_execution_engine_up->UnregisterJITEventListener(&size_recorder); });
365+
339366
// Make sure we see all sections, including ones that don't have
340367
// relocations...
341368
m_execution_engine_up->setProcessAllSections(true);
@@ -1325,15 +1352,17 @@ void IRExecutionUnit::PopulateSectionList(
13251352
lldb_private::SectionList &section_list) {
13261353
for (AllocationRecord &record : m_records) {
13271354
if (record.m_size > 0) {
1328-
lldb::SectionSP section_sp(new lldb_private::Section(
1355+
size_t non_jit_size = m_section_size_map.lookup(record.m_name);
1356+
lldb::SectionSP section_sp(new lldb_private::JITSection(
13291357
obj_file->GetModule(), obj_file, record.m_section_id,
13301358
ConstString(record.m_name), record.m_sect_type,
13311359
record.m_process_address, record.m_size,
13321360
record.m_host_address, // file_offset (which is the host address for
13331361
// the data)
13341362
record.m_size, // file_size
13351363
0,
1336-
record.m_permissions)); // flags
1364+
record.m_permissions, // flags
1365+
non_jit_size));
13371366
section_list.AddSection(section_sp);
13381367
}
13391368
}

lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,8 @@ bool SwiftUserExpression::Parse(DiagnosticManager &diagnostic_manager,
352352
const lldb::LanguageType lang_type = lldb::eLanguageTypeSwift;
353353

354354
m_options.SetLanguage(lang_type);
355+
m_options.SetGenerateDebugInfo(generate_debug_info);
356+
355357
uint32_t first_body_line = 0;
356358

357359
// I have to pass some value for add_locals. I'm passing "false" because
@@ -473,7 +475,14 @@ bool SwiftUserExpression::Parse(DiagnosticManager &diagnostic_manager,
473475
StreamString jit_module_name;
474476
jit_module_name.Printf("%s%u", FunctionName(),
475477
m_options.GetExpressionNumber());
476-
m_execution_unit_sp->CreateJITModule(jit_module_name.GetString().data());
478+
auto module = m_execution_unit_sp->CreateJITModule(jit_module_name.GetString().data());
479+
480+
auto *swift_runtime = SwiftLanguageRuntime::Get(process);
481+
if (module && swift_runtime) {
482+
ModuleList modules;
483+
modules.Append(module, false);
484+
swift_runtime->ModulesDidLoad(modules);
485+
}
477486
}
478487

479488
if (jit_error.Success()) {

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "Utility/ARM64_DWARF_Registers.h"
1919
#include "lldb/Breakpoint/StoppointCallbackContext.h"
2020
#include "lldb/Core/Debugger.h"
21+
#include "lldb/Core/JITSection.h"
2122
#include "lldb/Core/PluginManager.h"
2223
#include "lldb/Core/Section.h"
2324
#include "lldb/Core/ValueObjectConstResult.h"
@@ -543,6 +544,58 @@ void SwiftLanguageRuntime::ModulesDidLoad(const ModuleList &module_list) {
543544
}
544545
}
545546

547+
bool SwiftLanguageRuntimeImpl::AddJitObjectFileToReflectionContext(
548+
ObjectFile &obj_file, llvm::Triple::ObjectFormatType obj_format_type) {
549+
assert(obj_file.GetType() == ObjectFile::eTypeJIT &&
550+
"Not a JIT object file!");
551+
std::unique_ptr<swift::SwiftObjectFileFormat> obj_file_format;
552+
switch (obj_format_type) {
553+
case llvm::Triple::MachO:
554+
obj_file_format = std::make_unique<swift::SwiftObjectFileFormatMachO>();
555+
break;
556+
case llvm::Triple::ELF:
557+
obj_file_format = std::make_unique<swift::SwiftObjectFileFormatELF>();
558+
break;
559+
case llvm::Triple::COFF:
560+
obj_file_format = std::make_unique<swift::SwiftObjectFileFormatCOFF>();
561+
break;
562+
default:
563+
if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TYPES))
564+
log->Printf("%s: Could not find out swift reflection section names for "
565+
"object format type.",
566+
__FUNCTION__);
567+
return false;
568+
}
569+
570+
return m_reflection_ctx->addImage(
571+
[&](swift::ReflectionSectionKind section_kind)
572+
-> std::pair<swift::remote::RemoteRef<void>, uint64_t> {
573+
auto section_name =
574+
ConstString(obj_file_format->getSectionName(section_kind));
575+
for (auto section : *obj_file.GetSectionList()) {
576+
JITSection *jit_section = llvm::dyn_cast<JITSection>(section.get());
577+
if (jit_section && section->GetName() == section_name) {
578+
DataExtractor extractor;
579+
auto section_size = section->GetSectionData(extractor);
580+
if (!section_size)
581+
return {};
582+
auto size = jit_section->getNonJitSize();
583+
auto data = extractor.GetData();
584+
if (section_size < size || !data.begin())
585+
return {};
586+
587+
auto *Buf = malloc(size);
588+
std::memcpy(Buf, data.begin(), size);
589+
swift::remote::RemoteRef<void> remote_ref(section->GetFileAddress(),
590+
Buf);
591+
592+
return {remote_ref, size};
593+
}
594+
}
595+
return {};
596+
});
597+
}
598+
546599
bool SwiftLanguageRuntimeImpl::AddModuleToReflectionContext(
547600
const lldb::ModuleSP &module_sp) {
548601
// This function is called from within SetupReflection so it cannot
@@ -558,6 +611,12 @@ bool SwiftLanguageRuntimeImpl::AddModuleToReflectionContext(
558611
Address start_address = obj_file->GetBaseAddress();
559612
auto load_ptr = static_cast<uintptr_t>(
560613
start_address.GetLoadAddress(&(m_process.GetTarget())));
614+
if (obj_file->GetType() == ObjectFile::eTypeJIT) {
615+
auto object_format_type =
616+
module_sp->GetArchitecture().GetTriple().getObjectFormat();
617+
return AddJitObjectFileToReflectionContext(*obj_file, object_format_type);
618+
}
619+
561620
if (load_ptr == 0 || load_ptr == LLDB_INVALID_ADDRESS) {
562621
if (obj_file->GetType() != ObjectFile::eTypeJIT)
563622
if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TYPES))

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,73 +1805,6 @@ bool SwiftLanguageRuntimeImpl::IsValidErrorValue(ValueObject &in_value) {
18051805

18061806
return true;
18071807
}
1808-
/// Digs into the protocols inside a protocol composition and checks if
1809-
/// any of them belong to the LLDB module.
1810-
static bool
1811-
IsDeclaredInLLDBExpr(const swift::reflection::TypeRef *typeref) {
1812-
using swift::Demangle::Node;
1813-
1814-
const auto *protocol_typeref = llvm::dyn_cast_or_null<
1815-
const swift::reflection::ProtocolCompositionTypeRef>(typeref);
1816-
1817-
if (!protocol_typeref)
1818-
return false;
1819-
1820-
swift::Demangle::Demangler dem;
1821-
1822-
NodePointer type = protocol_typeref->getDemangling(dem);
1823-
if (!type || type->getKind() != Node::Kind::Type ||
1824-
type->getNumChildren() == 0)
1825-
return false;
1826-
1827-
NodePointer maybe_protocol_list = type->getFirstChild();
1828-
NodePointer protocol_list;
1829-
1830-
if (!maybe_protocol_list)
1831-
return false;
1832-
1833-
switch (maybe_protocol_list->getKind()) {
1834-
case Node::Kind::ProtocolList:
1835-
protocol_list = maybe_protocol_list;
1836-
break;
1837-
case Node::Kind::ProtocolListWithAnyObject:
1838-
case Node::Kind::ProtocolListWithClass:
1839-
if (maybe_protocol_list->getNumChildren() == 0)
1840-
return false;
1841-
protocol_list = maybe_protocol_list->getFirstChild();
1842-
break;
1843-
default:
1844-
return false;
1845-
}
1846-
1847-
if (!protocol_list || protocol_list->getKind() != Node::Kind::ProtocolList ||
1848-
protocol_list->getNumChildren() == 0)
1849-
return false;
1850-
1851-
NodePointer type_list = protocol_list->getFirstChild();
1852-
if (!type_list || type_list->getKind() != Node::Kind::TypeList)
1853-
return false;
1854-
1855-
for (NodePointer internal_type : *type_list) {
1856-
if (!internal_type || internal_type->getKind() != Node::Kind::Type ||
1857-
internal_type->getNumChildren() == 0)
1858-
continue;
1859-
1860-
NodePointer protocol = internal_type->getFirstChild();
1861-
if (!protocol || protocol->getKind() != Node::Kind::Protocol ||
1862-
protocol->getNumChildren() == 0)
1863-
continue;
1864-
1865-
NodePointer module = protocol->getFirstChild();
1866-
if (!module || module->getKind() != Node::Kind::Module ||
1867-
!module->hasText())
1868-
continue;
1869-
1870-
if (module->getText().startswith("__lldb_expr_"))
1871-
return true;
1872-
}
1873-
return false;
1874-
}
18751808

18761809
bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Protocol(
18771810
ValueObject &in_value, CompilerType protocol_type,
@@ -1957,17 +1890,6 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Protocol(
19571890
return false;
19581891
}
19591892

1960-
// If the protocol list contains any types declared in LLDB,
1961-
// we use the remote AST implementation since we currently
1962-
// don't register the metadata generated by LLDB.
1963-
if (IsDeclaredInLLDBExpr(protocol_typeref)) {
1964-
auto pair = remote_ast_impl(use_local_buffer, existential_address);
1965-
if (!pair)
1966-
return false;
1967-
class_type_or_name.SetCompilerType(std::get<CompilerType>(*pair));
1968-
address = std::get<Address>(*pair);
1969-
return true;
1970-
}
19711893

19721894
if (use_local_buffer)
19731895
PushLocalBuffer(existential_address, in_value.GetByteSize().getValueOr(0));

0 commit comments

Comments
 (0)