Author: ribrdb Date: Tue Oct 6 15:31:08 2015 New Revision: 249459 URL: http://llvm.org/viewvc/llvm-project?rev=249459&view=rev Log: Add missing GoLanguageRuntime files.
Added: lldb/trunk/source/Plugins/LanguageRuntime/Go/ lldb/trunk/source/Plugins/LanguageRuntime/Go/CMakeLists.txt lldb/trunk/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp lldb/trunk/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h lldb/trunk/source/Plugins/LanguageRuntime/Go/Makefile lldb/trunk/test/lang/go/runtime/ lldb/trunk/test/lang/go/runtime/TestGoASTContext.py lldb/trunk/test/lang/go/runtime/main.go Added: lldb/trunk/source/Plugins/LanguageRuntime/Go/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/Go/CMakeLists.txt?rev=249459&view=auto ============================================================================== --- lldb/trunk/source/Plugins/LanguageRuntime/Go/CMakeLists.txt (added) +++ lldb/trunk/source/Plugins/LanguageRuntime/Go/CMakeLists.txt Tue Oct 6 15:31:08 2015 @@ -0,0 +1,5 @@ +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginLanguageRuntimeGo + GoLanguageRuntime.cpp + ) Added: lldb/trunk/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp?rev=249459&view=auto ============================================================================== --- lldb/trunk/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp (added) +++ lldb/trunk/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp Tue Oct 6 15:31:08 2015 @@ -0,0 +1,238 @@ +//===-- GoLanguageRuntime.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "GoLanguageRuntime.h" + +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Symbol/GoASTContext.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "llvm/ADT/Twine.h" + +#include <vector> + +using namespace lldb; +using namespace lldb_private; + +namespace { +ValueObjectSP GetChild(ValueObject& obj, const char* name, bool dereference = true) { + ConstString name_const_str(name); + ValueObjectSP result = obj.GetChildMemberWithName(name_const_str, true); + if (dereference && result && result->IsPointerType()) { + Error err; + result = result->Dereference(err); + if (err.Fail()) + result.reset(); + } + return result; +} + +ConstString ReadString(ValueObject& str, Process* process) { + ConstString result; + ValueObjectSP data = GetChild(str, "str", false); + ValueObjectSP len = GetChild(str, "len"); + if (len && data) + { + Error err; + lldb::addr_t addr = data->GetPointerValue(); + if (addr == LLDB_INVALID_ADDRESS) + return result; + uint64_t byte_size = len->GetValueAsUnsigned(0); + char* buf = new char[byte_size + 1]; + buf[byte_size] = 0; + size_t bytes_read = process->ReadMemory (addr, + buf, + byte_size, + err); + if (!(err.Fail() || bytes_read != byte_size)) + result = ConstString(buf, bytes_read); + delete[] buf; + } + return result; +} + +ConstString +ReadTypeName(ValueObjectSP type, Process* process) +{ + if (ValueObjectSP uncommon = GetChild(*type, "x")) + { + ValueObjectSP name = GetChild(*uncommon, "name"); + ValueObjectSP package = GetChild(*uncommon, "pkgpath"); + if (name && name->GetPointerValue() != 0 && package && package->GetPointerValue() != 0) + { + ConstString package_const_str = ReadString(*package, process); + ConstString name_const_str = ReadString(*name, process); + if (package_const_str.GetLength() == 0) + return name_const_str; + return ConstString((package_const_str.GetStringRef() + "." + name_const_str.GetStringRef()).str()); + } + } + ValueObjectSP name = GetChild(*type, "_string"); + if (name) + return ReadString(*name, process); + return ConstString(""); +} + +CompilerType +LookupRuntimeType(ValueObjectSP type, ExecutionContext* exe_ctx, bool* is_direct) +{ + uint8_t kind = GetChild(*type, "kind")->GetValueAsUnsigned(0); + *is_direct = GoASTContext::IsDirectIface(kind); + if (GoASTContext::IsPointerKind(kind)) + { + CompilerType type_ptr = type->GetCompilerType().GetPointerType(); + Error err; + ValueObjectSP elem = type->CreateValueObjectFromAddress("elem", type->GetAddressOf() + type->GetByteSize(), *exe_ctx, type_ptr)->Dereference(err); + if (err.Fail()) + return CompilerType(); + bool tmp_direct; + return LookupRuntimeType(elem, exe_ctx, &tmp_direct).GetPointerType(); + } + Target *target = exe_ctx->GetTargetPtr(); + Process *process = exe_ctx->GetProcessPtr(); + + ConstString const_typename = ReadTypeName(type, process); + if (const_typename.GetLength() == 0) + return CompilerType(); + + SymbolContext sc; + TypeList type_list; + uint32_t num_matches = target->GetImages().FindTypes (sc, + const_typename, + false, + 2, + type_list); + if (num_matches > 0) { + return type_list.GetTypeAtIndex(0)->GetFullCompilerType(); + } + return CompilerType(); +} + +} + +bool +GoLanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value) +{ + return GoASTContext::IsGoInterface(in_value.GetCompilerType()); +} + +bool +GoLanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, + TypeAndOrName &class_type_or_name, Address &dynamic_address, + Value::ValueType &value_type) +{ + value_type = Value::eValueTypeScalar; + class_type_or_name.Clear(); + if (CouldHaveDynamicValue (in_value)) + { + Error err; + ValueObjectSP iface = in_value.GetStaticValue(); + ValueObjectSP data_sp = GetChild(*iface, "data", false); + if (!data_sp) + return false; + + if (ValueObjectSP tab = GetChild(*iface, "tab")) + iface = tab; + ValueObjectSP type = GetChild(*iface, "_type"); + if (!type) + { + return false; + } + + bool direct; + ExecutionContext exe_ctx (in_value.GetExecutionContextRef()); + CompilerType final_type = LookupRuntimeType(type, &exe_ctx, &direct); + if (!final_type) + return false; + if (direct) + { + class_type_or_name.SetCompilerType(final_type); + } + else + { + // TODO: implement reference types or fix caller to support dynamic types that aren't pointers + // so we don't have to introduce this extra pointer. + class_type_or_name.SetCompilerType(final_type.GetPointerType()); + } + + dynamic_address.SetLoadAddress(data_sp->GetPointerValue(), exe_ctx.GetTargetPtr()); + + return true; + } + return false; +} + +TypeAndOrName +GoLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) +{ + return type_and_or_name; +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ +LanguageRuntime * +GoLanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language) +{ + if (language == eLanguageTypeGo) + return new GoLanguageRuntime (process); + else + return NULL; +} + +void +GoLanguageRuntime::Initialize() +{ + PluginManager::RegisterPlugin (GetPluginNameStatic(), + "Go Language Runtime", + CreateInstance); +} + +void +GoLanguageRuntime::Terminate() +{ + PluginManager::UnregisterPlugin (CreateInstance); +} + +lldb_private::ConstString +GoLanguageRuntime::GetPluginNameStatic() +{ + static ConstString g_name("golang"); + return g_name; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +lldb_private::ConstString +GoLanguageRuntime::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +GoLanguageRuntime::GetPluginVersion() +{ + return 1; +} + Added: lldb/trunk/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h?rev=249459&view=auto ============================================================================== --- lldb/trunk/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h (added) +++ lldb/trunk/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h Tue Oct 6 15:31:08 2015 @@ -0,0 +1,93 @@ +//===-- GoLanguageRuntime.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_GoLanguageRuntime_h_ +#define liblldb_GoLanguageRuntime_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Target/LanguageRuntime.h" +#include "lldb/Core/Value.h" + +namespace lldb_private { + + class GoLanguageRuntime : + public lldb_private::LanguageRuntime + { + public: + ~GoLanguageRuntime() { } + + lldb::LanguageType + GetLanguageType() const override + { + return lldb::eLanguageTypeGo; + } + + bool + GetObjectDescription(Stream &str, ValueObject &object) override + { + // TODO(ribrdb): Maybe call String() method? + return false; + } + + bool + GetObjectDescription(Stream &str, Value &value, ExecutionContextScope *exe_scope) override + { + return false; + } + + bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, + TypeAndOrName &class_type_or_name, Address &address, + Value::ValueType &value_type) override; + + bool CouldHaveDynamicValue(ValueObject &in_value) override; + + lldb::BreakpointResolverSP + CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override + { + return lldb::BreakpointResolverSP(); + } + + TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override; + + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::LanguageRuntime * + CreateInstance (Process *process, lldb::LanguageType language); + + static lldb_private::ConstString + GetPluginNameStatic(); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual lldb_private::ConstString + GetPluginName(); + + virtual uint32_t + GetPluginVersion(); + + private: + GoLanguageRuntime(Process *process) : lldb_private::LanguageRuntime(process) { } // Call CreateInstance instead. + }; + +} // namespace lldb_private + +#endif // liblldb_GoLanguageRuntime_h_ Added: lldb/trunk/source/Plugins/LanguageRuntime/Go/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/Go/Makefile?rev=249459&view=auto ============================================================================== --- lldb/trunk/source/Plugins/LanguageRuntime/Go/Makefile (added) +++ lldb/trunk/source/Plugins/LanguageRuntime/Go/Makefile Tue Oct 6 15:31:08 2015 @@ -0,0 +1,14 @@ +##===- Source/Plugins/LangRuntime/Go/Makefile ----*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLDB_LEVEL := ../../../.. +LIBRARYNAME := lldbPluginLanguageRuntimeGo +BUILD_ARCHIVE = 1 + +include $(LLDB_LEVEL)/Makefile Added: lldb/trunk/test/lang/go/runtime/TestGoASTContext.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/go/runtime/TestGoASTContext.py?rev=249459&view=auto ============================================================================== --- lldb/trunk/test/lang/go/runtime/TestGoASTContext.py (added) +++ lldb/trunk/test/lang/go/runtime/TestGoASTContext.py Tue Oct 6 15:31:08 2015 @@ -0,0 +1,79 @@ +"""Test the go dynamic type handling.""" + +import os, time +import unittest2 +import lldb +import lldbutil +from lldbtest import * + +class TestGoLanguageRuntime(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @python_api_test + @skipIfRemote # Not remote test suite ready + @skipUnlessGoInstalled + def test_with_dsym_and_python_api(self): + """Test GoASTContext dwarf parsing.""" + self.buildGo() + self.launchProcess() + self.go_interface_types() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers to break inside main(). + self.main_source = "main.go" + self.break_line1 = line_number(self.main_source, '// Set breakpoint 1') + self.break_line2 = line_number(self.main_source, '// Set breakpoint 2') + + + def launchProcess(self): + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + bpt1 = target.BreakpointCreateByLocation(self.main_source, self.break_line1) + self.assertTrue(bpt1, VALID_BREAKPOINT) + bpt2 = target.BreakpointCreateByLocation(self.main_source, self.break_line2) + self.assertTrue(bpt2, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + self.assertTrue(process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt1) + + # Make sure we stopped at the first breakpoint. + self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.") + self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.") + + frame = thread_list[0].GetFrameAtIndex(0) + self.assertTrue (frame, "Got a valid frame 0 frame.") + + def go_interface_types(self): + f = self.frame() + v = f.FindVariable("a", lldb.eDynamicCanRunTarget) + self.assertEqual("*int", v.GetType().name) + self.assertEqual(1, v.Dereference().GetValueAsSigned()) + v = f.FindVariable("b", lldb.eDynamicCanRunTarget) + self.assertEqual("*float64", v.GetType().name) + err = lldb.SBError() + self.assertEqual(2.0, v.Dereference().GetData().GetDouble(err, 0)) + v = f.FindVariable("c", lldb.eDynamicCanRunTarget) + self.assertEqual("*main.SomeFooer", v.GetType().name) + self.assertEqual(9, v.Dereference().GetChildAtIndex(0).GetValueAsSigned()) + v = f.FindVariable("d", lldb.eDynamicCanRunTarget) + self.assertEqual("*main.AnotherFooer", v.GetType().name) + self.assertEqual(-1, v.Dereference().GetChildAtIndex(0).GetValueAsSigned()) + self.assertEqual(-2, v.Dereference().GetChildAtIndex(1).GetValueAsSigned()) + self.assertEqual(-3, v.Dereference().GetChildAtIndex(2).GetValueAsSigned()) + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Added: lldb/trunk/test/lang/go/runtime/main.go URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/go/runtime/main.go?rev=249459&view=auto ============================================================================== --- lldb/trunk/test/lang/go/runtime/main.go (added) +++ lldb/trunk/test/lang/go/runtime/main.go Tue Oct 6 15:31:08 2015 @@ -0,0 +1,38 @@ +package main + +import "fmt" + +type Fooer interface { + Foo() int +} + +type SomeFooer struct { + val int +} + +func (s SomeFooer) Foo() int { + return s.val +} + +type AnotherFooer struct { + a, b, c int +} + +func (s AnotherFooer) Foo() int { + return s.a +} + + +func printEface(a, b, c, d interface{}) { + fmt.Println(a, b, c, d) // Set breakpoint 1 +} + +func printIface(a, b Fooer) { + fmt.Println(a, b) // Set breakpoint 2 +} +func main() { + sf := SomeFooer{9} + af := AnotherFooer{-1, -2, -3} + printEface(1,2.0, sf, af) + printIface(sf, af) +} \ No newline at end of file _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits