Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -720,6 +720,8 @@ 9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703AE117675410086C050 /* SBInstruction.cpp */; }; 9AC703B1117675490086C050 /* SBInstructionList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703B0117675490086C050 /* SBInstructionList.cpp */; }; A36FF33C17D8E94600244D40 /* OptionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A36FF33B17D8E94600244D40 /* OptionParser.cpp */; }; + AE8F624919EF3E1E00326B21 /* OperatingSystemGo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE8F624719EF3E1E00326B21 /* OperatingSystemGo.cpp */; }; + AE8F624A19EF3E1E00326B21 /* OperatingSystemGo.h in Headers */ = {isa = PBXBuildFile; fileRef = AE8F624819EF3E1E00326B21 /* OperatingSystemGo.h */; }; AF061F87182C97ED00B6A19C /* RegisterContextHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */; }; AF061F88182C97ED00B6A19C /* RegisterContextHistory.h in Headers */ = {isa = PBXBuildFile; fileRef = AF061F86182C97ED00B6A19C /* RegisterContextHistory.h */; }; AF061F8B182C980000B6A19C /* HistoryThread.h in Headers */ = {isa = PBXBuildFile; fileRef = AF061F89182C980000B6A19C /* HistoryThread.h */; }; @@ -2145,6 +2147,8 @@ 9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBBreakpointLocation.cpp; path = source/API/SBBreakpointLocation.cpp; sourceTree = ""; }; A36FF33B17D8E94600244D40 /* OptionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OptionParser.cpp; sourceTree = ""; }; A36FF33D17D8E98800244D40 /* OptionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionParser.h; path = include/lldb/Host/OptionParser.h; sourceTree = ""; }; + AE8F624719EF3E1E00326B21 /* OperatingSystemGo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OperatingSystemGo.cpp; path = Go/OperatingSystemGo.cpp; sourceTree = ""; }; + AE8F624819EF3E1E00326B21 /* OperatingSystemGo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OperatingSystemGo.h; path = Go/OperatingSystemGo.h; sourceTree = ""; }; AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextHistory.cpp; path = Utility/RegisterContextHistory.cpp; sourceTree = ""; }; AF061F86182C97ED00B6A19C /* RegisterContextHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextHistory.h; path = Utility/RegisterContextHistory.h; sourceTree = ""; }; AF061F89182C980000B6A19C /* HistoryThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HistoryThread.h; path = Utility/HistoryThread.h; sourceTree = ""; }; @@ -2978,6 +2982,7 @@ 266DFE9013FD64D200D0C574 /* OperatingSystem */ = { isa = PBXGroup; children = ( + AE8F624519EF3DFC00326B21 /* Go */, 2698699715E6CBD0002415FF /* Python */, ); path = OperatingSystem; @@ -4349,6 +4354,15 @@ name = DataFormatters; sourceTree = ""; }; + AE8F624519EF3DFC00326B21 /* Go */ = { + isa = PBXGroup; + children = ( + AE8F624719EF3E1E00326B21 /* OperatingSystemGo.cpp */, + AE8F624819EF3E1E00326B21 /* OperatingSystemGo.h */, + ); + name = Go; + sourceTree = ""; + }; AF11CB34182CA85A00D9B618 /* SystemRuntime */ = { isa = PBXGroup; children = ( @@ -4503,6 +4517,7 @@ AF2BCA6D18C7EFDE005B4526 /* JITLoaderGDB.h in Headers */, 232CB61E191E00CD00EF39FC /* SoftwareBreakpoint.h in Headers */, 26BC17B218C7F4CB00D2196D /* ThreadElfCore.h in Headers */, + AE8F624A19EF3E1E00326B21 /* OperatingSystemGo.h in Headers */, 26FFC19E14FC072100087D58 /* DynamicLoaderPOSIXDYLD.h in Headers */, AF254E32170CCC33007AE5C9 /* PlatformDarwinKernel.h in Headers */, 2694E99E14FC0BB30076DE67 /* PlatformFreeBSD.h in Headers */, @@ -5158,6 +5173,7 @@ 2689008D13353E4200698AC0 /* DynamicLoaderMacOSXDYLD.cpp in Sources */, 2689008E13353E4200698AC0 /* DynamicLoaderStatic.cpp in Sources */, 2689009613353E4200698AC0 /* ObjectContainerBSDArchive.cpp in Sources */, + AE8F624919EF3E1E00326B21 /* OperatingSystemGo.cpp in Sources */, 26BC179A18C7F2B300D2196D /* JITLoaderList.cpp in Sources */, 2689009713353E4200698AC0 /* ObjectContainerUniversalMachO.cpp in Sources */, 2689009813353E4200698AC0 /* ELFHeader.cpp in Sources */, Index: source/Plugins/OperatingSystem/Go/OperatingSystemGo.h =================================================================== --- /dev/null +++ source/Plugins/OperatingSystem/Go/OperatingSystemGo.h @@ -0,0 +1,98 @@ +//===-- OperatingSystemGo.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===-------------------------------------------------------------------===// + +#ifndef _liblldb_OperatingSystemGo_h_ +#define _liblldb_OperatingSystemGo_h_ + +#include + +#include "lldb/Target/OperatingSystem.h" + +class DynamicRegisterInfo; + +class OperatingSystemGo : public lldb_private::OperatingSystem +{ + public: + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + static lldb_private::OperatingSystem * + CreateInstance(lldb_private::Process *process, bool force); + + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::ConstString + GetPluginNameStatic(); + + static const char * + GetPluginDescriptionStatic(); + + //------------------------------------------------------------------ + // Class Methods + //------------------------------------------------------------------ + OperatingSystemGo(lldb_private::Process *process); + + virtual ~OperatingSystemGo(); + + //------------------------------------------------------------------ + // lldb_private::PluginInterface Methods + //------------------------------------------------------------------ + virtual lldb_private::ConstString + GetPluginName(); + + virtual uint32_t + GetPluginVersion(); + + //------------------------------------------------------------------ + // lldb_private::OperatingSystem Methods + //------------------------------------------------------------------ + virtual bool + UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &real_thread_list, + lldb_private::ThreadList &new_thread_list); + + virtual void + ThreadWasSelected(lldb_private::Thread *thread); + + virtual lldb::RegisterContextSP + CreateRegisterContextForThread(lldb_private::Thread *thread, lldb::addr_t reg_data_addr); + + virtual lldb::StopInfoSP + CreateThreadStopReason(lldb_private::Thread *thread); + + //------------------------------------------------------------------ + // Method for lazy creation of threads on demand + //------------------------------------------------------------------ + virtual lldb::ThreadSP + CreateThread(lldb::tid_t tid, lldb::addr_t context); + + private: + struct Goroutine; + + static lldb::ValueObjectSP + FindGlobal(lldb::TargetSP target, const char *name); + + static lldb::TypeSP + FindType(lldb::TargetSP target_sp, const char *name); + + bool + Init(lldb_private::ThreadList &threads); + + Goroutine + CreateGoroutineAtIndex(uint64_t idx, lldb_private::Error &err); + + std::unique_ptr m_reginfo; + lldb::ValueObjectSP m_allg_sp; + lldb::ValueObjectSP m_allglen_sp; +}; + +#endif // #ifndef liblldb_OperatingSystemGo_h_ Index: source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp =================================================================== --- /dev/null +++ source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp @@ -0,0 +1,451 @@ +//===-- OperatingSystemGo.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "OperatingSystemGo.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Symbol/ClangNamespaceDecl.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadList.h" +#include "lldb/Target/Thread.h" +#include "Plugins/Process/Utility/DynamicRegisterInfo.h" +#include "Plugins/Process/Utility/RegisterContextMemory.h" +#include "Plugins/Process/Utility/ThreadMemory.h" + +using namespace lldb; +using namespace lldb_private; + +namespace +{ +class RegisterContextGo : public RegisterContextMemory +{ + public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContextGo(lldb_private::Thread &thread, uint32_t concrete_frame_idx, DynamicRegisterInfo ®_info, lldb::addr_t reg_data_addr) + : RegisterContextMemory(thread, concrete_frame_idx, reg_info, reg_data_addr) + { + const RegisterInfo *sp = + reg_info.GetRegisterInfoAtIndex(reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP)); + const RegisterInfo *pc = + reg_info.GetRegisterInfoAtIndex(reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC)); + size_t byte_size = std::max(sp->byte_offset + sp->byte_size, pc->byte_offset + pc->byte_size); + + DataBufferSP reg_data_sp(new DataBufferHeap(byte_size, 0)); + m_reg_data.SetData(reg_data_sp); + } + + virtual ~RegisterContextGo() {} + + virtual bool + ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue ®_value) + { + switch (reg_info->kinds[eRegisterKindGeneric]) + { + case LLDB_REGNUM_GENERIC_SP: + case LLDB_REGNUM_GENERIC_PC: + return RegisterContextMemory::ReadRegister(reg_info, reg_value); + default: + reg_value.SetValueToInvalid(); + return true; + } + } + + virtual bool + WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue ®_value) + { + switch (reg_info->kinds[eRegisterKindGeneric]) + { + case LLDB_REGNUM_GENERIC_SP: + case LLDB_REGNUM_GENERIC_PC: + return RegisterContextMemory::WriteRegister(reg_info, reg_value); + default: + return false; + } + } + + private: + DISALLOW_COPY_AND_ASSIGN(RegisterContextGo); +}; +} + +struct OperatingSystemGo::Goroutine +{ + uint64_t m_lostack; + uint64_t m_histack; + uint64_t m_goid; + addr_t m_gobuf; + uint32_t m_status; +}; + +void +OperatingSystemGo::Initialize() +{ + PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); +} + +void +OperatingSystemGo::Terminate() +{ + PluginManager::UnregisterPlugin(CreateInstance); +} + +OperatingSystem * +OperatingSystemGo::CreateInstance(Process *process, bool force) +{ + return new OperatingSystemGo(process); +} + +ConstString +OperatingSystemGo::GetPluginNameStatic() +{ + static ConstString g_name("Go"); + return g_name; +} + +const char * +OperatingSystemGo::GetPluginDescriptionStatic() +{ + return "Operating system plug-in that reads runtime data-structures for goroutines."; +} + +OperatingSystemGo::OperatingSystemGo(lldb_private::Process *process) + : OperatingSystem(process) + , m_reginfo(new DynamicRegisterInfo) +{ +} + +OperatingSystemGo::~OperatingSystemGo() +{ +} + +bool +OperatingSystemGo::Init(ThreadList &threads) +{ + if (threads.GetSize(false) < 1) + return false; + TargetSP target_sp = m_process->CalculateTarget(); + if (!target_sp) + return false; + m_allg_sp = FindGlobal(target_sp, "runtime.allg"); + m_allglen_sp = FindGlobal(target_sp, "runtime.allglen"); + + if (m_allg_sp && !m_allglen_sp) + { + StreamSP error_sp = target_sp->GetDebugger().GetAsyncErrorStream (); + error_sp->Printf ("Unsupported Go runtime version detected."); + return false; + } + + if (!m_allg_sp) + return false; + + RegisterContextSP real_registers_sp = threads.GetThreadAtIndex(0)->GetRegisterContext(); + + std::unordered_map register_sets; + for (size_t set_idx = 0; set_idx < real_registers_sp->GetRegisterSetCount(); ++set_idx) + { + const RegisterSet *set = real_registers_sp->GetRegisterSet(set_idx); + ConstString name(set->name); + for (int reg_idx = 0; reg_idx < set->num_registers; ++reg_idx) + { + register_sets[reg_idx] = name; + } + } + TypeSP gobuf_sp = FindType(target_sp, "runtime.gobuf"); + if (!gobuf_sp) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); + + if (log) + log->Printf("OperatingSystemGo unable to find struct Gobuf"); + return false; + } + ClangASTType gobuf_type(gobuf_sp->GetClangLayoutType()); + for (int idx = 0; idx < real_registers_sp->GetRegisterCount(); ++idx) + { + RegisterInfo reg = *real_registers_sp->GetRegisterInfoAtIndex(idx); + int field_index = -1; + if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_SP) + { + field_index = 0; + } + else if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC) + { + field_index = 1; + } + if (field_index == -1) + { + reg.byte_offset = ~0; + } + else + { + std::string field_name; + uint64_t bit_offset = 0; + ClangASTType field_type = gobuf_type.GetFieldAtIndex(field_index, field_name, &bit_offset, nullptr, nullptr); + reg.byte_size = field_type.GetByteSize(); + reg.byte_offset = bit_offset / 8; + } + ConstString name(reg.name); + ConstString alt_name(reg.alt_name); + m_reginfo->AddRegister(reg, name, alt_name, register_sets[idx]); + } + return true; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +ConstString +OperatingSystemGo::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +OperatingSystemGo::GetPluginVersion() +{ + return 1; +} + +bool +OperatingSystemGo::UpdateThreadList(ThreadList &old_thread_list, ThreadList &real_thread_list, ThreadList &new_thread_list) +{ + new_thread_list = real_thread_list; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); + + if (!(m_allg_sp || Init(real_thread_list)) || + (m_allg_sp && !m_allglen_sp)) + { + return new_thread_list.GetSize(false) > 0; + } + + if (log) + log->Printf("OperatingSystemGo::UpdateThreadList(%d, %d, %d) fetching thread data from Go for pid %" PRIu64, + old_thread_list.GetSize(false), real_thread_list.GetSize(false), new_thread_list.GetSize(0), m_process->GetID()); + uint64_t allglen = m_allglen_sp->GetValueAsUnsigned(0); + if (allglen == 0) + { + return new_thread_list.GetSize(false) > 0; + } + std::vector goroutines; + // The threads that are in "new_thread_list" upon entry are the threads from the + // lldb_private::Process subclass, no memory threads will be in this list. + + Error err; + for (uint64_t i = 0; i < allglen; ++i) + { + goroutines.push_back(CreateGoroutineAtIndex(i, err)); + if (err.Fail()) + { + err.PutToLog(log, "OperatingSystemGo::UpdateThreadList"); + return new_thread_list.GetSize(false) > 0; + } + } + // Make a map so we can match goroutines with backing threads. + std::map stack_map; + for (uint32_t i = 0; i < real_thread_list.GetSize(false); ++i) + { + ThreadSP thread = real_thread_list.GetThreadAtIndex(i, false); + stack_map[thread->GetRegisterContext()->GetSP()] = thread; + } + for (const Goroutine &goroutine : goroutines) + { + if (0 /* Gidle */ == goroutine.m_status || 6 /* Gdead */ == goroutine.m_status) + { + continue; + } + ThreadSP memory_thread = old_thread_list.FindThreadByID(goroutine.m_goid, false); + if (memory_thread && IsOperatingSystemPluginThread(memory_thread)) + { + memory_thread->ClearBackingThread(); + } + else + { + memory_thread.reset(new ThreadMemory(*m_process, goroutine.m_goid, nullptr, nullptr, goroutine.m_gobuf)); + } + // Search for the backing thread if the goroutine is running. + if (2 == (goroutine.m_status & 0xfff)) + { + auto backing_it = stack_map.lower_bound(goroutine.m_lostack); + if (backing_it != stack_map.end()) + { + if (goroutine.m_histack >= backing_it->first) + { + memory_thread->SetBackingThread(backing_it->second); + // Make sure the stop info propagates to the memory thread. + // Not sure why this is necessary. + memory_thread->GetStopInfo(); + new_thread_list.RemoveThreadByID(backing_it->second->GetID(), false); + } + } + } + new_thread_list.AddThread(memory_thread); + } + + return new_thread_list.GetSize(false) > 0; +} + +void +OperatingSystemGo::ThreadWasSelected(Thread *thread) +{ +} + +RegisterContextSP +OperatingSystemGo::CreateRegisterContextForThread(Thread *thread, addr_t reg_data_addr) +{ + RegisterContextSP reg_ctx_sp; + if (!thread) + return reg_ctx_sp; + + if (!IsOperatingSystemPluginThread(thread->shared_from_this())) + return reg_ctx_sp; + + reg_ctx_sp.reset(new RegisterContextGo(*thread, 0, *m_reginfo, reg_data_addr)); + return reg_ctx_sp; +} + +StopInfoSP +OperatingSystemGo::CreateThreadStopReason(lldb_private::Thread *thread) +{ + StopInfoSP stop_info_sp; + return stop_info_sp; +} + +lldb::ThreadSP +OperatingSystemGo::CreateThread(lldb::tid_t tid, addr_t context) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); + + if (log) + log->Printf("OperatingSystemGo::CreateThread (tid = 0x%" PRIx64 ", context = 0x%" PRIx64 ") not implemented", tid, context); + + return ThreadSP(); +} + +ValueObjectSP +OperatingSystemGo::FindGlobal(TargetSP target, const char *name) +{ + VariableList variable_list; + const bool append = true; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); + + if (log) + { + log->Printf("exe: %s", target->GetExecutableModule()->GetSpecificationDescription().c_str()); + log->Printf("modules: %zu", target->GetImages().GetSize()); + } + + uint32_t match_count = target->GetImages().FindGlobalVariables(ConstString(name), append, 1, variable_list); + if (match_count > 0) + { + ExecutionContextScope *exe_scope = target->GetProcessSP().get(); + if (exe_scope == NULL) + exe_scope = target.get(); + return ValueObjectVariable::Create(exe_scope, variable_list.GetVariableAtIndex(0)); + } + return ValueObjectSP(); +} + +TypeSP +OperatingSystemGo::FindType(TargetSP target_sp, const char *name) +{ + ConstString const_typename(name); + SymbolContext sc; + const bool exact_match = false; + + const ModuleList &module_list = target_sp->GetImages(); + size_t count = module_list.GetSize(); + for (size_t idx = 0; idx < count; idx++) + { + ModuleSP module_sp(module_list.GetModuleAtIndex(idx)); + if (module_sp) + { + TypeSP type_sp(module_sp->FindFirstType(sc, const_typename, exact_match)); + if (type_sp) + return type_sp; + } + } + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); + + if (log) + log->Printf("OperatingSystemGo::FindType(%s): not found", name); + return TypeSP(); +} + +OperatingSystemGo::Goroutine +OperatingSystemGo::CreateGoroutineAtIndex(uint64_t idx, Error &err) +{ + err.Clear(); + Goroutine result; + ValueObjectSP g = m_allg_sp->GetSyntheticArrayMemberFromPointer(idx, true)->Dereference(err); + if (err.Fail()) + { + return result; + } + + ConstString name("goid"); + ValueObjectSP val = g->GetChildMemberWithName(name, true); + bool success = false; + result.m_goid = val->GetValueAsUnsigned(0, &success); + if (!success) + { + err.SetErrorToGenericError(); + err.SetErrorString("unable to read goid"); + return result; + } + name.SetCString("atomicstatus"); + val = g->GetChildMemberWithName(name, true); + result.m_status = (uint32_t)val->GetValueAsUnsigned(0, &success); + if (!success) + { + err.SetErrorToGenericError(); + err.SetErrorString("unable to read atomicstatus"); + return result; + } + name.SetCString("sched"); + val = g->GetChildMemberWithName(name, true); + result.m_gobuf = val->GetAddressOf(false); + name.SetCString("stack"); + val = g->GetChildMemberWithName(name, true); + name.SetCString("lo"); + ValueObjectSP child = val->GetChildMemberWithName(name, true); + result.m_lostack = child->GetValueAsUnsigned(0, &success); + if (!success) + { + err.SetErrorToGenericError(); + err.SetErrorString("unable to read stack.lo"); + return result; + } + name.SetCString("hi"); + child = val->GetChildMemberWithName(name, true); + result.m_histack = child->GetValueAsUnsigned(0, &success); + if (!success) + { + err.SetErrorToGenericError(); + err.SetErrorString("unable to read stack.hi"); + return result; + } + return result; +} Index: source/lldb.cpp =================================================================== --- source/lldb.cpp +++ source/lldb.cpp @@ -58,6 +58,7 @@ #ifndef LLDB_DISABLE_PYTHON #include "Plugins/OperatingSystem/Python/OperatingSystemPython.h" #endif +#include "Plugins/OperatingSystem/Go/OperatingSystemGo.h" #if defined (__APPLE__) #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" @@ -154,6 +155,7 @@ ScriptInterpreterPython::InitializePrivate(); OperatingSystemPython::Initialize(); #endif + OperatingSystemGo::Initialize(); JITLoaderGDB::Initialize(); ProcessElfCore::Initialize(); MemoryHistoryASan::Initialize(); @@ -246,6 +248,7 @@ #ifndef LLDB_DISABLE_PYTHON OperatingSystemPython::Terminate(); #endif + OperatingSystemGo::Terminate(); JITLoaderGDB::Terminate(); ProcessElfCore::Terminate(); MemoryHistoryASan::Terminate();