1 //===-- GoLanguageRuntime.cpp --------------------------------------*- C++
4 // The LLVM Compiler Infrastructure
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 #include "GoLanguageRuntime.h"
13 #include "lldb/Breakpoint/BreakpointLocation.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/Scalar.h"
17 #include "lldb/Core/ValueObject.h"
18 #include "lldb/Core/ValueObjectMemory.h"
19 #include "lldb/Symbol/GoASTContext.h"
20 #include "lldb/Symbol/Symbol.h"
21 #include "lldb/Symbol/SymbolFile.h"
22 #include "lldb/Symbol/TypeList.h"
23 #include "lldb/Target/Process.h"
24 #include "lldb/Target/RegisterContext.h"
25 #include "lldb/Target/SectionLoadList.h"
26 #include "lldb/Target/StopInfo.h"
27 #include "lldb/Target/Target.h"
28 #include "lldb/Target/Thread.h"
29 #include "lldb/Utility/ConstString.h"
30 #include "lldb/Utility/Log.h"
31 #include "lldb/Utility/Status.h"
32 #include "llvm/ADT/Twine.h"
37 using namespace lldb_private;
40 ValueObjectSP GetChild(ValueObject &obj, const char *name,
41 bool dereference = true) {
42 ConstString name_const_str(name);
43 ValueObjectSP result = obj.GetChildMemberWithName(name_const_str, true);
44 if (dereference && result && result->IsPointerType()) {
46 result = result->Dereference(err);
53 ConstString ReadString(ValueObject &str, Process *process) {
55 ValueObjectSP data = GetChild(str, "str", false);
56 ValueObjectSP len = GetChild(str, "len");
59 lldb::addr_t addr = data->GetPointerValue();
60 if (addr == LLDB_INVALID_ADDRESS)
62 uint64_t byte_size = len->GetValueAsUnsigned(0);
63 char *buf = new char[byte_size + 1];
65 size_t bytes_read = process->ReadMemory(addr, buf, byte_size, err);
66 if (!(err.Fail() || bytes_read != byte_size))
67 result = ConstString(buf, bytes_read);
73 ConstString ReadTypeName(ValueObjectSP type, Process *process) {
74 if (ValueObjectSP uncommon = GetChild(*type, "x")) {
75 ValueObjectSP name = GetChild(*uncommon, "name");
76 ValueObjectSP package = GetChild(*uncommon, "pkgpath");
77 if (name && name->GetPointerValue() != 0 && package &&
78 package->GetPointerValue() != 0) {
79 ConstString package_const_str = ReadString(*package, process);
80 ConstString name_const_str = ReadString(*name, process);
81 if (package_const_str.GetLength() == 0)
82 return name_const_str;
83 return ConstString((package_const_str.GetStringRef() + "." +
84 name_const_str.GetStringRef())
88 ValueObjectSP name = GetChild(*type, "_string");
90 return ReadString(*name, process);
91 return ConstString("");
94 CompilerType LookupRuntimeType(ValueObjectSP type, ExecutionContext *exe_ctx,
96 uint8_t kind = GetChild(*type, "kind")->GetValueAsUnsigned(0);
97 *is_direct = GoASTContext::IsDirectIface(kind);
98 if (GoASTContext::IsPointerKind(kind)) {
99 CompilerType type_ptr = type->GetCompilerType().GetPointerType();
102 type->CreateValueObjectFromAddress("elem", type->GetAddressOf() +
107 return CompilerType();
109 return LookupRuntimeType(elem, exe_ctx, &tmp_direct).GetPointerType();
111 Target *target = exe_ctx->GetTargetPtr();
112 Process *process = exe_ctx->GetProcessPtr();
114 ConstString const_typename = ReadTypeName(type, process);
115 if (const_typename.GetLength() == 0)
116 return CompilerType();
120 llvm::DenseSet<SymbolFile *> searched_symbol_files;
121 uint32_t num_matches = target->GetImages().FindTypes(
122 sc, const_typename, false, 2, searched_symbol_files, type_list);
123 if (num_matches > 0) {
124 return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
126 return CompilerType();
130 bool GoLanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
131 return GoASTContext::IsGoInterface(in_value.GetCompilerType());
134 bool GoLanguageRuntime::GetDynamicTypeAndAddress(
135 ValueObject &in_value, lldb::DynamicValueType use_dynamic,
136 TypeAndOrName &class_type_or_name, Address &dynamic_address,
137 Value::ValueType &value_type) {
138 value_type = Value::eValueTypeScalar;
139 class_type_or_name.Clear();
140 if (CouldHaveDynamicValue(in_value)) {
142 ValueObjectSP iface = in_value.GetStaticValue();
143 ValueObjectSP data_sp = GetChild(*iface, "data", false);
147 if (ValueObjectSP tab = GetChild(*iface, "tab"))
149 ValueObjectSP type = GetChild(*iface, "_type");
155 ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
156 CompilerType final_type = LookupRuntimeType(type, &exe_ctx, &direct);
160 class_type_or_name.SetCompilerType(final_type);
162 // TODO: implement reference types or fix caller to support dynamic types
163 // that aren't pointers
164 // so we don't have to introduce this extra pointer.
165 class_type_or_name.SetCompilerType(final_type.GetPointerType());
168 dynamic_address.SetLoadAddress(data_sp->GetPointerValue(),
169 exe_ctx.GetTargetPtr());
177 GoLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
178 ValueObject &static_value) {
179 return type_and_or_name;
182 //------------------------------------------------------------------
184 //------------------------------------------------------------------
186 GoLanguageRuntime::CreateInstance(Process *process,
187 lldb::LanguageType language) {
188 if (language == eLanguageTypeGo)
189 return new GoLanguageRuntime(process);
194 void GoLanguageRuntime::Initialize() {
195 PluginManager::RegisterPlugin(GetPluginNameStatic(), "Go Language Runtime",
199 void GoLanguageRuntime::Terminate() {
200 PluginManager::UnregisterPlugin(CreateInstance);
203 lldb_private::ConstString GoLanguageRuntime::GetPluginNameStatic() {
204 static ConstString g_name("golang");
208 //------------------------------------------------------------------
209 // PluginInterface protocol
210 //------------------------------------------------------------------
211 lldb_private::ConstString GoLanguageRuntime::GetPluginName() {
212 return GetPluginNameStatic();
215 uint32_t GoLanguageRuntime::GetPluginVersion() { return 1; }