Skip to content

Commit 88f94ab

Browse files
authored
Merge pull request #3051 from augusto2112/parse-reflection-from-jit
[lldb] Implement parsing of metadata generated by the JIT.
2 parents ef46d4e + 2de488f commit 88f94ab

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)