Merge pull request #247 from llvm-beanz/swift-4.0-branch-stringref-perf
Swift 4.0 branch stringref perf
diff --git a/include/lldb/Target/LanguageRuntime.h b/include/lldb/Target/LanguageRuntime.h
index a53eb60..72763ee 100644
--- a/include/lldb/Target/LanguageRuntime.h
+++ b/include/lldb/Target/LanguageRuntime.h
@@ -164,6 +164,9 @@
virtual bool GetIRPasses(LLVMUserExpression::IRPasses &custom_passes) {
return false;
}
+
+ static bool
+ IsSymbolAnyRuntimeThunk(lldb::ProcessSP process, Symbol &symbol);
protected:
//------------------------------------------------------------------
diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h
index 0a45ae1..329eb65 100644
--- a/include/lldb/Target/Thread.h
+++ b/include/lldb/Target/Thread.h
@@ -777,6 +777,13 @@
LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
+ virtual lldb::ThreadPlanSP QueueThreadPlanForStepInRangeNoShouldStop(
+ bool abort_other_plans, const AddressRange &range,
+ const SymbolContext &addr_context, const char *step_in_target,
+ lldb::RunMode stop_other_threads,
+ LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
+ LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
+
// Helper function that takes a LineEntry to step, insted of an AddressRange.
// This may combine multiple
// LineEntries of the same source line number to step over a longer address
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile b/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile
new file mode 100644
index 0000000..5665652
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/simple/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+OBJC_SOURCES := main.m
+LDFLAGS = $(CFLAGS) -lobjc -framework Foundation -framework AppKit
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py b/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py
new file mode 100644
index 0000000..6a779ec
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/simple/TestMTCSimple.py
@@ -0,0 +1,57 @@
+"""
+Tests basic Main Thread Checker support (detecting a main-thread-only violation).
+"""
+
+import os
+import time
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbplatformutil import *
+import json
+
+
+class MTCSimpleTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessDarwin
+ def test(self):
+ self.mtc_dylib_path = findMainThreadCheckerDylib()
+ if self.mtc_dylib_path == "":
+ self.skipTest("This test requires libMainThreadChecker.dylib.")
+
+ self.build()
+ self.mtc_tests()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ def mtc_tests(self):
+ # Load the test
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.expect("file " + exe, patterns=["Current executable set to .*a.out"])
+
+ self.runCmd("env DYLD_INSERT_LIBRARIES=%s" % self.mtc_dylib_path)
+ self.runCmd("run")
+
+ process = self.dbg.GetSelectedTarget().process
+ thread = process.GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ self.expect("thread info", substrs=['stop reason = -[NSView superview] must be used from main thread only'])
+
+ self.expect(
+ "thread info -s",
+ substrs=["instrumentation_class", "api_name", "class_name", "selector", "description"])
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonInstrumentation)
+ output_lines = self.res.GetOutput().split('\n')
+ json_line = '\n'.join(output_lines[2:])
+ data = json.loads(json_line)
+ self.assertEqual(data["instrumentation_class"], "MainThreadChecker")
+ self.assertEqual(data["api_name"], "-[NSView superview]")
+ self.assertEqual(data["class_name"], "NSView")
+ self.assertEqual(data["selector"], "superview")
+ self.assertEqual(data["description"], "-[NSView superview] must be used from main thread only")
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m b/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m
new file mode 100644
index 0000000..651347c
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/simple/main.m
@@ -0,0 +1,15 @@
+#import <Foundation/Foundation.h>
+#import <AppKit/AppKit.h>
+
+int main() {
+ NSView *view = [[NSView alloc] init];
+ dispatch_group_t g = dispatch_group_create();
+ dispatch_group_enter(g);
+ [NSThread detachNewThreadWithBlock:^{
+ @autoreleasepool {
+ [view superview];
+ }
+ dispatch_group_leave(g);
+ }];
+ dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/swift-property/Makefile b/packages/Python/lldbsuite/test/functionalities/mtc/swift-property/Makefile
new file mode 100644
index 0000000..5af7875
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/swift-property/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+SWIFT_SOURCES := main.swift
+TRIPLE_SWIFTFLAGS := -target x86_64-apple-macosx10.12
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/swift-property/TestMTCSwiftProperty.py b/packages/Python/lldbsuite/test/functionalities/mtc/swift-property/TestMTCSwiftProperty.py
new file mode 100644
index 0000000..307325a
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/swift-property/TestMTCSwiftProperty.py
@@ -0,0 +1,57 @@
+"""
+Tests Main Thread Checker support on Swift properties.
+"""
+
+import os
+import time
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbplatformutil import *
+import json
+
+
+class MTCSwiftPropertyTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessDarwin
+ def test(self):
+ self.mtc_dylib_path = findMainThreadCheckerDylib()
+ if self.mtc_dylib_path == "":
+ self.skipTest("This test requires libMainThreadChecker.dylib.")
+
+ self.build()
+ self.mtc_tests()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ def mtc_tests(self):
+ # Load the test
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.expect("file " + exe, patterns=["Current executable set to .*a.out"])
+
+ self.runCmd("env DYLD_INSERT_LIBRARIES=%s" % self.mtc_dylib_path)
+ self.runCmd("run")
+
+ process = self.dbg.GetSelectedTarget().process
+ thread = process.GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ self.expect("thread info", substrs=['stop reason = NSView.superview must be used from main thread only'])
+
+ self.expect(
+ "thread info -s",
+ substrs=["instrumentation_class", "api_name", "class_name", "selector", "description"])
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonInstrumentation)
+ output_lines = self.res.GetOutput().split('\n')
+ json_line = '\n'.join(output_lines[2:])
+ data = json.loads(json_line)
+ self.assertEqual(data["instrumentation_class"], "MainThreadChecker")
+ self.assertEqual(data["api_name"], "NSView.superview")
+ self.assertEqual(data["class_name"], "NSView")
+ self.assertEqual(data["selector"], "superview")
+ self.assertEqual(data["description"], "NSView.superview must be used from main thread only")
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/swift-property/main.swift b/packages/Python/lldbsuite/test/functionalities/mtc/swift-property/main.swift
new file mode 100644
index 0000000..950b9c2
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/swift-property/main.swift
@@ -0,0 +1,25 @@
+// main.swift
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+// -----------------------------------------------------------------------------
+
+import Foundation
+import AppKit
+
+let view = NSView()
+let g = DispatchGroup()
+g.enter()
+Thread.detachNewThread {
+ autoreleasepool {
+ let _ = view.superview
+ }
+ g.leave()
+}
+g.wait()
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/swift/Makefile b/packages/Python/lldbsuite/test/functionalities/mtc/swift/Makefile
new file mode 100644
index 0000000..5af7875
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/swift/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+SWIFT_SOURCES := main.swift
+TRIPLE_SWIFTFLAGS := -target x86_64-apple-macosx10.12
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/swift/TestMTCSwift.py b/packages/Python/lldbsuite/test/functionalities/mtc/swift/TestMTCSwift.py
new file mode 100644
index 0000000..6def887
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/swift/TestMTCSwift.py
@@ -0,0 +1,57 @@
+"""
+Tests Main Thread Checker support on Swift code.
+"""
+
+import os
+import time
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbplatformutil import *
+import json
+
+
+class MTCSwiftTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessDarwin
+ def test(self):
+ self.mtc_dylib_path = findMainThreadCheckerDylib()
+ if self.mtc_dylib_path == "":
+ self.skipTest("This test requires libMainThreadChecker.dylib.")
+
+ self.build()
+ self.mtc_tests()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ def mtc_tests(self):
+ # Load the test
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.expect("file " + exe, patterns=["Current executable set to .*a.out"])
+
+ self.runCmd("env DYLD_INSERT_LIBRARIES=%s" % self.mtc_dylib_path)
+ self.runCmd("run")
+
+ process = self.dbg.GetSelectedTarget().process
+ thread = process.GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ self.expect("thread info", substrs=['stop reason = NSView.removeFromSuperview() must be used from main thread only'])
+
+ self.expect(
+ "thread info -s",
+ substrs=["instrumentation_class", "api_name", "class_name", "selector", "description"])
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonInstrumentation)
+ output_lines = self.res.GetOutput().split('\n')
+ json_line = '\n'.join(output_lines[2:])
+ data = json.loads(json_line)
+ self.assertEqual(data["instrumentation_class"], "MainThreadChecker")
+ self.assertEqual(data["api_name"], "NSView.removeFromSuperview()")
+ self.assertEqual(data["class_name"], "NSView")
+ self.assertEqual(data["selector"], "removeFromSuperview")
+ self.assertEqual(data["description"], "NSView.removeFromSuperview() must be used from main thread only")
diff --git a/packages/Python/lldbsuite/test/functionalities/mtc/swift/main.swift b/packages/Python/lldbsuite/test/functionalities/mtc/swift/main.swift
new file mode 100644
index 0000000..f9b4b47
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/mtc/swift/main.swift
@@ -0,0 +1,25 @@
+// main.swift
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+// -----------------------------------------------------------------------------
+
+import Foundation
+import AppKit
+
+let view = NSView()
+let g = DispatchGroup()
+g.enter()
+Thread.detachNewThread {
+ autoreleasepool {
+ view.removeFromSuperview()
+ }
+ g.leave()
+}
+g.wait()
diff --git a/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/Makefile b/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/Makefile
new file mode 100644
index 0000000..61b99a1
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/Makefile
@@ -0,0 +1,8 @@
+LEVEL = ../../../make
+
+DYLIB_NAME := swiftCore
+DYLIB_CXX_SOURCES := library.cpp
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/TestABIv2.py b/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/TestABIv2.py
new file mode 100644
index 0000000..a46f9ff
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/TestABIv2.py
@@ -0,0 +1,85 @@
+# TestABIv2.py
+#
+# This source file is part of the Swift.org open source project
+#
+# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+# Licensed under Apache License v2.0 with Runtime Library Exception
+#
+# See https://swift.org/LICENSE.txt for license information
+# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+#
+# ------------------------------------------------------------------------------
+"""
+Test Swift Runtime Reporting ABI v2.
+"""
+import lldb
+import lldbsuite.test.decorators as decorators
+import lldbsuite.test.lldbtest as lldbtest
+import lldbsuite.test.lldbutil as lldbutil
+import os
+import unittest2
+import json
+
+
+class SwiftRuntimeReportingABIv2TestCase(lldbtest.TestBase):
+
+ mydir = lldbtest.TestBase.compute_mydir(__file__)
+
+ @decorators.swiftTest
+ @decorators.skipIfLinux
+ def test_swift_runtime_reporting(self):
+ self.build()
+ self.do_test()
+
+ def setUp(self):
+ lldbtest.TestBase.setUp(self)
+
+ def do_test(self):
+ exe_name = "a.out"
+ exe = os.path.join(os.getcwd(), exe_name)
+
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, lldbtest.VALID_TARGET)
+
+ self.runCmd("run")
+
+ self.expect("thread list",
+ substrs=['stopped', 'stop reason = custom error message'])
+
+ self.assertEqual(
+ self.dbg.GetSelectedTarget().process.GetSelectedThread().GetStopReason(),
+ lldb.eStopReasonInstrumentation)
+
+ self.expect("thread info -s",
+ substrs=["instrumentation_class", "issue_type", "description"])
+
+ output_lines = self.res.GetOutput().split('\n')
+ json_line = '\n'.join(output_lines[2:])
+ data = json.loads(json_line)
+ self.assertEqual(data["instrumentation_class"], "SwiftRuntimeReporting")
+ self.assertEqual(data["issue_type"], "my-error")
+ self.assertEqual(data["memory_address"], 0)
+ self.assertEqual(data["description"], "custom error message")
+
+ self.assertEqual(len(data["notes"]), 3)
+ self.assertEqual(data["notes"][0]["description"], "note 1")
+ self.assertEqual(data["notes"][1]["description"], "note 2")
+ self.assertEqual(data["notes"][2]["description"], "note 3")
+
+ self.assertEqual(len(data["notes"][0]["fixits"]), 0)
+ self.assertEqual(len(data["notes"][1]["fixits"]), 0)
+ self.assertEqual(len(data["notes"][2]["fixits"]), 0)
+
+ self.assertEqual(len(data["fixits"]), 2)
+ self.assertEqual(data["fixits"][0]["filename"], "filename1")
+ self.assertEqual(data["fixits"][0]["start_line"], 42)
+ self.assertEqual(data["fixits"][0]["start_col"], 1)
+ self.assertEqual(data["fixits"][0]["end_line"], 43)
+ self.assertEqual(data["fixits"][0]["end_col"], 2)
+ self.assertEqual(data["fixits"][0]["replacement"], "replacement1")
+ self.assertEqual(data["fixits"][1]["filename"], "filename2")
+ self.assertEqual(data["fixits"][1]["start_line"], 44)
+ self.assertEqual(data["fixits"][1]["start_col"], 3)
+ self.assertEqual(data["fixits"][1]["end_line"], 45)
+ self.assertEqual(data["fixits"][1]["end_col"], 4)
+ self.assertEqual(data["fixits"][1]["replacement"], "replacement2")
diff --git a/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/library.cpp b/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/library.cpp
new file mode 100644
index 0000000..4706776
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/library.cpp
@@ -0,0 +1,16 @@
+// library.cpp
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+// -----------------------------------------------------------------------------
+
+#import "library.h"
+
+extern "C"
+void _swift_runtime_on_report(uintptr_t flags, const char *message, RuntimeErrorDetails *details) { }
diff --git a/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/library.h b/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/library.h
new file mode 100644
index 0000000..cc97819
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/library.h
@@ -0,0 +1,59 @@
+// library.h
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+// -----------------------------------------------------------------------------
+
+// From swift's include/swift/Runtime/Debug.h file.
+struct RuntimeErrorDetails {
+ uintptr_t version;
+ const char *errorType;
+ const char *currentStackDescription;
+ uintptr_t framesToSkip;
+ void *memoryAddress;
+
+ struct Thread {
+ const char *description;
+ uint64_t threadID;
+ uintptr_t numFrames;
+ void **frames;
+ };
+
+ uintptr_t numExtraThreads;
+ Thread *threads;
+
+ struct FixIt {
+ const char *filename;
+ uintptr_t startLine;
+ uintptr_t startColumn;
+ uintptr_t endLine;
+ uintptr_t endColumn;
+ const char *replacementText;
+ };
+
+ struct Note {
+ const char *description;
+ uintptr_t numFixIts;
+ FixIt *fixIts;
+ };
+
+ uintptr_t numFixIts;
+ FixIt *fixIts;
+
+ uintptr_t numNotes;
+ Note *notes;
+};
+
+enum: uintptr_t {
+ RuntimeErrorFlagNone = 0,
+ RuntimeErrorFlagFatal = 1 << 0
+};
+
+extern "C"
+void _swift_runtime_on_report(uintptr_t flags, const char *message, RuntimeErrorDetails *details);
diff --git a/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/main.cpp b/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/main.cpp
new file mode 100644
index 0000000..7aa5e6a
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/swift-runtime-reporting/abi-v2/main.cpp
@@ -0,0 +1,36 @@
+// main.cpp
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+// -----------------------------------------------------------------------------
+
+#import "library.h"
+
+int main() {
+ RuntimeErrorDetails::Note notes[] = {
+ { .description = "note 1" },
+ { .description = "note 2" },
+ { .description = "note 3" },
+ };
+ RuntimeErrorDetails::FixIt fixits[] = {
+ { .filename = "filename1", .startLine = 42, .startColumn = 1,
+ .endLine = 43, .endColumn = 2, .replacementText = "replacement1" },
+ { .filename = "filename2", .startLine = 44, .startColumn = 3,
+ .endLine = 45, .endColumn = 4, .replacementText = "replacement2" }
+ };
+ RuntimeErrorDetails details = {
+ .version = 2,
+ .errorType = "my-error",
+ .notes = ¬es[0],
+ .numNotes = 3,
+ .fixIts = &fixits[0],
+ .numFixIts = 2
+ };
+ _swift_runtime_on_report(RuntimeErrorFlagNone, "custom error message", &details);
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile
new file mode 100644
index 0000000..6e7d19b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+CFLAGS_EXTRAS := -fsanitize=undefined -g
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py
new file mode 100644
index 0000000..a5e5f57
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/TestUbsanUserExpression.py
@@ -0,0 +1,49 @@
+"""
+Test that hitting a UBSan issue while running user expression doesn't break the evaluation.
+"""
+
+import os
+import time
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+import lldbsuite.test.lldbutil as lldbutil
+import json
+
+
+class UbsanUserExpressionTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessUndefinedBehaviorSanitizer
+ def test(self):
+ self.build()
+ self.ubsan_tests()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ self.line_breakpoint = line_number('main.c', '// breakpoint line')
+
+ def ubsan_tests(self):
+ # Load the test
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.expect(
+ "file " + exe,
+ patterns=["Current executable set to .*a.out"])
+
+ self.runCmd("breakpoint set -f main.c -l %d" % self.line_breakpoint)
+
+ self.runCmd("run")
+
+ process = self.dbg.GetSelectedTarget().process
+ thread = process.GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stopped', 'stop reason = breakpoint'])
+
+ self.expect("p foo()", substrs=["(int) $0 = 42"])
+
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stopped', 'stop reason = breakpoint'])
diff --git a/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c
new file mode 100644
index 0000000..4786aaa
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/ubsan/user-expression/main.c
@@ -0,0 +1,9 @@
+int foo() {
+ int data[4];
+ int x = *(int *)(((char *)&data[0]) + 2);
+ return 42;
+}
+
+int main() {
+ return 0; // breakpoint line
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/TestMyFirstWatchpoint.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/TestMyFirstWatchpoint.py
index c74452f..46bd384 100644
--- a/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/TestMyFirstWatchpoint.py
+++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchpoint/TestMyFirstWatchpoint.py
@@ -39,6 +39,9 @@
@expectedFailureAll(
oslist=["windows"],
bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+ @expectedFailureAll(
+ oslist=["linux"],
+ bugnumber="https://bugs.swift.org/browse/SR-5555 MyFirstWatchpoint test fails on Ubuntu 16.04")
def test_hello_watchpoint_using_watchpoint_set(self):
"""Test a simple sequence of watchpoint creation and watchpoint hit."""
self.build(dictionary=self.d)
diff --git a/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py
index 96c5a33..77e5a8b 100644
--- a/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py
+++ b/packages/Python/lldbsuite/test/lang/objc/objc-new-syntax/TestObjCNewSyntax.py
@@ -121,6 +121,8 @@
'7.0.0'])
@skipIf(macos_version=["<", "10.12"])
@expectedFailureAll(archs=["i[3-6]86"])
+ @expectedFailureAll(debug_info="gmodules",
+ bugnumber="rdar://problem/32777981")
def test_update_dictionary(self):
self.runToBreakpoint()
@@ -163,6 +165,8 @@
'7.0.0'])
@skipIf(macos_version=["<", "10.12"])
@expectedFailureAll(archs=["i[3-6]86"])
+ @expectedFailureAll(debug_info="gmodules",
+ bugnumber="rdar://problem/32777981")
def test_dictionary_literal(self):
self.runToBreakpoint()
diff --git a/packages/Python/lldbsuite/test/lang/swift/let_int/TestSwiftLetInt.py b/packages/Python/lldbsuite/test/lang/swift/let_int/TestSwiftLetInt.py
index ad8d706..fba2ea4 100644
--- a/packages/Python/lldbsuite/test/lang/swift/let_int/TestSwiftLetInt.py
+++ b/packages/Python/lldbsuite/test/lang/swift/let_int/TestSwiftLetInt.py
@@ -68,6 +68,16 @@
lldbutil.check_variable(self, let, False, value="10")
lldbutil.check_variable(self, var, False, value="10")
+ get_arguments = False
+ get_locals = True
+ get_statics = False
+ get_in_scope_only = True
+ local_vars = self.frame.GetVariables(get_arguments, get_locals,
+ get_statics, get_in_scope_only)
+ self.assertTrue(local_vars.GetFirstValueByName("x").IsValid())
+ self.assertTrue(local_vars.GetFirstValueByName("y").IsValid())
+ self.assertTrue(not local_vars.GetFirstValueByName("z").IsValid())
+
if __name__ == '__main__':
import atexit
lldb.SBDebugger.Initialize()
diff --git a/packages/Python/lldbsuite/test/lang/swift/let_int/main.swift b/packages/Python/lldbsuite/test/lang/swift/let_int/main.swift
index f7dd177..81c6acc 100644
--- a/packages/Python/lldbsuite/test/lang/swift/let_int/main.swift
+++ b/packages/Python/lldbsuite/test/lang/swift/let_int/main.swift
@@ -9,10 +9,13 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
// -----------------------------------------------------------------------------
+
+let z = 10
+
func main() {
let x = 10
var y = 10
- print(x+y) // Set breakpoint here
+ print(x+y+z) // Set breakpoint here
}
main()
diff --git a/packages/Python/lldbsuite/test/lang/swift/stepping/TestSwiftStepping.py b/packages/Python/lldbsuite/test/lang/swift/stepping/TestSwiftStepping.py
index 7aa8e50..55c58c8 100644
--- a/packages/Python/lldbsuite/test/lang/swift/stepping/TestSwiftStepping.py
+++ b/packages/Python/lldbsuite/test/lang/swift/stepping/TestSwiftStepping.py
@@ -26,7 +26,6 @@
mydir = lldbtest.TestBase.compute_mydir(__file__)
@decorators.swiftTest
- @decorators.expectedFailureAll(bugnumber="rdar://31515444")
def test_swift_stepping(self):
"""Tests that we can step reliably in swift code."""
self.build()
@@ -289,11 +288,12 @@
# Step out of the protocol function, one step out should also
# get us past any dispatch thunk.
thread.StepOut()
- self.hit_correct_line(thread, "indirect.protocol_func(20)")
-
+ stop_on_caller = self.hit_correct_line(thread, "indirect.protocol_func(20)", False)
+
# And one step over is necessary because step out doesn't
# finish off the line.
- thread.StepOver()
+ if stop_on_caller:
+ thread.StepOver()
self.hit_correct_line(thread, "doSomethingWithFunction(cd_maker, 10)")
thread.StepInto()
diff --git a/packages/Python/lldbsuite/test/lang/swift/variables/bool/Makefile b/packages/Python/lldbsuite/test/lang/swift/variables/bool/Makefile
new file mode 100644
index 0000000..f9ac017
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/swift/variables/bool/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../../make
+
+SWIFT_SOURCES := main.swift
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/lang/swift/variables/bool/TestSwiftBool.py b/packages/Python/lldbsuite/test/lang/swift/variables/bool/TestSwiftBool.py
new file mode 100644
index 0000000..36fd40c
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/swift/variables/bool/TestSwiftBool.py
@@ -0,0 +1,84 @@
+# TestSwiftBool.py
+#
+# This source file is part of the Swift.org open source project
+#
+# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+# Licensed under Apache License v2.0 with Runtime Library Exception
+#
+# See https://swift.org/LICENSE.txt for license information
+# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+#
+# ------------------------------------------------------------------------------
+"""
+Test that we can inspect Swift Bools - they are 8 bit entities with only the
+LSB significant. Make sure that works.
+"""
+import lldb
+from lldbsuite.test.lldbtest import *
+import lldbsuite.test.decorators as decorators
+import lldbsuite.test.lldbutil as lldbutil
+import unittest2
+
+
+class TestSwiftBool(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @decorators.swiftTest
+ def test_swift_bool(self):
+ """Test that we can inspect various Swift bools"""
+ self.build()
+ self.do_test()
+
+ def setUp(self):
+ TestBase.setUp(self)
+ self.main_source = "main.swift"
+ self.main_source_spec = lldb.SBFileSpec(self.main_source)
+
+ def do_test(self):
+ """Tests that we can break and display simple types"""
+ exe_name = "a.out"
+ exe = os.path.join(os.getcwd(), exe_name)
+
+ # Create the target
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ # Set the breakpoints
+ breakpoint = target.BreakpointCreateBySourceRegex(
+ 'Set breakpoint here', self.main_source_spec)
+ self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT)
+
+ # Launch the process, and do not stop at the entry point.
+ process = target.LaunchSimple(None, None, os.getcwd())
+
+ self.assertTrue(process, PROCESS_IS_VALID)
+
+ # Frame #0 should be at our breakpoint.
+ threads = lldbutil.get_threads_stopped_at_breakpoint(
+ process, breakpoint)
+
+ self.assertTrue(len(threads) == 1)
+ thread = threads[0]
+
+ frame = thread.frames[0]
+ self.assertTrue(frame.IsValid(), "Couldn't get a frame.")
+
+ true_vars = ["reg_true", "odd_true", "odd_true_works", "odd_false_works"]
+ for name in true_vars:
+ var = frame.FindVariable(name)
+ summary = var.GetSummary()
+ self.assertTrue(summary == "true", "%s should be true, was: %s"%(name, summary))
+
+ false_vars = ["reg_false", "odd_false"]
+ for name in false_vars:
+ var = frame.FindVariable(name)
+ summary = var.GetSummary()
+ self.assertTrue(summary == "false", "%s should be false, was: %s"%(name, summary))
+
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lldb.SBDebugger.Terminate)
+ unittest2.main()
diff --git a/packages/Python/lldbsuite/test/lang/swift/variables/bool/main.swift b/packages/Python/lldbsuite/test/lang/swift/variables/bool/main.swift
new file mode 100644
index 0000000..48901e1
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/swift/variables/bool/main.swift
@@ -0,0 +1,29 @@
+// main.swift
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+// -----------------------------------------------------------------------------
+
+func main() -> Int {
+ let short_five : Int8 = 5
+ let short_four : Int8 = 4
+
+ var reg_true : Bool = true
+ var reg_false : Bool = false
+ var odd_true : Bool = unsafeBitCast(short_five, to: Bool.self)
+ var odd_false : Bool = unsafeBitCast(short_four, to: Bool.self)
+
+ var odd_true_works = reg_true == odd_true
+ var odd_false_works = reg_false == odd_false
+
+ print("stop here") // Set breakpoint here
+ return 0
+}
+
+main()
diff --git a/packages/Python/lldbsuite/test/lang/swift/variables/inout/TestInOutVariables.py b/packages/Python/lldbsuite/test/lang/swift/variables/inout/TestInOutVariables.py
index 5de59eb..fbbe01f 100644
--- a/packages/Python/lldbsuite/test/lang/swift/variables/inout/TestInOutVariables.py
+++ b/packages/Python/lldbsuite/test/lang/swift/variables/inout/TestInOutVariables.py
@@ -100,6 +100,9 @@
lldb.eDynamicCanRunTarget)
message_end = "from FindVariable"
+ # Make sure we can get the object description without crashing
+ _ = self.frame.FindVariable("x").description
+
self.assertTrue(x.IsValid(), "did not find x %s" % (message_end))
self.assertTrue(
x.GetNumChildren() == 1,
diff --git a/packages/Python/lldbsuite/test/lang/swift/variables/protocol/main.swift b/packages/Python/lldbsuite/test/lang/swift/variables/protocol/main.swift
index a3c0a28..767bee0 100644
--- a/packages/Python/lldbsuite/test/lang/swift/variables/protocol/main.swift
+++ b/packages/Python/lldbsuite/test/lang/swift/variables/protocol/main.swift
@@ -46,14 +46,18 @@
}
-func main() -> Int {
-
- var loc2d : protocol<PointUtils> = Point2D(1.25, 2.5)
- var loc3d : protocol<PointUtils> = Point3D(1.25, 2.5, 1.25)
- var sum2d = loc2d.sumOfCoordinates()
- var sum3d = loc3d.sumOfCoordinates()
+func takes_protocol(_ loc2d : PointUtils,_ loc3d : PointUtils) {
+ let sum2d = loc2d.sumOfCoordinates()
+ let sum3d = loc3d.sumOfCoordinates()
print("hello \(sum2d) \(sum3d)") // Set breakpoint here
- return 0
+}
+
+func main() {
+
+ var loc2d = Point2D(1.25, 2.5)
+ var loc3d = Point3D(1.25, 2.5, 1.25)
+
+ takes_protocol (loc2d, loc3d)
}
main()
diff --git a/packages/Python/lldbsuite/test/lldbplatformutil.py b/packages/Python/lldbsuite/test/lldbplatformutil.py
index 0d5254b..0673e7d 100644
--- a/packages/Python/lldbsuite/test/lldbplatformutil.py
+++ b/packages/Python/lldbsuite/test/lldbplatformutil.py
@@ -8,6 +8,7 @@
import re
import subprocess
import sys
+import os
# Third-party modules
import six
@@ -140,6 +141,19 @@
return getPlatform() in getDarwinOSTriples()
+def findMainThreadCheckerDylib():
+ if not platformIsDarwin():
+ return ""
+
+ with os.popen('xcode-select -p') as output:
+ xcode_developer_path = output.read().strip()
+ mtc_dylib_path = '%s/usr/lib/libMainThreadChecker.dylib' % xcode_developer_path
+ if os.path.isfile(mtc_dylib_path):
+ return mtc_dylib_path
+
+ return ""
+
+
class _PlatformContext(object):
"""Value object class which contains platform-specific options."""
diff --git a/packages/Python/lldbsuite/test/repl/breakpoints/TestREPLBreakpoints.py b/packages/Python/lldbsuite/test/repl/breakpoints/TestREPLBreakpoints.py
index d09fc17..3803a38 100644
--- a/packages/Python/lldbsuite/test/repl/breakpoints/TestREPLBreakpoints.py
+++ b/packages/Python/lldbsuite/test/repl/breakpoints/TestREPLBreakpoints.py
@@ -16,12 +16,12 @@
import unittest2
import lldb
import lldbsuite.test.decorators as decorators
-from lldbsuite.test.lldbrepl import REPLTest, load_tests
+import lldbsuite.test.lldbrepl as lldbrepl
-class REPLBreakpointsTestCase (REPLTest):
+class REPLBreakpointsTestCase (lldbrepl.REPLTest):
- mydir = REPLTest.compute_mydir(__file__)
+ mydir = lldbrepl.REPLTest.compute_mydir(__file__)
@decorators.swiftTest
@decorators.no_debug_info_test
diff --git a/packages/Python/lldbsuite/test/repl/closures/TestREPLClosure.py b/packages/Python/lldbsuite/test/repl/closures/TestREPLClosure.py
index e9ddaf9..77b0aff 100644
--- a/packages/Python/lldbsuite/test/repl/closures/TestREPLClosure.py
+++ b/packages/Python/lldbsuite/test/repl/closures/TestREPLClosure.py
@@ -15,12 +15,12 @@
import time
import unittest2
import lldb
-from lldbsuite.test.lldbrepl import REPLTest, load_tests
+import lldbsuite.test.lldbrepl as lldbrepl
-class REPLClosureTestCase (REPLTest):
+class REPLClosureTestCase (lldbrepl.REPLTest):
- mydir = REPLTest.compute_mydir(__file__)
+ mydir = lldbrepl.REPLTest.compute_mydir(__file__)
def doTest(self):
self.command(
diff --git a/packages/Python/lldbsuite/test/repl/dictionary/TestREPLDictionary.py b/packages/Python/lldbsuite/test/repl/dictionary/TestREPLDictionary.py
index 7373f76..51f07e3 100644
--- a/packages/Python/lldbsuite/test/repl/dictionary/TestREPLDictionary.py
+++ b/packages/Python/lldbsuite/test/repl/dictionary/TestREPLDictionary.py
@@ -15,13 +15,13 @@
import time
import unittest2
import lldb
-from lldbsuite.test.lldbrepl import REPLTest, load_tests
+import lldbsuite.test.lldbrepl as lldbrepl
import lldbsuite.test.decorators as decorators
-class REPLDictionaryTestCase (REPLTest):
+class REPLDictionaryTestCase (lldbrepl.REPLTest):
- mydir = REPLTest.compute_mydir(__file__)
+ mydir = lldbrepl.REPLTest.compute_mydir(__file__)
@decorators.swiftTest
@decorators.no_debug_info_test
@@ -29,7 +29,7 @@
oslist=['linux'],
bugnumber="bugs.swift.org/SR-843")
def testREPL(self):
- REPLTest.testREPL(self)
+ lldbrepl.REPLTest.testREPL(self)
def doTest(self):
self.sendline('[1:2, 2:3, 3:9]')
diff --git a/packages/Python/lldbsuite/test/repl/dyntype/TestREPLDynamicType.py b/packages/Python/lldbsuite/test/repl/dyntype/TestREPLDynamicType.py
index 8bb86e5..7f96a8a 100644
--- a/packages/Python/lldbsuite/test/repl/dyntype/TestREPLDynamicType.py
+++ b/packages/Python/lldbsuite/test/repl/dyntype/TestREPLDynamicType.py
@@ -15,12 +15,12 @@
import time
import unittest2
import lldb
-from lldbsuite.test.lldbrepl import REPLTest, load_tests
+import lldbsuite.test.lldbrepl as lldbrepl
-class REPLDynamicTypeTestCase (REPLTest):
+class REPLDynamicTypeTestCase (lldbrepl.REPLTest):
- mydir = REPLTest.compute_mydir(__file__)
+ mydir = lldbrepl.REPLTest.compute_mydir(__file__)
def doTest(self):
self.command('type(of: 1)', patterns=['\\$R0: Int.Type = Int'])
diff --git a/packages/Python/lldbsuite/test/repl/func_definition/TestREPLFunctionDefinition.py b/packages/Python/lldbsuite/test/repl/func_definition/TestREPLFunctionDefinition.py
index 87feb43..a25cfa6 100644
--- a/packages/Python/lldbsuite/test/repl/func_definition/TestREPLFunctionDefinition.py
+++ b/packages/Python/lldbsuite/test/repl/func_definition/TestREPLFunctionDefinition.py
@@ -15,12 +15,12 @@
import time
import unittest2
import lldb
-from lldbsuite.test.lldbrepl import REPLTest, load_tests
+import lldbsuite.test.lldbrepl as lldbrepl
-class REPLFuncDefinitionTestCase (REPLTest):
+class REPLFuncDefinitionTestCase (lldbrepl.REPLTest):
- mydir = REPLTest.compute_mydir(__file__)
+ mydir = lldbrepl.REPLTest.compute_mydir(__file__)
def doTest(self):
self.command(
diff --git a/packages/Python/lldbsuite/test/repl/int_vars/TestREPLIntVars.py b/packages/Python/lldbsuite/test/repl/int_vars/TestREPLIntVars.py
index f3f016f..cdf8bd3 100644
--- a/packages/Python/lldbsuite/test/repl/int_vars/TestREPLIntVars.py
+++ b/packages/Python/lldbsuite/test/repl/int_vars/TestREPLIntVars.py
@@ -16,12 +16,12 @@
import unittest2
import lldb
import lldbsuite.test.decorators as decorators
-from lldbsuite.test.lldbrepl import REPLTest, load_tests
+import lldbsuite.test.lldbrepl as lldbrepl
-class REPLIntVarsTestCase (REPLTest):
+class REPLIntVarsTestCase (lldbrepl.REPLTest):
- mydir = REPLTest.compute_mydir(__file__)
+ mydir = lldbrepl.REPLTest.compute_mydir(__file__)
@decorators.swiftTest
@decorators.no_debug_info_test
@@ -29,7 +29,7 @@
oslist=["linux"],
bugnumber="rdar://23081322")
def testREPL(self):
- REPLTest.testREPL(self)
+ lldbrepl.REPLTest.testREPL(self)
def doTest(self):
self.command('3 + 2', patterns=['\\$R0: Int = 5'])
diff --git a/packages/Python/lldbsuite/test/repl/multilevelarrays/TestMultilevelArrays.py b/packages/Python/lldbsuite/test/repl/multilevelarrays/TestMultilevelArrays.py
index d018b28..9e9dba4 100644
--- a/packages/Python/lldbsuite/test/repl/multilevelarrays/TestMultilevelArrays.py
+++ b/packages/Python/lldbsuite/test/repl/multilevelarrays/TestMultilevelArrays.py
@@ -15,12 +15,12 @@
import time
import unittest2
import lldb
-from lldbsuite.test.lldbrepl import REPLTest, load_tests
+import lldbsuite.test.lldbrepl as lldbrepl
-class REPLNestedArrayTestCase (REPLTest):
+class REPLNestedArrayTestCase (lldbrepl.REPLTest):
- mydir = REPLTest.compute_mydir(__file__)
+ mydir = lldbrepl.REPLTest.compute_mydir(__file__)
def doTest(self):
self.command('[[1,2,3,4],[1,2,3],[1,2],[],[1]]', patterns=[
diff --git a/packages/Python/lldbsuite/test/repl/nsobject_subclass/TestNSObjectSubclass.py b/packages/Python/lldbsuite/test/repl/nsobject_subclass/TestNSObjectSubclass.py
index 373b825..8a94152 100644
--- a/packages/Python/lldbsuite/test/repl/nsobject_subclass/TestNSObjectSubclass.py
+++ b/packages/Python/lldbsuite/test/repl/nsobject_subclass/TestNSObjectSubclass.py
@@ -15,20 +15,20 @@
import time
import unittest2
import lldb
-from lldbsuite.test.lldbrepl import REPLTest, load_tests
+import lldbsuite.test.lldbrepl as lldbrepl
import lldbsuite.test.decorators as decorators
import lldbsuite.test.lldbtest as lldbtest
-class REPLNSObjectSubclassTest (REPLTest):
+class REPLNSObjectSubclassTest (lldbrepl.REPLTest):
- mydir = REPLTest.compute_mydir(__file__)
+ mydir = lldbrepl.REPLTest.compute_mydir(__file__)
@decorators.swiftTest
@decorators.skipUnlessDarwin
@decorators.no_debug_info_test
def testREPL(self):
- REPLTest.testREPL(self)
+ lldbrepl.REPLTest.testREPL(self)
def doTest(self):
self.command('import Foundation', timeout=20)
diff --git a/packages/Python/lldbsuite/test/repl/nsstring/TestREPLNSString.py b/packages/Python/lldbsuite/test/repl/nsstring/TestREPLNSString.py
index c7035cf..a637d1f 100644
--- a/packages/Python/lldbsuite/test/repl/nsstring/TestREPLNSString.py
+++ b/packages/Python/lldbsuite/test/repl/nsstring/TestREPLNSString.py
@@ -16,18 +16,18 @@
import unittest2
import lldb
import lldbsuite.test.decorators as decorators
-from lldbsuite.test.lldbrepl import REPLTest, load_tests
+import lldbsuite.test.lldbrepl as lldbrepl
-class REPLNSStringTestCase (REPLTest):
+class REPLNSStringTestCase (lldbrepl.REPLTest):
- mydir = REPLTest.compute_mydir(__file__)
+ mydir = lldbrepl.REPLTest.compute_mydir(__file__)
@decorators.swiftTest
@decorators.skipUnlessDarwin
@decorators.no_debug_info_test
def testREPL(self):
- REPLTest.testREPL(self)
+ lldbrepl.REPLTest.testREPL(self)
def doTest(self):
self.command('import Foundation', timeout=20)
diff --git a/packages/Python/lldbsuite/test/repl/quicklookobject/TestREPLQuickLookObject.py b/packages/Python/lldbsuite/test/repl/quicklookobject/TestREPLQuickLookObject.py
index baf729f..2127aab 100644
--- a/packages/Python/lldbsuite/test/repl/quicklookobject/TestREPLQuickLookObject.py
+++ b/packages/Python/lldbsuite/test/repl/quicklookobject/TestREPLQuickLookObject.py
@@ -15,13 +15,13 @@
import time
import unittest2
import lldb
-from lldbsuite.test.lldbrepl import REPLTest, load_tests
+import lldbsuite.test.lldbrepl as lldbrepl
import lldbsuite.test.lldbtest as lldbtest
-class REPLQuickLookTestCase (REPLTest):
+class REPLQuickLookTestCase (lldbrepl.REPLTest):
- mydir = REPLTest.compute_mydir(__file__)
+ mydir = lldbrepl.REPLTest.compute_mydir(__file__)
def doTest(self):
self.command(
diff --git a/packages/Python/lldbsuite/test/repl/subclassing/TestREPLSubclassing.py b/packages/Python/lldbsuite/test/repl/subclassing/TestREPLSubclassing.py
index 38618b1..5e92c88 100644
--- a/packages/Python/lldbsuite/test/repl/subclassing/TestREPLSubclassing.py
+++ b/packages/Python/lldbsuite/test/repl/subclassing/TestREPLSubclassing.py
@@ -15,24 +15,21 @@
import time
import unittest2
import lldb
-from lldbsuite.test.lldbrepl import REPLTest, load_tests
+import lldbsuite.test.lldbrepl as lldbrepl
from lldbsuite.test import decorators
-class REPLSubclassingTestCase (REPLTest):
+class REPLSubclassingTestCase (lldbrepl.REPLTest):
- mydir = REPLTest.compute_mydir(__file__)
+ mydir = lldbrepl.REPLTest.compute_mydir(__file__)
- @decorators.expectedFailureAll(
- oslist=["macosx"],
- bugnumber="rdar://26768714")
def doTest(self):
self.command('class A {init(a: Int) {}}')
self.command(
- 'class B : A {let x: Int; init() { x = 10; super.init(a: x) } }')
+ 'class B : A {let x: Int; init() { x = 5 + 5; super.init(a: x) } }')
self.command('print(B().x)', patterns=['10'])
self.command(
- 'extension B : CustomStringConvertible { var description:String { return "class B is a subclass of class A"} }')
+ 'extension B : CustomStringConvertible { public var description:String { return "class B\(x) is a subclass of class A"} }')
self.command(
'print(B())',
- patterns=['class B is a subclass of class A'])
+ patterns=['class B(10) is a subclass of class A'])
diff --git a/scripts/Xcode/build-llvm.py b/scripts/Xcode/build-llvm.py
index 077abc3..94a6dfb 100755
--- a/scripts/Xcode/build-llvm.py
+++ b/scripts/Xcode/build-llvm.py
@@ -54,6 +54,9 @@
}
def XCODE_REPOSITORIES():
+ override = repo.get_override()
+ if override:
+ return [process_repo(r) for r in override]
identifier = repo.identifier()
if identifier == None:
return [fallback_repo(n) for n in ["llvm", "clang", "swift", "cmark", "ninja"]]
diff --git a/scripts/Xcode/repo.py b/scripts/Xcode/repo.py
index d6e1aee..355159c 100644
--- a/scripts/Xcode/repo.py
+++ b/scripts/Xcode/repo.py
@@ -20,6 +20,17 @@
pass
return None
+def get_override():
+ dir = os.path.dirname(os.path.realpath(__file__))
+ repos_dir = os.path.join(dir, "repos")
+ json_regex = re.compile(r"^.*.json$")
+ override_path = os.path.join(repos_dir, "OVERRIDE")
+ if os.path.isfile(override_path):
+ override_set = json.load(open(override_path))
+ return override_set["repos"]
+ else:
+ return None
+
def find(identifier):
dir = os.path.dirname(os.path.realpath(__file__))
repos_dir = os.path.join(dir, "repos")
diff --git a/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.cpp b/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.cpp
index 2bbb2c0..f73b655 100644
--- a/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.cpp
+++ b/source/Plugins/ExpressionParser/Swift/SwiftASTManipulator.cpp
@@ -835,10 +835,16 @@
virtual bool walkToDeclPre(swift::Decl *decl) {
if (swift::ValueDecl *value_decl =
llvm::dyn_cast<swift::ValueDecl>(decl)) {
- value_decl->overwriteAccessibility(swift::Accessibility::Public);
+ auto access = swift::Accessibility::Public;
+ if (swift::isa<swift::ClassDecl>(value_decl) ||
+ swift::isa<swift::ClassDecl>(value_decl->getDeclContext())) {
+ access = swift::Accessibility::Open;
+ }
+
+ value_decl->overwriteAccessibility(access);
if (swift::AbstractStorageDecl *var_decl =
llvm::dyn_cast<swift::AbstractStorageDecl>(decl))
- var_decl->overwriteSetterAccessibility(swift::Accessibility::Public);
+ var_decl->overwriteSetterAccessibility(access);
}
return true;
diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
index 84e32b7..27761d7 100644
--- a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
@@ -247,12 +247,16 @@
AddressSanitizerRuntime *const instance =
static_cast<AddressSanitizerRuntime *>(baton);
+ ProcessSP process_sp = instance->GetProcessSP();
+
+ if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
+ return false;
+
StructuredData::ObjectSP report = instance->RetrieveReportData();
std::string description;
if (report) {
description = instance->FormatDescription(report);
}
- ProcessSP process_sp = instance->GetProcessSP();
// Make sure this is the right process
if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) {
ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
diff --git a/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp b/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
index 0283523..54c13f6 100644
--- a/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
@@ -109,12 +109,32 @@
swift::DeclVisibilityKind Reason) {
if (result)
return; // Take the first result.
- if (swift::ClassDecl *cls = clang::dyn_cast<swift::ClassDecl>(VD)) {
- auto funcs = cls->lookupDirect(selectorToLookup, true);
- if (funcs.size() > 0) {
- result = funcs.front()->getFullName();
+ swift::ClassDecl *cls = llvm::dyn_cast<swift::ClassDecl>(VD);
+ if (!cls)
+ return;
+ auto funcs = cls->lookupDirect(selectorToLookup, true);
+ if (funcs.size() == 0)
+ return;
+
+ // If the decl is actually an accessor, use the property name instead.
+ swift::AbstractFunctionDecl *decl = funcs.front();
+ if (auto func = llvm::dyn_cast<swift::FuncDecl>(decl)) {
+ swift::DeclContext *funcCtx = func->getParent();
+ // We need to loadAllMembers(), otherwise 'isAccessor' returns false.
+ if (auto extension = llvm::dyn_cast<swift::ExtensionDecl>(funcCtx)) {
+ extension->loadAllMembers();
+ } else if (auto nominal =
+ llvm::dyn_cast<swift::NominalTypeDecl>(funcCtx)) {
+ nominal->loadAllMembers();
+ }
+
+ if (func->isAccessor()) {
+ result = func->getAccessorStorageDecl()->getFullName();
+ return;
}
}
+
+ result = decl->getFullName();
}
};
@@ -211,7 +231,7 @@
d->AddStringItem("class_name", className);
d->AddStringItem("selector", selector);
d->AddStringItem("description",
- apiName + " must be called from main thread only");
+ apiName + " must be used from main thread only");
d->AddIntegerItem("tid", thread_sp->GetIndexID());
d->AddItem("trace", trace_sp);
return dict_sp;
@@ -233,6 +253,9 @@
process_sp != context->exe_ctx_ref.GetProcessSP())
return false;
+ if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
+ return false;
+
StructuredData::ObjectSP report =
instance->RetrieveReportData(context->exe_ctx_ref);
diff --git a/source/Plugins/InstrumentationRuntime/SwiftRuntimeReporting/SwiftRuntimeReporting.cpp b/source/Plugins/InstrumentationRuntime/SwiftRuntimeReporting/SwiftRuntimeReporting.cpp
index 73e2b43..e0566f5 100644
--- a/source/Plugins/InstrumentationRuntime/SwiftRuntimeReporting/SwiftRuntimeReporting.cpp
+++ b/source/Plugins/InstrumentationRuntime/SwiftRuntimeReporting/SwiftRuntimeReporting.cpp
@@ -181,7 +181,7 @@
if (num_notes > 16) num_notes = 16;
addr_t fixits_ptr = process_sp->ReadUnsignedIntegerFromMemory(addr + ptr_size, ptr_size, 0, read_error);
for (int i = 0; i < num_notes; i++) {
- int note_struct_stride = 6 * ptr_size;
+ int note_struct_stride = 3 * ptr_size;
addr_t note_ptr = fixits_ptr + i * note_struct_stride;
std::string note_description;
@@ -340,6 +340,9 @@
process_sp != context->exe_ctx_ref.GetProcessSP())
return false;
+ if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
+ return false;
+
StructuredData::ObjectSP report =
instance->RetrieveReportData(context->exe_ctx_ref);
diff --git a/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp b/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp
index 9cc3f1a..70dca5b 100644
--- a/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp
@@ -803,6 +803,11 @@
ThreadSanitizerRuntime *const instance =
static_cast<ThreadSanitizerRuntime *>(baton);
+ ProcessSP process_sp = instance->GetProcessSP();
+
+ if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
+ return false;
+
StructuredData::ObjectSP report =
instance->RetrieveReportData(context->exe_ctx_ref);
std::string stop_reason_description;
@@ -851,7 +856,6 @@
all_addresses_are_same);
}
- ProcessSP process_sp = instance->GetProcessSP();
// Make sure this is the right process
if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) {
ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
diff --git a/source/Plugins/InstrumentationRuntime/UndefinedBehaviorSanitizer/UndefinedBehaviorSanitizerRuntime.cpp b/source/Plugins/InstrumentationRuntime/UndefinedBehaviorSanitizer/UndefinedBehaviorSanitizerRuntime.cpp
index c8e1ce8..09eda21 100644
--- a/source/Plugins/InstrumentationRuntime/UndefinedBehaviorSanitizer/UndefinedBehaviorSanitizerRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/UndefinedBehaviorSanitizer/UndefinedBehaviorSanitizerRuntime.cpp
@@ -216,6 +216,9 @@
process_sp != context->exe_ctx_ref.GetProcessSP())
return false;
+ if (process_sp->GetModIDRef().IsLastResumeForUserExpression())
+ return false;
+
StructuredData::ObjectSP report =
instance->RetrieveReportData(context->exe_ctx_ref);
diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp
index 2e2513f..fae0ebc 100644
--- a/source/Plugins/Language/ObjC/NSArray.cpp
+++ b/source/Plugins/Language/ObjC/NSArray.cpp
@@ -160,11 +160,47 @@
DataDescriptor_64 *m_data_64;
};
-class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+class NSArrayMSyntheticFrontEnd_1400 : public NSArrayMSyntheticFrontEnd {
public:
- NSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+ NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp);
- ~NSArrayISyntheticFrontEnd() override = default;
+ ~NSArrayMSyntheticFrontEnd_1400() override;
+
+ bool Update() override;
+
+protected:
+ lldb::addr_t GetDataAddress() override;
+
+ uint64_t GetUsedCount() override;
+
+ uint64_t GetOffset() override;
+
+ uint64_t GetSize() override;
+
+private:
+ struct DataDescriptor_32 {
+ uint32_t used;
+ uint32_t offset;
+ uint32_t size;
+ uint32_t list;
+ };
+
+ struct DataDescriptor_64 {
+ uint64_t used;
+ uint64_t offset;
+ uint64_t size;
+ uint64_t list;
+ };
+
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+};
+
+class NSArrayISyntheticFrontEnd_1300 : public SyntheticChildrenFrontEnd {
+public:
+ NSArrayISyntheticFrontEnd_1300(lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayISyntheticFrontEnd_1300() override = default;
size_t CalculateNumChildren() override;
@@ -184,6 +220,45 @@
CompilerType m_id_type;
};
+class NSArrayISyntheticFrontEnd_1400 : public SyntheticChildrenFrontEnd {
+public:
+ NSArrayISyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayISyntheticFrontEnd_1400() override;
+
+ size_t CalculateNumChildren() override;
+
+ lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+ bool Update() override;
+
+ bool MightHaveChildren() override;
+
+ size_t GetIndexOfChildWithName(const ConstString &name) override;
+
+private:
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+
+ struct DataDescriptor_32 {
+ uint32_t used;
+ uint32_t offset;
+ uint32_t size;
+ uint32_t list;
+ };
+
+ struct DataDescriptor_64 {
+ uint64_t used;
+ uint64_t offset;
+ uint64_t size;
+ uint64_t list;
+ };
+
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ CompilerType m_id_type;
+};
+
class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd {
public:
NSArray0SyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
@@ -257,6 +332,8 @@
static const ConstString g_NSArray0("__NSArray0");
static const ConstString g_NSArray1("__NSSingleObjectArrayI");
static const ConstString g_NSArrayCF("__NSCFArray");
+ static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
+ static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
if (class_name.IsEmpty())
return false;
@@ -273,6 +350,18 @@
ptr_size, 0, error);
if (error.Fail())
return false;
+ } else if (class_name == g_NSArrayMLegacy) {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
+ ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ } else if (class_name == g_NSArrayMImmutable) {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
+ ptr_size, 0, error);
+ if (error.Fail())
+ return false;
} else if (class_name == g_NSArray0) {
value = 0;
} else if (class_name == g_NSArray1) {
@@ -332,6 +421,11 @@
: NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr),
m_data_64(nullptr) {}
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::
+ NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp)
+ : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr),
+ m_data_64(nullptr) {}
+
size_t
lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren() {
return GetUsedCount();
@@ -416,6 +510,37 @@
return false;
}
+bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() {
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ m_ptr_size = 0;
+ delete m_data_32;
+ m_data_32 = nullptr;
+ delete m_data_64;
+ m_data_64 = nullptr;
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ Error error;
+ error.Clear();
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return false;
+ m_ptr_size = process_sp->GetAddressByteSize();
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ if (m_ptr_size == 4) {
+ m_data_32 = new DataDescriptor_32();
+ process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
+ error);
+ } else {
+ m_data_64 = new DataDescriptor_64();
+ process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
+ error);
+ }
+ if (error.Fail())
+ return false;
+ return false;
+}
+
bool lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren() {
return true;
}
@@ -498,7 +623,42 @@
return m_data_32 ? m_data_32->_size : m_data_64->_size;
}
-lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd(
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::
+ ~NSArrayMSyntheticFrontEnd_1400() {
+ delete m_data_32;
+ m_data_32 = nullptr;
+ delete m_data_64;
+ m_data_64 = nullptr;
+}
+
+lldb::addr_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetDataAddress() {
+ if (!m_data_32 && !m_data_64)
+ return LLDB_INVALID_ADDRESS;
+ return m_data_32 ? m_data_32->list : m_data_64->list;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetUsedCount() {
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->used : m_data_64->used;
+}
+
+uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetOffset() {
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->offset : m_data_64->offset;
+}
+
+uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetSize() {
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->size : m_data_64->size;
+}
+
+
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::NSArrayISyntheticFrontEnd_1300(
lldb::ValueObjectSP valobj_sp)
: SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
m_items(0), m_data_ptr(0) {
@@ -516,7 +676,7 @@
}
size_t
-lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName(
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetIndexOfChildWithName(
const ConstString &name) {
const char *item_name = name.GetCString();
uint32_t idx = ExtractIndexFromString(item_name);
@@ -526,11 +686,11 @@
}
size_t
-lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren() {
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::CalculateNumChildren() {
return m_items;
}
-bool lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() {
+bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::Update() {
m_ptr_size = 0;
m_items = 0;
m_data_ptr = 0;
@@ -552,12 +712,12 @@
return false;
}
-bool lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren() {
+bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::MightHaveChildren() {
return true;
}
lldb::ValueObjectSP
-lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex(
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetChildAtIndex(
size_t idx) {
if (idx >= CalculateNumChildren())
return lldb::ValueObjectSP();
@@ -575,6 +735,99 @@
m_exe_ctx_ref, m_id_type);
}
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::NSArrayISyntheticFrontEnd_1400(
+ lldb::ValueObjectSP valobj_sp)
+ : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
+ m_data_32(nullptr), m_data_64(nullptr) {
+ if (valobj_sp) {
+ CompilerType type = valobj_sp->GetCompilerType();
+ if (type) {
+ ClangASTContext *ast = valobj_sp->GetExecutionContextRef()
+ .GetTargetSP()
+ ->GetScratchClangASTContext();
+ if (ast)
+ m_id_type = CompilerType(ast->getASTContext(),
+ ast->getASTContext()->ObjCBuiltinIdTy);
+ }
+ }
+}
+
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::~NSArrayISyntheticFrontEnd_1400() {
+ delete m_data_32;
+ m_data_32 = nullptr;
+ delete m_data_64;
+ m_data_64 = nullptr;
+}
+
+size_t
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetIndexOfChildWithName(
+ const ConstString &name) {
+ const char *item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+}
+
+size_t
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::CalculateNumChildren() {
+ return m_data_32 ? m_data_32->used : m_data_64->used;
+}
+
+bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() {
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ m_ptr_size = 0;
+ delete m_data_32;
+ m_data_32 = nullptr;
+ delete m_data_64;
+ m_data_64 = nullptr;
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ Error error;
+ error.Clear();
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return false;
+ m_ptr_size = process_sp->GetAddressByteSize();
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ if (m_ptr_size == 4) {
+ m_data_32 = new DataDescriptor_32();
+ process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
+ error);
+ } else {
+ m_data_64 = new DataDescriptor_64();
+ process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
+ error);
+ }
+ if (error.Fail())
+ return false;
+ return false;
+}
+
+bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::MightHaveChildren() {
+ return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetChildAtIndex(
+ size_t idx) {
+ if (idx >= CalculateNumChildren())
+ return lldb::ValueObjectSP();
+ lldb::addr_t object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list;
+ object_at_idx += (idx * m_ptr_size);
+ ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+ Error error;
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx,
+ m_exe_ctx_ref, m_id_type);
+}
+
lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd(
lldb::ValueObjectSP valobj_sp)
: SyntheticChildrenFrontEnd(*valobj_sp) {}
@@ -683,17 +936,24 @@
static const ConstString g_NSArrayM("__NSArrayM");
static const ConstString g_NSArray0("__NSArray0");
static const ConstString g_NSArray1("__NSSingleObjectArrayI");
+ static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
+ static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
if (class_name.IsEmpty())
return nullptr;
if (class_name == g_NSArrayI) {
- return (new NSArrayISyntheticFrontEnd(valobj_sp));
+ if (runtime->GetFoundationVersion() >= 1400)
+ return (new NSArrayISyntheticFrontEnd_1400(valobj_sp));
+ else
+ return (new NSArrayISyntheticFrontEnd_1300(valobj_sp));
} else if (class_name == g_NSArray0) {
return (new NSArray0SyntheticFrontEnd(valobj_sp));
} else if (class_name == g_NSArray1) {
return (new NSArray1SyntheticFrontEnd(valobj_sp));
} else if (class_name == g_NSArrayM) {
+ if (runtime->GetFoundationVersion() >= 1400)
+ return (new NSArrayMSyntheticFrontEnd_1400(valobj_sp));
if (runtime->GetFoundationVersion() >= 1100)
return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp));
else
diff --git a/source/Plugins/Language/ObjC/NSDictionary.cpp b/source/Plugins/Language/ObjC/NSDictionary.cpp
index 23a445f..8cbb043 100644
--- a/source/Plugins/Language/ObjC/NSDictionary.cpp
+++ b/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -34,6 +34,7 @@
// FIXME: we should not need this
#include "Plugins/Language/Swift/SwiftDictionary.h"
+#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
#include <mutex>
using namespace lldb;
@@ -187,6 +188,52 @@
private:
struct DataDescriptor_32 {
+ uint32_t used : 26;
+ uint32_t kvo : 1;
+ uint32_t size;
+ uint32_t buffer;
+ };
+
+ struct DataDescriptor_64 {
+ uint64_t used : 58;
+ uint32_t kvo : 1;
+ uint64_t size;
+ uint64_t buffer;
+ };
+
+ struct DictionaryItemDescriptor {
+ lldb::addr_t key_ptr;
+ lldb::addr_t val_ptr;
+ lldb::ValueObjectSP valobj_sp;
+ };
+
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ lldb::ByteOrder m_order;
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ CompilerType m_pair_type;
+ std::vector<DictionaryItemDescriptor> m_children;
+};
+
+class NSDictionaryMLegacySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+ ~NSDictionaryMLegacySyntheticFrontEnd() override;
+
+ size_t CalculateNumChildren() override;
+
+ lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+ bool Update() override;
+
+ bool MightHaveChildren() override;
+
+ size_t GetIndexOfChildWithName(const ConstString &name) override;
+
+private:
+ struct DataDescriptor_32 {
uint32_t _used : 26;
uint32_t _kvo : 1;
uint32_t _size;
@@ -256,19 +303,21 @@
static const ConstString g_DictionaryI("__NSDictionaryI");
static const ConstString g_DictionaryM("__NSDictionaryM");
+ static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
+ static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
if (class_name.IsEmpty())
return false;
- if (class_name == g_DictionaryI) {
+ if (class_name == g_DictionaryI || class_name == g_DictionaryMImmutable) {
Error error;
value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
ptr_size, 0, error);
if (error.Fail())
return false;
value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
- } else if (class_name == g_DictionaryM) {
+ } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) {
Error error;
value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
ptr_size, 0, error);
@@ -317,9 +366,8 @@
lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
if (!process_sp)
return nullptr;
- ObjCLanguageRuntime *runtime =
- (ObjCLanguageRuntime *)process_sp->GetLanguageRuntime(
- lldb::eLanguageTypeObjC);
+ AppleObjCRuntime *runtime =
+ llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime());
if (!runtime)
return nullptr;
@@ -344,6 +392,8 @@
static const ConstString g_DictionaryI("__NSDictionaryI");
static const ConstString g_DictionaryM("__NSDictionaryM");
static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
+ static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable");
+ static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
if (class_name.IsEmpty())
return nullptr;
@@ -351,7 +401,13 @@
if (class_name == g_DictionaryI) {
return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
} else if (class_name == g_DictionaryM) {
- return (new NSDictionaryMSyntheticFrontEnd(valobj_sp));
+ if (runtime->GetFoundationVersion() > 1400) {
+ return (new NSDictionaryMSyntheticFrontEnd(valobj_sp));
+ } else {
+ return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp));
+ }
+ } else if (class_name == g_DictionaryMLegacy) {
+ return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp));
} else if (class_name == g_Dictionary1) {
return (new NSDictionary1SyntheticFrontEnd(valobj_sp));
} else {
@@ -617,7 +673,7 @@
CalculateNumChildren() {
if (!m_data_32 && !m_data_64)
return 0;
- return (m_data_32 ? m_data_32->_used : m_data_64->_used);
+ return (m_data_32 ? m_data_32->used : m_data_64->used);
}
bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() {
@@ -661,6 +717,165 @@
lldb::ValueObjectSP
lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex(
size_t idx) {
+ lldb::addr_t m_keys_ptr;
+ lldb::addr_t m_values_ptr;
+ if (m_data_32) {
+ uint32_t size = m_data_32->size;
+ m_keys_ptr = m_data_32->buffer;
+ m_values_ptr = m_data_32->buffer + (m_ptr_size * size);
+ } else {
+ uint32_t size = m_data_64->size;
+ m_keys_ptr = m_data_64->buffer;
+ m_values_ptr = m_data_64->buffer + (m_ptr_size * size);
+ }
+
+ uint32_t num_children = CalculateNumChildren();
+
+ if (idx >= num_children)
+ return lldb::ValueObjectSP();
+
+ if (m_children.empty()) {
+ // do the scan phase
+ lldb::addr_t key_at_idx = 0, val_at_idx = 0;
+
+ uint32_t tries = 0;
+ uint32_t test_idx = 0;
+
+ while (tries < num_children) {
+ key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
+ val_at_idx = m_values_ptr + (test_idx * m_ptr_size);
+ ;
+ ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+ Error error;
+ key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+ val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+
+ test_idx++;
+
+ if (!key_at_idx || !val_at_idx)
+ continue;
+ tries++;
+
+ DictionaryItemDescriptor descriptor = {key_at_idx, val_at_idx,
+ lldb::ValueObjectSP()};
+
+ m_children.push_back(descriptor);
+ }
+ }
+
+ if (idx >= m_children.size()) // should never happen
+ return lldb::ValueObjectSP();
+
+ DictionaryItemDescriptor &dict_item = m_children[idx];
+ if (!dict_item.valobj_sp) {
+ if (!m_pair_type.IsValid()) {
+ TargetSP target_sp(m_backend.GetTargetSP());
+ if (!target_sp)
+ return ValueObjectSP();
+ m_pair_type = GetLLDBNSPairType(target_sp);
+ }
+ if (!m_pair_type.IsValid())
+ return ValueObjectSP();
+
+ DataBufferSP buffer_sp(new DataBufferHeap(2 * m_ptr_size, 0));
+
+ if (m_ptr_size == 8) {
+ uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
+ *data_ptr = dict_item.key_ptr;
+ *(data_ptr + 1) = dict_item.val_ptr;
+ } else {
+ uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
+ *data_ptr = dict_item.key_ptr;
+ *(data_ptr + 1) = dict_item.val_ptr;
+ }
+
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ DataExtractor data(buffer_sp, m_order, m_ptr_size);
+ dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetString(), data,
+ m_exe_ctx_ref, m_pair_type);
+ }
+ return dict_item.valobj_sp;
+}
+
+
+lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::
+ NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+ : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
+ m_order(lldb::eByteOrderInvalid), m_data_32(nullptr), m_data_64(nullptr),
+ m_pair_type() {}
+
+lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::
+ ~NSDictionaryMLegacySyntheticFrontEnd() {
+ delete m_data_32;
+ m_data_32 = nullptr;
+ delete m_data_64;
+ m_data_64 = nullptr;
+}
+
+size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::
+ GetIndexOfChildWithName(const ConstString &name) {
+ const char *item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+}
+
+size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::
+ CalculateNumChildren() {
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return (m_data_32 ? m_data_32->_used : m_data_64->_used);
+}
+
+bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::Update() {
+ m_children.clear();
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ m_ptr_size = 0;
+ delete m_data_32;
+ m_data_32 = nullptr;
+ delete m_data_64;
+ m_data_64 = nullptr;
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ Error error;
+ error.Clear();
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return false;
+ m_ptr_size = process_sp->GetAddressByteSize();
+ m_order = process_sp->GetByteOrder();
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ if (m_ptr_size == 4) {
+ m_data_32 = new DataDescriptor_32();
+ process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
+ error);
+ } else {
+ m_data_64 = new DataDescriptor_64();
+ process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
+ error);
+ }
+ if (error.Fail())
+ return false;
+ return false;
+}
+
+bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::
+ MightHaveChildren() {
+ return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::GetChildAtIndex(
+ size_t idx) {
lldb::addr_t m_keys_ptr =
(m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
lldb::addr_t m_values_ptr =
diff --git a/source/Plugins/Language/ObjC/NSSet.cpp b/source/Plugins/Language/ObjC/NSSet.cpp
index 542c242..60f56cc 100644
--- a/source/Plugins/Language/ObjC/NSSet.cpp
+++ b/source/Plugins/Language/ObjC/NSSet.cpp
@@ -13,6 +13,7 @@
// Project includes
#include "NSSet.h"
+#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Stream.h"
@@ -84,11 +85,12 @@
std::vector<SetItemDescriptor> m_children;
};
-class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+template <typename D32, typename D64>
+class GenericNSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
public:
- NSSetMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+ GenericNSSetMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
- ~NSSetMSyntheticFrontEnd() override;
+ ~GenericNSSetMSyntheticFrontEnd() override;
size_t CalculateNumChildren() override;
@@ -101,19 +103,6 @@
size_t GetIndexOfChildWithName(const ConstString &name) override;
private:
- struct DataDescriptor_32 {
- uint32_t _used : 26;
- uint32_t _size;
- uint32_t _mutations;
- uint32_t _objs_addr;
- };
-
- struct DataDescriptor_64 {
- uint64_t _used : 58;
- uint64_t _size;
- uint64_t _mutations;
- uint64_t _objs_addr;
- };
struct SetItemDescriptor {
lldb::addr_t item_ptr;
@@ -122,11 +111,49 @@
ExecutionContextRef m_exe_ctx_ref;
uint8_t m_ptr_size;
- DataDescriptor_32 *m_data_32;
- DataDescriptor_64 *m_data_64;
+ D32 *m_data_32;
+ D64 *m_data_64;
std::vector<SetItemDescriptor> m_children;
};
-
+
+namespace Foundation1300 {
+ struct DataDescriptor_32 {
+ uint32_t _used : 26;
+ uint32_t _size;
+ uint32_t _mutations;
+ uint32_t _objs_addr;
+ };
+
+ struct DataDescriptor_64 {
+ uint64_t _used : 58;
+ uint64_t _size;
+ uint64_t _mutations;
+ uint64_t _objs_addr;
+ };
+
+ using NSSetMSyntheticFrontEnd =
+ GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
+}
+
+namespace Foundation1400 {
+ struct DataDescriptor_32 {
+ uint32_t _used : 26;
+ uint32_t _size;
+ uint32_t _objs_addr;
+ uint32_t _mutations;
+ };
+
+ struct DataDescriptor_64 {
+ uint64_t _used : 58;
+ uint64_t _size;
+ uint64_t _objs_addr;
+ uint64_t _mutations;
+ };
+
+ using NSSetMSyntheticFrontEnd =
+ GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
+}
+
class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
public:
NSSetCodeRunningSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
@@ -283,7 +310,12 @@
if (!strcmp(class_name, "__NSSetI")) {
return (new NSSetISyntheticFrontEnd(valobj_sp));
} else if (!strcmp(class_name, "__NSSetM")) {
- return (new NSSetMSyntheticFrontEnd(valobj_sp));
+ AppleObjCRuntime *apple_runtime =
+ llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
+ if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1400)
+ return (new Foundation1400::NSSetMSyntheticFrontEnd(valobj_sp));
+ else
+ return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp));
} else {
auto &map(NSSet_Additionals::GetAdditionalSynthetics());
auto iter = map.find(class_name_cs), end = map.end();
@@ -442,7 +474,9 @@
return set_item.valobj_sp;
}
-lldb_private::formatters::NSSetMSyntheticFrontEnd::NSSetMSyntheticFrontEnd(
+template <typename D32, typename D64>
+lldb_private::formatters::
+ GenericNSSetMSyntheticFrontEnd<D32, D64>::GenericNSSetMSyntheticFrontEnd(
lldb::ValueObjectSP valobj_sp)
: SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
m_data_32(nullptr), m_data_64(nullptr) {
@@ -450,15 +484,19 @@
Update();
}
-lldb_private::formatters::NSSetMSyntheticFrontEnd::~NSSetMSyntheticFrontEnd() {
+template <typename D32, typename D64>
+lldb_private::formatters::
+ GenericNSSetMSyntheticFrontEnd<D32, D64>::~GenericNSSetMSyntheticFrontEnd() {
delete m_data_32;
m_data_32 = nullptr;
delete m_data_64;
m_data_64 = nullptr;
}
+template <typename D32, typename D64>
size_t
-lldb_private::formatters::NSSetMSyntheticFrontEnd::GetIndexOfChildWithName(
+lldb_private::formatters::
+ GenericNSSetMSyntheticFrontEnd<D32, D64>::GetIndexOfChildWithName(
const ConstString &name) {
const char *item_name = name.GetCString();
uint32_t idx = ExtractIndexFromString(item_name);
@@ -467,14 +505,19 @@
return idx;
}
+template <typename D32, typename D64>
size_t
-lldb_private::formatters::NSSetMSyntheticFrontEnd::CalculateNumChildren() {
+lldb_private::formatters::
+ GenericNSSetMSyntheticFrontEnd<D32, D64>::CalculateNumChildren() {
if (!m_data_32 && !m_data_64)
return 0;
return (m_data_32 ? m_data_32->_used : m_data_64->_used);
}
-bool lldb_private::formatters::NSSetMSyntheticFrontEnd::Update() {
+template <typename D32, typename D64>
+bool
+lldb_private::formatters::
+ GenericNSSetMSyntheticFrontEnd<D32, D64>::Update() {
m_children.clear();
ValueObjectSP valobj_sp = m_backend.GetSP();
m_ptr_size = 0;
@@ -500,12 +543,12 @@
m_ptr_size = process_sp->GetAddressByteSize();
uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
if (m_ptr_size == 4) {
- m_data_32 = new DataDescriptor_32();
- process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32),
+ m_data_32 = new D32();
+ process_sp->ReadMemory(data_location, m_data_32, sizeof(D32),
error);
} else {
- m_data_64 = new DataDescriptor_64();
- process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64),
+ m_data_64 = new D64();
+ process_sp->ReadMemory(data_location, m_data_64, sizeof(D64),
error);
}
if (error.Fail())
@@ -513,12 +556,17 @@
return false;
}
-bool lldb_private::formatters::NSSetMSyntheticFrontEnd::MightHaveChildren() {
+template <typename D32, typename D64>
+bool
+lldb_private::formatters::
+ GenericNSSetMSyntheticFrontEnd<D32, D64>::MightHaveChildren() {
return true;
}
+template <typename D32, typename D64>
lldb::ValueObjectSP
-lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
+lldb_private::formatters::
+ GenericNSSetMSyntheticFrontEnd<D32, D64>::GetChildAtIndex(size_t idx) {
lldb::addr_t m_objs_addr =
(m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
diff --git a/source/Plugins/Language/Swift/SwiftFormatters.cpp b/source/Plugins/Language/Swift/SwiftFormatters.cpp
index c4b2d02..4d3df75 100644
--- a/source/Plugins/Language/Swift/SwiftFormatters.cpp
+++ b/source/Plugins/Language/Swift/SwiftFormatters.cpp
@@ -376,7 +376,16 @@
ValueObjectSP value_child(valobj.GetChildMemberWithName(g_value, true));
if (!value_child)
return false;
- auto value = value_child->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ // Swift Bools are stored in a byte, but only the LSB of the byte is
+ // significant. The swift::irgen::FixedTypeInfo structure represents
+ // this information by providing a mask of the "extra bits" for the type.
+ // But at present CompilerType has no way to represent that information.
+ // So for now we hard code it.
+ uint64_t value = value_child->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ const uint64_t mask = 1 << 0;
+ value &= mask;
+
switch (value) {
case 0:
stream.Printf("false");
diff --git a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
index c5a3dde..97875c7 100644
--- a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
+++ b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
@@ -47,7 +47,7 @@
namespace {
static PropertyDefinition g_properties[] = {
- {"enable", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
+ {"enable", OptionValue::eTypeBoolean, true, false, nullptr, nullptr,
"Specify whether goroutines should be treated as threads."},
{NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};
@@ -451,8 +451,14 @@
OperatingSystemGo::CreateGoroutineAtIndex(uint64_t idx, Error &err) {
err.Clear();
Goroutine result = {};
- ValueObjectSP g =
- m_allg_sp->GetSyntheticArrayMember(idx, true)->Dereference(err);
+ ValueObjectSP child_sp = m_allg_sp->GetSyntheticArrayMember(idx, true);
+ if (!child_sp) {
+ err.SetErrorToGenericError();
+ err.SetErrorString("unable to find goroutines in array");
+ return result;
+ }
+
+ ValueObjectSP g = child_sp->Dereference(err);
if (err.Fail()) {
return result;
}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index b08d1ad..9101f7d 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -4268,7 +4268,15 @@
}
}
} else {
- if (location_is_const_value_data)
+ // The heuristic for inferring static variables works for Clang's
+ // behavior on C-like languages, which generally does not emit
+ // AT_const_value for locals.
+ //
+ // However, the Swift compiler can and does emit AT_const_value for
+ // locals, and function-level statics don't exist, so we flip the
+ // heuristic here.
+ if (location_is_const_value_data &&
+ !IsSwiftLanguage(sc.comp_unit->GetLanguage()))
scope = eValueTypeVariableStatic;
else {
scope = eValueTypeVariableLocal;
diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
index 9aad2e1..fe31039 100644
--- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
+++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
@@ -577,9 +577,10 @@
}
bool x86AssemblyInspectionEngine::instruction_length(uint8_t *insn_p,
- int &length) {
+ int &length,
+ uint32_t buffer_remaining_bytes) {
- const uint32_t max_op_byte_size = m_arch.GetMaximumOpcodeByteSize();
+ uint32_t max_op_byte_size = std::min(buffer_remaining_bytes, m_arch.GetMaximumOpcodeByteSize());
llvm::SmallVector<uint8_t, 32> opcode_data;
opcode_data.resize(max_op_byte_size);
@@ -671,8 +672,9 @@
bool row_updated = false; // The UnwindPlan::Row 'row' has been updated
m_cur_insn = data + current_func_text_offset;
- if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 ||
- insn_len > kMaxInstructionByteSize) {
+ if (!instruction_length(m_cur_insn, insn_len, size - current_func_text_offset)
+ || insn_len == 0
+ || insn_len > kMaxInstructionByteSize) {
// An unrecognized/junk instruction
break;
}
@@ -969,8 +971,9 @@
while (offset < size) {
m_cur_insn = data + offset;
int insn_len;
- if (!instruction_length(m_cur_insn, insn_len) || insn_len == 0 ||
- insn_len > kMaxInstructionByteSize) {
+ if (!instruction_length(m_cur_insn, insn_len, size - offset)
+ || insn_len == 0
+ || insn_len > kMaxInstructionByteSize) {
// An unrecognized/junk instruction.
break;
}
@@ -1181,8 +1184,9 @@
int scratch;
m_cur_insn = data + offset;
- if (!instruction_length(m_cur_insn, insn_len) ||
- insn_len > kMaxInstructionByteSize || insn_len == 0) {
+ if (!instruction_length(m_cur_insn, insn_len, size - offset)
+ || insn_len > kMaxInstructionByteSize
+ || insn_len == 0) {
// An error parsing the instruction, i.e. probably data/garbage - stop
// scanning
break;
diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
index 0294f5a..abcaf8a 100644
--- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
+++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
@@ -112,7 +112,7 @@
bool ret_pattern_p();
uint32_t extract_4(uint8_t *b);
- bool instruction_length(uint8_t *insn, int &length);
+ bool instruction_length(uint8_t *insn, int &length, uint32_t buffer_remaining_bytes);
bool machine_regno_to_lldb_regno(int machine_regno, uint32_t &lldb_regno);
diff --git a/source/Symbol/SwiftASTContext.cpp b/source/Symbol/SwiftASTContext.cpp
index 69b0cd8..dd7e9d0 100644
--- a/source/Symbol/SwiftASTContext.cpp
+++ b/source/Symbol/SwiftASTContext.cpp
@@ -4185,6 +4185,7 @@
case swift::DeclKind::IfConfig:
case swift::DeclKind::Param:
case swift::DeclKind::Module:
+ case swift::DeclKind::MissingMember:
break;
case swift::DeclKind::InfixOperator:
diff --git a/source/Target/LanguageRuntime.cpp b/source/Target/LanguageRuntime.cpp
index bb3bba4..a3160e0 100644
--- a/source/Target/LanguageRuntime.cpp
+++ b/source/Target/LanguageRuntime.cpp
@@ -342,3 +342,25 @@
else
return eLanguageTypeUnknown;
}
+
+bool
+LanguageRuntime::IsSymbolAnyRuntimeThunk(ProcessSP process_sp, Symbol &symbol)
+{
+ if (!process_sp)
+ return false;
+
+ enum LanguageType languages_to_try[] = {
+ eLanguageTypeSwift, eLanguageTypeObjC, eLanguageTypeC_plus_plus};
+
+ LanguageRuntime *language_runtime;
+ for (enum LanguageType language : languages_to_try) {
+ language_runtime = process_sp->GetLanguageRuntime(language);
+ if (language_runtime) {
+ if (language_runtime->IsSymbolARuntimeThunk(symbol))
+ return true;
+ }
+ }
+ return false;
+}
+
+
diff --git a/source/Target/SwiftLanguageRuntime.cpp b/source/Target/SwiftLanguageRuntime.cpp
index 3adf2b2..d982526 100644
--- a/source/Target/SwiftLanguageRuntime.cpp
+++ b/source/Target/SwiftLanguageRuntime.cpp
@@ -366,6 +366,8 @@
ValueObjectSP static_sp(object.GetStaticValue());
CompilerType static_type(static_sp->GetCompilerType());
+ if (auto non_reference_type = static_type.GetNonReferenceType())
+ static_type = non_reference_type;
Error error;
@@ -2781,13 +2783,12 @@
if (num_global_children == 0)
return ThunkKind::Unknown;
- swift::Demangle::NodePointer global_node_ptr = nodes->getFirstChild();
- if (global_node_ptr->getKind() != swift::Demangle::Node::Kind::Global)
+ if (nodes->getKind() != swift::Demangle::Node::Kind::Global)
return ThunkKind::Unknown;
- if (global_node_ptr->getNumChildren() == 0)
+ if (nodes->getNumChildren() == 0)
return ThunkKind::Unknown;
- swift::Demangle::NodePointer node_ptr = global_node_ptr->getFirstChild();
+ swift::Demangle::NodePointer node_ptr = nodes->getFirstChild();
kind = node_ptr->getKind();
switch (kind)
{
@@ -2803,6 +2804,8 @@
break;
case swift::Demangle::Node::Kind::ReabstractionThunkHelper:
return ThunkKind::Reabstraction;
+ case swift::Demangle::Node::Kind::PartialApplyForwarder:
+ return ThunkKind::PartialApply;
case swift::Demangle::Node::Kind::Allocator:
if (node_ptr->getNumChildren() == 0)
return ThunkKind::Unknown;
@@ -2848,7 +2851,7 @@
case ThunkKind::ObjCAttribute:
return ThunkAction::GetThunkTarget;
case ThunkKind::Reabstraction:
- return ThunkAction::GetThunkTarget;
+ return ThunkAction::StepThrough;
case ThunkKind::ProtocolConformance:
return ThunkAction::StepIntoConformance;
}
@@ -2900,7 +2903,9 @@
bool SwiftLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) {
llvm::StringRef symbol_name = symbol.GetMangled().GetMangledName().GetStringRef();
-
+ if (symbol_name.empty())
+ return false;
+
swift::Demangle::Context demangle_ctx;
return demangle_ctx.isThunkSymbol(symbol_name);
}
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index 9a5e981..a4a1ce4 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -1391,6 +1391,28 @@
return thread_plan_sp;
}
+ThreadPlanSP Thread::QueueThreadPlanForStepInRangeNoShouldStop(
+ bool abort_other_plans, const AddressRange &range,
+ const SymbolContext &addr_context, const char *step_in_target,
+ lldb::RunMode stop_other_threads,
+ LazyBool step_in_avoids_code_without_debug_info,
+ LazyBool step_out_avoids_code_without_debug_info) {
+ ThreadPlanSP thread_plan_sp(
+ new ThreadPlanStepInRange(*this, range, addr_context, stop_other_threads,
+ step_in_avoids_code_without_debug_info,
+ step_out_avoids_code_without_debug_info));
+ ThreadPlanStepInRange *plan =
+ static_cast<ThreadPlanStepInRange *>(thread_plan_sp.get());
+
+ if (step_in_target)
+ plan->SetStepInTarget(step_in_target);
+
+ plan->ClearShouldStopHereCallbacks();
+
+ QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ return thread_plan_sp;
+}
+
// Call the QueueThreadPlanForStepInRange method which takes an address range.
ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
bool abort_other_plans, const LineEntry &line_entry,
diff --git a/source/Target/ThreadPlanShouldStopHere.cpp b/source/Target/ThreadPlanShouldStopHere.cpp
index cb16b3c..e0f2c35 100644
--- a/source/Target/ThreadPlanShouldStopHere.cpp
+++ b/source/Target/ThreadPlanShouldStopHere.cpp
@@ -90,20 +90,9 @@
if (operation == eFrameCompareOlder) {
Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
if (symbol) {
- LanguageRuntime *language_runtime;
- bool is_thunk = false;
ProcessSP process_sp(current_plan->GetThread().GetProcess());
- enum LanguageType languages_to_try[] = {
- eLanguageTypeSwift, eLanguageTypeObjC, eLanguageTypeC_plus_plus};
-
- for (enum LanguageType language : languages_to_try) {
- language_runtime = process_sp->GetLanguageRuntime(language);
- if (language_runtime)
- is_thunk = language_runtime->IsSymbolARuntimeThunk(*symbol);
- if (is_thunk) {
+ if (LanguageRuntime::IsSymbolAnyRuntimeThunk(process_sp, *symbol)) {
should_stop_here = false;
- break;
- }
}
}
}
@@ -143,29 +132,54 @@
if (sc.line_entry.line == 0) {
AddressRange range = sc.line_entry.range;
- // If the whole function is marked line 0 just step out, that's easier &
- // faster than continuing
- // to step through it.
+ // If this is a runtime thunk, just step out:
bool just_step_out = false;
- if (sc.symbol && sc.symbol->ValueIsAddress()) {
- Address symbol_end = sc.symbol->GetAddress();
- symbol_end.Slide(sc.symbol->GetByteSize() - 1);
- if (range.ContainsFileAddress(sc.symbol->GetAddress()) &&
- range.ContainsFileAddress(symbol_end)) {
- if (log)
- log->Printf("Stopped in a function with only line 0 lines, just "
- "stepping out.");
+ if (sc.symbol) {
+ ProcessSP process_sp(current_plan->GetThread().GetProcess());
+
+ if (LanguageRuntime::IsSymbolAnyRuntimeThunk(process_sp, *sc.symbol)) {
+ if (log)
+ log->Printf("In runtime thunk %s - stepping out.",
+ sc.symbol->GetName().GetCString());
just_step_out = true;
}
+ // If the whole function is marked line 0 just step out, that's easier &
+ // faster than continuing to step through it.
+ // FIXME: This assumes that the function is a single line range. It could
+ // be a series of contiguous line 0 ranges. Check for that too.
+ if (!just_step_out && sc.symbol->ValueIsAddress()) {
+ Address symbol_end = sc.symbol->GetAddress();
+ symbol_end.Slide(sc.symbol->GetByteSize() - 1);
+ if (range.ContainsFileAddress(sc.symbol->GetAddress()) &&
+ range.ContainsFileAddress(symbol_end)) {
+ if (log)
+ log->Printf("Stopped in a function with only line 0 lines, just "
+ "stepping out.");
+ just_step_out = true;
+ }
+ }
}
+
if (!just_step_out) {
- if (log)
- log->Printf("ThreadPlanShouldStopHere::DefaultStepFromHereCallback "
- "Queueing StepInRange plan to step through line 0 code.");
-
- return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepInRange(
- false, range, sc, NULL, eOnlyDuringStepping, eLazyBoolCalculate,
- eLazyBoolNo);
+ // If the current plan is a "Step In" plan we should use step in, otherwise
+ // just step over:
+ if (current_plan->GetKind() == ThreadPlan::eKindStepInRange) {
+ if (log)
+ log->Printf("ThreadPlanShouldStopHere::DefaultStepFromHereCallback "
+ "Queueing StepInRange plan to step through line 0 code.");
+ return_plan_sp =
+ current_plan
+ ->GetThread().QueueThreadPlanForStepInRangeNoShouldStop(
+ false, range, sc, NULL, eOnlyDuringStepping, eLazyBoolCalculate,
+ eLazyBoolNo);
+ } else {
+ if (log)
+ log->Printf("ThreadPlanShouldStopHere::DefaultStepFromHereCallback "
+ "Queueing StepOverRange plan to step through line 0 code.");
+ return_plan_sp =
+ current_plan->GetThread().QueueThreadPlanForStepOverRange(
+ false, range, sc, eOnlyDuringStepping, eLazyBoolNo);
+ }
}
}
diff --git a/source/Target/ThreadPlanStepOut.cpp b/source/Target/ThreadPlanStepOut.cpp
index 7a4bfb0..3118f77 100644
--- a/source/Target/ThreadPlanStepOut.cpp
+++ b/source/Target/ThreadPlanStepOut.cpp
@@ -372,6 +372,15 @@
} else {
m_step_out_further_plan_sp =
QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder);
+ if (m_step_out_further_plan_sp->GetKind() == eKindStepOut)
+ {
+ // If we are planning to step out further, then the frame we are going
+ // to step out to is about to go away, so we need to reset the frame
+ // we are stepping out to to the one our step out plan is aiming for.
+ ThreadPlanStepOut *as_step_out
+ = static_cast<ThreadPlanStepOut *>(m_step_out_further_plan_sp.get());
+ m_step_out_to_id = as_step_out->m_step_out_to_id;
+ }
done = false;
}
}
diff --git a/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp b/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
index e216d4b..49b6a5d 100644
--- a/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
+++ b/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
@@ -2337,3 +2337,27 @@
EXPECT_FALSE(row_sp->GetRegisterInfo(k_rbp, regloc));
}
+
+// Give the disassembler random bytes to test that it doesn't exceed
+// the bounds of the array when run under clang's address sanitizer.
+TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyJunkBytes) {
+ AddressRange sample_range;
+ UnwindPlan unwind_plan(eRegisterKindLLDB);
+ std::unique_ptr<x86AssemblyInspectionEngine> engine32 = Geti386Inspector();
+ std::unique_ptr<x86AssemblyInspectionEngine> engine64 = Getx86_64Inspector();
+
+ uint8_t data[] = {
+ 0x10, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+
+ sample_range = AddressRange(0x1000, sizeof(data));
+
+ EXPECT_TRUE(engine32->GetNonCallSiteUnwindPlanFromAssembly(
+ data, sizeof(data), sample_range, unwind_plan));
+
+ unwind_plan.Clear();
+
+ EXPECT_TRUE(engine64->GetNonCallSiteUnwindPlanFromAssembly(
+ data, sizeof(data), sample_range, unwind_plan));
+
+}