blob: 3f60839315131fe615380c5b8743acad5ccd664d [file] [log] [blame]
Eugene Zelenko45a40142015-10-22 21:24:37 +00001//===-- OperatingSystemGo.cpp -----------------------------------*- C++ -*-===//
Ryan Brown65d4d5c2015-09-16 21:20:44 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Ryan Brown65d4d5c2015-09-16 21:20:44 +00009
10// C Includes
11// C++ Includes
12#include <unordered_map>
13
14// Other libraries and framework includes
Eugene Zelenko45a40142015-10-22 21:24:37 +000015// Project includes
16#include "OperatingSystemGo.h"
17
Kate Stoneb9c1b512016-09-06 20:57:50 +000018#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
19#include "Plugins/Process/Utility/RegisterContextMemory.h"
20#include "Plugins/Process/Utility/ThreadMemory.h"
Ryan Brown65d4d5c2015-09-16 21:20:44 +000021#include "lldb/Core/Debugger.h"
22#include "lldb/Core/Module.h"
23#include "lldb/Core/PluginManager.h"
24#include "lldb/Core/RegisterValue.h"
25#include "lldb/Core/Section.h"
Ryan Brown65d4d5c2015-09-16 21:20:44 +000026#include "lldb/Core/ValueObjectVariable.h"
27#include "lldb/Interpreter/CommandInterpreter.h"
Ryan Brown65d4d5c2015-09-16 21:20:44 +000028#include "lldb/Interpreter/OptionGroupBoolean.h"
29#include "lldb/Interpreter/OptionGroupUInt64.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000030#include "lldb/Interpreter/OptionValueProperties.h"
31#include "lldb/Interpreter/Options.h"
Ryan Brown65d4d5c2015-09-16 21:20:44 +000032#include "lldb/Interpreter/Property.h"
33#include "lldb/Symbol/ObjectFile.h"
34#include "lldb/Symbol/Type.h"
35#include "lldb/Symbol/VariableList.h"
36#include "lldb/Target/Process.h"
37#include "lldb/Target/StopInfo.h"
38#include "lldb/Target/Target.h"
Ryan Brown65d4d5c2015-09-16 21:20:44 +000039#include "lldb/Target/Thread.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000040#include "lldb/Target/ThreadList.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000041#include "lldb/Utility/DataBufferHeap.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000042#include "lldb/Utility/StreamString.h"
Ryan Brown65d4d5c2015-09-16 21:20:44 +000043
44using namespace lldb;
45using namespace lldb_private;
46
Kate Stoneb9c1b512016-09-06 20:57:50 +000047namespace {
Ryan Brown65d4d5c2015-09-16 21:20:44 +000048
Kate Stoneb9c1b512016-09-06 20:57:50 +000049static PropertyDefinition g_properties[] = {
50 {"enable", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
51 "Specify whether goroutines should be treated as threads."},
52 {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};
Ryan Brown65d4d5c2015-09-16 21:20:44 +000053
Kate Stoneb9c1b512016-09-06 20:57:50 +000054enum {
55 ePropertyEnableGoroutines,
Ryan Brown65d4d5c2015-09-16 21:20:44 +000056};
57
Kate Stoneb9c1b512016-09-06 20:57:50 +000058class PluginProperties : public Properties {
Eugene Zelenko45a40142015-10-22 21:24:37 +000059public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000060 PluginProperties() : Properties() {
61 m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
62 m_collection_sp->Initialize(g_properties);
63 }
Ryan Brown65d4d5c2015-09-16 21:20:44 +000064
Kate Stoneb9c1b512016-09-06 20:57:50 +000065 ~PluginProperties() override = default;
Eugene Zelenko45a40142015-10-22 21:24:37 +000066
Kate Stoneb9c1b512016-09-06 20:57:50 +000067 static ConstString GetSettingName() {
68 return OperatingSystemGo::GetPluginNameStatic();
69 }
Ryan Brown65d4d5c2015-09-16 21:20:44 +000070
Kate Stoneb9c1b512016-09-06 20:57:50 +000071 bool GetEnableGoroutines() {
72 const uint32_t idx = ePropertyEnableGoroutines;
73 return m_collection_sp->GetPropertyAtIndexAsBoolean(
74 NULL, idx, g_properties[idx].default_uint_value);
75 }
Ryan Brown65d4d5c2015-09-16 21:20:44 +000076
Kate Stoneb9c1b512016-09-06 20:57:50 +000077 bool SetEnableGoroutines(bool enable) {
78 const uint32_t idx = ePropertyEnableGoroutines;
79 return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, enable);
80 }
Ryan Brown65d4d5c2015-09-16 21:20:44 +000081};
82
83typedef std::shared_ptr<PluginProperties> OperatingSystemGoPropertiesSP;
84
Kate Stoneb9c1b512016-09-06 20:57:50 +000085static const OperatingSystemGoPropertiesSP &GetGlobalPluginProperties() {
86 static OperatingSystemGoPropertiesSP g_settings_sp;
87 if (!g_settings_sp)
88 g_settings_sp.reset(new PluginProperties());
89 return g_settings_sp;
Ryan Brown65d4d5c2015-09-16 21:20:44 +000090}
91
Kate Stoneb9c1b512016-09-06 20:57:50 +000092class RegisterContextGo : public RegisterContextMemory {
Eugene Zelenko45a40142015-10-22 21:24:37 +000093public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000094 RegisterContextGo(lldb_private::Thread &thread, uint32_t concrete_frame_idx,
95 DynamicRegisterInfo &reg_info, lldb::addr_t reg_data_addr)
96 : RegisterContextMemory(thread, concrete_frame_idx, reg_info,
97 reg_data_addr) {
98 const RegisterInfo *sp = reg_info.GetRegisterInfoAtIndex(
99 reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
100 LLDB_REGNUM_GENERIC_SP));
101 const RegisterInfo *pc = reg_info.GetRegisterInfoAtIndex(
102 reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
103 LLDB_REGNUM_GENERIC_PC));
104 size_t byte_size = std::max(sp->byte_offset + sp->byte_size,
105 pc->byte_offset + pc->byte_size);
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000106
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107 DataBufferSP reg_data_sp(new DataBufferHeap(byte_size, 0));
108 m_reg_data.SetData(reg_data_sp);
109 }
110
111 ~RegisterContextGo() override = default;
112
113 bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
114 lldb_private::RegisterValue &reg_value) override {
115 switch (reg_info->kinds[eRegisterKindGeneric]) {
116 case LLDB_REGNUM_GENERIC_SP:
117 case LLDB_REGNUM_GENERIC_PC:
118 return RegisterContextMemory::ReadRegister(reg_info, reg_value);
119 default:
120 reg_value.SetValueToInvalid();
121 return true;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000122 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000123 }
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000124
Kate Stoneb9c1b512016-09-06 20:57:50 +0000125 bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
126 const lldb_private::RegisterValue &reg_value) override {
127 switch (reg_info->kinds[eRegisterKindGeneric]) {
128 case LLDB_REGNUM_GENERIC_SP:
129 case LLDB_REGNUM_GENERIC_PC:
130 return RegisterContextMemory::WriteRegister(reg_info, reg_value);
131 default:
132 return false;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000133 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000134 }
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000135
Eugene Zelenko45a40142015-10-22 21:24:37 +0000136private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137 DISALLOW_COPY_AND_ASSIGN(RegisterContextGo);
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000138};
139
Eugene Zelenko45a40142015-10-22 21:24:37 +0000140} // anonymous namespace
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000141
Kate Stoneb9c1b512016-09-06 20:57:50 +0000142struct OperatingSystemGo::Goroutine {
143 uint64_t m_lostack;
144 uint64_t m_histack;
145 uint64_t m_goid;
146 addr_t m_gobuf;
147 uint32_t m_status;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000148};
149
Kate Stoneb9c1b512016-09-06 20:57:50 +0000150void OperatingSystemGo::Initialize() {
151 PluginManager::RegisterPlugin(GetPluginNameStatic(),
152 GetPluginDescriptionStatic(), CreateInstance,
153 DebuggerInitialize);
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000154}
155
Kate Stoneb9c1b512016-09-06 20:57:50 +0000156void OperatingSystemGo::DebuggerInitialize(Debugger &debugger) {
157 if (!PluginManager::GetSettingForOperatingSystemPlugin(
158 debugger, PluginProperties::GetSettingName())) {
159 const bool is_global_setting = true;
160 PluginManager::CreateSettingForOperatingSystemPlugin(
161 debugger, GetGlobalPluginProperties()->GetValueProperties(),
162 ConstString("Properties for the goroutine thread plug-in."),
163 is_global_setting);
164 }
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000165}
166
Kate Stoneb9c1b512016-09-06 20:57:50 +0000167void OperatingSystemGo::Terminate() {
168 PluginManager::UnregisterPlugin(CreateInstance);
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000169}
170
Kate Stoneb9c1b512016-09-06 20:57:50 +0000171OperatingSystem *OperatingSystemGo::CreateInstance(Process *process,
172 bool force) {
173 if (!force) {
174 TargetSP target_sp = process->CalculateTarget();
175 if (!target_sp)
176 return nullptr;
177 ModuleList &module_list = target_sp->GetImages();
178 std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
179 const size_t num_modules = module_list.GetSize();
180 bool found_go_runtime = false;
181 for (size_t i = 0; i < num_modules; ++i) {
182 Module *module = module_list.GetModulePointerAtIndexUnlocked(i);
183 const SectionList *section_list = module->GetSectionList();
184 if (section_list) {
185 SectionSP section_sp(
186 section_list->FindSectionByType(eSectionTypeGoSymtab, true));
187 if (section_sp) {
188 found_go_runtime = true;
189 break;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000190 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000191 }
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000192 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000193 if (!found_go_runtime)
194 return nullptr;
195 }
196 return new OperatingSystemGo(process);
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000197}
198
Eugene Zelenko45a40142015-10-22 21:24:37 +0000199OperatingSystemGo::OperatingSystemGo(lldb_private::Process *process)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000200 : OperatingSystem(process), m_reginfo(new DynamicRegisterInfo) {}
Eugene Zelenko45a40142015-10-22 21:24:37 +0000201
202OperatingSystemGo::~OperatingSystemGo() = default;
203
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204ConstString OperatingSystemGo::GetPluginNameStatic() {
205 static ConstString g_name("goroutines");
206 return g_name;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000207}
208
Kate Stoneb9c1b512016-09-06 20:57:50 +0000209const char *OperatingSystemGo::GetPluginDescriptionStatic() {
210 return "Operating system plug-in that reads runtime data-structures for "
211 "goroutines.";
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000212}
213
Kate Stoneb9c1b512016-09-06 20:57:50 +0000214bool OperatingSystemGo::Init(ThreadList &threads) {
215 if (threads.GetSize(false) < 1)
216 return false;
217 TargetSP target_sp = m_process->CalculateTarget();
218 if (!target_sp)
219 return false;
220 // Go 1.6 stores goroutines in a slice called runtime.allgs
221 ValueObjectSP allgs_sp = FindGlobal(target_sp, "runtime.allgs");
222 if (allgs_sp) {
223 m_allg_sp = allgs_sp->GetChildMemberWithName(ConstString("array"), true);
224 m_allglen_sp = allgs_sp->GetChildMemberWithName(ConstString("len"), true);
225 } else {
226 // Go 1.4 stores goroutines in the variable runtime.allg.
227 m_allg_sp = FindGlobal(target_sp, "runtime.allg");
228 m_allglen_sp = FindGlobal(target_sp, "runtime.allglen");
229 }
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000230
Kate Stoneb9c1b512016-09-06 20:57:50 +0000231 if (m_allg_sp && !m_allglen_sp) {
232 StreamSP error_sp = target_sp->GetDebugger().GetAsyncErrorStream();
233 error_sp->Printf("Unsupported Go runtime version detected.");
234 return false;
235 }
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000236
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237 if (!m_allg_sp)
238 return false;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000239
Kate Stoneb9c1b512016-09-06 20:57:50 +0000240 RegisterContextSP real_registers_sp =
241 threads.GetThreadAtIndex(0, false)->GetRegisterContext();
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000242
Kate Stoneb9c1b512016-09-06 20:57:50 +0000243 std::unordered_map<size_t, ConstString> register_sets;
244 for (size_t set_idx = 0; set_idx < real_registers_sp->GetRegisterSetCount();
245 ++set_idx) {
246 const RegisterSet *set = real_registers_sp->GetRegisterSet(set_idx);
247 ConstString name(set->name);
248 for (size_t reg_idx = 0; reg_idx < set->num_registers; ++reg_idx) {
249 register_sets[reg_idx] = name;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000250 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000251 }
252 TypeSP gobuf_sp = FindType(target_sp, "runtime.gobuf");
253 if (!gobuf_sp) {
254 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000255
Kate Stoneb9c1b512016-09-06 20:57:50 +0000256 if (log)
257 log->Printf("OperatingSystemGo unable to find struct Gobuf");
258 return false;
259 }
260 CompilerType gobuf_type(gobuf_sp->GetLayoutCompilerType());
261 for (size_t idx = 0; idx < real_registers_sp->GetRegisterCount(); ++idx) {
262 RegisterInfo reg = *real_registers_sp->GetRegisterInfoAtIndex(idx);
263 int field_index = -1;
264 if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_SP) {
265 field_index = 0;
266 } else if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC) {
267 field_index = 1;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000268 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000269 if (field_index == -1) {
270 reg.byte_offset = ~0;
271 } else {
272 std::string field_name;
273 uint64_t bit_offset = 0;
274 CompilerType field_type = gobuf_type.GetFieldAtIndex(
275 field_index, field_name, &bit_offset, nullptr, nullptr);
276 reg.byte_size = field_type.GetByteSize(nullptr);
277 reg.byte_offset = bit_offset / 8;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000278 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279 ConstString name(reg.name);
280 ConstString alt_name(reg.alt_name);
281 m_reginfo->AddRegister(reg, name, alt_name, register_sets[idx]);
282 }
283 return true;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000284}
285
286//------------------------------------------------------------------
287// PluginInterface protocol
288//------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289ConstString OperatingSystemGo::GetPluginName() { return GetPluginNameStatic(); }
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000290
Kate Stoneb9c1b512016-09-06 20:57:50 +0000291uint32_t OperatingSystemGo::GetPluginVersion() { return 1; }
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000292
Kate Stoneb9c1b512016-09-06 20:57:50 +0000293bool OperatingSystemGo::UpdateThreadList(ThreadList &old_thread_list,
294 ThreadList &real_thread_list,
295 ThreadList &new_thread_list) {
296 new_thread_list = real_thread_list;
297 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000298
Kate Stoneb9c1b512016-09-06 20:57:50 +0000299 if (!(m_allg_sp || Init(real_thread_list)) || (m_allg_sp && !m_allglen_sp) ||
300 !GetGlobalPluginProperties()->GetEnableGoroutines()) {
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000301 return new_thread_list.GetSize(false) > 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000302 }
303
304 if (log)
305 log->Printf("OperatingSystemGo::UpdateThreadList(%d, %d, %d) fetching "
306 "thread data from Go for pid %" PRIu64,
307 old_thread_list.GetSize(false), real_thread_list.GetSize(false),
308 new_thread_list.GetSize(0), m_process->GetID());
309 uint64_t allglen = m_allglen_sp->GetValueAsUnsigned(0);
310 if (allglen == 0) {
311 return new_thread_list.GetSize(false) > 0;
312 }
313 std::vector<Goroutine> goroutines;
314 // The threads that are in "new_thread_list" upon entry are the threads from
Adrian Prantl05097242018-04-30 16:49:04 +0000315 // the lldb_private::Process subclass, no memory threads will be in this
316 // list.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000317
Zachary Turner97206d52017-05-12 04:51:55 +0000318 Status err;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000319 for (uint64_t i = 0; i < allglen; ++i) {
320 goroutines.push_back(CreateGoroutineAtIndex(i, err));
321 if (err.Fail()) {
Zachary Turner33aba3c2017-02-06 18:31:44 +0000322 LLDB_LOG(log, "error: {0}", err);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000323 return new_thread_list.GetSize(false) > 0;
324 }
325 }
326 // Make a map so we can match goroutines with backing threads.
327 std::map<uint64_t, ThreadSP> stack_map;
328 for (uint32_t i = 0; i < real_thread_list.GetSize(false); ++i) {
329 ThreadSP thread = real_thread_list.GetThreadAtIndex(i, false);
330 stack_map[thread->GetRegisterContext()->GetSP()] = thread;
331 }
332 for (const Goroutine &goroutine : goroutines) {
333 if (0 /* Gidle */ == goroutine.m_status ||
334 6 /* Gdead */ == goroutine.m_status) {
335 continue;
336 }
337 ThreadSP memory_thread =
338 old_thread_list.FindThreadByID(goroutine.m_goid, false);
339 if (memory_thread && IsOperatingSystemPluginThread(memory_thread) &&
340 memory_thread->IsValid()) {
341 memory_thread->ClearBackingThread();
342 } else {
Zachary Turner28333212017-05-12 05:49:54 +0000343 memory_thread.reset(new ThreadMemory(*m_process, goroutine.m_goid, "", "",
344 goroutine.m_gobuf));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000345 }
346 // Search for the backing thread if the goroutine is running.
347 if (2 == (goroutine.m_status & 0xfff)) {
348 auto backing_it = stack_map.lower_bound(goroutine.m_lostack);
349 if (backing_it != stack_map.end()) {
350 if (goroutine.m_histack >= backing_it->first) {
351 if (log)
352 log->Printf(
353 "OperatingSystemGo::UpdateThreadList found backing thread "
354 "%" PRIx64 " (%" PRIx64 ") for thread %" PRIx64 "",
355 backing_it->second->GetID(),
356 backing_it->second->GetProtocolID(), memory_thread->GetID());
357 memory_thread->SetBackingThread(backing_it->second);
358 new_thread_list.RemoveThreadByID(backing_it->second->GetID(), false);
359 }
360 }
361 }
362 new_thread_list.AddThread(memory_thread);
363 }
364
365 return new_thread_list.GetSize(false) > 0;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000366}
367
Kate Stoneb9c1b512016-09-06 20:57:50 +0000368void OperatingSystemGo::ThreadWasSelected(Thread *thread) {}
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000369
370RegisterContextSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000371OperatingSystemGo::CreateRegisterContextForThread(Thread *thread,
372 addr_t reg_data_addr) {
373 RegisterContextSP reg_ctx_sp;
374 if (!thread)
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000375 return reg_ctx_sp;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000376
377 if (!IsOperatingSystemPluginThread(thread->shared_from_this()))
378 return reg_ctx_sp;
379
380 reg_ctx_sp.reset(
381 new RegisterContextGo(*thread, 0, *m_reginfo, reg_data_addr));
382 return reg_ctx_sp;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000383}
384
385StopInfoSP
Kate Stoneb9c1b512016-09-06 20:57:50 +0000386OperatingSystemGo::CreateThreadStopReason(lldb_private::Thread *thread) {
387 StopInfoSP stop_info_sp;
388 return stop_info_sp;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000389}
390
Kate Stoneb9c1b512016-09-06 20:57:50 +0000391lldb::ThreadSP OperatingSystemGo::CreateThread(lldb::tid_t tid,
392 addr_t context) {
393 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000394
Kate Stoneb9c1b512016-09-06 20:57:50 +0000395 if (log)
396 log->Printf("OperatingSystemGo::CreateThread (tid = 0x%" PRIx64
397 ", context = 0x%" PRIx64 ") not implemented",
398 tid, context);
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000399
Kate Stoneb9c1b512016-09-06 20:57:50 +0000400 return ThreadSP();
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000401}
402
Kate Stoneb9c1b512016-09-06 20:57:50 +0000403ValueObjectSP OperatingSystemGo::FindGlobal(TargetSP target, const char *name) {
404 VariableList variable_list;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000405
Kate Stoneb9c1b512016-09-06 20:57:50 +0000406 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000407
Kate Stoneb9c1b512016-09-06 20:57:50 +0000408 if (log) {
409 log->Printf(
410 "exe: %s",
411 target->GetExecutableModule()->GetSpecificationDescription().c_str());
412 log->Printf("modules: %zu", target->GetImages().GetSize());
413 }
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000414
Kate Stoneb9c1b512016-09-06 20:57:50 +0000415 uint32_t match_count = target->GetImages().FindGlobalVariables(
Pavel Labath34cda142018-05-31 09:46:26 +0000416 ConstString(name), 1, variable_list);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000417 if (match_count > 0) {
418 ExecutionContextScope *exe_scope = target->GetProcessSP().get();
419 if (exe_scope == NULL)
420 exe_scope = target.get();
421 return ValueObjectVariable::Create(exe_scope,
422 variable_list.GetVariableAtIndex(0));
423 }
424 return ValueObjectSP();
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000425}
426
Kate Stoneb9c1b512016-09-06 20:57:50 +0000427TypeSP OperatingSystemGo::FindType(TargetSP target_sp, const char *name) {
428 ConstString const_typename(name);
429 SymbolContext sc;
430 const bool exact_match = false;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000431
Kate Stoneb9c1b512016-09-06 20:57:50 +0000432 const ModuleList &module_list = target_sp->GetImages();
433 size_t count = module_list.GetSize();
434 for (size_t idx = 0; idx < count; idx++) {
435 ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
436 if (module_sp) {
437 TypeSP type_sp(module_sp->FindFirstType(sc, const_typename, exact_match));
438 if (type_sp)
439 return type_sp;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000440 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000441 }
442 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000443
Kate Stoneb9c1b512016-09-06 20:57:50 +0000444 if (log)
445 log->Printf("OperatingSystemGo::FindType(%s): not found", name);
446 return TypeSP();
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000447}
448
449OperatingSystemGo::Goroutine
Zachary Turner97206d52017-05-12 04:51:55 +0000450OperatingSystemGo::CreateGoroutineAtIndex(uint64_t idx, Status &err) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000451 err.Clear();
452 Goroutine result = {};
453 ValueObjectSP g =
454 m_allg_sp->GetSyntheticArrayMember(idx, true)->Dereference(err);
455 if (err.Fail()) {
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000456 return result;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000457 }
458
459 ConstString name("goid");
460 ValueObjectSP val = g->GetChildMemberWithName(name, true);
461 bool success = false;
462 result.m_goid = val->GetValueAsUnsigned(0, &success);
463 if (!success) {
464 err.SetErrorToGenericError();
465 err.SetErrorString("unable to read goid");
466 return result;
467 }
468 name.SetCString("atomicstatus");
469 val = g->GetChildMemberWithName(name, true);
470 result.m_status = (uint32_t)val->GetValueAsUnsigned(0, &success);
471 if (!success) {
472 err.SetErrorToGenericError();
473 err.SetErrorString("unable to read atomicstatus");
474 return result;
475 }
476 name.SetCString("sched");
477 val = g->GetChildMemberWithName(name, true);
478 result.m_gobuf = val->GetAddressOf(false);
479 name.SetCString("stack");
480 val = g->GetChildMemberWithName(name, true);
481 name.SetCString("lo");
482 ValueObjectSP child = val->GetChildMemberWithName(name, true);
483 result.m_lostack = child->GetValueAsUnsigned(0, &success);
484 if (!success) {
485 err.SetErrorToGenericError();
486 err.SetErrorString("unable to read stack.lo");
487 return result;
488 }
489 name.SetCString("hi");
490 child = val->GetChildMemberWithName(name, true);
491 result.m_histack = child->GetValueAsUnsigned(0, &success);
492 if (!success) {
493 err.SetErrorToGenericError();
494 err.SetErrorString("unable to read stack.hi");
495 return result;
496 }
497 return result;
Ryan Brown65d4d5c2015-09-16 21:20:44 +0000498}