diff options
author | dim <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2016-01-06 20:12:03 +0000 |
commit | 78b9749c0a4ea980a8b934645da6ae98fcc665e8 (patch) | |
tree | dd2a1ddf0476664c2b823409c36cbccd52662ca7 /packages/Python/lldbsuite/test/python_api | |
parent | 60cb593f9d55fa5ca7a5372b731f2330345b4b9a (diff) | |
download | FreeBSD-src-78b9749c0a4ea980a8b934645da6ae98fcc665e8.zip FreeBSD-src-78b9749c0a4ea980a8b934645da6ae98fcc665e8.tar.gz |
Vendor import of lldb trunk r256945:
https://llvm.org/svn/llvm-project/lldb/trunk@256945
Diffstat (limited to 'packages/Python/lldbsuite/test/python_api')
150 files changed, 8357 insertions, 0 deletions
diff --git a/packages/Python/lldbsuite/test/python_api/.categories b/packages/Python/lldbsuite/test/python_api/.categories new file mode 100644 index 0000000..db8069c --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/.categories @@ -0,0 +1 @@ +pyapi diff --git a/packages/Python/lldbsuite/test/python_api/breakpoint/Makefile b/packages/Python/lldbsuite/test/python_api/breakpoint/Makefile new file mode 100644 index 0000000..0d70f25 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/breakpoint/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/breakpoint/TestBreakpointAPI.py b/packages/Python/lldbsuite/test/python_api/breakpoint/TestBreakpointAPI.py new file mode 100644 index 0000000..1f4fa20 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/breakpoint/TestBreakpointAPI.py @@ -0,0 +1,45 @@ +""" +Test SBBreakpoint APIs. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class BreakpointAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + def test_breakpoint_is_valid(self): + """Make sure that if an SBBreakpoint gets deleted its IsValid returns false.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'AFunction'. + breakpoint = target.BreakpointCreateByName('AFunction', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now delete it: + did_delete = target.BreakpointDelete(breakpoint.GetID()) + self.assertTrue (did_delete, "Did delete the breakpoint we just created.") + + # Make sure we can't find it: + del_bkpt = target.FindBreakpointByID (breakpoint.GetID()) + self.assertTrue (not del_bkpt, "We did delete the breakpoint.") + + # Finally make sure the original breakpoint is no longer valid. + self.assertTrue (not breakpoint, "Breakpoint we deleted is no longer valid.") diff --git a/packages/Python/lldbsuite/test/python_api/breakpoint/main.c b/packages/Python/lldbsuite/test/python_api/breakpoint/main.c new file mode 100644 index 0000000..2677594 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/breakpoint/main.c @@ -0,0 +1,14 @@ +#include <stdio.h> + +void +AFunction() +{ + printf ("I am a function.\n"); +} + +int +main () +{ + AFunction(); + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/class_members/Makefile b/packages/Python/lldbsuite/test/python_api/class_members/Makefile new file mode 100644 index 0000000..0d7550f --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/class_members/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +OBJCXX_SOURCES := main.mm + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/class_members/TestSBTypeClassMembers.py b/packages/Python/lldbsuite/test/python_api/class_members/TestSBTypeClassMembers.py new file mode 100644 index 0000000..e1d5520 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/class_members/TestSBTypeClassMembers.py @@ -0,0 +1,77 @@ +""" +Test SBType APIs to fetch member function types. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class SBTypeMemberFunctionsTest(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # We'll use the test method name as the exe_name. + self.exe_name = self.testMethodName + # Find the line number to break at. + self.source = 'main.mm' + self.line = line_number(self.source, '// set breakpoint here') + + @skipUnlessDarwin + @add_test_categories(['pyapi']) + def test(self): + """Test SBType APIs to fetch member function types.""" + d = {'EXE': self.exe_name} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + exe = os.path.join(os.getcwd(), self.exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint inside function 'main'. + breakpoint = target.BreakpointCreateByLocation(self.source, self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Get Frame #0. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + + variable = frame0.FindVariable("d") + Derived = variable.GetType() + Base = Derived.GetDirectBaseClassAtIndex(0).GetType() + + self.assertTrue(Derived.GetNumberOfMemberFunctions() == 2, "Derived declares two methods") + self.assertTrue(Derived.GetMemberFunctionAtIndex(0).GetType().GetFunctionReturnType().GetName() == "int", "Derived::dImpl returns int") + + self.assertTrue(Base.GetNumberOfMemberFunctions() == 4, "Base declares three methods") + self.assertTrue(Base.GetMemberFunctionAtIndex(3).GetType().GetFunctionArgumentTypes().GetSize() == 3, "Base::sfunc takes three arguments") + self.assertTrue(Base.GetMemberFunctionAtIndex(3).GetName() == "sfunc", "Base::sfunc not found") + self.assertTrue(Base.GetMemberFunctionAtIndex(3).GetKind() == lldb.eMemberFunctionKindStaticMethod, "Base::sfunc is a static") + self.assertTrue(Base.GetMemberFunctionAtIndex(2).GetType().GetFunctionArgumentTypes().GetSize() == 0, "Base::dat takes no arguments") + self.assertTrue(Base.GetMemberFunctionAtIndex(1).GetType().GetFunctionArgumentTypes().GetTypeAtIndex(1).GetName() == "char", "Base::bar takes a second 'char' argument") + self.assertTrue(Base.GetMemberFunctionAtIndex(1).GetName() == "bar", "Base::bar not found") + + variable = frame0.FindVariable("thingy") + Thingy = variable.GetType() + + self.assertTrue(Thingy.GetNumberOfMemberFunctions() == 2, "Thingy declares two methods") + + self.assertTrue(Thingy.GetMemberFunctionAtIndex(0).GetReturnType().GetName() == "id", "Thingy::init returns an id") + self.assertTrue(Thingy.GetMemberFunctionAtIndex(1).GetNumberOfArguments() == 2, "Thingy::foo takes two arguments") + self.assertTrue(Thingy.GetMemberFunctionAtIndex(1).GetArgumentTypeAtIndex(0).GetName() == "int", "Thingy::foo takes an int") diff --git a/packages/Python/lldbsuite/test/python_api/class_members/main.mm b/packages/Python/lldbsuite/test/python_api/class_members/main.mm new file mode 100644 index 0000000..ff61b36 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/class_members/main.mm @@ -0,0 +1,47 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +class Base { +public: + int foo(int x, int y) { return 1; } + char bar(int x, char y) { return 2; } + void dat() {} + static int sfunc(char, int, float) { return 3; } +}; + +class Derived: public Base { +protected: + int dImpl() { return 1; } +public: + float baz(float b) { return b + 1.0; } +}; + +@interface Thingy: NSObject { +} +- (id)init; +- (id)fooWithBar: (int)bar andBaz:(id)baz; +@end + +@implementation Thingy { +} +- (id)init { + return (self = [super init]); +} +- (id)fooWithBar: (int)bar andBaz:(id)baz { + return nil; +} +@end + +int main() { + Derived d; + Thingy *thingy = [[Thingy alloc] init]; + return 0; // set breakpoint here +} diff --git a/packages/Python/lldbsuite/test/python_api/debugger/TestDebuggerAPI.py b/packages/Python/lldbsuite/test/python_api/debugger/TestDebuggerAPI.py new file mode 100644 index 0000000..98feda8 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/debugger/TestDebuggerAPI.py @@ -0,0 +1,40 @@ +""" +Test Debugger APIs. +""" + +import os +import lldb +from lldbsuite.test.lldbtest import * + + +class DebuggerAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_debugger_api_boundary_condition(self): + """Exercise SBDebugger APIs with boundary conditions.""" + self.dbg.HandleCommand(None) + self.dbg.SetDefaultArchitecture(None) + self.dbg.GetScriptingLanguage(None) + self.dbg.CreateTarget(None) + self.dbg.CreateTarget(None, None, None, True, lldb.SBError()) + self.dbg.CreateTargetWithFileAndTargetTriple(None, None) + self.dbg.CreateTargetWithFileAndArch(None, None) + self.dbg.FindTargetWithFileAndArch(None, None) + self.dbg.SetInternalVariable(None, None, None) + self.dbg.GetInternalVariableValue(None, None) + # FIXME (filcab): We must first allow for the swig bindings to know if + # a Python callback is set. (Check python-typemaps.swig) + #self.dbg.SetLoggingCallback(None) + self.dbg.SetPrompt(None) + self.dbg.SetCurrentPlatform(None) + self.dbg.SetCurrentPlatformSDKRoot(None) + + @add_test_categories(['pyapi']) + def test_debugger_delete_invalid_target(self): + """SBDebugger.DeleteTarget() should not crash LLDB given and invalid target.""" + target = lldb.SBTarget() + self.assertFalse(target.IsValid()) + self.dbg.DeleteTarget(target) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py b/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py new file mode 100644 index 0000000..aa3a614 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py @@ -0,0 +1,395 @@ +""" +Test lldb Python API object's default constructor and make sure it is invalid +after initial construction. + +There are also some cases of boundary condition testings sprinkled throughout +the tests where None is passed to SB API which expects (const char *) in the +C++ API counterpart. Passing None should not crash lldb! + +There are three exceptions to the above general rules, though; API objects +SBCommadnReturnObject, SBStream, and SBSymbolContextList, are all valid objects +after default construction. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class APIDefaultConstructorTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBAddress(self): + obj = lldb.SBAddress() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_address + sb_address.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBBlock(self): + obj = lldb.SBBlock() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_block + sb_block.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBBreakpoint(self): + obj = lldb.SBBreakpoint() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_breakpoint + sb_breakpoint.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBBreakpointLocation(self): + obj = lldb.SBBreakpointLocation() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_breakpointlocation + sb_breakpointlocation.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBBroadcaster(self): + obj = lldb.SBBroadcaster() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_broadcaster + sb_broadcaster.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBCommandReturnObject(self): + """SBCommandReturnObject object is valid after default construction.""" + obj = lldb.SBCommandReturnObject() + if self.TraceOn(): + print(obj) + self.assertTrue(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBCommunication(self): + obj = lldb.SBCommunication() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_communication + sb_communication.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBCompileUnit(self): + obj = lldb.SBCompileUnit() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_compileunit + sb_compileunit.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBDebugger(self): + obj = lldb.SBDebugger() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_debugger + sb_debugger.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + # darwin: This test passes with swig 3.0.2, fails w/3.0.5 other tests fail with 2.0.12 http://llvm.org/pr23488 + def test_SBError(self): + obj = lldb.SBError() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_error + sb_error.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBEvent(self): + obj = lldb.SBEvent() + # This is just to test that typemap, as defined in lldb.swig, works. + obj2 = lldb.SBEvent(0, "abc") + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_event + sb_event.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + def test_SBFileSpec(self): + obj = lldb.SBFileSpec() + # This is just to test that FileSpec(None) does not crash. + obj2 = lldb.SBFileSpec(None, True) + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_filespec + sb_filespec.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBFrame(self): + obj = lldb.SBFrame() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_frame + sb_frame.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBFunction(self): + obj = lldb.SBFunction() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_function + sb_function.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBInstruction(self): + obj = lldb.SBInstruction() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_instruction + sb_instruction.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBInstructionList(self): + obj = lldb.SBInstructionList() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_instructionlist + sb_instructionlist.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBLineEntry(self): + obj = lldb.SBLineEntry() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_lineentry + sb_lineentry.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBListener(self): + obj = lldb.SBListener() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_listener + sb_listener.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + # Py3 asserts due to a bug in SWIG. Trying to upstream a patch to fix this in 3.0.8 + @skipIf(py_version=['>=', (3,0)], swig_version=['<', (3,0,8)]) + def test_SBModule(self): + obj = lldb.SBModule() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_module + sb_module.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBProcess(self): + obj = lldb.SBProcess() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_process + sb_process.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBSection(self): + obj = lldb.SBSection() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_section + sb_section.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBStream(self): + """SBStream object is valid after default construction.""" + obj = lldb.SBStream() + if self.TraceOn(): + print(obj) + self.assertTrue(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBStringList(self): + obj = lldb.SBStringList() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_stringlist + sb_stringlist.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBSymbol(self): + obj = lldb.SBSymbol() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_symbol + sb_symbol.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBSymbolContext(self): + obj = lldb.SBSymbolContext() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_symbolcontext + sb_symbolcontext.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBSymbolContextList(self): + """SBSymbolContextList object is valid after default construction.""" + obj = lldb.SBSymbolContextList() + if self.TraceOn(): + print(obj) + self.assertTrue(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBTarget(self): + obj = lldb.SBTarget() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_target + sb_target.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBThread(self): + obj = lldb.SBThread() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_thread + sb_thread.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBType(self): + try: + obj = lldb.SBType() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # If we reach here, the test fails. + self.fail("lldb.SBType() should fail, not succeed!") + except: + # Exception is expected. + return + + # Unreachable code because lldb.SBType() should fail. + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_type + sb_type.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBTypeList(self): + """SBTypeList object is valid after default construction.""" + obj = lldb.SBTypeList() + if self.TraceOn(): + print(obj) + self.assertTrue(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBValue(self): + obj = lldb.SBValue() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_value + sb_value.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBValueList(self): + obj = lldb.SBValueList() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_valuelist + sb_valuelist.fuzz_obj(obj) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_SBWatchpoint(self): + obj = lldb.SBWatchpoint() + if self.TraceOn(): + print(obj) + self.assertFalse(obj) + # Do fuzz testing on the invalid obj, it should not crash lldb. + import sb_watchpoint + sb_watchpoint.fuzz_obj(obj) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_address.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_address.py new file mode 100644 index 0000000..f0e9795 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_address.py @@ -0,0 +1,22 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetFileAddress() + obj.GetLoadAddress(lldb.SBTarget()) + obj.SetLoadAddress(0xffff, lldb.SBTarget()) + obj.OffsetAddress(sys.maxsize) + obj.GetDescription(lldb.SBStream()) + obj.GetSection() + obj.GetSymbolContext(lldb.eSymbolContextEverything) + obj.GetModule() + obj.GetCompileUnit() + obj.GetFunction() + obj.GetBlock() + obj.GetSymbol() + obj.GetLineEntry() + obj.Clear() diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_block.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_block.py new file mode 100644 index 0000000..3eeb24b --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_block.py @@ -0,0 +1,17 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.IsInlined() + obj.GetInlinedName() + obj.GetInlinedCallSiteFile() + obj.GetInlinedCallSiteLine() + obj.GetInlinedCallSiteColumn() + obj.GetParent() + obj.GetSibling() + obj.GetFirstChild() + obj.GetDescription(lldb.SBStream()) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_breakpoint.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_breakpoint.py new file mode 100644 index 0000000..2c05990 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_breakpoint.py @@ -0,0 +1,36 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetID() + obj.ClearAllBreakpointSites() + obj.FindLocationByAddress(sys.maxsize) + obj.FindLocationIDByAddress(sys.maxsize) + obj.FindLocationByID(0) + obj.GetLocationAtIndex(0) + obj.SetEnabled(True) + obj.IsEnabled() + obj.GetHitCount() + obj.SetIgnoreCount(1) + obj.GetIgnoreCount() + obj.SetCondition("i >= 10") + obj.GetCondition() + obj.SetThreadID(0) + obj.GetThreadID() + obj.SetThreadIndex(0) + obj.GetThreadIndex() + obj.SetThreadName("worker thread") + obj.GetThreadName() + obj.SetQueueName("my queue") + obj.GetQueueName() + obj.SetScriptCallbackFunction(None) + obj.SetScriptCallbackBody (None) + obj.GetNumResolvedLocations() + obj.GetNumLocations() + obj.GetDescription(lldb.SBStream()) + for bp_loc in obj: + s = str(bp_loc) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_breakpointlocation.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_breakpointlocation.py new file mode 100644 index 0000000..2251892 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_breakpointlocation.py @@ -0,0 +1,28 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetAddress() + obj.GetLoadAddress() + obj.SetEnabled(True) + obj.IsEnabled() + obj.SetCondition("i >= 10") + obj.GetCondition() + obj.SetThreadID(0) + obj.GetThreadID() + obj.SetThreadIndex(0) + obj.GetThreadIndex() + obj.SetThreadName("worker thread") + obj.GetThreadName() + obj.SetQueueName("my queue") + obj.GetQueueName() + obj.IsResolved() + obj.GetDescription(lldb.SBStream(), lldb.eDescriptionLevelVerbose) + breakpoint = obj.GetBreakpoint() + # Do fuzz testing on the breakpoint obj, it should not crash lldb. + import sb_breakpoint + sb_breakpoint.fuzz_obj(breakpoint) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_broadcaster.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_broadcaster.py new file mode 100644 index 0000000..27539e8 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_broadcaster.py @@ -0,0 +1,20 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.BroadcastEventByType(lldb.eBreakpointEventTypeInvalidType, True) + obj.BroadcastEvent(lldb.SBEvent(), False) + listener = lldb.SBListener("fuzz_testing") + obj.AddInitialEventsToListener(listener, 0xffffffff) + obj.AddInitialEventsToListener(listener, 0) + obj.AddListener(listener, 0xffffffff) + obj.AddListener(listener, 0) + obj.GetName() + obj.EventTypeHasListeners(0) + obj.RemoveListener(listener, 0xffffffff) + obj.RemoveListener(listener, 0) + obj.Clear() diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_communication.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_communication.py new file mode 100644 index 0000000..d4b9084 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_communication.py @@ -0,0 +1,28 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + broadcaster = obj.GetBroadcaster() + # Do fuzz testing on the broadcaster obj, it should not crash lldb. + import sb_broadcaster + sb_broadcaster.fuzz_obj(broadcaster) + obj.AdoptFileDesriptor(0, False) + obj.AdoptFileDesriptor(1, False) + obj.AdoptFileDesriptor(2, False) + obj.Connect("file:/tmp/myfile") + obj.Connect(None) + obj.Disconnect() + obj.IsConnected() + obj.GetCloseOnEOF() + obj.SetCloseOnEOF(True) + obj.SetCloseOnEOF(False) + #obj.Write(None, sys.maxint, None) + #obj.Read(None, sys.maxint, 0xffffffff, None) + obj.ReadThreadStart() + obj.ReadThreadStop() + obj.ReadThreadIsRunning() + obj.SetReadThreadBytesReceivedCallback(None, None) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_compileunit.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_compileunit.py new file mode 100644 index 0000000..92755ff --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_compileunit.py @@ -0,0 +1,15 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetFileSpec() + obj.GetNumLineEntries() + obj.GetLineEntryAtIndex(0xffffffff) + obj.FindLineEntryIndex(0, 0xffffffff, None) + obj.GetDescription(lldb.SBStream()) + for line_entry in obj: + s = str(line_entry) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_debugger.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_debugger.py new file mode 100644 index 0000000..e7c188f --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_debugger.py @@ -0,0 +1,56 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.SetAsync(True) + obj.SetAsync(False) + obj.GetAsync() + obj.SkipLLDBInitFiles(True) + obj.SetInputFileHandle(None, True) + obj.SetOutputFileHandle(None, True) + obj.SetErrorFileHandle(None, True) + obj.GetInputFileHandle() + obj.GetOutputFileHandle() + obj.GetErrorFileHandle() + obj.GetCommandInterpreter() + obj.HandleCommand("nothing here") + listener = obj.GetListener() + obj.HandleProcessEvent(lldb.SBProcess(), lldb.SBEvent(), None, None) + obj.CreateTargetWithFileAndTargetTriple("a.out", "A-B-C") + obj.CreateTargetWithFileAndArch("b.out", "arm") + obj.CreateTarget("c.out") + obj.DeleteTarget(lldb.SBTarget()) + obj.GetTargetAtIndex(0xffffffff) + obj.FindTargetWithProcessID(0) + obj.FindTargetWithFileAndArch("a.out", "arm") + obj.GetNumTargets() + obj.GetSelectedTarget() + obj.GetSourceManager() + obj.SetSelectedTarget(lldb.SBTarget()) + obj.SetCurrentPlatformSDKRoot("tmp/sdk-root") + try: + obj.DispatchInput(None) + except Exception: + pass + obj.DispatchInputInterrupt() + obj.DispatchInputEndOfFile() + obj.GetInstanceName() + obj.GetDescription(lldb.SBStream()) + obj.GetTerminalWidth() + obj.SetTerminalWidth(0xffffffff) + obj.GetID() + obj.GetPrompt() + obj.SetPrompt("Hi, Mom!") + obj.GetScriptLanguage() + obj.SetScriptLanguage(lldb.eScriptLanguageNone) + obj.SetScriptLanguage(lldb.eScriptLanguagePython) + obj.GetCloseInputOnEOF() + obj.SetCloseInputOnEOF(True) + obj.SetCloseInputOnEOF(False) + obj.Clear() + for target in obj: + s = str(target) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_error.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_error.py new file mode 100644 index 0000000..7e06932 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_error.py @@ -0,0 +1,25 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetCString() + obj.Fail() + obj.Success() + obj.GetError() + obj.GetType() + obj.SetError(5, lldb.eErrorTypeGeneric) + obj.SetErrorToErrno() + obj.SetErrorToGenericError() + obj.SetErrorString("xyz") + obj.SetErrorString(None) + obj.SetErrorStringWithFormat("%s!", "error") + obj.SetErrorStringWithFormat(None) + obj.SetErrorStringWithFormat("error") + obj.SetErrorStringWithFormat("%s %s", "warning", "danger") + obj.SetErrorStringWithFormat("%s %s %s", "danger", "will", "robinson") + obj.GetDescription(lldb.SBStream()) + obj.Clear() diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_event.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_event.py new file mode 100644 index 0000000..c64f9ba --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_event.py @@ -0,0 +1,17 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetDataFlavor() + obj.GetType() + broadcaster = obj.GetBroadcaster() + # Do fuzz testing on the broadcaster obj, it should not crash lldb. + import sb_broadcaster + sb_broadcaster.fuzz_obj(broadcaster) + obj.BroadcasterMatchesRef(broadcaster) + obj.GetDescription(lldb.SBStream()) + obj.Clear() diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_filespec.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_filespec.py new file mode 100644 index 0000000..3aa9235 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_filespec.py @@ -0,0 +1,14 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.Exists() + obj.ResolveExecutableLocation() + obj.GetFilename() + obj.GetDirectory() + obj.GetPath(None, 0) + obj.GetDescription(lldb.SBStream()) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_frame.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_frame.py new file mode 100644 index 0000000..41edaff --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_frame.py @@ -0,0 +1,37 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetFrameID() + obj.GetPC() + obj.SetPC(0xffffffff) + obj.GetSP() + obj.GetFP() + obj.GetPCAddress() + obj.GetSymbolContext(0) + obj.GetModule() + obj.GetCompileUnit() + obj.GetFunction() + obj.GetSymbol() + obj.GetBlock() + obj.GetFunctionName() + obj.IsInlined() + obj.EvaluateExpression("x + y") + obj.EvaluateExpression("x + y", lldb.eDynamicCanRunTarget) + obj.GetFrameBlock() + obj.GetLineEntry() + obj.GetThread() + obj.Disassemble() + obj.GetVariables(True, True, True, True) + obj.GetVariables(True, True, True, False, lldb.eDynamicCanRunTarget) + obj.GetRegisters() + obj.FindVariable("my_var") + obj.FindVariable("my_var", lldb.eDynamicCanRunTarget) + obj.FindValue("your_var", lldb.eValueTypeVariableGlobal) + obj.FindValue("your_var", lldb.eValueTypeVariableStatic, lldb.eDynamicCanRunTarget) + obj.GetDescription(lldb.SBStream()) + obj.Clear() diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_function.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_function.py new file mode 100644 index 0000000..fb88d37 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_function.py @@ -0,0 +1,19 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetName() + obj.GetMangledName() + obj.GetInstructions(lldb.SBTarget()) + sa = obj.GetStartAddress() + ea = obj.GetEndAddress() + # Do fuzz testing on the address obj, it should not crash lldb. + import sb_address + sb_address.fuzz_obj(sa) + sb_address.fuzz_obj(ea) + obj.GetPrologueByteSize + obj.GetDescription(lldb.SBStream()) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_instruction.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_instruction.py new file mode 100644 index 0000000..b961bc3 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_instruction.py @@ -0,0 +1,16 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetAddress() + obj.GetByteSize() + obj.DoesBranch() + obj.Print(None) + obj.GetDescription(lldb.SBStream()) + obj.EmulateWithFrame(lldb.SBFrame(), 0) + obj.DumpEmulation("armv7") + obj.TestEmulation(lldb.SBStream(), "my-file") diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_instructionlist.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_instructionlist.py new file mode 100644 index 0000000..09d62f9 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_instructionlist.py @@ -0,0 +1,17 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetSize() + obj.GetInstructionAtIndex(0xffffffff) + obj.AppendInstruction(lldb.SBInstruction()) + obj.Print(None) + obj.GetDescription(lldb.SBStream()) + obj.DumpEmulationForAllInstructions("armv7") + obj.Clear() + for inst in obj: + s = str(inst) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_lineentry.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_lineentry.py new file mode 100644 index 0000000..d97f251 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_lineentry.py @@ -0,0 +1,14 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetStartAddress() + obj.GetEndAddress() + obj.GetFileSpec() + obj.GetLine() + obj.GetColumn() + obj.GetDescription(lldb.SBStream()) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_listener.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_listener.py new file mode 100644 index 0000000..0747547 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_listener.py @@ -0,0 +1,23 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.AddEvent(lldb.SBEvent()) + obj.StartListeningForEvents(lldb.SBBroadcaster(), 0xffffffff) + obj.StopListeningForEvents(lldb.SBBroadcaster(), 0xffffffff) + event = lldb.SBEvent() + broadcaster = lldb.SBBroadcaster() + obj.WaitForEvent(5, event) + obj.WaitForEventForBroadcaster(5, broadcaster, event) + obj.WaitForEventForBroadcasterWithType(5, broadcaster, 0xffffffff, event) + obj.PeekAtNextEvent(event) + obj.PeekAtNextEventForBroadcaster(broadcaster, event) + obj.PeekAtNextEventForBroadcasterWithType(broadcaster, 0xffffffff, event) + obj.GetNextEvent(event) + obj.GetNextEventForBroadcaster(broadcaster, event) + obj.GetNextEventForBroadcasterWithType(broadcaster, 0xffffffff, event) + obj.HandleBroadcastEvent(event) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_module.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_module.py new file mode 100644 index 0000000..0b9aa99 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_module.py @@ -0,0 +1,29 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetFileSpec() + obj.GetPlatformFileSpec() + obj.SetPlatformFileSpec(lldb.SBFileSpec()) + obj.GetUUIDString() + obj.ResolveFileAddress(sys.maxsize) + obj.ResolveSymbolContextForAddress(lldb.SBAddress(), 0) + obj.GetDescription(lldb.SBStream()) + obj.GetNumSymbols() + obj.GetSymbolAtIndex(sys.maxsize) + sc_list = obj.FindFunctions("my_func") + sc_list = obj.FindFunctions("my_func", lldb.eFunctionNameTypeAny) + obj.FindGlobalVariables(lldb.SBTarget(), "my_global_var", 1) + for section in obj.section_iter(): + s = str(section) + for symbol in obj.symbol_in_section_iter(lldb.SBSection()): + s = str(symbol) + for symbol in obj: + s = str(symbol) + obj.GetAddressByteSize() + obj.GetByteOrder() + obj.GetTriple() diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_process.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_process.py new file mode 100644 index 0000000..40132b1 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_process.py @@ -0,0 +1,49 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetTarget() + obj.GetByteOrder() + obj.PutSTDIN("my data") + obj.GetSTDOUT(6) + obj.GetSTDERR(6) + event = lldb.SBEvent() + obj.ReportEventState(event, None) + obj.AppendEventStateReport(event, lldb.SBCommandReturnObject()) + error = lldb.SBError() + obj.RemoteAttachToProcessWithID(123, error) + obj.RemoteLaunch(None, None, None, None, None, None, 0, False, error) + obj.GetNumThreads() + obj.GetThreadAtIndex(0) + obj.GetThreadByID(0) + obj.GetSelectedThread() + obj.SetSelectedThread(lldb.SBThread()) + obj.SetSelectedThreadByID(0) + obj.GetState() + obj.GetExitStatus() + obj.GetExitDescription() + obj.GetProcessID() + obj.GetAddressByteSize() + obj.Destroy() + obj.Continue() + obj.Stop() + obj.Kill() + obj.Detach() + obj.Signal(7) + obj.ReadMemory(0x0000ffff, 10, error) + obj.WriteMemory(0x0000ffff, "hi data", error) + obj.ReadCStringFromMemory(0x0, 128, error) + obj.ReadUnsignedFromMemory(0xff, 4, error) + obj.ReadPointerFromMemory(0xff, error) + obj.GetBroadcaster() + obj.GetDescription(lldb.SBStream()) + obj.LoadImage(lldb.SBFileSpec(), error) + obj.UnloadImage(0) + obj.Clear() + obj.GetNumSupportedHardwareWatchpoints(error) + for thread in obj: + s = str(thread) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_section.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_section.py new file mode 100644 index 0000000..899130a --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_section.py @@ -0,0 +1,22 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.IsValid() + obj.GetName() + obj.FindSubSection("hello_section_name") + obj.GetNumSubSections() + obj.GetSubSectionAtIndex(600) + obj.GetFileAddress() + obj.GetByteSize() + obj.GetFileOffset() + obj.GetFileByteSize() + obj.GetSectionData(1000, 100) + obj.GetSectionType() + obj.GetDescription(lldb.SBStream()) + for subsec in obj: + s = str(subsec) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_stringlist.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_stringlist.py new file mode 100644 index 0000000..9d8242c --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_stringlist.py @@ -0,0 +1,17 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.AppendString("another string") + obj.AppendString(None) + obj.AppendList(None, 0) + obj.AppendList(lldb.SBStringList()) + obj.GetSize() + obj.GetStringAtIndex(0xffffffff) + obj.Clear() + for n in obj: + s = str(n) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_symbol.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_symbol.py new file mode 100644 index 0000000..4a4c67a --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_symbol.py @@ -0,0 +1,16 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetName() + obj.GetMangledName() + obj.GetInstructions(lldb.SBTarget()) + obj.GetStartAddress() + obj.GetEndAddress() + obj.GetPrologueByteSize() + obj.GetType() + obj.GetDescription(lldb.SBStream()) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_symbolcontext.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_symbolcontext.py new file mode 100644 index 0000000..01b5b7b --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_symbolcontext.py @@ -0,0 +1,15 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetModule() + obj.GetCompileUnit() + obj.GetFunction() + obj.GetBlock() + obj.GetLineEntry() + obj.GetSymbol() + obj.GetDescription(lldb.SBStream()) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_target.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_target.py new file mode 100644 index 0000000..3b01be3 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_target.py @@ -0,0 +1,65 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetProcess() + listener = lldb.SBListener() + error = lldb.SBError() + obj.Launch(listener, None, None, None, None, None, None, 0, True, error) + obj.LaunchSimple(None, None, None) + obj.AttachToProcessWithID(listener, 123, error) + obj.AttachToProcessWithName(listener, 'lldb', False, error) + obj.ConnectRemote(listener, "connect://to/here", None, error) + obj.GetExecutable() + obj.GetNumModules() + obj.GetModuleAtIndex(0xffffffff) + obj.GetDebugger() + filespec = lldb.SBFileSpec() + obj.FindModule(filespec) + sc_list = obj.FindFunctions("the_func") + sc_list = obj.FindFunctions("the_func", lldb.eFunctionNameTypeAny) + obj.FindFirstType("dont_care") + obj.FindTypes("dont_care") + obj.FindFirstType(None) + obj.GetInstructions(lldb.SBAddress(), bytearray()) + obj.GetSourceManager() + obj.FindGlobalVariables("my_global_var", 1) + address = obj.ResolveLoadAddress(0xffff) + obj.ResolveSymbolContextForAddress(address, 0) + obj.BreakpointCreateByLocation("filename", 20) + obj.BreakpointCreateByLocation(filespec, 20) + obj.BreakpointCreateByName("func", None) + obj.BreakpointCreateByRegex("func.", None) + obj.BreakpointCreateByAddress(0xf0f0) + obj.GetNumBreakpoints() + obj.GetBreakpointAtIndex(0) + obj.BreakpointDelete(0) + obj.FindBreakpointByID(0) + obj.EnableAllBreakpoints() + obj.DisableAllBreakpoints() + obj.DeleteAllBreakpoints() + obj.GetNumWatchpoints() + obj.GetWatchpointAtIndex(0) + obj.DeleteWatchpoint(0) + obj.FindWatchpointByID(0) + obj.EnableAllWatchpoints() + obj.DisableAllWatchpoints() + obj.DeleteAllWatchpoints() + obj.GetAddressByteSize() + obj.GetByteOrder() + obj.GetTriple() + error = lldb.SBError() + obj.WatchAddress(123, 8, True, True, error) + obj.GetBroadcaster() + obj.GetDescription(lldb.SBStream(), lldb.eDescriptionLevelBrief) + obj.Clear() + for module in obj.module_iter(): + s = str(module) + for bp in obj.breakpoint_iter(): + s = str(bp) + for wp in obj.watchpoint_iter(): + s = str(wp) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_thread.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_thread.py new file mode 100644 index 0000000..b69b22e --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_thread.py @@ -0,0 +1,37 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetStopReason() + obj.GetStopReasonDataCount() + obj.GetStopReasonDataAtIndex(100) + obj.GetStopDescription(256) + obj.GetThreadID() + obj.GetIndexID() + obj.GetName() + obj.GetQueueName() + obj.StepOver(lldb.eOnlyDuringStepping) + obj.StepInto(lldb.eOnlyDuringStepping) + obj.StepOut() + frame = lldb.SBFrame() + obj.StepOutOfFrame(frame) + obj.StepInstruction(True) + filespec = lldb.SBFileSpec() + obj.StepOverUntil(frame, filespec, 1234) + obj.RunToAddress(0xabcd) + obj.Suspend() + obj.Resume() + obj.IsSuspended() + obj.GetNumFrames() + obj.GetFrameAtIndex(200) + obj.GetSelectedFrame() + obj.SetSelectedFrame(999) + obj.GetProcess() + obj.GetDescription(lldb.SBStream()) + obj.Clear() + for frame in obj: + s = str(frame) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_type.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_type.py new file mode 100644 index 0000000..5c801c1 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_type.py @@ -0,0 +1,22 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetName() + obj.GetByteSize() + #obj.GetEncoding(5) + obj.GetNumberChildren(True) + member = lldb.SBTypeMember() + obj.GetChildAtIndex(True, 0, member) + obj.GetChildIndexForName(True, "_member_field") + obj.IsAPointerType() + obj.GetPointeeType() + obj.GetDescription(lldb.SBStream()) + obj.IsPointerType(None) + lldb.SBType.IsPointerType(None) + for child_type in obj: + s = str(child_type) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_value.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_value.py new file mode 100644 index 0000000..2bb8c58 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_value.py @@ -0,0 +1,67 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetError() + obj.GetID() + obj.GetName() + obj.GetTypeName() + obj.GetByteSize() + obj.IsInScope() + obj.GetFormat() + obj.SetFormat(lldb.eFormatBoolean) + obj.GetValue() + obj.GetValueType() + obj.GetValueDidChange() + obj.GetSummary() + obj.GetObjectDescription() + obj.GetLocation() + obj.SetValueFromCString("my_new_value") + obj.GetChildAtIndex(1) + obj.GetChildAtIndex(2, lldb.eNoDynamicValues, False) + obj.GetIndexOfChildWithName("my_first_child") + obj.GetChildMemberWithName("my_first_child") + obj.GetChildMemberWithName("my_first_child", lldb.eNoDynamicValues) + obj.GetNumChildren() + obj.GetOpaqueType() + obj.Dereference() + obj.TypeIsPointerType() + stream = lldb.SBStream() + obj.GetDescription(stream) + obj.GetExpressionPath(stream) + obj.GetExpressionPath(stream, True) + error = lldb.SBError() + obj.Watch(True, True, False, error) + obj.WatchPointee(True, False, True, error) + for child_val in obj: + s = str(child_val) + error = lldb.SBError() + obj.GetValueAsSigned (error, 0) + obj.GetValueAsUnsigned (error, 0) + obj.GetValueAsSigned(0) + obj.GetValueAsUnsigned(0) + obj.GetDynamicValue (lldb.eNoDynamicValues) + obj.GetStaticValue () + obj.IsDynamic() + invalid_type = lldb.SBType() + obj.CreateChildAtOffset ("a", 12, invalid_type) + obj.Cast (invalid_type) + obj.CreateValueFromExpression ("pt->x", "pt->x") + obj.CreateValueFromAddress ("x", 0x123, invalid_type) + invalid_data = lldb.SBData() + obj.CreateValueFromData ("x", invalid_data, invalid_type) + obj.GetValueForExpressionPath("[0]") + obj.AddressOf() + obj.GetLoadAddress() + obj.GetAddress() + obj.GetPointeeData (0, 1) + obj.GetData () + obj.GetTarget() + obj.GetProcess() + obj.GetThread() + obj.GetFrame() + obj.GetType() diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_valuelist.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_valuelist.py new file mode 100644 index 0000000..32f12f9 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_valuelist.py @@ -0,0 +1,14 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.Append(lldb.SBValue()) + obj.GetSize() + obj.GetValueAtIndex(100) + obj.FindValueObjectByUID(200) + for val in obj: + s = str(val) diff --git a/packages/Python/lldbsuite/test/python_api/default-constructor/sb_watchpoint.py b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_watchpoint.py new file mode 100644 index 0000000..f462e62 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/default-constructor/sb_watchpoint.py @@ -0,0 +1,21 @@ +""" +Fuzz tests an object after the default construction to make sure it does not crash lldb. +""" + +import sys +import lldb + +def fuzz_obj(obj): + obj.GetID() + obj.IsValid() + obj.GetHardwareIndex() + obj.GetWatchAddress() + obj.GetWatchSize() + obj.SetEnabled(True) + obj.IsEnabled() + obj.GetHitCount() + obj.GetIgnoreCount() + obj.SetIgnoreCount(5) + obj.GetDescription(lldb.SBStream(), lldb.eDescriptionLevelVerbose) + obj.SetCondition("shouldWeStop()") + obj.GetCondition() diff --git a/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassembleRawData.py b/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassembleRawData.py new file mode 100644 index 0000000..20333ab --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassembleRawData.py @@ -0,0 +1,39 @@ +""" +Use lldb Python API to disassemble raw machine code bytes +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class DisassembleRawDataTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_disassemble_raw_data(self): + """Test disassembling raw bytes with the API.""" + # Create a target from the debugger. + target = self.dbg.CreateTargetWithFileAndTargetTriple ("", "x86_64") + self.assertTrue(target, VALID_TARGET) + + raw_bytes = bytearray([0x48, 0x89, 0xe5]) + + insts = target.GetInstructions(lldb.SBAddress(0, target), raw_bytes) + + inst = insts.GetInstructionAtIndex(0) + + if self.TraceOn(): + print() + print("Raw bytes: ", [hex(x) for x in raw_bytes]) + print("Disassembled%s" % str(inst)) + + self.assertTrue (inst.GetMnemonic(target) == "movq") + self.assertTrue (inst.GetOperands(target) == '%' + "rsp, " + '%' + "rbp") diff --git a/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassemble_VST1_64.py b/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassemble_VST1_64.py new file mode 100644 index 0000000..e24b2ee --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/disassemble-raw-data/TestDisassemble_VST1_64.py @@ -0,0 +1,58 @@ +""" +Use lldb Python API to disassemble raw machine code bytes +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class Disassemble_VST1_64(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIf(True) # llvm.org/pr24575: all tests get ERRORs in dotest.py after this + @add_test_categories(['pyapi']) + @no_debug_info_test + def test_disassemble_invalid_vst_1_64_raw_data(self): + """Test disassembling invalid vst1.64 raw bytes with the API.""" + # Create a target from the debugger. + target = self.dbg.CreateTargetWithFileAndTargetTriple ("", "thumbv7") + self.assertTrue(target, VALID_TARGET) + + raw_bytes = bytearray([0xf0, 0xb5, 0x03, 0xaf, + 0x2d, 0xe9, 0x00, 0x0d, + 0xad, 0xf1, 0x40, 0x04, + 0x24, 0xf0, 0x0f, 0x04, + 0xa5, 0x46]) + + insts = target.GetInstructions(lldb.SBAddress(), raw_bytes) + + if self.TraceOn(): + print() + for i in insts: + print("Disassembled%s" % str(i)) + + # Remove the following return statement when the radar is fixed. + return + + # rdar://problem/11034702 + # VST1 (multiple single elements) encoding? + # The disassembler should not crash! + raw_bytes = bytearray([0x04, 0xf9, 0xed, 0x82]) + + insts = target.GetInstructions(lldb.SBAddress(), raw_bytes) + + inst = insts.GetInstructionAtIndex(0) + + if self.TraceOn(): + print() + print("Raw bytes: ", [hex(x) for x in raw_bytes]) + print("Disassembled%s" % str(inst)) + + self.assertTrue (inst.GetMnemonic(target) == "vst1.64") diff --git a/packages/Python/lldbsuite/test/python_api/event/Makefile b/packages/Python/lldbsuite/test/python_api/event/Makefile new file mode 100644 index 0000000..0d70f25 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/event/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/event/TestEvents.py b/packages/Python/lldbsuite/test/python_api/event/TestEvents.py new file mode 100644 index 0000000..0a1a0df --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/event/TestEvents.py @@ -0,0 +1,288 @@ +""" +Test lldb Python event APIs. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +@skipIfDarwin # llvm.org/pr25924, sometimes generating SIGSEGV +class EventAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to of function 'c'. + self.line = line_number('main.c', '// Find the line number of function "c" here.') + + @add_test_categories(['pyapi']) + @expectedFailureLinux("llvm.org/pr23730") # Flaky, fails ~1/10 cases + @skipIfLinux # skip to avoid crashes + def test_listen_for_and_print_event(self): + """Exercise SBEvent API.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + self.dbg.SetAsync(True) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + + listener = lldb.SBListener("my listener") + + # Now launch the process, and do not stop at the entry point. + error = lldb.SBError() + process = target.Launch (listener, + None, # argv + None, # envp + None, # stdin_path + None, # stdout_path + None, # stderr_path + None, # working directory + 0, # launch flags + False, # Stop at entry + error) # error + + self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + + # Create an empty event object. + event = lldb.SBEvent() + + traceOn = self.TraceOn() + if traceOn: + lldbutil.print_stacktraces(process) + + # Create MyListeningThread class to wait for any kind of event. + import threading + class MyListeningThread(threading.Thread): + def run(self): + count = 0 + # Let's only try at most 4 times to retrieve any kind of event. + # After that, the thread exits. + while not count > 3: + if traceOn: + print("Try wait for event...") + if listener.WaitForEvent(5, event): + if traceOn: + desc = lldbutil.get_description(event) + print("Event description:", desc) + print("Event data flavor:", event.GetDataFlavor()) + print("Process state:", lldbutil.state_type_to_str(process.GetState())) + print() + else: + if traceOn: + print("timeout occurred waiting for event...") + count = count + 1 + return + + # Let's start the listening thread to retrieve the events. + my_thread = MyListeningThread() + my_thread.start() + + # Use Python API to continue the process. The listening thread should be + # able to receive the state changed events. + process.Continue() + + # Use Python API to kill the process. The listening thread should be + # able to receive the state changed event, too. + process.Kill() + + # Wait until the 'MyListeningThread' terminates. + my_thread.join() + + @add_test_categories(['pyapi']) + @expectedFlakeyLinux("llvm.org/pr23730") # Flaky, fails ~1/100 cases + def test_wait_for_event(self): + """Exercise SBListener.WaitForEvent() API.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + self.dbg.SetAsync(True) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Get the debugger listener. + listener = self.dbg.GetListener() + + # Now launch the process, and do not stop at entry point. + error = lldb.SBError() + process = target.Launch (listener, + None, # argv + None, # envp + None, # stdin_path + None, # stdout_path + None, # stderr_path + None, # working directory + 0, # launch flags + False, # Stop at entry + error) # error + self.assertTrue(error.Success() and process, PROCESS_IS_VALID) + + # Create an empty event object. + event = lldb.SBEvent() + self.assertFalse(event, "Event should not be valid initially") + + # Create MyListeningThread to wait for any kind of event. + import threading + class MyListeningThread(threading.Thread): + def run(self): + count = 0 + # Let's only try at most 3 times to retrieve any kind of event. + while not count > 3: + if listener.WaitForEvent(5, event): + #print("Got a valid event:", event) + #print("Event data flavor:", event.GetDataFlavor()) + #print("Event type:", lldbutil.state_type_to_str(event.GetType())) + return + count = count + 1 + print("Timeout: listener.WaitForEvent") + + return + + # Use Python API to kill the process. The listening thread should be + # able to receive a state changed event. + process.Kill() + + # Let's start the listening thread to retrieve the event. + my_thread = MyListeningThread() + my_thread.start() + + # Wait until the 'MyListeningThread' terminates. + my_thread.join() + + self.assertTrue(event, + "My listening thread successfully received an event") + + @skipIfFreeBSD # llvm.org/pr21325 + @add_test_categories(['pyapi']) + @expectedFlakeyLinux("llvm.org/pr23617") # Flaky, fails ~1/10 cases + @expectedFailureWindows("llvm.org/pr24778") + def test_add_listener_to_broadcaster(self): + """Exercise some SBBroadcaster APIs.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + self.dbg.SetAsync(True) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + listener = lldb.SBListener("my listener") + + # Now launch the process, and do not stop at the entry point. + error = lldb.SBError() + process = target.Launch (listener, + None, # argv + None, # envp + None, # stdin_path + None, # stdout_path + None, # stderr_path + None, # working directory + 0, # launch flags + False, # Stop at entry + error) # error + + # Create an empty event object. + event = lldb.SBEvent() + self.assertFalse(event, "Event should not be valid initially") + + + # The finite state machine for our custom listening thread, with an + # initial state of None, which means no event has been received. + # It changes to 'connected' after 'connected' event is received (for remote platforms) + # It changes to 'running' after 'running' event is received (should happen only if the + # currentstate is either 'None' or 'connected') + # It changes to 'stopped' if a 'stopped' event is received (should happen only if the + # current state is 'running'.) + self.state = None + + # Create MyListeningThread to wait for state changed events. + # By design, a "running" event is expected following by a "stopped" event. + import threading + class MyListeningThread(threading.Thread): + def run(self): + #print("Running MyListeningThread:", self) + + # Regular expression pattern for the event description. + pattern = re.compile("data = {.*, state = (.*)}$") + + # Let's only try at most 6 times to retrieve our events. + count = 0 + while True: + if listener.WaitForEvent(5, event): + desc = lldbutil.get_description(event) + #print("Event description:", desc) + match = pattern.search(desc) + if not match: + break; + if match.group(1) == 'connected': + # When debugging remote targets with lldb-server, we + # first get the 'connected' event. + self.context.assertTrue(self.context.state == None) + self.context.state = 'connected' + continue + elif match.group(1) == 'running': + self.context.assertTrue(self.context.state == None or self.context.state == 'connected') + self.context.state = 'running' + continue + elif match.group(1) == 'stopped': + self.context.assertTrue(self.context.state == 'running') + # Whoopee, both events have been received! + self.context.state = 'stopped' + break + else: + break + print("Timeout: listener.WaitForEvent") + count = count + 1 + if count > 6: + break + + return + + # Use Python API to continue the process. The listening thread should be + # able to receive the state changed events. + process.Continue() + + # Start the listening thread to receive the "running" followed by the + # "stopped" events. + my_thread = MyListeningThread() + # Supply the enclosing context so that our listening thread can access + # the 'state' variable. + my_thread.context = self + my_thread.start() + + # Wait until the 'MyListeningThread' terminates. + my_thread.join() + + # The final judgement. :-) + self.assertTrue(self.state == 'stopped', + "Both expected state changed events received") diff --git a/packages/Python/lldbsuite/test/python_api/event/main.c b/packages/Python/lldbsuite/test/python_api/event/main.c new file mode 100644 index 0000000..3435265 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/event/main.c @@ -0,0 +1,49 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to test the lldb Python API related to events. + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; // Find the line number of function "c" here. +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) + printf("a(3) returns %d\n", A3); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/exprpath_synthetic/TestExprPathSynthetic.py b/packages/Python/lldbsuite/test/python_api/exprpath_synthetic/TestExprPathSynthetic.py new file mode 100644 index 0000000..80305e3 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/exprpath_synthetic/TestExprPathSynthetic.py @@ -0,0 +1,4 @@ +import lldbsuite.test.lldbinline as lldbinline +import lldbsuite.test.lldbtest as lldbtest + +lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.skipIfFreeBSD,lldbtest.skipIfLinux,lldbtest.skipIfWindows]) diff --git a/packages/Python/lldbsuite/test/python_api/exprpath_synthetic/main.mm b/packages/Python/lldbsuite/test/python_api/exprpath_synthetic/main.mm new file mode 100644 index 0000000..f7383a5 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/exprpath_synthetic/main.mm @@ -0,0 +1,20 @@ +//===-- main.mm --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#import <Cocoa/Cocoa.h> +#include <vector> + +int main (int argc, char const *argv[]) +{ + std::vector<int> v{1,2,3,4,5}; + NSArray *a = @[@"Hello",@"World",@"From Me"]; + return 0; //% v = self.frame().FindVariable("v"); v0 = v.GetChildAtIndex(0); s = lldb.SBStream(); v0.GetExpressionPath(s); + //% self.runCmd("expr %s = 12" % s.GetData()); self.assertTrue(v0.GetValueAsUnsigned() == 12, "value change via expr failed") + //% a = self.frame().FindVariable("a"); a1 = a.GetChildAtIndex(1); s = lldb.SBStream(); a1.GetExpressionPath(s); + //% self.expect("po %s" % s.GetData(), substrs = ["World"]) +} diff --git a/packages/Python/lldbsuite/test/python_api/findvalue_duplist/Makefile b/packages/Python/lldbsuite/test/python_api/findvalue_duplist/Makefile new file mode 100644 index 0000000..ddffdcf --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/findvalue_duplist/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +# Clean renamed executable on 'make clean' +clean: OBJECTS+=no_synth + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/findvalue_duplist/TestSBFrameFindValue.py b/packages/Python/lldbsuite/test/python_api/findvalue_duplist/TestSBFrameFindValue.py new file mode 100644 index 0000000..96d4f51 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/findvalue_duplist/TestSBFrameFindValue.py @@ -0,0 +1,50 @@ +"""Test that SBFrame::FindValue finds things but does not duplicate the entire variables list""" + +from __future__ import print_function + + + +import os, sys, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class SBFrameFindValueTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + def test_formatters_api(self): + """Test that SBFrame::FindValue finds things but does not duplicate the entire variables list""" + self.build() + self.setTearDownCleanup() + + 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', lldb.SBFileSpec("main.cpp")) + self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple(None, None, self.get_process_working_directory()) + + 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) + self.thread = threads[0] + self.frame = self.thread.frames[0] + self.assertTrue(self.frame, "Frame 0 is valid.") + + self.assertTrue(self.frame.GetVariables(True,True,False,True).GetSize() == 2, "variable count is off") + self.assertFalse(self.frame.FindValue("NoSuchThing",lldb.eValueTypeVariableArgument,lldb.eDynamicCanRunTarget).IsValid(), "found something that should not be here") + self.assertTrue(self.frame.GetVariables(True,True,False,True).GetSize() == 2, "variable count is off after failed FindValue()") + self.assertTrue(self.frame.FindValue("a",lldb.eValueTypeVariableArgument,lldb.eDynamicCanRunTarget).IsValid(), "FindValue() didn't find an argument") + self.assertTrue(self.frame.GetVariables(True,True,False,True).GetSize() == 2, "variable count is off after successful FindValue()") diff --git a/packages/Python/lldbsuite/test/python_api/findvalue_duplist/main.cpp b/packages/Python/lldbsuite/test/python_api/findvalue_duplist/main.cpp new file mode 100644 index 0000000..7058d46 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/findvalue_duplist/main.cpp @@ -0,0 +1,7 @@ +int foo(int a, int b) { + return a + b; // Set breakpoint here +} + +int main() { + return foo(1,3); +} diff --git a/packages/Python/lldbsuite/test/python_api/formatters/Makefile b/packages/Python/lldbsuite/test/python_api/formatters/Makefile new file mode 100644 index 0000000..ddffdcf --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/formatters/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +# Clean renamed executable on 'make clean' +clean: OBJECTS+=no_synth + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/formatters/TestFormattersSBAPI.py b/packages/Python/lldbsuite/test/python_api/formatters/TestFormattersSBAPI.py new file mode 100644 index 0000000..de7f15f --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/formatters/TestFormattersSBAPI.py @@ -0,0 +1,346 @@ +"""Test Python APIs for working with formatters""" + +from __future__ import print_function + + + +import os, sys, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class SBFormattersAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line = line_number('main.cpp', '// Set break point at this line.') + + @add_test_categories(['pyapi']) + def test_formatters_api(self): + """Test Python APIs for working with formatters""" + self.build() + self.setTearDownCleanup() + + """Test Python APIs for working with formatters""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synthetic clear', check=False) + self.runCmd('type category delete foobar', check=False) + self.runCmd('type category delete JASSynth', check=False) + self.runCmd('type category delete newbar', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + + format = lldb.SBTypeFormat(lldb.eFormatHex) + category = self.dbg.GetDefaultCategory() + category.AddTypeFormat(lldb.SBTypeNameSpecifier("int"),format) + + self.expect("frame variable foo.A", + substrs = ['0x00000001']) + self.expect("frame variable foo.E", matching=False, + substrs = ['b8cca70a']) + + category.AddTypeFormat(lldb.SBTypeNameSpecifier("long"),format) + self.expect("frame variable foo.A", + substrs = ['0x00000001']) + self.expect("frame variable foo.E", + substrs = ['b8cca70a']) + + format.format = lldb.eFormatOctal + category.AddTypeFormat(lldb.SBTypeNameSpecifier("int"),format) + self.expect("frame variable foo.A", + substrs = ['01']) + self.expect("frame variable foo.E", + substrs = ['b8cca70a']) + + category.DeleteTypeFormat(lldb.SBTypeNameSpecifier("int")) + category.DeleteTypeFormat(lldb.SBTypeNameSpecifier("long")) + self.expect("frame variable foo.A", matching=False, + substrs = ['01']) + self.expect("frame variable foo.E", matching=False, + substrs = ['b8cca70a']) + + summary = lldb.SBTypeSummary.CreateWithSummaryString("the hello world you'll never see") + summary.SetSummaryString('hello world') + new_category = self.dbg.GetCategory("foobar") + self.assertFalse(new_category.IsValid(), "getting a non-existing category worked") + new_category = self.dbg.CreateCategory("foobar") + new_category.enabled = True + new_category.AddTypeSummary(lldb.SBTypeNameSpecifier("^.*t$",True),summary) + self.expect("frame variable foo.A", + substrs = ['hello world']) + self.expect("frame variable foo.E", matching=False, + substrs = ['hello world']) + self.expect("frame variable foo.B", + substrs = ['hello world']) + self.expect("frame variable foo.F", + substrs = ['hello world']) + new_category.enabled = False + self.expect("frame variable foo.A", matching=False, + substrs = ['hello world']) + self.expect("frame variable foo.E", matching=False, + substrs = ['hello world']) + self.expect("frame variable foo.B", matching=False, + substrs = ['hello world']) + self.expect("frame variable foo.F", matching=False, + substrs = ['hello world']) + self.dbg.DeleteCategory(new_category.GetName()) + self.expect("frame variable foo.A", matching=False, + substrs = ['hello world']) + self.expect("frame variable foo.E", matching=False, + substrs = ['hello world']) + self.expect("frame variable foo.B", matching=False, + substrs = ['hello world']) + self.expect("frame variable foo.F", matching=False, + substrs = ['hello world']) + + filter = lldb.SBTypeFilter(0) + filter.AppendExpressionPath("A") + filter.AppendExpressionPath("D") + self.assertTrue(filter.GetNumberOfExpressionPaths() == 2, "filter with two items does not have two items") + + category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"),filter) + self.expect("frame variable foo", + substrs = ['A = 1', 'D = 6.28']) + self.expect("frame variable foo", matching=False, + substrs = ['B = ', 'C = ', 'E = ', 'F = ']) + + category.DeleteTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct",True)) + self.expect("frame variable foo", + substrs = ['A = 1', 'D = 6.28']) + self.expect("frame variable foo", matching=False, + substrs = ['B = ', 'C = ', 'E = ', 'F = ']) + + category.DeleteTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct",False)) + self.expect("frame variable foo", + substrs = ['A = 1', 'D = 6.28']) + self.expect("frame variable foo", matching=True, + substrs = ['B = ', 'C = ', 'E = ', 'F = ']) + + self.runCmd("command script import --allow-reload ./synth.py") + + self.expect("frame variable foo", matching=False, + substrs = ['X = 1']) + + self.dbg.GetCategory("JASSynth").SetEnabled(True) + self.expect("frame variable foo", matching=True, + substrs = ['X = 1']) + + self.dbg.GetCategory("CCCSynth").SetEnabled(True) + self.expect("frame variable ccc", matching=True, + substrs = ['CCC object with leading value (int) a = 111', 'a = 111', 'b = 222', 'c = 333']) + + foo_var = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().FindVariable('foo') + self.assertTrue(foo_var.IsValid(), 'could not find foo') + self.assertTrue(foo_var.GetDeclaration().IsValid(), 'foo declaration is invalid') + + self.assertTrue(foo_var.GetNumChildren() == 2, 'synthetic value has wrong number of child items (synth)') + self.assertTrue(foo_var.GetChildMemberWithName('X').GetValueAsUnsigned() == 1, 'foo_synth.X has wrong value (synth)') + self.assertFalse(foo_var.GetChildMemberWithName('B').IsValid(), 'foo_synth.B is valid but should not (synth)') + + self.dbg.GetCategory("JASSynth").SetEnabled(False) + foo_var = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().FindVariable('foo') + self.assertTrue(foo_var.IsValid(), 'could not find foo') + + self.assertFalse(foo_var.GetNumChildren() == 2, 'still seeing synthetic value') + + filter = lldb.SBTypeFilter(0) + filter.AppendExpressionPath("A") + filter.AppendExpressionPath("D") + category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"),filter) + self.expect("frame variable foo", + substrs = ['A = 1', 'D = 6.28']) + + foo_var = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().FindVariable('foo') + self.assertTrue(foo_var.IsValid(), 'could not find foo') + + self.assertTrue(foo_var.GetNumChildren() == 2, 'synthetic value has wrong number of child items (filter)') + self.assertTrue(foo_var.GetChildMemberWithName('X').GetValueAsUnsigned() == 0, 'foo_synth.X has wrong value (filter)') + self.assertTrue(foo_var.GetChildMemberWithName('A').GetValueAsUnsigned() == 1, 'foo_synth.A has wrong value (filter)') + + self.assertTrue(filter.ReplaceExpressionPathAtIndex(0,"C"), "failed to replace an expression path in filter") + self.expect("frame variable foo", + substrs = ['A = 1', 'D = 6.28']) + category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"),filter) + self.expect("frame variable foo", + substrs = ["C = 'e'", 'D = 6.28']) + category.AddTypeFilter(lldb.SBTypeNameSpecifier("FooType"),filter) + filter.ReplaceExpressionPathAtIndex(1,"F") + self.expect("frame variable foo", + substrs = ["C = 'e'", 'D = 6.28']) + category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"),filter) + self.expect("frame variable foo", + substrs = ["C = 'e'", 'F = 0']) + self.expect("frame variable bar", + substrs = ["C = 'e'", 'D = 6.28']) + + foo_var = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().FindVariable('foo') + self.assertTrue(foo_var.IsValid(), 'could not find foo') + self.assertTrue(foo_var.GetChildMemberWithName('C').GetValueAsUnsigned() == ord('e'), 'foo_synth.C has wrong value (filter)') + + chosen = self.dbg.GetFilterForType(lldb.SBTypeNameSpecifier("JustAStruct")) + self.assertTrue(chosen.count == 2, "wrong filter found for JustAStruct") + self.assertTrue(chosen.GetExpressionPathAtIndex(0) == 'C', "wrong item at index 0 for JustAStruct") + self.assertTrue(chosen.GetExpressionPathAtIndex(1) == 'F', "wrong item at index 1 for JustAStruct") + + self.assertFalse(category.DeleteTypeFilter(lldb.SBTypeNameSpecifier("NoSuchType")),"deleting a non-existing filter worked") + self.assertFalse(category.DeleteTypeSummary(lldb.SBTypeNameSpecifier("NoSuchType")),"deleting a non-existing summary worked") + self.assertFalse(category.DeleteTypeFormat(lldb.SBTypeNameSpecifier("NoSuchType")),"deleting a non-existing format worked") + self.assertFalse(category.DeleteTypeSynthetic(lldb.SBTypeNameSpecifier("NoSuchType")),"deleting a non-existing synthetic worked") + + self.assertFalse(category.DeleteTypeFilter(lldb.SBTypeNameSpecifier("")),"deleting a filter for '' worked") + self.assertFalse(category.DeleteTypeSummary(lldb.SBTypeNameSpecifier("")),"deleting a summary for '' worked") + self.assertFalse(category.DeleteTypeFormat(lldb.SBTypeNameSpecifier("")),"deleting a format for '' worked") + self.assertFalse(category.DeleteTypeSynthetic(lldb.SBTypeNameSpecifier("")),"deleting a synthetic for '' worked") + + try: + self.assertFalse(category.AddTypeSummary(lldb.SBTypeNameSpecifier("NoneSuchType"), None), "adding a summary valued None worked") + except: + pass + else: + self.assertFalse(True, "adding a summary valued None worked") + + try: + self.assertFalse(category.AddTypeFilter(lldb.SBTypeNameSpecifier("NoneSuchType"), None), "adding a filter valued None worked") + except: + pass + else: + self.assertFalse(True, "adding a filter valued None worked") + + try: + self.assertFalse(category.AddTypeSynthetic(lldb.SBTypeNameSpecifier("NoneSuchType"), None), "adding a synthetic valued None worked") + except: + pass + else: + self.assertFalse(True, "adding a synthetic valued None worked") + + try: + self.assertFalse(category.AddTypeFormat(lldb.SBTypeNameSpecifier("NoneSuchType"), None), "adding a format valued None worked") + except: + pass + else: + self.assertFalse(True, "adding a format valued None worked") + + + self.assertFalse(category.AddTypeSummary(lldb.SBTypeNameSpecifier("EmptySuchType"), lldb.SBTypeSummary()), "adding a summary without value worked") + self.assertFalse(category.AddTypeFilter(lldb.SBTypeNameSpecifier("EmptySuchType"), lldb.SBTypeFilter()), "adding a filter without value worked") + self.assertFalse(category.AddTypeSynthetic(lldb.SBTypeNameSpecifier("EmptySuchType"), lldb.SBTypeSynthetic()), "adding a synthetic without value worked") + self.assertFalse(category.AddTypeFormat(lldb.SBTypeNameSpecifier("EmptySuchType"), lldb.SBTypeFormat()), "adding a format without value worked") + + self.assertFalse(category.AddTypeSummary(lldb.SBTypeNameSpecifier(""), lldb.SBTypeSummary.CreateWithSummaryString("")), "adding a summary for an invalid type worked") + self.assertFalse(category.AddTypeFilter(lldb.SBTypeNameSpecifier(""), lldb.SBTypeFilter(0)), "adding a filter for an invalid type worked") + self.assertFalse(category.AddTypeSynthetic(lldb.SBTypeNameSpecifier(""), lldb.SBTypeSynthetic.CreateWithClassName("")), "adding a synthetic for an invalid type worked") + self.assertFalse(category.AddTypeFormat(lldb.SBTypeNameSpecifier(""), lldb.SBTypeFormat(lldb.eFormatHex)), "adding a format for an invalid type worked") + + new_category = self.dbg.CreateCategory("newbar") + new_category.AddTypeSummary(lldb.SBTypeNameSpecifier("JustAStruct"), + lldb.SBTypeSummary.CreateWithScriptCode("return 'hello scripted world';")) + self.expect("frame variable foo", matching=False, + substrs = ['hello scripted world']) + new_category.enabled = True + self.expect("frame variable foo", matching=True, + substrs = ['hello scripted world']) + + self.expect("frame variable foo_ptr", matching=True, + substrs = ['hello scripted world']) + new_category.AddTypeSummary(lldb.SBTypeNameSpecifier("JustAStruct"), + lldb.SBTypeSummary.CreateWithScriptCode("return 'hello scripted world';", + lldb.eTypeOptionSkipPointers)) + self.expect("frame variable foo", matching=True, + substrs = ['hello scripted world']) + + frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() + foo_ptr = frame.FindVariable("foo_ptr") + summary = foo_ptr.GetTypeSummary() + + self.assertFalse(summary.IsValid(), "summary found for foo* when none was planned") + + self.expect("frame variable foo_ptr", matching=False, + substrs = ['hello scripted world']) + + new_category.AddTypeSummary(lldb.SBTypeNameSpecifier("JustAStruct"), + lldb.SBTypeSummary.CreateWithSummaryString("hello static world", + lldb.eTypeOptionNone)) + + summary = foo_ptr.GetTypeSummary() + + self.assertTrue(summary.IsValid(), "no summary found for foo* when one was in place") + self.assertTrue(summary.GetData() == "hello static world", "wrong summary found for foo*") + + self.expect("frame variable e1", substrs=["I am an empty Empty1 {}"]) + self.expect("frame variable e2", substrs=["I am an empty Empty2"]) + self.expect("frame variable e2", substrs=["I am an empty Empty2 {}"], matching=False) + + self.assertTrue(self.dbg.GetCategory(lldb.eLanguageTypeObjC) is not None, "ObjC category is None") + + @add_test_categories(['pyapi']) + def test_force_synth_off(self): + """Test that one can have the public API return non-synthetic SBValues if desired""" + self.build(dictionary={'EXE':'no_synth'}) + self.setTearDownCleanup() + + self.runCmd("file no_synth", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synthetic clear', check=False) + self.runCmd('type category delete foobar', check=False) + self.runCmd('type category delete JASSynth', check=False) + self.runCmd('type category delete newbar', check=False) + self.runCmd('settings set target.enable-synthetic-value true') + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() + int_vector = frame.FindVariable("int_vector") + if self.TraceOn(): + print(int_vector) + self.assertTrue(int_vector.GetNumChildren() == 0, 'synthetic vector is empty') + + self.runCmd('settings set target.enable-synthetic-value false') + frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() + int_vector = frame.FindVariable("int_vector") + if self.TraceOn(): + print(int_vector) + self.assertFalse(int_vector.GetNumChildren() == 0, '"physical" vector is not empty') + + self.runCmd('settings set target.enable-synthetic-value true') + frame = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame() + int_vector = frame.FindVariable("int_vector") + if self.TraceOn(): + print(int_vector) + self.assertTrue(int_vector.GetNumChildren() == 0, 'synthetic vector is still empty') diff --git a/packages/Python/lldbsuite/test/python_api/formatters/main.cpp b/packages/Python/lldbsuite/test/python_api/formatters/main.cpp new file mode 100644 index 0000000..f21c956 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/formatters/main.cpp @@ -0,0 +1,59 @@ +#include <stdio.h> +#include <vector> + +struct JustAStruct +{ + int A; + float B; + char C; + double D; + long E; + short F; +}; + +struct FooType +{ + int A; + float B; + char C; + double D; + long E; + short F; +}; + +struct CCC +{ + int a, b, c; +}; + +struct Empty1 { void *data; }; +struct Empty2 { void *data; }; + + +int main(int argc, char const *argv[]) { + JustAStruct foo; + foo.A = 1; + foo.B = 3.14; + foo.C = 'e'; + foo.D = 6.28; + foo.E = 3100419850; + foo.F = 0; + + FooType bar; + bar.A = 1; + bar.B = 3.14; + bar.C = 'e'; + bar.D = 6.28; + bar.E = 3100419850; + bar.F = 0; + JustAStruct* foo_ptr = &foo; + + std::vector<int> int_vector; + + CCC ccc = {111, 222, 333}; + + Empty1 e1; + Empty2 e2; + + return 0; // Set break point at this line. +} diff --git a/packages/Python/lldbsuite/test/python_api/formatters/synth.py b/packages/Python/lldbsuite/test/python_api/formatters/synth.py new file mode 100644 index 0000000..5a30c9a --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/formatters/synth.py @@ -0,0 +1,105 @@ +import lldb + +class jasSynthProvider: + def __init__(self, valobj, dict): + self.valobj = valobj; + def num_children(self): + return 2; + def get_child_at_index(self, index): + child = None + if index == 0: + child = self.valobj.GetChildMemberWithName('A'); + if index == 1: + child = self.valobj.CreateValueFromExpression('X', '(int)1') + return child; + def get_child_index(self, name): + if name == 'A': + return 0; + if name == 'X': + return 1; + return None; + + +def ccc_summary(sbvalue, internal_dict): + sbvalue = sbvalue.GetNonSyntheticValue() + # This tests that the SBValue.GetNonSyntheticValue() actually returns a + # non-synthetic value. If it does not, then sbvalue.GetChildMemberWithName("a") + # in the following statement will call the 'get_child_index' method of the + # synthetic child provider CCCSynthProvider below (which raises an exception). + return "CCC object with leading value " + str(sbvalue.GetChildMemberWithName("a")) + + +class CCCSynthProvider(object): + def __init__(self, sbvalue, internal_dict): + self._sbvalue = sbvalue + + def num_children(self): + return 3 + + def get_child_index(self, name): + raise RuntimeError("I don't want to be called!") + + def get_child_at_index(self, index): + if index == 0: + return self._sbvalue.GetChildMemberWithName("a") + if index == 1: + return self._sbvalue.GetChildMemberWithName("b") + if index == 2: + return self._sbvalue.GetChildMemberWithName("c") + + +def empty1_summary(sbvalue, internal_dict): + return "I am an empty Empty1" + + +class Empty1SynthProvider(object): + def __init__(self, sbvalue, internal_dict): + self._sbvalue = sbvalue + + def num_children(self): + return 0 + + def get_child_at_index(self, index): + return None + + +def empty2_summary(sbvalue, internal_dict): + return "I am an empty Empty2" + + +class Empty2SynthProvider(object): + def __init__(self, sbvalue, internal_dict): + self._sbvalue = sbvalue + + def num_children(self): + return 0 + + def get_child_at_index(self, index): + return None + + +def __lldb_init_module(debugger,dict): + debugger.CreateCategory("JASSynth").AddTypeSynthetic(lldb.SBTypeNameSpecifier("JustAStruct"), + lldb.SBTypeSynthetic.CreateWithClassName("synth.jasSynthProvider")) + cat = lldb.debugger.CreateCategory("CCCSynth") + cat.AddTypeSynthetic( + lldb.SBTypeNameSpecifier("CCC"), + lldb.SBTypeSynthetic.CreateWithClassName("synth.CCCSynthProvider", + lldb.eTypeOptionCascade)) + cat.AddTypeSummary( + lldb.SBTypeNameSpecifier("CCC"), + lldb.SBTypeSummary.CreateWithFunctionName("synth.ccc_summary", + lldb.eTypeOptionCascade)) + cat.AddTypeSynthetic( + lldb.SBTypeNameSpecifier("Empty1"), + lldb.SBTypeSynthetic.CreateWithClassName("synth.Empty1SynthProvider")) + cat.AddTypeSummary( + lldb.SBTypeNameSpecifier("Empty1"), + lldb.SBTypeSummary.CreateWithFunctionName("synth.empty1_summary")) + cat.AddTypeSynthetic( + lldb.SBTypeNameSpecifier("Empty2"), + lldb.SBTypeSynthetic.CreateWithClassName("synth.Empty2SynthProvider")) + cat.AddTypeSummary( + lldb.SBTypeNameSpecifier("Empty2"), + lldb.SBTypeSummary.CreateWithFunctionName("synth.empty2_summary", + lldb.eTypeOptionHideEmptyAggregates)) diff --git a/packages/Python/lldbsuite/test/python_api/frame/Makefile b/packages/Python/lldbsuite/test/python_api/frame/Makefile new file mode 100644 index 0000000..0d70f25 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/frame/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py b/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py new file mode 100644 index 0000000..7cc976f --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py @@ -0,0 +1,207 @@ +""" +Use lldb Python SBFrame API to get the argument values of the call stacks. +And other SBFrame API tests. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class FrameAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + @expectedFailureWindows("llvm.org/pr24778") + def test_get_arg_vals_for_call_stack(self): + """Exercise SBFrame.GetVariables() API to get argument vals.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + process = target.GetProcess() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + + # Keeps track of the number of times 'a' is called where it is within a + # depth of 3 of the 'c' leaf function. + callsOfA = 0 + + from six import StringIO as SixStringIO + session = SixStringIO() + while process.GetState() == lldb.eStateStopped: + thread = process.GetThreadAtIndex(0) + # Inspect at most 3 frames. + numFrames = min(3, thread.GetNumFrames()) + for i in range(numFrames): + frame = thread.GetFrameAtIndex(i) + if self.TraceOn(): + print("frame:", frame) + + name = frame.GetFunction().GetName() + if name == 'a': + callsOfA = callsOfA + 1 + + # We'll inspect only the arguments for the current frame: + # + # arguments => True + # locals => False + # statics => False + # in_scope_only => True + valList = frame.GetVariables(True, False, False, True) + argList = [] + for val in valList: + argList.append("(%s)%s=%s" % (val.GetTypeName(), + val.GetName(), + val.GetValue())) + print("%s(%s)" % (name, ", ".join(argList)), file=session) + + # Also check the generic pc & stack pointer. We can't test their absolute values, + # but they should be valid. Uses get_GPRs() from the lldbutil module. + gpr_reg_set = lldbutil.get_GPRs(frame) + pc_value = gpr_reg_set.GetChildMemberWithName("pc") + self.assertTrue (pc_value, "We should have a valid PC.") + pc_value_int = int(pc_value.GetValue(), 0) + # Make sure on arm targets we dont mismatch PC value on the basis of thumb bit. + # Frame PC will not have thumb bit set in case of a thumb instruction as PC. + if self.getArchitecture() in ['arm']: + pc_value_int &= ~1 + self.assertTrue (pc_value_int == frame.GetPC(), "PC gotten as a value should equal frame's GetPC") + sp_value = gpr_reg_set.GetChildMemberWithName("sp") + self.assertTrue (sp_value, "We should have a valid Stack Pointer.") + self.assertTrue (int(sp_value.GetValue(), 0) == frame.GetSP(), "SP gotten as a value should equal frame's GetSP") + + print("---", file=session) + process.Continue() + + # At this point, the inferior process should have exited. + self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED) + + # Expect to find 'a' on the call stacks two times. + self.assertTrue(callsOfA == 2, + "Expect to find 'a' on the call stacks two times") + # By design, the 'a' call frame has the following arg vals: + # o a((int)val=1, (char)ch='A') + # o a((int)val=3, (char)ch='A') + if self.TraceOn(): + print("Full stack traces when stopped on the breakpoint 'c':") + print(session.getvalue()) + self.expect(session.getvalue(), "Argugment values displayed correctly", + exe=False, + substrs = ["a((int)val=1, (char)ch='A')", + "a((int)val=3, (char)ch='A')"]) + + @add_test_categories(['pyapi']) + def test_frame_api_boundary_condition(self): + """Exercise SBFrame APIs with boundary condition inputs.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + process = target.GetProcess() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + + thread = process.GetThreadAtIndex(0) + frame = thread.GetFrameAtIndex(0) + if self.TraceOn(): + print("frame:", frame) + + # Boundary condition testings. + val1 = frame.FindVariable(None, True) + val2 = frame.FindVariable(None, False) + val3 = frame.FindValue(None, lldb.eValueTypeVariableGlobal) + if self.TraceOn(): + print("val1:", val1) + print("val2:", val2) + + frame.EvaluateExpression(None) + + @add_test_categories(['pyapi']) + def test_frame_api_IsEqual(self): + """Exercise SBFrame API IsEqual.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + process = target.GetProcess() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + + thread = process.GetThreadAtIndex(0) + self.assertTrue(thread) + + frameEntered = thread.GetFrameAtIndex(0) + if self.TraceOn(): + print(frameEntered) + lldbutil.print_stacktrace(thread) + self.assertTrue(frameEntered) + + # Doing two step overs while still inside c(). + thread.StepOver() + thread.StepOver() + self.assertTrue(thread) + frameNow = thread.GetFrameAtIndex(0) + if self.TraceOn(): + print(frameNow) + lldbutil.print_stacktrace(thread) + self.assertTrue(frameNow) + + # The latest two frames are considered equal. + self.assertTrue(frameEntered.IsEqual(frameNow)) + + # Now let's step out of frame c(). + thread.StepOutOfFrame(frameNow) + frameOutOfC = thread.GetFrameAtIndex(0) + if self.TraceOn(): + print(frameOutOfC) + lldbutil.print_stacktrace(thread) + self.assertTrue(frameOutOfC) + + # The latest two frames should not be equal. + self.assertFalse(frameOutOfC.IsEqual(frameNow)) diff --git a/packages/Python/lldbsuite/test/python_api/frame/inlines/Makefile b/packages/Python/lldbsuite/test/python_api/frame/inlines/Makefile new file mode 100644 index 0000000..641ee5d --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/frame/inlines/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../../make + +C_SOURCES := inlines.c + +ifneq (,$(findstring icc,$(CC))) + CFLAGS += -debug inline-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/frame/inlines/TestInlinedFrame.py b/packages/Python/lldbsuite/test/python_api/frame/inlines/TestInlinedFrame.py new file mode 100644 index 0000000..d4cf8fe --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/frame/inlines/TestInlinedFrame.py @@ -0,0 +1,79 @@ +""" +Testlldb Python SBFrame APIs IsInlined() and GetFunctionName(). +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class InlinedFrameAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to of function 'c'. + self.source = 'inlines.c' + self.first_stop = line_number(self.source, '// This should correspond to the first break stop.') + self.second_stop = line_number(self.source, '// This should correspond to the second break stop.') + + @add_test_categories(['pyapi']) + def test_stop_at_outer_inline(self): + """Exercise SBFrame.IsInlined() and SBFrame.GetFunctionName().""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by the name of 'inner_inline'. + breakpoint = target.BreakpointCreateByName('inner_inline', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() > 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + process = target.GetProcess() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + + import lldbsuite.test.lldbutil as lldbutil + stack_traces1 = lldbutil.print_stacktraces(process, string_buffer=True) + if self.TraceOn(): + print("Full stack traces when first stopped on the breakpoint 'inner_inline':") + print(stack_traces1) + + # The first breakpoint should correspond to an inlined call frame. + # If it's an inlined call frame, expect to find, in the stack trace, + # that there is a frame which corresponds to the following call site: + # + # outer_inline (argc); + # + frame0 = process.GetThreadAtIndex(0).GetFrameAtIndex(0) + if frame0.IsInlined(): + filename = frame0.GetLineEntry().GetFileSpec().GetFilename() + self.assertTrue(filename == self.source) + self.expect(stack_traces1, "First stop at %s:%d" % (self.source, self.first_stop), exe=False, + substrs = ['%s:%d' % (self.source, self.first_stop)]) + + # Expect to break again for the second time. + process.Continue() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + stack_traces2 = lldbutil.print_stacktraces(process, string_buffer=True) + if self.TraceOn(): + print("Full stack traces when stopped on the breakpoint 'inner_inline' for the second time:") + print(stack_traces2) + self.expect(stack_traces2, "Second stop at %s:%d" % (self.source, self.second_stop), exe=False, + substrs = ['%s:%d' % (self.source, self.second_stop)]) diff --git a/packages/Python/lldbsuite/test/python_api/frame/inlines/inlines.c b/packages/Python/lldbsuite/test/python_api/frame/inlines/inlines.c new file mode 100644 index 0000000..a2a8212 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/frame/inlines/inlines.c @@ -0,0 +1,53 @@ +#include <stdio.h> +#include "inlines.h" + +#define INLINE_ME __inline__ __attribute__((always_inline)) + +int +not_inlined_2 (int input) +{ + printf ("Called in not_inlined_2 with : %d.\n", input); + return input; +} + +int +not_inlined_1 (int input) +{ + printf ("Called in not_inlined_1 with %d.\n", input); + return not_inlined_2(input); +} + +INLINE_ME int +inner_inline (int inner_input, int mod_value) +{ + int inner_result; + inner_result = inner_input % mod_value; + printf ("Returning: %d.\n", inner_result); + return not_inlined_1 (inner_result); +} + +INLINE_ME int +outer_inline (int outer_input) +{ + int outer_result; + + outer_result = inner_inline (outer_input, outer_input % 3); + return outer_result; +} + +int +main (int argc, char **argv) +{ + printf ("Starting...\n"); + + int (*func_ptr) (int); + func_ptr = outer_inline; + + outer_inline (argc); // This should correspond to the first break stop. + + func_ptr (argc); // This should correspond to the second break stop. + + return 0; +} + + diff --git a/packages/Python/lldbsuite/test/python_api/frame/inlines/inlines.h b/packages/Python/lldbsuite/test/python_api/frame/inlines/inlines.h new file mode 100644 index 0000000..265d7b4 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/frame/inlines/inlines.h @@ -0,0 +1,4 @@ +int inner_inline (int inner_input, int mod_value); +int outer_inline (int outer_input); +int not_inlined_2 (int input); +int not_inlined_1 (int input); diff --git a/packages/Python/lldbsuite/test/python_api/frame/main.c b/packages/Python/lldbsuite/test/python_api/frame/main.c new file mode 100644 index 0000000..35209db --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/frame/main.c @@ -0,0 +1,58 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to test the lldb Python API related to frames. + +int a(int, char); +int b(int, char); +int c(int, char); + +int a(int val, char ch) +{ + int my_val = val; + char my_ch = ch; + printf("a(val=%d, ch='%c')\n", val, ch); + if (val <= 1) + return b(val+1, ch+1); + else if (val >= 3) + return c(val+1, ch+1); + + return val; +} + +int b(int val, char ch) +{ + int my_val = val; + char my_ch = ch; + printf("b(val=%d, ch='%c')\n", val, ch); + return c(val+1, ch+1); +} + +int c(int val, char ch) +{ + int my_val = val; + char my_ch = ch; + printf("c(val=%d, ch='%c')\n", val, ch); + return val + 3 + ch; +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1, 'A'); // a(1, 'A') -> b(2, 'B') -> c(3, 'C') + printf("a(1, 'A') returns %d\n", A1); + + int B2 = b(2, 'B'); // b(2, 'B') -> c(3, 'C') + printf("b(2, 'B') returns %d\n", B2); + + int A3 = a(3, 'A'); // a(3, 'A') -> c(4, 'B') + printf("a(3, 'A') returns %d\n", A3); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/function_symbol/Makefile b/packages/Python/lldbsuite/test/python_api/function_symbol/Makefile new file mode 100644 index 0000000..0d70f25 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/function_symbol/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/function_symbol/TestDisasmAPI.py b/packages/Python/lldbsuite/test/python_api/function_symbol/TestDisasmAPI.py new file mode 100644 index 0000000..c9876a8 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/function_symbol/TestDisasmAPI.py @@ -0,0 +1,111 @@ +""" +Test retrieval of SBAddress from function/symbol, disassembly, and SBAddress APIs. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class DisasmAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to of function 'c'. + self.line1 = line_number('main.c', '// Find the line number for breakpoint 1 here.') + self.line2 = line_number('main.c', '// Find the line number for breakpoint 2 here.') + + @add_test_categories(['pyapi']) + def test(self): + """Exercise getting SBAddress objects, disassembly, and SBAddress APIs.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create the two breakpoints inside function 'a'. + breakpoint1 = target.BreakpointCreateByLocation('main.c', self.line1) + breakpoint2 = target.BreakpointCreateByLocation('main.c', self.line2) + #print("breakpoint1:", breakpoint1) + #print("breakpoint2:", breakpoint2) + self.assertTrue(breakpoint1 and + breakpoint1.GetNumLocations() == 1, + VALID_BREAKPOINT) + self.assertTrue(breakpoint2 and + breakpoint2.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.line1. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + lineEntry = frame0.GetLineEntry() + self.assertTrue(lineEntry.GetLine() == self.line1) + + address1 = lineEntry.GetStartAddress() + #print("address1:", address1) + + # Now call SBTarget.ResolveSymbolContextForAddress() with address1. + context1 = target.ResolveSymbolContextForAddress(address1, lldb.eSymbolContextEverything) + + self.assertTrue(context1) + if self.TraceOn(): + print("context1:", context1) + + # Continue the inferior, the breakpoint 2 should be hit. + process.Continue() + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + lineEntry = frame0.GetLineEntry() + self.assertTrue(lineEntry.GetLine() == self.line2) + + # Verify that the symbol and the function has the same address range per function 'a'. + symbol = context1.GetSymbol() + function = frame0.GetFunction() + self.assertTrue(symbol and function) + + disasm_output = lldbutil.disassemble(target, symbol) + if self.TraceOn(): + print("symbol:", symbol) + print("disassembly=>\n", disasm_output) + + disasm_output = lldbutil.disassemble(target, function) + if self.TraceOn(): + print("function:", function) + print("disassembly=>\n", disasm_output) + + sa1 = symbol.GetStartAddress() + #print("sa1:", sa1) + #print("sa1.GetFileAddress():", hex(sa1.GetFileAddress())) + #ea1 = symbol.GetEndAddress() + #print("ea1:", ea1) + sa2 = function.GetStartAddress() + #print("sa2:", sa2) + #print("sa2.GetFileAddress():", hex(sa2.GetFileAddress())) + #ea2 = function.GetEndAddress() + #print("ea2:", ea2) + self.assertTrue(sa1 and sa2 and sa1 == sa2, + "The two starting addresses should be the same") + + from lldbsuite.test.lldbutil import get_description + desc1 = get_description(sa1) + desc2 = get_description(sa2) + self.assertTrue(desc1 and desc2 and desc1 == desc2, + "SBAddress.GetDescription() API of sa1 and sa2 should return the same string") diff --git a/packages/Python/lldbsuite/test/python_api/function_symbol/TestSymbolAPI.py b/packages/Python/lldbsuite/test/python_api/function_symbol/TestSymbolAPI.py new file mode 100644 index 0000000..d45f572 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/function_symbol/TestSymbolAPI.py @@ -0,0 +1,81 @@ +""" +Test newly added SBSymbol and SBAddress APIs. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class SymbolAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to of function 'c'. + self.line1 = line_number('main.c', '// Find the line number for breakpoint 1 here.') + self.line2 = line_number('main.c', '// Find the line number for breakpoint 2 here.') + + @add_test_categories(['pyapi']) + @expectedFailureWindows("llvm.org/pr24778") + def test(self): + """Exercise some SBSymbol and SBAddress APIs.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create the two breakpoints inside function 'a'. + breakpoint1 = target.BreakpointCreateByLocation('main.c', self.line1) + breakpoint2 = target.BreakpointCreateByLocation('main.c', self.line2) + #print("breakpoint1:", breakpoint1) + #print("breakpoint2:", breakpoint2) + self.assertTrue(breakpoint1 and + breakpoint1.GetNumLocations() == 1, + VALID_BREAKPOINT) + self.assertTrue(breakpoint2 and + breakpoint2.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.line1. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + symbol_line1 = frame0.GetSymbol() + # We should have a symbol type of code. + self.assertTrue(symbol_line1.GetType() == lldb.eSymbolTypeCode) + addr_line1 = symbol_line1.GetStartAddress() + # And a section type of code, too. + self.assertTrue(addr_line1.GetSection().GetSectionType() == lldb.eSectionTypeCode) + + # Continue the inferior, the breakpoint 2 should be hit. + process.Continue() + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + symbol_line2 = frame0.GetSymbol() + # We should have a symbol type of code. + self.assertTrue(symbol_line2.GetType() == lldb.eSymbolTypeCode) + addr_line2 = symbol_line2.GetStartAddress() + # And a section type of code, too. + self.assertTrue(addr_line2.GetSection().GetSectionType() == lldb.eSectionTypeCode) + + # Now verify that both addresses point to the same module. + if self.TraceOn(): + print("UUID:", addr_line1.GetModule().GetUUIDString()) + self.assertTrue(addr_line1.GetModule().GetUUIDString() == addr_line2.GetModule().GetUUIDString()) diff --git a/packages/Python/lldbsuite/test/python_api/function_symbol/main.c b/packages/Python/lldbsuite/test/python_api/function_symbol/main.c new file mode 100644 index 0000000..b60b2fa --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/function_symbol/main.c @@ -0,0 +1,60 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to test the lldb Python APIs SBTarget, SBFrame, +// SBFunction, SBSymbol, and SBAddress. +// +// When stopped on breakppint 1, we can get the line entry using SBFrame API +// SBFrame.GetLineEntry(). We'll get the start address for the line entry +// with the SBAddress type, resolve the symbol context using the SBTarget API +// SBTarget.ResolveSymbolContextForAddress() in order to get the SBSymbol. +// +// We then stop at breakpoint 2, get the SBFrame, and the SBFunction object. +// +// The address from calling GetStartAddress() on the symbol and the function +// should point to the same address, and we also verify that. + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) // Find the line number for breakpoint 1 here. + val = b(val); + else if (val >= 3) + val = c(val); + + return val; // Find the line number for breakpoint 2 here. +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) + printf("a(3) returns %d\n", A3); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/hello_world/Makefile b/packages/Python/lldbsuite/test/python_api/hello_world/Makefile new file mode 100644 index 0000000..9976203 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/hello_world/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../make + +C_SOURCES := main.c +# See TestHelloWorld.py, which specifies the executable name with a dictionary. +EXE := hello_world + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py b/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py new file mode 100644 index 0000000..47c3ba1 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py @@ -0,0 +1,147 @@ +"""Test Python APIs for target (launch and attach), breakpoint, and process.""" + +from __future__ import print_function + + + +import os, sys, time +import lldb +import time +from lldbsuite.test.lldbtest import * + +class HelloWorldTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Get the full path to our executable to be attached/debugged. + self.exe = os.path.join(os.getcwd(), self.testMethodName) + self.d = {'EXE': self.testMethodName} + # Find a couple of the line numbers within main.c. + self.line1 = line_number('main.c', '// Set break point at this line.') + self.line2 = line_number('main.c', '// Waiting to be attached...') + + def tearDown(self): + # Destroy process before TestBase.tearDown() + self.dbg.GetSelectedTarget().GetProcess().Destroy() + # Call super's tearDown(). + TestBase.tearDown(self) + + @add_test_categories(['pyapi']) + @skipIfiOSSimulator + def test_with_process_launch_api(self): + """Create target, breakpoint, launch a process, and then kill it.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + target = self.dbg.CreateTarget(self.exe) + + breakpoint = target.BreakpointCreateByLocation("main.c", self.line1) + + # The default state after breakpoint creation should be enabled. + self.assertTrue(breakpoint.IsEnabled(), + "Breakpoint should be enabled after creation") + + breakpoint.SetEnabled(False) + self.assertTrue(not breakpoint.IsEnabled(), + "Breakpoint.SetEnabled(False) works") + + breakpoint.SetEnabled(True) + self.assertTrue(breakpoint.IsEnabled(), + "Breakpoint.SetEnabled(True) works") + + # rdar://problem/8364687 + # SBTarget.Launch() issue (or is there some race condition)? + + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + # The following isn't needed anymore, rdar://8364687 is fixed. + # + # Apply some dances after LaunchProcess() in order to break at "main". + # It only works sometimes. + #self.breakAfterLaunch(process, "main") + + process = target.GetProcess() + self.assertTrue(process, PROCESS_IS_VALID) + + thread = process.GetThreadAtIndex(0) + if thread.GetStopReason() != lldb.eStopReasonBreakpoint: + from lldbsuite.test.lldbutil import stop_reason_to_str + self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % + stop_reason_to_str(thread.GetStopReason())) + + # The breakpoint should have a hit count of 1. + self.assertTrue(breakpoint.GetHitCount() == 1, BREAKPOINT_HIT_ONCE) + + @add_test_categories(['pyapi']) + @expectedFailureWindows("llvm.org/pr24600") + @expectedFailurei386("llvm.org/pr25338") + @skipIfiOSSimulator + def test_with_attach_to_process_with_id_api(self): + """Create target, spawn a process, and attach to it with process id.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + target = self.dbg.CreateTarget(self.exe) + + # Spawn a new process + popen = self.spawnSubprocess(self.exe, ["abc", "xyz"]) + self.addTearDownHook(self.cleanupSubprocesses) + + # Give the subprocess time to start and wait for user input + time.sleep(0.25) + + listener = lldb.SBListener("my.attach.listener") + error = lldb.SBError() + process = target.AttachToProcessWithID(listener, popen.pid, error) + + self.assertTrue(error.Success() and process, PROCESS_IS_VALID) + + # Let's check the stack traces of the attached process. + import lldbsuite.test.lldbutil as lldbutil + stacktraces = lldbutil.print_stacktraces(process, string_buffer=True) + self.expect(stacktraces, exe=False, + substrs = ['main.c:%d' % self.line2, + '(int)argc=3']) + + @add_test_categories(['pyapi']) + @expectedFailureWindows("llvm.org/pr24600") + @expectedFailurei386("llvm.org/pr25338") + @skipIfiOSSimulator + def test_with_attach_to_process_with_name_api(self): + """Create target, spawn a process, and attach to it with process name.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + target = self.dbg.CreateTarget(self.exe) + + # Spawn a new process + popen = self.spawnSubprocess(self.exe, ["abc", "xyz"]) + self.addTearDownHook(self.cleanupSubprocesses) + + # Give the subprocess time to start and wait for user input + time.sleep(0.25) + + listener = lldb.SBListener("my.attach.listener") + error = lldb.SBError() + # Pass 'False' since we don't want to wait for new instance of "hello_world" to be launched. + name = os.path.basename(self.exe) + + # While we're at it, make sure that passing a None as the process name + # does not hang LLDB. + target.AttachToProcessWithName(listener, None, False, error) + # Also boundary condition test ConnectRemote(), too. + target.ConnectRemote(listener, None, None, error) + + process = target.AttachToProcessWithName(listener, name, False, error) + + self.assertTrue(error.Success() and process, PROCESS_IS_VALID) + + # Verify that after attach, our selected target indeed matches name. + self.expect(self.dbg.GetSelectedTarget().GetExecutable().GetFilename(), exe=False, + startstr = name) + + # Let's check the stack traces of the attached process. + import lldbsuite.test.lldbutil as lldbutil + stacktraces = lldbutil.print_stacktraces(process, string_buffer=True) + self.expect(stacktraces, exe=False, + substrs = ['main.c:%d' % self.line2, + '(int)argc=3']) diff --git a/packages/Python/lldbsuite/test/python_api/hello_world/main.c b/packages/Python/lldbsuite/test/python_api/hello_world/main.c new file mode 100644 index 0000000..31a041e --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/hello_world/main.c @@ -0,0 +1,35 @@ +#include <stdio.h> + +#if defined(__linux__) +#include <sys/prctl.h> +#endif + +int main(int argc, char const *argv[]) { + +#if defined(__linux__) + // Immediately enable any ptracer so that we can allow the stub attach + // operation to succeed. Some Linux kernels are locked down so that + // only an ancestor process can be a ptracer of a process. This disables that + // restriction. Without it, attach-related stub tests will fail. +#if defined(PR_SET_PTRACER) && defined(PR_SET_PTRACER_ANY) + int prctl_result; + + // For now we execute on best effort basis. If this fails for + // some reason, so be it. + prctl_result = prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0); + (void) prctl_result; +#endif +#endif + + printf("Hello world.\n"); // Set break point at this line. + if (argc == 1) + return 0; + + // Waiting to be attached by the debugger, otherwise. + char line[100]; + while (fgets(line, sizeof(line), stdin)) { // Waiting to be attached... + printf("input line=>%s\n", line); + } + + printf("Exiting now\n"); +} diff --git a/packages/Python/lldbsuite/test/python_api/interpreter/Makefile b/packages/Python/lldbsuite/test/python_api/interpreter/Makefile new file mode 100644 index 0000000..0d70f25 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/interpreter/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/interpreter/TestCommandInterpreterAPI.py b/packages/Python/lldbsuite/test/python_api/interpreter/TestCommandInterpreterAPI.py new file mode 100644 index 0000000..faff118 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/interpreter/TestCommandInterpreterAPI.py @@ -0,0 +1,73 @@ +"""Test the SBCommandInterpreter APIs.""" + +from __future__ import print_function + + + +import os +import lldb +from lldbsuite.test.lldbtest import * + +class CommandInterpreterAPICase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break on inside main.cpp. + self.line = line_number('main.c', 'Hello world.') + + @add_test_categories(['pyapi']) + def test_with_process_launch_api(self): + """Test the SBCommandInterpreter APIs.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Retrieve the associated command interpreter from our debugger. + ci = self.dbg.GetCommandInterpreter() + self.assertTrue(ci, VALID_COMMAND_INTERPRETER) + + # Exercise some APIs.... + + self.assertTrue(ci.HasCommands()) + self.assertTrue(ci.HasAliases()) + self.assertTrue(ci.HasAliasOptions()) + self.assertTrue(ci.CommandExists("breakpoint")) + self.assertTrue(ci.CommandExists("target")) + self.assertTrue(ci.CommandExists("platform")) + self.assertTrue(ci.AliasExists("file")) + self.assertTrue(ci.AliasExists("run")) + self.assertTrue(ci.AliasExists("bt")) + + res = lldb.SBCommandReturnObject() + ci.HandleCommand("breakpoint set -f main.c -l %d" % self.line, res) + self.assertTrue(res.Succeeded()) + ci.HandleCommand("process launch", res) + self.assertTrue(res.Succeeded()) + + # Boundary conditions should not crash lldb! + self.assertFalse(ci.CommandExists(None)) + self.assertFalse(ci.AliasExists(None)) + ci.HandleCommand(None, res) + self.assertFalse(res.Succeeded()) + res.AppendMessage("Just appended a message.") + res.AppendMessage(None) + if self.TraceOn(): + print(res) + + process = ci.GetProcess() + self.assertTrue(process) + + import lldbsuite.test.lldbutil as lldbutil + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + if self.TraceOn(): + lldbutil.print_stacktraces(process) diff --git a/packages/Python/lldbsuite/test/python_api/interpreter/main.c b/packages/Python/lldbsuite/test/python_api/interpreter/main.c new file mode 100644 index 0000000..277aa54 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/interpreter/main.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +int main(int argc, char const *argv[]) { + printf("Hello world.\n"); + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/frame/Makefile b/packages/Python/lldbsuite/test/python_api/lldbutil/frame/Makefile new file mode 100644 index 0000000..69b74b5 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/frame/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +MAKE_DSYM :=NO + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/frame/TestFrameUtils.py b/packages/Python/lldbsuite/test/python_api/lldbutil/frame/TestFrameUtils.py new file mode 100644 index 0000000..2cde05a --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/frame/TestFrameUtils.py @@ -0,0 +1,59 @@ +""" +Test utility functions for the frame object. +""" + +from __future__ import print_function + + + +import os +import lldb +from lldbsuite.test.lldbtest import * + +class FrameUtilsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.c', + "// Find the line number here.") + + @add_test_categories(['pyapi']) + def test_frame_utils(self): + """Test utility functions for the frame object.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.c", self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.LaunchProcess() failed") + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + + import lldbsuite.test.lldbutil as lldbutil + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue (thread) + frame0 = thread.GetFrameAtIndex(0) + self.assertTrue (frame0) + frame1 = thread.GetFrameAtIndex(1) + self.assertTrue (frame1) + parent = lldbutil.get_parent_frame(frame0) + self.assertTrue(parent and parent.GetFrameID() == frame1.GetFrameID()) + frame0_args = lldbutil.get_args_as_string(frame0) + parent_args = lldbutil.get_args_as_string(parent) + self.assertTrue(frame0_args and parent_args and "(int)val=1" in frame0_args) + if self.TraceOn(): + lldbutil.print_stacktrace(thread) + print("Current frame: %s" % frame0_args) + print("Parent frame: %s" % parent_args) diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/frame/main.c b/packages/Python/lldbsuite/test/python_api/lldbutil/frame/main.c new file mode 100644 index 0000000..e6eeef5 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/frame/main.c @@ -0,0 +1,47 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; // Find the line number here. +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) + printf("a(3) returns %d\n", A3); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/iter/Makefile b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/Makefile new file mode 100644 index 0000000..0513541 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make + +CFLAGS_EXTRAS += -D__STDC_LIMIT_MACROS +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp +MAKE_DSYM := NO + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py new file mode 100644 index 0000000..07177c1 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py @@ -0,0 +1,122 @@ +""" +Test the iteration protocol for some lldb container objects. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * + +class LLDBIteratorTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers to break inside main(). + self.line1 = line_number('main.cpp', '// Set break point at this line.') + self.line2 = line_number('main.cpp', '// And that line.') + + @add_test_categories(['pyapi']) + def test_lldb_iter_module(self): + """Test module_iter works correctly for SBTarget -> SBModule.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line1) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.LaunchProcess() failed") + + from lldbsuite.test.lldbutil import get_description + yours = [] + for i in range(target.GetNumModules()): + yours.append(target.GetModuleAtIndex(i)) + mine = [] + for m in target.module_iter(): + mine.append(m) + + self.assertTrue(len(yours) == len(mine)) + for i in range(len(yours)): + if self.TraceOn(): + print("yours[%d]='%s'" % (i, get_description(yours[i]))) + print("mine[%d]='%s'" % (i, get_description(mine[i]))) + self.assertTrue(yours[i] == mine[i], + "UUID+FileSpec of yours[{0}] and mine[{0}] matches".format(i)) + + @add_test_categories(['pyapi']) + def test_lldb_iter_breakpoint(self): + """Test breakpoint_iter works correctly for SBTarget -> SBBreakpoint.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line1) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line2) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + self.assertTrue(target.GetNumBreakpoints() == 2) + + from lldbsuite.test.lldbutil import get_description + yours = [] + for i in range(target.GetNumBreakpoints()): + yours.append(target.GetBreakpointAtIndex(i)) + mine = [] + for b in target.breakpoint_iter(): + mine.append(b) + + self.assertTrue(len(yours) == len(mine)) + for i in range(len(yours)): + if self.TraceOn(): + print("yours[%d]='%s'" % (i, get_description(yours[i]))) + print("mine[%d]='%s'" % (i, get_description(mine[i]))) + self.assertTrue(yours[i] == mine[i], + "ID of yours[{0}] and mine[{0}] matches".format(i)) + + @add_test_categories(['pyapi']) + def test_lldb_iter_frame(self): + """Test iterator works correctly for SBProcess->SBThread->SBFrame.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line1) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.LaunchProcess() failed") + + from lldbsuite.test.lldbutil import print_stacktrace + stopped_due_to_breakpoint = False + for thread in process: + if self.TraceOn(): + print_stacktrace(thread) + ID = thread.GetThreadID() + if thread.GetStopReason() == lldb.eStopReasonBreakpoint: + stopped_due_to_breakpoint = True + for frame in thread: + self.assertTrue(frame.GetThread().GetThreadID() == ID) + if self.TraceOn(): + print(frame) + + self.assertTrue(stopped_due_to_breakpoint) diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestRegistersIterator.py b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestRegistersIterator.py new file mode 100644 index 0000000..1645ae1 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestRegistersIterator.py @@ -0,0 +1,94 @@ +""" +Test the iteration protocol for frame registers. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * + +class RegistersIteratorTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line1 = line_number('main.cpp', '// Set break point at this line.') + + @add_test_categories(['pyapi']) + @expectedFailureWindows # Test crashes + def test_iter_registers(self): + """Test iterator works correctly for lldbutil.iter_registers().""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line1) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.LaunchProcess() failed") + + import lldbsuite.test.lldbutil as lldbutil + for thread in process: + if thread.GetStopReason() == lldb.eStopReasonBreakpoint: + for frame in thread: + # Dump the registers of this frame using lldbutil.get_GPRs() and friends. + if self.TraceOn(): + print(frame) + + REGs = lldbutil.get_GPRs(frame) + num = len(REGs) + if self.TraceOn(): + print("\nNumber of general purpose registers: %d" % num) + for reg in REGs: + self.assertTrue(reg) + if self.TraceOn(): + print("%s => %s" % (reg.GetName(), reg.GetValue())) + + REGs = lldbutil.get_FPRs(frame) + num = len(REGs) + if self.TraceOn(): + print("\nNumber of floating point registers: %d" % num) + for reg in REGs: + self.assertTrue(reg) + if self.TraceOn(): + print("%s => %s" % (reg.GetName(), reg.GetValue())) + + REGs = lldbutil.get_ESRs(frame) + if self.platformIsDarwin(): + num = len(REGs) + if self.TraceOn(): + print("\nNumber of exception state registers: %d" % num) + for reg in REGs: + self.assertTrue(reg) + if self.TraceOn(): + print("%s => %s" % (reg.GetName(), reg.GetValue())) + else: + self.assertIsNone(REGs) + + # And these should also work. + for kind in ["General Purpose Registers", + "Floating Point Registers"]: + REGs = lldbutil.get_registers(frame, kind) + self.assertTrue(REGs) + + REGs = lldbutil.get_registers(frame, "Exception State Registers") + if self.platformIsDarwin(): + self.assertIsNotNone(REGs) + else: + self.assertIsNone(REGs) + + # We've finished dumping the registers for frame #0. + break diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/iter/main.cpp b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/main.cpp new file mode 100644 index 0000000..8fb45f9 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/iter/main.cpp @@ -0,0 +1,134 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C includes +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> + +// C++ includes +#include <chrono> +#include <mutex> +#include <random> +#include <thread> + +std::thread g_thread_1; +std::thread g_thread_2; +std::thread g_thread_3; +std::mutex g_mask_mutex; + +typedef enum { + eGet, + eAssign, + eClearBits +} MaskAction; + +uint32_t mask_access (MaskAction action, uint32_t mask = 0); + +uint32_t +mask_access (MaskAction action, uint32_t mask) +{ + static uint32_t g_mask = 0; + + std::lock_guard<std::mutex> lock(g_mask_mutex); + switch (action) + { + case eGet: + break; + + case eAssign: + g_mask |= mask; + break; + + case eClearBits: + g_mask &= ~mask; + break; + } + return g_mask; +} + +void * +thread_func (void *arg) +{ + uint32_t thread_index = *((uint32_t *)arg); + uint32_t thread_mask = (1u << (thread_index)); + printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); + + std::default_random_engine generator; + std::uniform_int_distribution<int> distribution(0, 3000000); + + while (mask_access(eGet) & thread_mask) + { + // random micro second sleep from zero to 3 seconds + int usec = distribution(generator); + printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); + + std::chrono::microseconds duration(usec); + std::this_thread::sleep_for(duration); + printf ("%s (thread = %u) after usleep ...\n", __FUNCTION__, thread_index); // Set break point at this line. + } + printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); + return NULL; +} + + +int main (int argc, char const *argv[]) +{ + uint32_t thread_index_1 = 1; + uint32_t thread_index_2 = 2; + uint32_t thread_index_3 = 3; + uint32_t thread_mask_1 = (1u << thread_index_1); + uint32_t thread_mask_2 = (1u << thread_index_2); + uint32_t thread_mask_3 = (1u << thread_index_3); + + // Make a mask that will keep all threads alive + mask_access (eAssign, thread_mask_1 | thread_mask_2 | thread_mask_3); // And that line. + + // Create 3 threads + g_thread_1 = std::thread(thread_func, (void*)&thread_index_1); + g_thread_2 = std::thread(thread_func, (void*)&thread_index_2); + g_thread_3 = std::thread(thread_func, (void*)&thread_index_3); + + char line[64]; + while (mask_access(eGet) != 0) + { + printf ("Enter thread index to kill or ENTER for all:\n"); + fflush (stdout); + // Kill threads by index, or ENTER for all threads + + if (fgets (line, sizeof(line), stdin)) + { + if (line[0] == '\n' || line[0] == '\r' || line[0] == '\0') + { + printf ("Exiting all threads...\n"); + break; + } + int32_t index = strtoul (line, NULL, 0); + switch (index) + { + case 1: mask_access (eClearBits, thread_mask_1); break; + case 2: mask_access (eClearBits, thread_mask_2); break; + case 3: mask_access (eClearBits, thread_mask_3); break; + } + continue; + } + + break; + } + + // Clear all thread bits to they all exit + mask_access (eClearBits, UINT32_MAX); + + // Join all of our threads + g_thread_1.join(); + g_thread_2.join(); + g_thread_3.join(); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/process/Makefile b/packages/Python/lldbsuite/test/python_api/lldbutil/process/Makefile new file mode 100644 index 0000000..93fc28b --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/process/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../../make + +CFLAGS_EXTRAS += -D__STDC_LIMIT_MACROS +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp +MAKE_DSYM :=NO + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/process/TestPrintStackTraces.py b/packages/Python/lldbsuite/test/python_api/lldbutil/process/TestPrintStackTraces.py new file mode 100644 index 0000000..b48ded4 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/process/TestPrintStackTraces.py @@ -0,0 +1,52 @@ +""" +Test SBprocess and SBThread APIs with printing of the stack traces using lldbutil. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * + +class ThreadsStackTracesTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// Set break point at this line.') + + @expectedFailureAll("llvm.org/pr23043", ["linux"], archs=["i386"]) # We are unable to produce a backtrace of the main thread when the thread is blocked in fgets + @expectedFailureWindows("llvm.org/pr24778") + @add_test_categories(['pyapi']) + def test_stack_traces(self): + """Test SBprocess and SBThread APIs with printing of the stack traces.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (["abc", "xyz"], None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.LaunchProcess() failed") + + import lldbsuite.test.lldbutil as lldbutil + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + stacktraces = lldbutil.print_stacktraces(process, string_buffer=True) + self.expect(stacktraces, exe=False, + substrs = ['(int)argc=3']) diff --git a/packages/Python/lldbsuite/test/python_api/lldbutil/process/main.cpp b/packages/Python/lldbsuite/test/python_api/lldbutil/process/main.cpp new file mode 100644 index 0000000..6b87c3d --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/lldbutil/process/main.cpp @@ -0,0 +1,136 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C includes +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> + +// C++ includes +#include <chrono> +#include <mutex> +#include <random> +#include <thread> + +std::thread g_thread_1; +std::thread g_thread_2; +std::thread g_thread_3; +std::mutex g_mask_mutex; + +typedef enum { + eGet, + eAssign, + eClearBits +} MaskAction; + +uint32_t mask_access (MaskAction action, uint32_t mask = 0); + +uint32_t +mask_access (MaskAction action, uint32_t mask) +{ + static uint32_t g_mask = 0; + + std::lock_guard<std::mutex> lock(g_mask_mutex); + switch (action) + { + case eGet: + break; + + case eAssign: + g_mask |= mask; + break; + + case eClearBits: + g_mask &= ~mask; + break; + } + return g_mask; +} + +void * +thread_func (void *arg) +{ + uint32_t thread_index = *((uint32_t *)arg); + uint32_t thread_mask = (1u << (thread_index)); + printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); + + std::default_random_engine generator; + std::uniform_int_distribution<int> distribution(0, 3000000); + + while (mask_access(eGet) & thread_mask) + { + // random micro second sleep from zero to 3 seconds + int usec = distribution(generator); + + printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); + std::chrono::microseconds duration(usec); + std::this_thread::sleep_for(duration); + printf ("%s (thread = %u) after usleep ...\n", __FUNCTION__, thread_index); // Set break point at this line. + } + printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); + return NULL; +} + + +int main (int argc, char const *argv[]) +{ + int err; + void *thread_result = NULL; + uint32_t thread_index_1 = 1; + uint32_t thread_index_2 = 2; + uint32_t thread_index_3 = 3; + uint32_t thread_mask_1 = (1u << thread_index_1); + uint32_t thread_mask_2 = (1u << thread_index_2); + uint32_t thread_mask_3 = (1u << thread_index_3); + + // Make a mask that will keep all threads alive + mask_access (eAssign, thread_mask_1 | thread_mask_2 | thread_mask_3); // And that line. + + // Create 3 threads + g_thread_1 = std::thread(thread_func, (void*)&thread_index_1); + g_thread_2 = std::thread(thread_func, (void*)&thread_index_2); + g_thread_3 = std::thread(thread_func, (void*)&thread_index_3); + + char line[64]; + while (mask_access(eGet) != 0) + { + printf ("Enter thread index to kill or ENTER for all:\n"); + fflush (stdout); + // Kill threads by index, or ENTER for all threads + + if (fgets (line, sizeof(line), stdin)) + { + if (line[0] == '\n' || line[0] == '\r' || line[0] == '\0') + { + printf ("Exiting all threads...\n"); + break; + } + int32_t index = strtoul (line, NULL, 0); + switch (index) + { + case 1: mask_access (eClearBits, thread_mask_1); break; + case 2: mask_access (eClearBits, thread_mask_2); break; + case 3: mask_access (eClearBits, thread_mask_3); break; + } + continue; + } + + break; + } + + // Clear all thread bits to they all exit + mask_access (eClearBits, UINT32_MAX); + + // Join all of our threads + g_thread_1.join(); + g_thread_2.join(); + g_thread_3.join(); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/module_section/Makefile b/packages/Python/lldbsuite/test/python_api/module_section/Makefile new file mode 100644 index 0000000..ee74eba --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/module_section/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../make + +CFLAGS_EXTRAS += -D__STDC_LIMIT_MACROS +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp b.cpp c.cpp +MAKE_DSYM :=NO + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/module_section/TestModuleAndSection.py b/packages/Python/lldbsuite/test/python_api/module_section/TestModuleAndSection.py new file mode 100644 index 0000000..bc97d43 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/module_section/TestModuleAndSection.py @@ -0,0 +1,127 @@ +""" +Test some SBModule and SBSection APIs. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.lldbutil import symbol_type_to_str + +class ModuleAndSectionAPIsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + def test_module_and_section(self): + """Test module and section APIs.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + self.assertTrue(target.GetNumModules() > 0) + + # Hide stdout if not running with '-t' option. + if not self.TraceOn(): + self.HideStdout() + + print("Number of modules for the target: %d" % target.GetNumModules()) + for module in target.module_iter(): + print(module) + + # Get the executable module at index 0. + exe_module = target.GetModuleAtIndex(0) + + print("Exe module: %s" % str(exe_module)) + print("Number of sections: %d" % exe_module.GetNumSections()) + INDENT = ' ' * 4 + INDENT2 = INDENT * 2 + for sec in exe_module.section_iter(): + print(sec) + print(INDENT + "Number of subsections: %d" % sec.GetNumSubSections()) + if sec.GetNumSubSections() == 0: + for sym in exe_module.symbol_in_section_iter(sec): + print(INDENT + str(sym)) + print(INDENT + "symbol type: %s" % symbol_type_to_str(sym.GetType())) + else: + for subsec in sec: + print(INDENT + str(subsec)) + # Now print the symbols belonging to the subsection.... + for sym in exe_module.symbol_in_section_iter(subsec): + print(INDENT2 + str(sym)) + print(INDENT2 + "symbol type: %s" % symbol_type_to_str(sym.GetType())) + + @add_test_categories(['pyapi']) + def test_module_and_section_boundary_condition(self): + """Test module and section APIs by passing None when it expects a Python string.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + self.assertTrue(target.GetNumModules() > 0) + + # Hide stdout if not running with '-t' option. + if not self.TraceOn(): + self.HideStdout() + + print("Number of modules for the target: %d" % target.GetNumModules()) + for module in target.module_iter(): + print(module) + + # Get the executable module at index 0. + exe_module = target.GetModuleAtIndex(0) + + print("Exe module: %s" % str(exe_module)) + print("Number of sections: %d" % exe_module.GetNumSections()) + + # Boundary condition testings. Should not crash lldb! + exe_module.FindFirstType(None) + exe_module.FindTypes(None) + exe_module.FindGlobalVariables(target, None, 1) + exe_module.FindFunctions(None, 0) + exe_module.FindSection(None) + + # Get the section at index 1. + if exe_module.GetNumSections() > 1: + sec1 = exe_module.GetSectionAtIndex(1) + print(sec1) + else: + sec1 = None + + if sec1: + sec1.FindSubSection(None) + + @add_test_categories(['pyapi']) + def test_module_compile_unit_iter(self): + """Test module's compile unit iterator APIs.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + self.assertTrue(target.GetNumModules() > 0) + + # Hide stdout if not running with '-t' option. + if not self.TraceOn(): + self.HideStdout() + + print("Number of modules for the target: %d" % target.GetNumModules()) + for module in target.module_iter(): + print(module) + + # Get the executable module at index 0. + exe_module = target.GetModuleAtIndex(0) + + print("Exe module: %s" % str(exe_module)) + print("Number of compile units: %d" % exe_module.GetNumCompileUnits()) + INDENT = ' ' * 4 + INDENT2 = INDENT * 2 + for cu in exe_module.compile_unit_iter(): + print(cu) + diff --git a/packages/Python/lldbsuite/test/python_api/module_section/b.cpp b/packages/Python/lldbsuite/test/python_api/module_section/b.cpp new file mode 100644 index 0000000..4e3e541 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/module_section/b.cpp @@ -0,0 +1,3 @@ +int b_function(int input) { + return input * 2; +} diff --git a/packages/Python/lldbsuite/test/python_api/module_section/c.cpp b/packages/Python/lldbsuite/test/python_api/module_section/c.cpp new file mode 100644 index 0000000..3c87bfe --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/module_section/c.cpp @@ -0,0 +1,3 @@ +int c_function(int input) { + return input * 3; +} diff --git a/packages/Python/lldbsuite/test/python_api/module_section/main.cpp b/packages/Python/lldbsuite/test/python_api/module_section/main.cpp new file mode 100644 index 0000000..6b87c3d --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/module_section/main.cpp @@ -0,0 +1,136 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C includes +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> + +// C++ includes +#include <chrono> +#include <mutex> +#include <random> +#include <thread> + +std::thread g_thread_1; +std::thread g_thread_2; +std::thread g_thread_3; +std::mutex g_mask_mutex; + +typedef enum { + eGet, + eAssign, + eClearBits +} MaskAction; + +uint32_t mask_access (MaskAction action, uint32_t mask = 0); + +uint32_t +mask_access (MaskAction action, uint32_t mask) +{ + static uint32_t g_mask = 0; + + std::lock_guard<std::mutex> lock(g_mask_mutex); + switch (action) + { + case eGet: + break; + + case eAssign: + g_mask |= mask; + break; + + case eClearBits: + g_mask &= ~mask; + break; + } + return g_mask; +} + +void * +thread_func (void *arg) +{ + uint32_t thread_index = *((uint32_t *)arg); + uint32_t thread_mask = (1u << (thread_index)); + printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); + + std::default_random_engine generator; + std::uniform_int_distribution<int> distribution(0, 3000000); + + while (mask_access(eGet) & thread_mask) + { + // random micro second sleep from zero to 3 seconds + int usec = distribution(generator); + + printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); + std::chrono::microseconds duration(usec); + std::this_thread::sleep_for(duration); + printf ("%s (thread = %u) after usleep ...\n", __FUNCTION__, thread_index); // Set break point at this line. + } + printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); + return NULL; +} + + +int main (int argc, char const *argv[]) +{ + int err; + void *thread_result = NULL; + uint32_t thread_index_1 = 1; + uint32_t thread_index_2 = 2; + uint32_t thread_index_3 = 3; + uint32_t thread_mask_1 = (1u << thread_index_1); + uint32_t thread_mask_2 = (1u << thread_index_2); + uint32_t thread_mask_3 = (1u << thread_index_3); + + // Make a mask that will keep all threads alive + mask_access (eAssign, thread_mask_1 | thread_mask_2 | thread_mask_3); // And that line. + + // Create 3 threads + g_thread_1 = std::thread(thread_func, (void*)&thread_index_1); + g_thread_2 = std::thread(thread_func, (void*)&thread_index_2); + g_thread_3 = std::thread(thread_func, (void*)&thread_index_3); + + char line[64]; + while (mask_access(eGet) != 0) + { + printf ("Enter thread index to kill or ENTER for all:\n"); + fflush (stdout); + // Kill threads by index, or ENTER for all threads + + if (fgets (line, sizeof(line), stdin)) + { + if (line[0] == '\n' || line[0] == '\r' || line[0] == '\0') + { + printf ("Exiting all threads...\n"); + break; + } + int32_t index = strtoul (line, NULL, 0); + switch (index) + { + case 1: mask_access (eClearBits, thread_mask_1); break; + case 2: mask_access (eClearBits, thread_mask_2); break; + case 3: mask_access (eClearBits, thread_mask_3); break; + } + continue; + } + + break; + } + + // Clear all thread bits to they all exit + mask_access (eClearBits, UINT32_MAX); + + // Join all of our threads + g_thread_1.join(); + g_thread_2.join(); + g_thread_3.join(); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/objc_type/Makefile b/packages/Python/lldbsuite/test/python_api/objc_type/Makefile new file mode 100644 index 0000000..31e57fe --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/objc_type/Makefile @@ -0,0 +1,9 @@ +LEVEL = ../../make + +OBJC_SOURCES := main.m + +CFLAGS_EXTRAS += -w + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/packages/Python/lldbsuite/test/python_api/objc_type/TestObjCType.py b/packages/Python/lldbsuite/test/python_api/objc_type/TestObjCType.py new file mode 100644 index 0000000..e9b29b9 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/objc_type/TestObjCType.py @@ -0,0 +1,64 @@ +""" +Test SBType for ObjC classes. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ObjCSBTypeTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + self.line = line_number("main.m", '// Break at this line') + + @skipUnlessDarwin + @add_test_categories(['pyapi']) + def test(self): + """Test SBType for ObjC classes.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint inside function 'main'. + breakpoint = target.BreakpointCreateByLocation("main.m", self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + + + # Get Frame #0. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + + aBar = self.frame().FindVariable("aBar") + aBarType = aBar.GetType() + self.assertTrue(aBarType.IsValid(), "Bar should be a valid data type") + self.assertTrue(aBarType.GetName() == "Bar *", "Bar has the right name") + + self.assertTrue(aBarType.GetNumberOfDirectBaseClasses() == 1, "Bar has a superclass") + aFooType = aBarType.GetDirectBaseClassAtIndex(0) + + self.assertTrue(aFooType.IsValid(), "Foo should be a valid data type") + self.assertTrue(aFooType.GetName() == "Foo", "Foo has the right name") + + self.assertTrue(aBarType.GetNumberOfFields() == 1, "Bar has a field") + aBarField = aBarType.GetFieldAtIndex(0) + + self.assertTrue(aBarField.GetName() == "_iVar", "The field has the right name") diff --git a/packages/Python/lldbsuite/test/python_api/objc_type/main.m b/packages/Python/lldbsuite/test/python_api/objc_type/main.m new file mode 100644 index 0000000..6ae54ad --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/objc_type/main.m @@ -0,0 +1,52 @@ +//===-- main.m ------------------------------------------------*- ObjC -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#import <Foundation/Foundation.h> + +@interface Foo: NSObject +{} +- (id) init; +@end + +@interface Bar: Foo +{ + int _iVar; +} +- (id) init; +@end + +@implementation Foo + +- (id) init +{ + self = [super init]; + return self; +} + +@end + +@implementation Bar + +- (id) init +{ + self = [super init]; + if (self) + self->_iVar = 5; + return self; +} + +@end + +int main() +{ + Bar* aBar = [Bar new]; + id nothing = [aBar noSuchSelector]; // Break at this line + return 0; +} + diff --git a/packages/Python/lldbsuite/test/python_api/process/Makefile b/packages/Python/lldbsuite/test/python_api/process/Makefile new file mode 100644 index 0000000..8a7102e --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/process/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py b/packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py new file mode 100644 index 0000000..f312bc8 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/process/TestProcessAPI.py @@ -0,0 +1,289 @@ +""" +Test SBProcess APIs, including ReadMemory(), WriteMemory(), and others. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbutil import get_stopped_thread, state_type_to_str +from lldbsuite.test.lldbtest import * + +class ProcessAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number("main.cpp", "// Set break point at this line and check variable 'my_char'.") + + @add_test_categories(['pyapi']) + def test_read_memory(self): + """Test Python SBProcess.ReadMemory() API.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") + frame = thread.GetFrameAtIndex(0) + + # Get the SBValue for the global variable 'my_char'. + val = frame.FindValue("my_char", lldb.eValueTypeVariableGlobal) + self.DebugSBValue(val) + + # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and + # expect to get a Python string as the result object! + error = lldb.SBError() + self.assertFalse(val.TypeIsPointerType()) + content = process.ReadMemory(val.AddressOf().GetValueAsUnsigned(), 1, error) + if not error.Success(): + self.fail("SBProcess.ReadMemory() failed") + if self.TraceOn(): + print("memory content:", content) + + self.expect(content, "Result from SBProcess.ReadMemory() matches our expected output: 'x'", + exe=False, + startstr = 'x') + + # Read (char *)my_char_ptr. + val = frame.FindValue("my_char_ptr", lldb.eValueTypeVariableGlobal) + self.DebugSBValue(val) + cstring = process.ReadCStringFromMemory(val.GetValueAsUnsigned(), 256, error) + if not error.Success(): + self.fail("SBProcess.ReadCStringFromMemory() failed") + if self.TraceOn(): + print("cstring read is:", cstring) + + self.expect(cstring, "Result from SBProcess.ReadCStringFromMemory() matches our expected output", + exe=False, + startstr = 'Does it work?') + + # Get the SBValue for the global variable 'my_cstring'. + val = frame.FindValue("my_cstring", lldb.eValueTypeVariableGlobal) + self.DebugSBValue(val) + + # Due to the typemap magic (see lldb.swig), we pass in 256 to read at most 256 bytes + # from the address, and expect to get a Python string as the result object! + self.assertFalse(val.TypeIsPointerType()) + cstring = process.ReadCStringFromMemory(val.AddressOf().GetValueAsUnsigned(), 256, error) + if not error.Success(): + self.fail("SBProcess.ReadCStringFromMemory() failed") + if self.TraceOn(): + print("cstring read is:", cstring) + + self.expect(cstring, "Result from SBProcess.ReadCStringFromMemory() matches our expected output", + exe=False, + startstr = 'lldb.SBProcess.ReadCStringFromMemory() works!') + + # Get the SBValue for the global variable 'my_uint32'. + val = frame.FindValue("my_uint32", lldb.eValueTypeVariableGlobal) + self.DebugSBValue(val) + + # Due to the typemap magic (see lldb.swig), we pass in 4 to read 4 bytes + # from the address, and expect to get an int as the result! + self.assertFalse(val.TypeIsPointerType()) + my_uint32 = process.ReadUnsignedFromMemory(val.AddressOf().GetValueAsUnsigned(), 4, error) + if not error.Success(): + self.fail("SBProcess.ReadCStringFromMemory() failed") + if self.TraceOn(): + print("uint32 read is:", my_uint32) + + if my_uint32 != 12345: + self.fail("Result from SBProcess.ReadUnsignedFromMemory() does not match our expected output") + + @add_test_categories(['pyapi']) + def test_write_memory(self): + """Test Python SBProcess.WriteMemory() API.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") + frame = thread.GetFrameAtIndex(0) + + # Get the SBValue for the global variable 'my_char'. + val = frame.FindValue("my_char", lldb.eValueTypeVariableGlobal) + self.DebugSBValue(val) + + # If the variable does not have a load address, there's no sense continuing. + if not val.GetLocation().startswith("0x"): + return + + # OK, let's get the hex location of the variable. + location = int(val.GetLocation(), 16) + + # The program logic makes the 'my_char' variable to have memory content as 'x'. + # But we want to use the WriteMemory() API to assign 'a' to the variable. + + # Now use WriteMemory() API to write 'a' into the global variable. + error = lldb.SBError() + result = process.WriteMemory(location, 'a', error) + if not error.Success() or result != 1: + self.fail("SBProcess.WriteMemory() failed") + + # Read from the memory location. This time it should be 'a'. + # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and + # expect to get a Python string as the result object! + content = process.ReadMemory(location, 1, error) + if not error.Success(): + self.fail("SBProcess.ReadMemory() failed") + if self.TraceOn(): + print("memory content:", content) + + self.expect(content, "Result from SBProcess.ReadMemory() matches our expected output: 'a'", + exe=False, + startstr = 'a') + + @add_test_categories(['pyapi']) + def test_access_my_int(self): + """Test access 'my_int' using Python SBProcess.GetByteOrder() and other APIs.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") + frame = thread.GetFrameAtIndex(0) + + # Get the SBValue for the global variable 'my_int'. + val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal) + self.DebugSBValue(val) + + # If the variable does not have a load address, there's no sense continuing. + if not val.GetLocation().startswith("0x"): + return + + # OK, let's get the hex location of the variable. + location = int(val.GetLocation(), 16) + + # Note that the canonical from of the bytearray is little endian. + from lldbsuite.test.lldbutil import int_to_bytearray, bytearray_to_int + + byteSize = val.GetByteSize() + bytes = int_to_bytearray(256, byteSize) + + byteOrder = process.GetByteOrder() + if byteOrder == lldb.eByteOrderBig: + bytes.reverse() + elif byteOrder == lldb.eByteOrderLittle: + pass + else: + # Neither big endian nor little endian? Return for now. + # Add more logic here if we want to handle other types. + return + + # The program logic makes the 'my_int' variable to have int type and value of 0. + # But we want to use the WriteMemory() API to assign 256 to the variable. + + # Now use WriteMemory() API to write 256 into the global variable. + new_value = str(bytes) + error = lldb.SBError() + result = process.WriteMemory(location, new_value, error) + if not error.Success() or result != byteSize: + self.fail("SBProcess.WriteMemory() failed") + + # Make sure that the val we got originally updates itself to notice the change: + self.expect(val.GetValue(), + "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'", + exe=False, + startstr = '256') + + # And for grins, get the SBValue for the global variable 'my_int' again, to make sure that also tracks the new value: + val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal) + self.expect(val.GetValue(), + "SBProcess.ReadMemory() successfully writes (int)256 to the memory location for 'my_int'", + exe=False, + startstr = '256') + + # Now read the memory content. The bytearray should have (byte)1 as the second element. + content = process.ReadMemory(location, byteSize, error) + if not error.Success(): + self.fail("SBProcess.ReadMemory() failed") + + # Use "ascii" as the encoding because each element of 'content' is in the range [0..255]. + new_bytes = bytearray(content, "ascii") + + # The bytearray_to_int utility function expects a little endian bytearray. + if byteOrder == lldb.eByteOrderBig: + new_bytes.reverse() + + new_value = bytearray_to_int(new_bytes, byteSize) + if new_value != 256: + self.fail("Memory content read from 'my_int' does not match (int)256") + + # Dump the memory content.... + if self.TraceOn(): + for i in new_bytes: + print("byte:", i) + + @add_test_categories(['pyapi']) + def test_remote_launch(self): + """Test SBProcess.RemoteLaunch() API with a process not in eStateConnected, and it should fail.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + if self.TraceOn(): + print("process state:", state_type_to_str(process.GetState())) + self.assertTrue(process.GetState() != lldb.eStateConnected) + + error = lldb.SBError() + success = process.RemoteLaunch(None, None, None, None, None, None, 0, False, error) + self.assertTrue(not success, "RemoteLaunch() should fail for process state != eStateConnected") + + @add_test_categories(['pyapi']) + def test_get_num_supported_hardware_watchpoints(self): + """Test SBProcess.GetNumSupportedHardwareWatchpoints() API with a process.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + error = lldb.SBError(); + num = process.GetNumSupportedHardwareWatchpoints(error) + if self.TraceOn() and error.Success(): + print("Number of supported hardware watchpoints: %d" % num) + diff --git a/packages/Python/lldbsuite/test/python_api/process/io/Makefile b/packages/Python/lldbsuite/test/python_api/process/io/Makefile new file mode 100644 index 0000000..5361f2a --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/process/io/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +C_SOURCES := main.c +EXE := process_io + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/process/io/TestProcessIO.py b/packages/Python/lldbsuite/test/python_api/process/io/TestProcessIO.py new file mode 100644 index 0000000..2944ee7 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/process/io/TestProcessIO.py @@ -0,0 +1,206 @@ +"""Test Python APIs for process IO.""" + +from __future__ import print_function + + + +import os, sys, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class ProcessIOTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Get the full path to our executable to be debugged. + self.exe = os.path.join(os.getcwd(), "process_io") + self.local_input_file = os.path.join(os.getcwd(), "input.txt") + self.local_output_file = os.path.join(os.getcwd(), "output.txt") + self.local_error_file = os.path.join(os.getcwd(), "error.txt") + + self.input_file = os.path.join(self.get_process_working_directory(), "input.txt") + self.output_file = os.path.join(self.get_process_working_directory(), "output.txt") + self.error_file = os.path.join(self.get_process_working_directory(), "error.txt") + self.lines = ["Line 1", "Line 2", "Line 3"] + + @skipIfWindows # stdio manipulation unsupported on Windows + @add_test_categories(['pyapi']) + def test_stdin_by_api(self): + """Exercise SBProcess.PutSTDIN().""" + self.build() + self.create_target() + self.run_process(True) + output = self.process.GetSTDOUT(1000) + self.check_process_output(output, output) + + @skipIfWindows # stdio manipulation unsupported on Windows + @add_test_categories(['pyapi']) + def test_stdin_redirection(self): + """Exercise SBLaunchInfo::AddOpenFileAction() for STDIN without specifying STDOUT or STDERR.""" + self.build() + self.create_target() + self.redirect_stdin() + self.run_process(False) + output = self.process.GetSTDOUT(1000) + self.check_process_output(output, output) + + @skipIfWindows # stdio manipulation unsupported on Windows + @add_test_categories(['pyapi']) + def test_stdout_redirection(self): + """Exercise SBLaunchInfo::AddOpenFileAction() for STDOUT without specifying STDIN or STDERR.""" + self.build() + self.create_target() + self.redirect_stdout() + self.run_process(True) + output = self.read_output_file_and_delete() + error = self.process.GetSTDOUT(1000) + self.check_process_output(output, error) + + @skipIfWindows # stdio manipulation unsupported on Windows + @add_test_categories(['pyapi']) + def test_stderr_redirection(self): + """Exercise SBLaunchInfo::AddOpenFileAction() for STDERR without specifying STDIN or STDOUT.""" + self.build() + self.create_target() + self.redirect_stderr() + self.run_process(True) + output = self.process.GetSTDOUT(1000) + error = self.read_error_file_and_delete() + self.check_process_output(output, error) + + @skipIfWindows # stdio manipulation unsupported on Windows + @add_test_categories(['pyapi']) + def test_stdout_stderr_redirection(self): + """Exercise SBLaunchInfo::AddOpenFileAction() for STDOUT and STDERR without redirecting STDIN.""" + self.build() + self.create_target() + self.redirect_stdout() + self.redirect_stderr() + self.run_process(True) + output = self.read_output_file_and_delete() + error = self.read_error_file_and_delete() + self.check_process_output(output, error) + + # target_file - path on local file system or remote file system if running remote + # local_file - path on local system + def read_file_and_delete(self, target_file, local_file): + if lldb.remote_platform: + self.runCmd('platform get-file "{remote}" "{local}"'.format( + remote=target_file, local=local_file)) + + self.assertTrue(os.path.exists(local_file), 'Make sure "{local}" file exists'.format(local=local_file)) + f = open(local_file, 'r') + contents = f.read() + f.close() + + #TODO: add 'platform delete-file' file command + #if lldb.remote_platform: + # self.runCmd('platform delete-file "{remote}"'.format(remote=target_file)) + os.unlink(local_file) + return contents + + def read_output_file_and_delete(self): + return self.read_file_and_delete(self.output_file, self.local_output_file) + + def read_error_file_and_delete(self): + return self.read_file_and_delete(self.error_file, self.local_error_file) + + def create_target(self): + '''Create the target and launch info that will be used by all tests''' + self.target = self.dbg.CreateTarget(self.exe) + self.launch_info = lldb.SBLaunchInfo([self.exe]) + self.launch_info.SetWorkingDirectory(self.get_process_working_directory()) + + def redirect_stdin(self): + '''Redirect STDIN (file descriptor 0) to use our input.txt file + + Make the input.txt file to use when redirecting STDIN, setup a cleanup action + to delete the input.txt at the end of the test in case exceptions are thrown, + and redirect STDIN in the launch info.''' + f = open(self.local_input_file, 'w') + for line in self.lines: + f.write(line + "\n") + f.close() + + if lldb.remote_platform: + self.runCmd('platform put-file "{local}" "{remote}"'.format( + local=self.local_input_file, remote=self.input_file)) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + os.unlink(self.local_input_file) + #TODO: add 'platform delete-file' file command + #if lldb.remote_platform: + # self.runCmd('platform delete-file "{remote}"'.format(remote=self.input_file)) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + self.launch_info.AddOpenFileAction(0, self.input_file, True, False); + + def redirect_stdout(self): + '''Redirect STDOUT (file descriptor 1) to use our output.txt file''' + self.launch_info.AddOpenFileAction(1, self.output_file, False, True); + + def redirect_stderr(self): + '''Redirect STDERR (file descriptor 2) to use our error.txt file''' + self.launch_info.AddOpenFileAction(2, self.error_file, False, True); + + def run_process(self, put_stdin): + '''Run the process to completion and optionally put lines to STDIN via the API if "put_stdin" is True''' + # Set the breakpoints + self.breakpoint = self.target.BreakpointCreateBySourceRegex('Set breakpoint here', lldb.SBFileSpec("main.c")) + self.assertTrue(self.breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + error = lldb.SBError() + # This should launch the process and it should exit by the time we get back + # because we have synchronous mode enabled + self.process = self.target.Launch (self.launch_info, error) + + self.assertTrue(error.Success(), "Make sure process launched successfully") + self.assertTrue(self.process, PROCESS_IS_VALID) + + if self.TraceOn(): + print("process launched.") + + # Frame #0 should be at our breakpoint. + threads = lldbutil.get_threads_stopped_at_breakpoint (self.process, self.breakpoint) + + self.assertTrue(len(threads) == 1) + self.thread = threads[0] + self.frame = self.thread.frames[0] + self.assertTrue(self.frame, "Frame 0 is valid.") + + if self.TraceOn(): + print("process stopped at breakpoint, sending STDIN via LLDB API.") + + # Write data to stdin via the public API if we were asked to + if put_stdin: + for line in self.lines: + self.process.PutSTDIN(line + "\n") + + # Let process continue so it will exit + self.process.Continue() + state = self.process.GetState() + self.assertTrue(state == lldb.eStateExited, PROCESS_IS_VALID) + + def check_process_output (self, output, error): + # Since we launched the process without specifying stdin/out/err, + # a pseudo terminal is used for stdout/err, and we are satisfied + # once "input line=>1" appears in stdout. + # See also main.c. + if self.TraceOn(): + print("output = '%s'" % output) + print("error = '%s'" % error) + + for line in self.lines: + check_line = 'input line to stdout: %s' % (line) + self.assertTrue(check_line in output, "verify stdout line shows up in STDOUT") + for line in self.lines: + check_line = 'input line to stderr: %s' % (line) + self.assertTrue(check_line in error, "verify stderr line shows up in STDERR") diff --git a/packages/Python/lldbsuite/test/python_api/process/io/main.c b/packages/Python/lldbsuite/test/python_api/process/io/main.c new file mode 100644 index 0000000..c9a5707 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/process/io/main.c @@ -0,0 +1,19 @@ +#include <stdio.h> + +int main(int argc, char const *argv[]) { + printf("Hello world.\n"); // Set breakpoint here + char line[100]; + if (fgets(line, sizeof(line), stdin)) { + fprintf(stdout, "input line to stdout: %s", line); + fprintf(stderr, "input line to stderr: %s", line); + } + if (fgets(line, sizeof(line), stdin)) { + fprintf(stdout, "input line to stdout: %s", line); + fprintf(stderr, "input line to stderr: %s", line); + } + if (fgets(line, sizeof(line), stdin)) { + fprintf(stdout, "input line to stdout: %s", line); + fprintf(stderr, "input line to stderr: %s", line); + } + printf("Exiting now\n"); +} diff --git a/packages/Python/lldbsuite/test/python_api/process/main.cpp b/packages/Python/lldbsuite/test/python_api/process/main.cpp new file mode 100644 index 0000000..9610936 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/process/main.cpp @@ -0,0 +1,31 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdint.h> + +// This simple program is to test the lldb Python API related to process. + +char my_char = 'u'; +char my_cstring[] = "lldb.SBProcess.ReadCStringFromMemory() works!"; +char *my_char_ptr = (char *)"Does it work?"; +uint32_t my_uint32 = 12345; +int my_int = 0; + +int main (int argc, char const *argv[]) +{ + for (int i = 0; i < 3; ++i) { + printf("my_char='%c'\n", my_char); + ++my_char; + } + + printf("after the loop: my_char='%c'\n", my_char); // 'my_char' should print out as 'x'. + + return 0; // Set break point at this line and check variable 'my_char'. + // Use lldb Python API to set memory content for my_int and check the result. +} diff --git a/packages/Python/lldbsuite/test/python_api/rdar-12481949/Makefile b/packages/Python/lldbsuite/test/python_api/rdar-12481949/Makefile new file mode 100644 index 0000000..8a7102e --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/rdar-12481949/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/rdar-12481949/Test-rdar-12481949.py b/packages/Python/lldbsuite/test/python_api/rdar-12481949/Test-rdar-12481949.py new file mode 100644 index 0000000..f56fd96 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/rdar-12481949/Test-rdar-12481949.py @@ -0,0 +1,54 @@ +""" +Check that SBValue.GetValueAsSigned() does the right thing for a 32-bit -1. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class Radar12481949DataFormatterTestCase(TestBase): + + # test for rdar://problem/12481949 + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def test_with_run_command(self): + """Check that SBValue.GetValueAsSigned() does the right thing for a 32-bit -1.""" + self.build() + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format delete hex', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.assertTrue(self.frame().FindVariable("myvar").GetValueAsSigned() == -1, "GetValueAsSigned() says -1") + self.assertTrue(self.frame().FindVariable("myvar").GetValueAsSigned() != 0xFFFFFFFF, "GetValueAsSigned() does not say 0xFFFFFFFF") + self.assertTrue(self.frame().FindVariable("myvar").GetValueAsSigned() != 0xFFFFFFFFFFFFFFFF, "GetValueAsSigned() does not say 0xFFFFFFFFFFFFFFFF") + + self.assertTrue(self.frame().FindVariable("myvar").GetValueAsUnsigned() != -1, "GetValueAsUnsigned() does not say -1") + self.assertTrue(self.frame().FindVariable("myvar").GetValueAsUnsigned() == 0xFFFFFFFF, "GetValueAsUnsigned() says 0xFFFFFFFF") + self.assertTrue(self.frame().FindVariable("myvar").GetValueAsUnsigned() != 0xFFFFFFFFFFFFFFFF, "GetValueAsUnsigned() does not says 0xFFFFFFFFFFFFFFFF") diff --git a/packages/Python/lldbsuite/test/python_api/rdar-12481949/main.cpp b/packages/Python/lldbsuite/test/python_api/rdar-12481949/main.cpp new file mode 100644 index 0000000..e8ebf36 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/rdar-12481949/main.cpp @@ -0,0 +1,17 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdint.h> +int main () +{ + int32_t myvar = -1; + printf ("%d\n", myvar); // Set break point at this line. + return myvar+1; +} diff --git a/packages/Python/lldbsuite/test/python_api/sbdata/Makefile b/packages/Python/lldbsuite/test/python_api/sbdata/Makefile new file mode 100644 index 0000000..8a7102e --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbdata/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/sbdata/TestSBData.py b/packages/Python/lldbsuite/test/python_api/sbdata/TestSBData.py new file mode 100644 index 0000000..2ff516e --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbdata/TestSBData.py @@ -0,0 +1,348 @@ +"""Test the SBData APIs.""" + +from __future__ import print_function + + + +import os +import lldb +from lldbsuite.test.lldbtest import * +from math import fabs +import lldbsuite.test.lldbutil as lldbutil + +class SBDataAPICase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break on inside main.cpp. + self.line = line_number('main.cpp', '// set breakpoint here') + + @add_test_categories(['pyapi']) + def test_with_run_command(self): + """Test the SBData APIs.""" + self.build() + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + target = self.dbg.GetSelectedTarget() + + process = target.GetProcess() + + thread = process.GetThreadAtIndex(0) + + frame = thread.GetSelectedFrame() + if self.TraceOn(): + print(frame) + foobar = frame.FindVariable('foobar') + self.assertTrue(foobar.IsValid()) + if self.TraceOn(): + print(foobar) + + data = foobar.GetPointeeData(0, 2) + + if self.TraceOn(): + print(data) + + offset = 0 + error = lldb.SBError() + + self.assert_data(data.GetUnsignedInt32, offset, 1) + offset += 4 + low = data.GetSignedInt16(error, offset) + self.assertTrue(error.Success()) + offset += 2 + high = data.GetSignedInt16(error, offset) + self.assertTrue(error.Success()) + offset += 2 + self.assertTrue ((low == 9 and high == 0) or (low == 0 and high == 9), 'foo[0].b == 9') + self.assertTrue( fabs(data.GetFloat(error, offset) - 3.14) < 1, 'foo[0].c == 3.14') + self.assertTrue(error.Success()) + offset += 4 + self.assert_data(data.GetUnsignedInt32, offset, 8) + offset += 4 + self.assert_data(data.GetUnsignedInt32, offset, 5) + offset += 4 + + self.runCmd("n") + + offset = 16 + + self.assert_data(data.GetUnsignedInt32, offset, 5) + + data = foobar.GetPointeeData(1, 1) + + offset = 0 + + self.assert_data(data.GetSignedInt32, offset, 8) + offset += 4 + self.assert_data(data.GetSignedInt32, offset, 7) + offset += 8 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 0, 'do not read beyond end') + self.assertTrue(not error.Success()) + error.Clear() # clear the error for the next test + + star_foobar = foobar.Dereference() + self.assertTrue(star_foobar.IsValid()) + + data = star_foobar.GetData() + + if self.TraceOn(): + print(data) + + offset = 0 + self.assert_data(data.GetUnsignedInt32, offset, 1) + offset += 4 + self.assert_data(data.GetUnsignedInt32, offset, 9) + + foobar_addr = star_foobar.GetLoadAddress() + foobar_addr += 12 + + # http://llvm.org/bugs/show_bug.cgi?id=11579 + # lldb::SBValue::CreateValueFromAddress does not verify SBType::GetPointerType succeeds + # This should not crash LLDB. + nothing = foobar.CreateValueFromAddress("nothing", foobar_addr, star_foobar.GetType().GetBasicType(lldb.eBasicTypeInvalid)) + + new_foobar = foobar.CreateValueFromAddress("f00", foobar_addr, star_foobar.GetType()) + self.assertTrue(new_foobar.IsValid()) + if self.TraceOn(): + print(new_foobar) + + data = new_foobar.GetData() + + if self.TraceOn(): + print(data) + + self.assertTrue(data.uint32[0] == 8, 'then foo[1].a == 8') + self.assertTrue(data.uint32[1] == 7, 'then foo[1].b == 7') + self.assertTrue(fabs(data.float[2] - 3.14) < 1, 'foo[1].c == 3.14') # exploiting that sizeof(uint32) == sizeof(float) + + self.runCmd("n") + + offset = 0 + self.assert_data(data.GetUnsignedInt32, offset, 8) + offset += 4 + self.assert_data(data.GetUnsignedInt32, offset, 7) + offset += 4 + self.assertTrue(fabs(data.GetFloat(error, offset) - 3.14) < 1, 'foo[1].c == 3.14') + self.assertTrue(error.Success()) + + data = new_foobar.GetData() + + if self.TraceOn(): + print(data) + + offset = 0 + self.assert_data(data.GetUnsignedInt32, offset, 8) + offset += 4 + self.assert_data(data.GetUnsignedInt32, offset, 7) + offset += 4 + self.assertTrue(fabs(data.GetFloat(error, offset) - 6.28) < 1, 'foo[1].c == 6.28') + self.assertTrue(error.Success()) + + self.runCmd("n") + + barfoo = frame.FindVariable('barfoo') + + data = barfoo.GetData() + + if self.TraceOn(): + print(barfoo) + + if self.TraceOn(): + print(data) + + offset = 0 + self.assert_data(data.GetUnsignedInt32, offset, 1) + offset += 4 + self.assert_data(data.GetUnsignedInt32, offset, 2) + offset += 4 + self.assertTrue(fabs(data.GetFloat(error, offset) - 3) < 1, 'barfoo[0].c == 3') + self.assertTrue(error.Success()) + offset += 4 + self.assert_data(data.GetUnsignedInt32, offset, 4) + offset += 4 + self.assert_data(data.GetUnsignedInt32, offset, 5) + offset += 4 + self.assertTrue(fabs(data.GetFloat(error, offset) - 6) < 1, 'barfoo[1].c == 6') + self.assertTrue(error.Success()) + + new_object = barfoo.CreateValueFromData("new_object",data,barfoo.GetType().GetBasicType(lldb.eBasicTypeInt)) + + if self.TraceOn(): + print(new_object) + + self.assertTrue(new_object.GetValue() == "1", 'new_object == 1') + + data.SetData(error, 'A\0\0\0', data.GetByteOrder(), data.GetAddressByteSize()) + self.assertTrue(error.Success()) + + data2 = lldb.SBData() + data2.SetData(error, 'BCD', data.GetByteOrder(), data.GetAddressByteSize()) + self.assertTrue(error.Success()) + + data.Append(data2) + + if self.TraceOn(): + print(data) + + # this breaks on EBCDIC + offset = 0 + self.assert_data(data.GetUnsignedInt32, offset, 65) + offset += 4 + self.assert_data(data.GetUnsignedInt8, offset, 66) + offset += 1 + self.assert_data(data.GetUnsignedInt8, offset, 67) + offset += 1 + self.assert_data(data.GetUnsignedInt8, offset, 68) + offset += 1 + + # check the new API calls introduced per LLVM llvm.org/prenhancement request + # 11619 (Allow creating SBData values from arrays or primitives in Python) + + hello_str = "hello!" + data2 = lldb.SBData.CreateDataFromCString(process.GetByteOrder(),process.GetAddressByteSize(),hello_str) + self.assertTrue(len(data2.uint8) == len(hello_str)) + self.assertTrue(data2.uint8[0] == 104, 'h == 104') + self.assertTrue(data2.uint8[1] == 101, 'e == 101') + self.assertTrue(data2.uint8[2] == 108, 'l == 108') + self.assert_data(data2.GetUnsignedInt8, 3, 108) # l + self.assertTrue(data2.uint8[4] == 111, 'o == 111') + self.assert_data(data2.GetUnsignedInt8, 5, 33) # ! + + uint_lists = [ [1,2,3,4,5], [int(i) for i in [1, 2, 3, 4, 5]] ] + int_lists = [ [2, -2], [int(i) for i in [2, -2]] ] + + for l in uint_lists: + data2 = lldb.SBData.CreateDataFromUInt64Array(process.GetByteOrder(), process.GetAddressByteSize(), l) + self.assert_data(data2.GetUnsignedInt64, 0, 1) + self.assert_data(data2.GetUnsignedInt64, 8, 2) + self.assert_data(data2.GetUnsignedInt64, 16, 3) + self.assert_data(data2.GetUnsignedInt64, 24, 4) + self.assert_data(data2.GetUnsignedInt64, 32, 5) + + self.assertTrue(data2.uint64s == [1,2,3,4,5], 'read_data_helper failure: data2 == [1,2,3,4,5]') + + for l in int_lists: + data2 = lldb.SBData.CreateDataFromSInt32Array(process.GetByteOrder(), process.GetAddressByteSize(), l) + self.assertTrue(data2.sint32[0:2] == [2,-2], 'signed32 data2 = [2,-2]') + + data2.Append(lldb.SBData.CreateDataFromSInt64Array(process.GetByteOrder(), process.GetAddressByteSize(), int_lists[0])) + self.assert_data(data2.GetSignedInt32, 0, 2) + self.assert_data(data2.GetSignedInt32, 4, -2) + self.assertTrue(data2.sint64[1:3] == [2,-2], 'signed64 data2 = [2,-2]') + + for l in int_lists: + data2 = lldb.SBData.CreateDataFromSInt64Array(process.GetByteOrder(), process.GetAddressByteSize(), l) + self.assert_data(data2.GetSignedInt64, 0, 2) + self.assert_data(data2.GetSignedInt64, 8, -2) + self.assertTrue(data2.sint64[0:2] == [2,-2], 'signed64 data2 = [2,-2]') + + for l in uint_lists: + data2 = lldb.SBData.CreateDataFromUInt32Array(process.GetByteOrder(), process.GetAddressByteSize(), l) + self.assert_data(data2.GetUnsignedInt32,0, 1) + self.assert_data(data2.GetUnsignedInt32,4, 2) + self.assert_data(data2.GetUnsignedInt32,8, 3) + self.assert_data(data2.GetUnsignedInt32,12, 4) + self.assert_data(data2.GetUnsignedInt32,16, 5) + + bool_list = [True, True, False, False, True, False] + + data2 = lldb.SBData.CreateDataFromSInt32Array(process.GetByteOrder(), process.GetAddressByteSize(), bool_list) + self.assertTrue(data2.sint32[0:6] == [1, 1, 0, 0, 1, 0], 'signed32 data2 = [1, 1, 0, 0, 1, 0]') + + data2 = lldb.SBData.CreateDataFromUInt32Array(process.GetByteOrder(), process.GetAddressByteSize(), bool_list) + self.assertTrue(data2.uint32[0:6] == [1, 1, 0, 0, 1, 0], 'unsigned32 data2 = [1, 1, 0, 0, 1, 0]') + + data2 = lldb.SBData.CreateDataFromSInt64Array(process.GetByteOrder(), process.GetAddressByteSize(), bool_list) + self.assertTrue(data2.sint64[0:6] == [1, 1, 0, 0, 1, 0], 'signed64 data2 = [1, 1, 0, 0, 1, 0]') + + data2 = lldb.SBData.CreateDataFromUInt64Array(process.GetByteOrder(), process.GetAddressByteSize(), bool_list) + self.assertTrue(data2.uint64[0:6] == [1, 1, 0, 0, 1, 0], 'signed64 data2 = [1, 1, 0, 0, 1, 0]') + + data2 = lldb.SBData.CreateDataFromDoubleArray(process.GetByteOrder(),process.GetAddressByteSize(),[3.14,6.28,2.71]) + self.assertTrue( fabs(data2.GetDouble(error,0) - 3.14) < 0.5, 'double data2[0] = 3.14') + self.assertTrue(error.Success()) + self.assertTrue( fabs(data2.GetDouble(error,8) - 6.28) < 0.5, 'double data2[1] = 6.28') + self.assertTrue(error.Success()) + self.assertTrue( fabs(data2.GetDouble(error,16) - 2.71) < 0.5, 'double data2[2] = 2.71') + self.assertTrue(error.Success()) + + data2 = lldb.SBData() + + data2.SetDataFromCString(hello_str) + self.assertTrue(len(data2.uint8) == len(hello_str)) + self.assert_data(data2.GetUnsignedInt8, 0, 104) + self.assert_data(data2.GetUnsignedInt8, 1, 101) + self.assert_data(data2.GetUnsignedInt8, 2, 108) + self.assert_data(data2.GetUnsignedInt8, 3, 108) + self.assert_data(data2.GetUnsignedInt8, 4, 111) + self.assert_data(data2.GetUnsignedInt8, 5, 33) + + data2.SetDataFromUInt64Array([1,2,3,4,5]) + self.assert_data(data2.GetUnsignedInt64, 0, 1) + self.assert_data(data2.GetUnsignedInt64, 8, 2) + self.assert_data(data2.GetUnsignedInt64, 16, 3) + self.assert_data(data2.GetUnsignedInt64, 24, 4) + self.assert_data(data2.GetUnsignedInt64, 32, 5) + + self.assertTrue(data2.uint64[0] == 1, 'read_data_helper failure: set data2[0] = 1') + self.assertTrue(data2.uint64[1] == 2, 'read_data_helper failure: set data2[1] = 2') + self.assertTrue(data2.uint64[2] == 3, 'read_data_helper failure: set data2[2] = 3') + self.assertTrue(data2.uint64[3] == 4, 'read_data_helper failure: set data2[3] = 4') + self.assertTrue(data2.uint64[4] == 5, 'read_data_helper failure: set data2[4] = 5') + + self.assertTrue(data2.uint64[0:2] == [1,2], 'read_data_helper failure: set data2[0:2] = [1,2]') + + data2.SetDataFromSInt32Array([2, -2]) + self.assert_data(data2.GetSignedInt32, 0, 2) + self.assert_data(data2.GetSignedInt32, 4, -2) + + data2.SetDataFromSInt64Array([2, -2]) + self.assert_data(data2.GetSignedInt32, 0, 2) + self.assert_data(data2.GetSignedInt32, 8, -2) + + data2.SetDataFromUInt32Array([1,2,3,4,5]) + self.assert_data(data2.GetUnsignedInt32, 0, 1) + self.assert_data(data2.GetUnsignedInt32, 4, 2) + self.assert_data(data2.GetUnsignedInt32, 8, 3) + self.assert_data(data2.GetUnsignedInt32, 12, 4) + self.assert_data(data2.GetUnsignedInt32, 16, 5) + + self.assertTrue(data2.uint32[0] == 1, 'read_data_helper failure: set 32-bit data2[0] = 1') + self.assertTrue(data2.uint32[1] == 2, 'read_data_helper failure: set 32-bit data2[1] = 2') + self.assertTrue(data2.uint32[2] == 3, 'read_data_helper failure: set 32-bit data2[2] = 3') + self.assertTrue(data2.uint32[3] == 4, 'read_data_helper failure: set 32-bit data2[3] = 4') + self.assertTrue(data2.uint32[4] == 5, 'read_data_helper failure: set 32-bit data2[4] = 5') + + data2.SetDataFromDoubleArray([3.14,6.28,2.71]) + self.assertTrue( fabs(data2.GetDouble(error,0) - 3.14) < 0.5, 'set double data2[0] = 3.14') + self.assertTrue( fabs(data2.GetDouble(error,8) - 6.28) < 0.5, 'set double data2[1] = 6.28') + self.assertTrue( fabs(data2.GetDouble(error,16) - 2.71) < 0.5, 'set double data2[2] = 2.71') + + self.assertTrue( fabs(data2.double[0] - 3.14) < 0.5, 'read_data_helper failure: set double data2[0] = 3.14') + self.assertTrue( fabs(data2.double[1] - 6.28) < 0.5, 'read_data_helper failure: set double data2[1] = 6.28') + self.assertTrue( fabs(data2.double[2] - 2.71) < 0.5, 'read_data_helper failure: set double data2[2] = 2.71') + + def assert_data(self, func, arg, expected): + """ Asserts func(SBError error, arg) == expected. """ + error = lldb.SBError() + result = func(error, arg) + if not error.Success(): + stream = lldb.SBStream() + error.GetDescription(stream) + self.assertTrue(error.Success(), + "%s(error, %s) did not succeed: %s" % (func.__name__, + arg, + stream.GetData())) + self.assertTrue(expected == result, "%s(error, %s) == %s != %s" % (func.__name__, arg, result, expected)) diff --git a/packages/Python/lldbsuite/test/python_api/sbdata/main.cpp b/packages/Python/lldbsuite/test/python_api/sbdata/main.cpp new file mode 100644 index 0000000..6018475 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbdata/main.cpp @@ -0,0 +1,43 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdint.h> + +struct foo +{ + uint32_t a; + uint32_t b; + float c; + foo() : a(0), b(1), c(3.14) {} + foo(uint32_t A, uint32_t B, float C) : + a(A), + b(B), + c(C) + {} +}; + +int main (int argc, char const *argv[]) +{ + foo* foobar = new foo[2]; + + foobar[0].a = 1; + foobar[0].b = 9; + + foobar[1].a = 8; + foobar[1].b = 5; + + foobar[1].b = 7; // set breakpoint here + + foobar[1].c = 6.28; + + foo barfoo[] = {foo(1,2,3), foo(4,5,6)}; + + delete[] foobar; + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/sbtype_typeclass/TestSBTypeTypeClass.py b/packages/Python/lldbsuite/test/python_api/sbtype_typeclass/TestSBTypeTypeClass.py new file mode 100644 index 0000000..80305e3 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbtype_typeclass/TestSBTypeTypeClass.py @@ -0,0 +1,4 @@ +import lldbsuite.test.lldbinline as lldbinline +import lldbsuite.test.lldbtest as lldbtest + +lldbinline.MakeInlineTest(__file__, globals(), [lldbtest.skipIfFreeBSD,lldbtest.skipIfLinux,lldbtest.skipIfWindows]) diff --git a/packages/Python/lldbsuite/test/python_api/sbtype_typeclass/main.m b/packages/Python/lldbsuite/test/python_api/sbtype_typeclass/main.m new file mode 100644 index 0000000..599d361 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbtype_typeclass/main.m @@ -0,0 +1,34 @@ +//===-- main.m --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#import <Cocoa/Cocoa.h> + +@interface ThisClassTestsThings : NSObject +@end + +@implementation ThisClassTestsThings +- (int)doSomething { + + id s = self; + NSLog(@"%@",s); //% s = self.frame().FindVariable("s"); s.SetPreferDynamicValue(lldb.eDynamicCanRunTarget) + //% s_type = s.GetType() + //% typeClass = s_type.GetTypeClass() + //% condition = (typeClass == lldb.eTypeClassClass) or (typeClass ==lldb.eTypeClassObjCObject) or (typeClass == lldb.eTypeClassObjCInterface) or (typeClass == lldb.eTypeClassObjCObjectPointer) or (typeClass == lldb.eTypeClassPointer) + //% self.assertTrue(condition, "s has the wrong TypeClass") + return 0; +} +- (id)init { + return (self = [super init]); +} +@end + + +int main (int argc, char const *argv[]) +{ + return [[[ThisClassTestsThings alloc] init] doSomething]; +} diff --git a/packages/Python/lldbsuite/test/python_api/sbvalue_const_addrof/Makefile b/packages/Python/lldbsuite/test/python_api/sbvalue_const_addrof/Makefile new file mode 100644 index 0000000..a9c1edd --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbvalue_const_addrof/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../make +CXX_SOURCES := main.cpp +CXXFLAGS += -std=c++11 +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/sbvalue_const_addrof/TestSBValueConstAddrOf.py b/packages/Python/lldbsuite/test/python_api/sbvalue_const_addrof/TestSBValueConstAddrOf.py new file mode 100644 index 0000000..a3d43c1 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbvalue_const_addrof/TestSBValueConstAddrOf.py @@ -0,0 +1,3 @@ +import lldbsuite.test.lldbinline as lldbinline + +lldbinline.MakeInlineTest(__file__, globals()) diff --git a/packages/Python/lldbsuite/test/python_api/sbvalue_const_addrof/main.cpp b/packages/Python/lldbsuite/test/python_api/sbvalue_const_addrof/main.cpp new file mode 100644 index 0000000..eb9c8e0 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbvalue_const_addrof/main.cpp @@ -0,0 +1,40 @@ +#include <stdio.h> +#include <stdint.h> + +struct RegisterContext +{ + uintptr_t r0; + uintptr_t r1; + uintptr_t r2; + uintptr_t r3; + uintptr_t r4; + uintptr_t pc; + uintptr_t fp; + uintptr_t sp; +}; + +struct ThreadInfo { + uint32_t tid; + const char *name; + RegisterContext regs; + ThreadInfo *next; +}; +int main (int argc, char const *argv[], char const *envp[]); + +ThreadInfo g_thread2 = { 0x2222, "thread2", { 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, (uintptr_t)&main, 0x2006, 0x2007 }, NULL }; +ThreadInfo g_thread1 = { 0x1111, "thread1", { 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, (uintptr_t)&main, 0x1006, 0x1007 }, &g_thread2 }; +ThreadInfo *g_thread_list_ptr = &g_thread1; + +int main (int argc, char const *argv[], char const *envp[]) +{ + printf ("g_thread_list is %p\n", g_thread_list_ptr); + return 0; //% v = lldb.target.FindFirstGlobalVariable('g_thread_list_ptr') + //% v_gla = v.GetChildMemberWithName('regs').GetLoadAddress() + //% v_aof = v.GetChildMemberWithName('regs').AddressOf().GetValueAsUnsigned(lldb.LLDB_INVALID_ADDRESS) + //% expr = '(%s)0x%x' % (v.GetType().GetName(), v.GetValueAsUnsigned(0)) + //% e = v.CreateValueFromExpression('e', expr) + //% e_gla = e.GetChildMemberWithName('regs').GetLoadAddress() + //% e_aof = e.GetChildMemberWithName('regs').AddressOf().GetValueAsUnsigned(lldb.LLDB_INVALID_ADDRESS) + //% self.assertTrue(v_gla == e_gla, "GetLoadAddress() differs") + //% self.assertTrue(v_aof == e_aof, "AddressOf() differs") +} diff --git a/packages/Python/lldbsuite/test/python_api/sbvalue_persist/Makefile b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/Makefile new file mode 100644 index 0000000..e5c7b91 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/Makefile @@ -0,0 +1,15 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +# Clean renamed executable on 'make clean' +clean: OBJECTS+=no_synth + +# clang-3.5+ outputs FullDebugInfo by default for Darwin/FreeBSD +# targets. Other targets do not, which causes this test to fail. +# This flag enables FullDebugInfo for all targets. +ifneq (,$(findstring clang,$(CC))) + CFLAGS_EXTRAS += -fno-limit-debug-info +endif + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/sbvalue_persist/TestSBValuePersist.py b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/TestSBValuePersist.py new file mode 100644 index 0000000..6edbbda --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/TestSBValuePersist.py @@ -0,0 +1,74 @@ +"""Test SBValue::Persist""" + +from __future__ import print_function + + + +import os, sys, time +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class SBValuePersistTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + @expectedFailureWindows("llvm.org/pr24772") + def test(self): + """Test SBValue::Persist""" + self.build() + self.setTearDownCleanup() + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_source_regexp (self, "break here") + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + self.runCmd('type filter clear', check=False) + self.runCmd('type synthetic clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + foo = self.frame().FindVariable("foo") + bar = self.frame().FindVariable("bar") + baz = self.frame().FindVariable("baz") + + self.assertTrue(foo.IsValid(), "foo is not valid") + self.assertTrue(bar.IsValid(), "bar is not valid") + self.assertTrue(baz.IsValid(), "baz is not valid") + + fooPersist = foo.Persist() + barPersist = bar.Persist() + bazPersist = baz.Persist() + + self.assertTrue(fooPersist.IsValid(), "fooPersist is not valid") + self.assertTrue(barPersist.IsValid(), "barPersist is not valid") + self.assertTrue(bazPersist.IsValid(), "bazPersist is not valid") + + self.assertTrue(fooPersist.GetValueAsUnsigned(0) == 10, "fooPersist != 10") + self.assertTrue(barPersist.GetPointeeData().sint32[0] == 4, "barPersist != 4") + self.assertTrue(bazPersist.GetSummary() == '"85"', "bazPersist != 85") + + self.runCmd("continue") + + self.assertTrue(fooPersist.IsValid(), "fooPersist is not valid") + self.assertTrue(barPersist.IsValid(), "barPersist is not valid") + self.assertTrue(bazPersist.IsValid(), "bazPersist is not valid") + + self.assertTrue(fooPersist.GetValueAsUnsigned(0) == 10, "fooPersist != 10") + self.assertTrue(barPersist.GetPointeeData().sint32[0] == 4, "barPersist != 4") + self.assertTrue(bazPersist.GetSummary() == '"85"', "bazPersist != 85") + + self.expect("expr *(%s)" % (barPersist.GetName()), substrs = ['= 4']) diff --git a/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp new file mode 100644 index 0000000..650d87a --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp @@ -0,0 +1,14 @@ +#include <vector> +#include <string> + +void f() {} + +int main() { + int foo = 10; + int *bar = new int(4); + std::string baz = "85"; + + f(); // break here + f(); // break here + return 0; +}
\ No newline at end of file diff --git a/packages/Python/lldbsuite/test/python_api/section/Makefile b/packages/Python/lldbsuite/test/python_api/section/Makefile new file mode 100644 index 0000000..0d70f25 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/section/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/section/TestSectionAPI.py b/packages/Python/lldbsuite/test/python_api/section/TestSectionAPI.py new file mode 100644 index 0000000..5872164 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/section/TestSectionAPI.py @@ -0,0 +1,41 @@ +""" +Test SBSection APIs. +""" + +from __future__ import print_function + + + +from lldbsuite.test.lldbtest import * + +class SectionAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + def test_get_target_byte_size(self): + d = {'EXE': 'b.out'} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + exe = os.path.join(os.getcwd(), 'b.out') + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # find the .data section of the main module + mod = target.GetModuleAtIndex(0) + data_section = None + for s in mod.sections: + sect_type = s.GetSectionType() + if sect_type == lldb.eSectionTypeData: + data_section = s + break + elif sect_type == lldb.eSectionTypeContainer: + for i in range(s.GetNumSubSections()): + ss = s.GetSubSectionAtIndex(i) + sect_type = ss.GetSectionType() + if sect_type == lldb.eSectionTypeData: + data_section = ss + break + + self.assertIsNotNone(data_section) + self.assertEqual(data_section.target_byte_size, 1) diff --git a/packages/Python/lldbsuite/test/python_api/section/main.c b/packages/Python/lldbsuite/test/python_api/section/main.c new file mode 100644 index 0000000..746681d --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/section/main.c @@ -0,0 +1,28 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <string.h> + +// This simple program is to test the lldb Python API SBSection. It includes +// somes global data, and so the build process produces a DATA section, which +// the test code can use to query for the target byte size + +char my_global_var_of_char_type = 'X'; + +int main (int argc, char const *argv[]) +{ + // this code just "does something" with the global so that it is not + // optimised away + if (argc > 1 && strlen(argv[1])) + { + my_global_var_of_char_type += argv[1][0]; + } + + return my_global_var_of_char_type; +} diff --git a/packages/Python/lldbsuite/test/python_api/signals/Makefile b/packages/Python/lldbsuite/test/python_api/signals/Makefile new file mode 100644 index 0000000..8a7102e --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/signals/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/signals/TestSignalsAPI.py b/packages/Python/lldbsuite/test/python_api/signals/TestSignalsAPI.py new file mode 100644 index 0000000..9825c553 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/signals/TestSignalsAPI.py @@ -0,0 +1,47 @@ +""" +Test SBProcess APIs, including ReadMemory(), WriteMemory(), and others. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbutil import get_stopped_thread, state_type_to_str +from lldbsuite.test.lldbtest import * + +class SignalsAPITestCase(TestBase): + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + @expectedFlakeyLinux # this test fails 1/100 dosep runs + @skipIfWindows # Windows doesn't have signals + def test_ignore_signal(self): + """Test Python SBUnixSignals.Suppress/Stop/Notify() API.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + line = line_number("main.cpp", "// Set break point at this line and setup signal ignores.") + breakpoint = target.BreakpointCreateByLocation("main.cpp", line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") + + unix_signals = process.GetUnixSignals() + sigint = unix_signals.GetSignalNumberFromName("SIGINT") + unix_signals.SetShouldSuppress(sigint, True) + unix_signals.SetShouldStop(sigint, False) + unix_signals.SetShouldNotify(sigint, False) + + process.Continue() + self.assertTrue(process.state == lldb.eStateExited, "The process should have exited") + self.assertTrue(process.GetExitStatus() == 0, "The process should have returned 0") diff --git a/packages/Python/lldbsuite/test/python_api/signals/main.cpp b/packages/Python/lldbsuite/test/python_api/signals/main.cpp new file mode 100644 index 0000000..81924f4 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/signals/main.cpp @@ -0,0 +1,28 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <sys/types.h> +#if defined(_WIN32) +#include <windows.h> +#else +#include <unistd.h> +#include <signal.h> +#endif + +// This simple program is to test the lldb Python API related to process. + +int main (int argc, char const *argv[]) +{ +#if defined(_WIN32) + ::ExitProcess(1); +#else + kill(getpid(), SIGINT); // Set break point at this line and setup signal ignores. +#endif + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/symbol-context/Makefile b/packages/Python/lldbsuite/test/python_api/symbol-context/Makefile new file mode 100644 index 0000000..0d70f25 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/symbol-context/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/symbol-context/TestSymbolContext.py b/packages/Python/lldbsuite/test/python_api/symbol-context/TestSymbolContext.py new file mode 100644 index 0000000..2fec8db --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/symbol-context/TestSymbolContext.py @@ -0,0 +1,89 @@ +""" +Test SBSymbolContext APIs. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class SymbolContextAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to of function 'c'. + self.line = line_number('main.c', '// Find the line number of function "c" here.') + + @add_test_categories(['pyapi']) + @expectedFailureWindows("llvm.org/pr24778") + def test(self): + """Exercise SBSymbolContext API extensively.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + #print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.line. + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") + frame0 = thread.GetFrameAtIndex(0) + self.assertTrue(frame0.GetLineEntry().GetLine() == self.line) + + # Now get the SBSymbolContext from this frame. We want everything. :-) + context = frame0.GetSymbolContext(lldb.eSymbolContextEverything) + self.assertTrue(context) + + # Get the description of this module. + module = context.GetModule() + desc = lldbutil.get_description(module) + self.expect(desc, "The module should match", exe=False, + substrs = [os.path.join(self.mydir, 'a.out')]) + + compileUnit = context.GetCompileUnit() + self.expect(str(compileUnit), "The compile unit should match", exe=False, + substrs = [os.path.join(self.mydir, 'main.c')]) + + function = context.GetFunction() + self.assertTrue(function) + #print("function:", function) + + block = context.GetBlock() + self.assertTrue(block) + #print("block:", block) + + lineEntry = context.GetLineEntry() + #print("line entry:", lineEntry) + self.expect(lineEntry.GetFileSpec().GetDirectory(), "The line entry should have the correct directory", + exe=False, + substrs = [self.mydir]) + self.expect(lineEntry.GetFileSpec().GetFilename(), "The line entry should have the correct filename", + exe=False, + substrs = ['main.c']) + self.assertTrue(lineEntry.GetLine() == self.line, + "The line entry's line number should match ") + + symbol = context.GetSymbol() + self.assertTrue(function.GetName() == symbol.GetName() and symbol.GetName() == 'c', + "The symbol name should be 'c'") diff --git a/packages/Python/lldbsuite/test/python_api/symbol-context/main.c b/packages/Python/lldbsuite/test/python_api/symbol-context/main.c new file mode 100644 index 0000000..3ac1825 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/symbol-context/main.c @@ -0,0 +1,51 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to test the lldb Python API SBSymbolContext. +// When stopped on a frame, we can get the symbol context using the SBFrame API +// SBFrame.GetSymbolContext(). + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; // Find the line number of function "c" here. +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) + printf("a(3) returns %d\n", A3); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/target/Makefile b/packages/Python/lldbsuite/test/python_api/target/Makefile new file mode 100644 index 0000000..0d70f25 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/target/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/target/TestTargetAPI.py b/packages/Python/lldbsuite/test/python_api/target/TestTargetAPI.py new file mode 100644 index 0000000..0231d28 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/target/TestTargetAPI.py @@ -0,0 +1,372 @@ +""" +Test SBTarget APIs. +""" + +from __future__ import print_function + + + +import unittest2 +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TargetAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to of function 'c'. + self.line1 = line_number('main.c', '// Find the line number for breakpoint 1 here.') + self.line2 = line_number('main.c', '// Find the line number for breakpoint 2 here.') + self.line_main = line_number("main.c", "// Set a break at entry to main.") + + #rdar://problem/9700873 + # Find global variable value fails for dwarf if inferior not started + # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94) + # + # It does not segfaults now. But for dwarf, the variable value is None if + # the inferior process does not exist yet. The radar has been updated. + #@unittest232.skip("segmentation fault -- skipping") + @add_test_categories(['pyapi']) + def test_find_global_variables(self): + """Exercise SBTarget.FindGlobalVariables() API.""" + d = {'EXE': 'b.out'} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.find_global_variables('b.out') + + @add_test_categories(['pyapi']) + @expectedFailureWindows("llvm.org/pr24778") + def test_find_functions(self): + """Exercise SBTarget.FindFunctions() API.""" + d = {'EXE': 'b.out'} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.find_functions('b.out') + + @add_test_categories(['pyapi']) + def test_get_description(self): + """Exercise SBTarget.GetDescription() API.""" + self.build() + self.get_description() + + @add_test_categories(['pyapi']) + def test_launch_new_process_and_redirect_stdout(self): + """Exercise SBTarget.Launch() API.""" + self.build() + self.launch_new_process_and_redirect_stdout() + + @add_test_categories(['pyapi']) + def test_resolve_symbol_context_with_address(self): + """Exercise SBTarget.ResolveSymbolContextForAddress() API.""" + self.build() + self.resolve_symbol_context_with_address() + + @add_test_categories(['pyapi']) + def test_get_platform(self): + d = {'EXE': 'b.out'} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + target = self.create_simple_target('b.out') + platform = target.platform + self.assertTrue(platform, VALID_PLATFORM) + + @add_test_categories(['pyapi']) + def test_get_data_byte_size(self): + d = {'EXE': 'b.out'} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + target = self.create_simple_target('b.out') + self.assertEqual(target.data_byte_size, 1) + + @add_test_categories(['pyapi']) + def test_get_code_byte_size(self): + d = {'EXE': 'b.out'} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + target = self.create_simple_target('b.out') + self.assertEqual(target.code_byte_size, 1) + + @add_test_categories(['pyapi']) + def test_resolve_file_address(self): + d = {'EXE': 'b.out'} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + target = self.create_simple_target('b.out') + + # find the file address in the .data section of the main + # module + data_section = self.find_data_section(target) + data_section_addr = data_section.file_addr + + # resolve the above address, and compare the address produced + # by the resolution against the original address/section + res_file_addr = target.ResolveFileAddress(data_section_addr) + self.assertTrue(res_file_addr.IsValid()) + + self.assertEqual(data_section_addr, res_file_addr.file_addr) + + data_section2 = res_file_addr.section + self.assertIsNotNone(data_section2) + self.assertEqual(data_section.name, data_section2.name) + + @add_test_categories(['pyapi']) + def test_read_memory(self): + d = {'EXE': 'b.out'} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + target = self.create_simple_target('b.out') + + breakpoint = target.BreakpointCreateByLocation("main.c", self.line_main) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Put debugger into synchronous mode so when we target.LaunchSimple returns + # it will guaranteed to be at the breakpoint + self.dbg.SetAsync(False) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + # find the file address in the .data section of the main + # module + data_section = self.find_data_section(target) + sb_addr = lldb.SBAddress(data_section, 0) + error = lldb.SBError() + content = target.ReadMemory(sb_addr, 1, error) + self.assertTrue(error.Success(), "Make sure memory read succeeded") + self.assertEqual(len(content), 1) + + def create_simple_target(self, fn): + exe = os.path.join(os.getcwd(), fn) + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + return target + + def find_data_section(self, target): + mod = target.GetModuleAtIndex(0) + data_section = None + for s in mod.sections: + sect_type = s.GetSectionType() + if sect_type == lldb.eSectionTypeData: + data_section = s + break + elif sect_type == lldb.eSectionTypeContainer: + for i in range(s.GetNumSubSections()): + ss = s.GetSubSectionAtIndex(i) + sect_type = ss.GetSectionType() + if sect_type == lldb.eSectionTypeData: + data_section = ss + break + + self.assertIsNotNone(data_section) + return data_section + + def find_global_variables(self, exe_name): + """Exercise SBTaget.FindGlobalVariables() API.""" + exe = os.path.join(os.getcwd(), exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + #rdar://problem/9700873 + # Find global variable value fails for dwarf if inferior not started + # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94) + # + # Remove the lines to create a breakpoint and to start the inferior + # which are workarounds for the dwarf case. + + breakpoint = target.BreakpointCreateByLocation('main.c', self.line1) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + # Make sure we hit our breakpoint: + thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint) + self.assertTrue (len(thread_list) == 1) + + value_list = target.FindGlobalVariables('my_global_var_of_char_type', 3) + self.assertTrue(value_list.GetSize() == 1) + my_global_var = value_list.GetValueAtIndex(0) + self.DebugSBValue(my_global_var) + self.assertTrue(my_global_var) + self.expect(my_global_var.GetName(), exe=False, + startstr = "my_global_var_of_char_type") + self.expect(my_global_var.GetTypeName(), exe=False, + startstr = "char") + self.expect(my_global_var.GetValue(), exe=False, + startstr = "'X'") + + # While we are at it, let's also exercise the similar SBModule.FindGlobalVariables() API. + for m in target.module_iter(): + if os.path.normpath(m.GetFileSpec().GetDirectory()) == os.getcwd() and m.GetFileSpec().GetFilename() == exe_name: + value_list = m.FindGlobalVariables(target, 'my_global_var_of_char_type', 3) + self.assertTrue(value_list.GetSize() == 1) + self.assertTrue(value_list.GetValueAtIndex(0).GetValue() == "'X'") + break + + def find_functions(self, exe_name): + """Exercise SBTaget.FindFunctions() API.""" + exe = os.path.join(os.getcwd(), exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + list = target.FindFunctions('c', lldb.eFunctionNameTypeAuto) + self.assertTrue(list.GetSize() == 1) + + for sc in list: + self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name) + self.assertTrue(sc.GetSymbol().GetName() == 'c') + + def get_description(self): + """Exercise SBTaget.GetDescription() API.""" + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + from lldbsuite.test.lldbutil import get_description + + # get_description() allows no option to mean lldb.eDescriptionLevelBrief. + desc = get_description(target) + #desc = get_description(target, option=lldb.eDescriptionLevelBrief) + if not desc: + self.fail("SBTarget.GetDescription() failed") + self.expect(desc, exe=False, + substrs = ['a.out']) + self.expect(desc, exe=False, matching=False, + substrs = ['Target', 'Module', 'Breakpoint']) + + desc = get_description(target, option=lldb.eDescriptionLevelFull) + if not desc: + self.fail("SBTarget.GetDescription() failed") + self.expect(desc, exe=False, + substrs = ['a.out', 'Target', 'Module', 'Breakpoint']) + + @not_remote_testsuite_ready + def launch_new_process_and_redirect_stdout(self): + """Exercise SBTaget.Launch() API with redirected stdout.""" + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Add an extra twist of stopping the inferior in a breakpoint, and then continue till it's done. + # We should still see the entire stdout redirected once the process is finished. + line = line_number('main.c', '// a(3) -> c(3)') + breakpoint = target.BreakpointCreateByLocation('main.c', line) + + # Now launch the process, do not stop at entry point, and redirect stdout to "stdout.txt" file. + # The inferior should run to completion after "process.Continue()" call. + local_path = "stdout.txt"; + if lldb.remote_platform: + stdout_path = lldbutil.append_to_process_working_directory("lldb-stdout-redirect.txt") + else: + stdout_path = local_path + error = lldb.SBError() + process = target.Launch (self.dbg.GetListener(), None, None, None, stdout_path, None, None, 0, False, error) + process.Continue() + #self.runCmd("process status") + if lldb.remote_platform: + # copy output file to host + lldb.remote_platform.Get(lldb.SBFileSpec(stdout_path), lldb.SBFileSpec(local_path)) + + # The 'stdout.txt' file should now exist. + self.assertTrue(os.path.isfile("stdout.txt"), + "'stdout.txt' exists due to redirected stdout via SBTarget.Launch() API.") + + # Read the output file produced by running the program. + with open('stdout.txt', 'r') as f: + output = f.read() + + # Let's delete the 'stdout.txt' file as a cleanup step. + try: + os.remove("stdout.txt") + pass + except OSError: + pass + + self.expect(output, exe=False, + substrs = ["a(1)", "b(2)", "a(3)"]) + + + def resolve_symbol_context_with_address(self): + """Exercise SBTaget.ResolveSymbolContextForAddress() API.""" + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create the two breakpoints inside function 'a'. + breakpoint1 = target.BreakpointCreateByLocation('main.c', self.line1) + breakpoint2 = target.BreakpointCreateByLocation('main.c', self.line2) + #print("breakpoint1:", breakpoint1) + #print("breakpoint2:", breakpoint2) + self.assertTrue(breakpoint1 and + breakpoint1.GetNumLocations() == 1, + VALID_BREAKPOINT) + self.assertTrue(breakpoint2 and + breakpoint2.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.line1. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + #self.runCmd("process status") + frame0 = thread.GetFrameAtIndex(0) + lineEntry = frame0.GetLineEntry() + self.assertTrue(lineEntry.GetLine() == self.line1) + + address1 = lineEntry.GetStartAddress() + + # Continue the inferior, the breakpoint 2 should be hit. + process.Continue() + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + #self.runCmd("process status") + frame0 = thread.GetFrameAtIndex(0) + lineEntry = frame0.GetLineEntry() + self.assertTrue(lineEntry.GetLine() == self.line2) + + address2 = lineEntry.GetStartAddress() + + #print("address1:", address1) + #print("address2:", address2) + + # Now call SBTarget.ResolveSymbolContextForAddress() with the addresses from our line entry. + context1 = target.ResolveSymbolContextForAddress(address1, lldb.eSymbolContextEverything) + context2 = target.ResolveSymbolContextForAddress(address2, lldb.eSymbolContextEverything) + + self.assertTrue(context1 and context2) + #print("context1:", context1) + #print("context2:", context2) + + # Verify that the context point to the same function 'a'. + symbol1 = context1.GetSymbol() + symbol2 = context2.GetSymbol() + self.assertTrue(symbol1 and symbol2) + #print("symbol1:", symbol1) + #print("symbol2:", symbol2) + + from lldbsuite.test.lldbutil import get_description + desc1 = get_description(symbol1) + desc2 = get_description(symbol2) + self.assertTrue(desc1 and desc2 and desc1 == desc2, + "The two addresses should resolve to the same symbol") diff --git a/packages/Python/lldbsuite/test/python_api/target/main.c b/packages/Python/lldbsuite/test/python_api/target/main.c new file mode 100644 index 0000000..ba82a54 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/target/main.c @@ -0,0 +1,60 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to test the lldb Python API SBTarget. +// +// When stopped on breakppint 1, and then 2, we can get the line entries using +// SBFrame API SBFrame.GetLineEntry(). We'll get the start addresses for the +// two line entries; with the start address (of SBAddress type), we can then +// resolve the symbol context using the SBTarget API +// SBTarget.ResolveSymbolContextForAddress(). +// +// The two symbol context should point to the same symbol, i.e., 'a' function. + +char my_global_var_of_char_type = 'X'; // Test SBTarget.FindGlobalVariables(...). + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) // Find the line number for breakpoint 1 here. + val = b(val); + else if (val >= 3) + val = c(val); + + return val; // Find the line number for breakpoint 2 here. +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; +} + +int main (int argc, char const *argv[]) +{ + // Set a break at entry to main. + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) + printf("a(3) returns %d\n", A3); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/thread/Makefile b/packages/Python/lldbsuite/test/python_api/thread/Makefile new file mode 100644 index 0000000..aa257ae --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/thread/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES ?= main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/thread/TestThreadAPI.py b/packages/Python/lldbsuite/test/python_api/thread/TestThreadAPI.py new file mode 100644 index 0000000..dad829a --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/thread/TestThreadAPI.py @@ -0,0 +1,245 @@ +""" +Test SBThread APIs. +""" + +from __future__ import print_function + + + +import os, time +import lldb +from lldbsuite.test.lldbutil import get_stopped_thread, get_caller_symbol +from lldbsuite.test.lldbtest import * + +class ThreadAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(['pyapi']) + def test_get_process(self): + """Test Python SBThread.GetProcess() API.""" + self.build() + self.get_process() + + @add_test_categories(['pyapi']) + def test_get_stop_description(self): + """Test Python SBThread.GetStopDescription() API.""" + self.build() + self.get_stop_description() + + @add_test_categories(['pyapi']) + def test_run_to_address(self): + """Test Python SBThread.RunToAddress() API.""" + # We build a different executable than the default build() does. + d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.run_to_address(self.exe_name) + + @add_test_categories(['pyapi']) + @expectedFailureFreeBSD # llvm.org/pr20476 + @expectedFailureWindows # Test crashes + def test_step_out_of_malloc_into_function_b(self): + """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b().""" + # We build a different executable than the default build() does. + d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.step_out_of_malloc_into_function_b(self.exe_name) + + @add_test_categories(['pyapi']) + def test_step_over_3_times(self): + """Test Python SBThread.StepOver() API.""" + # We build a different executable than the default build() does. + d = {'CXX_SOURCES': 'main2.cpp', 'EXE': self.exe_name} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.step_over_3_times(self.exe_name) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number within main.cpp to break inside main(). + self.break_line = line_number("main.cpp", "// Set break point at this line and check variable 'my_char'.") + # Find the line numbers within main2.cpp for step_out_of_malloc_into_function_b() and step_over_3_times(). + self.step_out_of_malloc = line_number("main2.cpp", "// thread step-out of malloc into function b.") + self.after_3_step_overs = line_number("main2.cpp", "// we should reach here after 3 step-over's.") + + # We'll use the test method name as the exe_name for executable comppiled from main2.cpp. + self.exe_name = self.testMethodName + + def get_process(self): + """Test Python SBThread.GetProcess() API.""" + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.break_line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + self.runCmd("breakpoint list") + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") + self.runCmd("process status") + + proc_of_thread = thread.GetProcess() + #print("proc_of_thread:", proc_of_thread) + self.assertTrue(proc_of_thread.GetProcessID() == process.GetProcessID()) + + def get_stop_description(self): + """Test Python SBThread.GetStopDescription() API.""" + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation("main.cpp", self.break_line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + #self.runCmd("breakpoint list") + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") + #self.runCmd("process status") + + # Due to the typemap magic (see lldb.swig), we pass in an (int)length to GetStopDescription + # and expect to get a Python string as the return object! + # The 100 is just an arbitrary number specifying the buffer size. + stop_description = thread.GetStopDescription(100) + self.expect(stop_description, exe=False, + startstr = 'breakpoint') + + def step_out_of_malloc_into_function_b(self, exe_name): + """Test Python SBThread.StepOut() API to step out of a malloc call where the call site is at function b().""" + exe = os.path.join(os.getcwd(), exe_name) + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByName('malloc') + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + while True: + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint") + caller_symbol = get_caller_symbol(thread) + if not caller_symbol: + self.fail("Test failed: could not locate the caller symbol of malloc") + + # Our top frame may be an inlined function in malloc() (e.g., on + # FreeBSD). Apply a simple heuristic of stepping out until we find + # a non-malloc caller + while caller_symbol.startswith("malloc"): + thread.StepOut() + self.assertTrue(thread.IsValid(), "Thread valid after stepping to outer malloc") + caller_symbol = get_caller_symbol(thread) + + if caller_symbol == "b(int)": + break + process.Continue() + + # On Linux malloc calls itself in some case. Remove the breakpoint because we don't want + # to hit it during step-out. + target.BreakpointDelete(breakpoint.GetID()) + + thread.StepOut() + self.runCmd("thread backtrace") + self.assertTrue(thread.GetFrameAtIndex(0).GetLineEntry().GetLine() == self.step_out_of_malloc, + "step out of malloc into function b is successful") + + def step_over_3_times(self, exe_name): + """Test Python SBThread.StepOver() API.""" + exe = os.path.join(os.getcwd(), exe_name) + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation('main2.cpp', self.step_out_of_malloc) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + self.runCmd("breakpoint list") + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.step_out_of_malloc. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + self.runCmd("thread backtrace") + frame0 = thread.GetFrameAtIndex(0) + lineEntry = frame0.GetLineEntry() + self.assertTrue(lineEntry.GetLine() == self.step_out_of_malloc) + + thread.StepOver() + thread.StepOver() + thread.StepOver() + self.runCmd("thread backtrace") + + # Verify that we are stopped at the correct source line number in main2.cpp. + frame0 = thread.GetFrameAtIndex(0) + lineEntry = frame0.GetLineEntry() + self.assertTrue(thread.GetStopReason() == lldb.eStopReasonPlanComplete) + # Expected failure with clang as the compiler. + # rdar://problem/9223880 + # + # Which has been fixed on the lldb by compensating for inaccurate line + # table information with r140416. + self.assertTrue(lineEntry.GetLine() == self.after_3_step_overs) + + def run_to_address(self, exe_name): + """Test Python SBThread.RunToAddress() API.""" + exe = os.path.join(os.getcwd(), exe_name) + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByLocation('main2.cpp', self.step_out_of_malloc) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + self.runCmd("breakpoint list") + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.step_out_of_malloc. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + self.runCmd("thread backtrace") + frame0 = thread.GetFrameAtIndex(0) + lineEntry = frame0.GetLineEntry() + self.assertTrue(lineEntry.GetLine() == self.step_out_of_malloc) + + # Get the start/end addresses for this line entry. + start_addr = lineEntry.GetStartAddress().GetLoadAddress(target) + end_addr = lineEntry.GetEndAddress().GetLoadAddress(target) + if self.TraceOn(): + print("start addr:", hex(start_addr)) + print("end addr:", hex(end_addr)) + + # Disable the breakpoint. + self.assertTrue(target.DisableAllBreakpoints()) + self.runCmd("breakpoint list") + + thread.StepOver() + thread.StepOver() + thread.StepOver() + self.runCmd("thread backtrace") + + # Now ask SBThread to run to the address 'start_addr' we got earlier, which + # corresponds to self.step_out_of_malloc line entry's start address. + thread.RunToAddress(start_addr) + self.runCmd("process status") + #self.runCmd("thread backtrace") diff --git a/packages/Python/lldbsuite/test/python_api/thread/main.cpp b/packages/Python/lldbsuite/test/python_api/thread/main.cpp new file mode 100644 index 0000000..8d80690 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/thread/main.cpp @@ -0,0 +1,26 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to test the lldb Python API related to thread. + +char my_char = 'u'; +int my_int = 0; + +int main (int argc, char const *argv[]) +{ + for (int i = 0; i < 3; ++i) { + printf("my_char='%c'\n", my_char); + ++my_char; + } + + printf("after the loop: my_char='%c'\n", my_char); // 'my_char' should print out as 'x'. + + return 0; // Set break point at this line and check variable 'my_char'. +} diff --git a/packages/Python/lldbsuite/test/python_api/thread/main2.cpp b/packages/Python/lldbsuite/test/python_api/thread/main2.cpp new file mode 100644 index 0000000..a95d7d7 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/thread/main2.cpp @@ -0,0 +1,54 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdlib.h> + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); + + return val; +} + +int b(int val) +{ + int rc = c(val); + void *ptr = malloc(1024); // thread step-out of malloc into function b. + if (!ptr) + return -1; + else + printf("ptr=%p\n", ptr); + return rc; // we should reach here after 3 step-over's. +} + +int c(int val) +{ + return val + 3; +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); + printf("a(1) returns %d\n", A1); + + int B2 = b(2); + printf("b(2) returns %d\n", B2); + + int A3 = a(3); + printf("a(3) returns %d\n", A3); + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/type/Makefile b/packages/Python/lldbsuite/test/python_api/type/Makefile new file mode 100644 index 0000000..8a7102e --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/type/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py b/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py new file mode 100644 index 0000000..d9e5719 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/type/TestTypeList.py @@ -0,0 +1,116 @@ +""" +Test SBType and SBTypeList API. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TypeAndTypeListTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # We'll use the test method name as the exe_name. + self.exe_name = self.testMethodName + # Find the line number to break at. + self.source = 'main.cpp' + self.line = line_number(self.source, '// Break at this line') + + @add_test_categories(['pyapi']) + def test(self): + """Exercise SBType and SBTypeList API.""" + d = {'EXE': self.exe_name} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + exe = os.path.join(os.getcwd(), self.exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint inside function 'main'. + breakpoint = target.BreakpointCreateByLocation(self.source, self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Get Frame #0. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + + # Get the type 'Task'. + type_list = target.FindTypes('Task') + if self.TraceOn(): + print("Size of type_list from target.FindTypes('Task') query: %d" % type_list.GetSize()) + self.assertTrue(len(type_list) >= 1) # a second Task make be scared up by the Objective-C runtime + for type in type_list: + self.assertTrue(type) + self.DebugSBType(type) + self.assertFalse(type.IsAnonymousType(), "Task is not anonymous") + for field in type.fields: + if field.name == "type": + for enum_member in field.type.enum_members: + self.assertTrue(enum_member) + self.DebugSBType(enum_member.type) + elif field.name == "my_type_is_nameless": + self.assertTrue(field.type.IsAnonymousType(), "my_type_is_nameless has an anonymous type") + elif field.name == "my_type_is_named": + self.assertFalse(field.type.IsAnonymousType(), "my_type_is_named has a named type") + + # Pass an empty string. LLDB should not crash. :-) + fuzz_types = target.FindTypes(None) + fuzz_type = target.FindFirstType(None) + + # Now use the SBTarget.FindFirstType() API to find 'Task'. + task_type = target.FindFirstType('Task') + self.assertTrue(task_type) + self.DebugSBType(task_type) + + # Get the reference type of 'Task', just for fun. + task_ref_type = task_type.GetReferenceType() + self.assertTrue(task_ref_type) + self.DebugSBType(task_ref_type) + + # Get the pointer type of 'Task', which is the same as task_head's type. + task_pointer_type = task_type.GetPointerType() + self.assertTrue(task_pointer_type) + self.DebugSBType(task_pointer_type) + + # Get variable 'task_head'. + task_head = frame0.FindVariable('task_head') + self.assertTrue(task_head, VALID_VARIABLE) + self.DebugSBValue(task_head) + task_head_type = task_head.GetType() + self.DebugSBType(task_head_type) + self.assertTrue(task_head_type.IsPointerType()) + + self.assertTrue(task_head_type == task_pointer_type) + + # Get the pointee type of 'task_head'. + task_head_pointee_type = task_head_type.GetPointeeType() + self.DebugSBType(task_head_pointee_type) + + self.assertTrue(task_type == task_head_pointee_type) + + # We'll now get the child member 'id' from 'task_head'. + id = task_head.GetChildMemberWithName('id') + self.DebugSBValue(id) + id_type = id.GetType() + self.DebugSBType(id_type) + + # SBType.GetBasicType() takes an enum 'BasicType' (lldb-enumerations.h). + int_type = id_type.GetBasicType(lldb.eBasicTypeInt) + self.assertTrue(id_type == int_type) diff --git a/packages/Python/lldbsuite/test/python_api/type/main.cpp b/packages/Python/lldbsuite/test/python_api/type/main.cpp new file mode 100644 index 0000000..b7f3dcc --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/type/main.cpp @@ -0,0 +1,60 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +class Task { +public: + int id; + Task *next; + enum { + TASK_TYPE_1, + TASK_TYPE_2 + } type; + struct { + int x; + } my_type_is_nameless; + struct name { + int x; + } my_type_is_named; + Task(int i, Task *n): + id(i), + next(n), + type(TASK_TYPE_1) + {} +}; + + +int main (int argc, char const *argv[]) +{ + Task *task_head = new Task(-1, NULL); + Task *task1 = new Task(1, NULL); + Task *task2 = new Task(2, NULL); + Task *task3 = new Task(3, NULL); // Orphaned. + Task *task4 = new Task(4, NULL); + Task *task5 = new Task(5, NULL); + + task_head->next = task1; + task1->next = task2; + task2->next = task4; + task4->next = task5; + + int total = 0; + Task *t = task_head; + while (t != NULL) { + if (t->id >= 0) + ++total; + t = t->next; + } + printf("We have a total number of %d tasks\n", total); + + // This corresponds to an empty task list. + Task *empty_task_head = new Task(-1, NULL); + + return 0; // Break at this line +} diff --git a/packages/Python/lldbsuite/test/python_api/value/Makefile b/packages/Python/lldbsuite/test/python_api/value/Makefile new file mode 100644 index 0000000..0d70f25 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py b/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py new file mode 100644 index 0000000..77ff07e --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py @@ -0,0 +1,135 @@ +""" +Test some SBValue APIs. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ValueAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # We'll use the test method name as the exe_name. + self.exe_name = self.testMethodName + # Find the line number to of function 'c'. + self.line = line_number('main.c', '// Break at this line') + + @expectedFailureWindows("llvm.org/pr24772") + @add_test_categories(['pyapi']) + def test(self): + """Exercise some SBValue APIs.""" + d = {'EXE': self.exe_name} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + exe = os.path.join(os.getcwd(), self.exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint inside function 'main'. + breakpoint = target.BreakpointCreateByLocation('main.c', self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Get Frame #0. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + + # Get global variable 'days_of_week'. + list = target.FindGlobalVariables('days_of_week', 1) + days_of_week = list.GetValueAtIndex(0) + self.assertTrue(days_of_week, VALID_VARIABLE) + self.assertTrue(days_of_week.GetNumChildren() == 7, VALID_VARIABLE) + self.DebugSBValue(days_of_week) + + # Get global variable 'weekdays'. + list = target.FindGlobalVariables('weekdays', 1) + weekdays = list.GetValueAtIndex(0) + self.assertTrue(weekdays, VALID_VARIABLE) + self.assertTrue(weekdays.GetNumChildren() == 5, VALID_VARIABLE) + self.DebugSBValue(weekdays) + + # Get global variable 'g_table'. + list = target.FindGlobalVariables('g_table', 1) + g_table = list.GetValueAtIndex(0) + self.assertTrue(g_table, VALID_VARIABLE) + self.assertTrue(g_table.GetNumChildren() == 2, VALID_VARIABLE) + self.DebugSBValue(g_table) + + fmt = lldbutil.BasicFormatter() + cvf = lldbutil.ChildVisitingFormatter(indent_child=2) + rdf = lldbutil.RecursiveDecentFormatter(indent_child=2) + if self.TraceOn(): + print(fmt.format(days_of_week)) + print(cvf.format(days_of_week)) + print(cvf.format(weekdays)) + print(rdf.format(g_table)) + + # Get variable 'my_int_ptr'. + value = frame0.FindVariable('my_int_ptr') + self.assertTrue(value, VALID_VARIABLE) + self.DebugSBValue(value) + + # Get what 'my_int_ptr' points to. + pointed = value.GetChildAtIndex(0) + self.assertTrue(pointed, VALID_VARIABLE) + self.DebugSBValue(pointed) + + # While we are at it, verify that 'my_int_ptr' points to 'g_my_int'. + symbol = target.ResolveLoadAddress(int(pointed.GetLocation(), 0)).GetSymbol() + self.assertTrue(symbol) + self.expect(symbol.GetName(), exe=False, + startstr = 'g_my_int') + + # Get variable 'str_ptr'. + value = frame0.FindVariable('str_ptr') + self.assertTrue(value, VALID_VARIABLE) + self.DebugSBValue(value) + + # SBValue::TypeIsPointerType() should return true. + self.assertTrue(value.TypeIsPointerType()) + + # Verify the SBValue::GetByteSize() API is working correctly. + arch = self.getArchitecture() + if arch == 'i386': + self.assertTrue(value.GetByteSize() == 4) + elif arch == 'x86_64': + self.assertTrue(value.GetByteSize() == 8) + + # Get child at index 5 => 'Friday'. + child = value.GetChildAtIndex(5, lldb.eNoDynamicValues, True) + self.assertTrue(child, VALID_VARIABLE) + self.DebugSBValue(child) + + self.expect(child.GetSummary(), exe=False, + substrs = ['Friday']) + + # Now try to get at the same variable using GetValueForExpressionPath(). + # These two SBValue objects should have the same value. + val2 = value.GetValueForExpressionPath('[5]') + self.assertTrue(val2, VALID_VARIABLE) + self.DebugSBValue(val2) + self.assertTrue(child.GetValue() == val2.GetValue() and + child.GetSummary() == val2.GetSummary()) + + val_i = target.EvaluateExpression('i') + val_s = target.EvaluateExpression('s') + val_a = target.EvaluateExpression('a') + self.assertTrue(val_s.GetChildMemberWithName('a').AddressOf(), VALID_VARIABLE) + self.assertTrue(val_a.Cast(val_i.GetType()).AddressOf(), VALID_VARIABLE) diff --git a/packages/Python/lldbsuite/test/python_api/value/change_values/Makefile b/packages/Python/lldbsuite/test/python_api/value/change_values/Makefile new file mode 100644 index 0000000..b09a579 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value/change_values/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/value/change_values/TestChangeValueAPI.py b/packages/Python/lldbsuite/test/python_api/value/change_values/TestChangeValueAPI.py new file mode 100644 index 0000000..77aefe0 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value/change_values/TestChangeValueAPI.py @@ -0,0 +1,148 @@ +""" +Test some SBValue APIs. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ChangeValueAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # We'll use the test method name as the exe_name. + self.exe_name = self.testMethodName + # Find the line number to of function 'c'. + self.line = line_number('main.c', '// Stop here and set values') + self.check_line = line_number('main.c', '// Stop here and check values') + self.end_line = line_number ('main.c', '// Set a breakpoint here at the end') + + @expectedFailureWindows("llvm.org/pr24772") + @add_test_categories(['pyapi']) + def test_change_value(self): + """Exercise the SBValue::SetValueFromCString API.""" + d = {'EXE': self.exe_name} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + exe = os.path.join(os.getcwd(), self.exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint inside function 'main'. + breakpoint = target.BreakpointCreateByLocation('main.c', self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Create the breakpoint inside the function 'main' + check_breakpoint = target.BreakpointCreateByLocation('main.c', self.check_line) + self.assertTrue(check_breakpoint, VALID_BREAKPOINT) + + # Create the breakpoint inside function 'main'. + end_breakpoint = target.BreakpointCreateByLocation('main.c', self.end_line) + self.assertTrue(end_breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Get Frame #0. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + self.assertTrue (frame0.IsValid(), "Got a valid frame.") + + # Get the val variable and change it: + error = lldb.SBError() + + val_value = frame0.FindVariable ("val") + self.assertTrue (val_value.IsValid(), "Got the SBValue for val") + actual_value = val_value.GetValueAsSigned (error, 0); + self.assertTrue (error.Success(), "Got a value from val") + self.assertTrue (actual_value == 100, "Got the right value from val") + + result = val_value.SetValueFromCString ("12345") + self.assertTrue (result, "Setting val returned True.") + actual_value = val_value.GetValueAsSigned (error, 0); + self.assertTrue (error.Success(), "Got a changed value from val") + self.assertTrue (actual_value == 12345, "Got the right changed value from val") + + # Now check that we can set a structure element: + + mine_value = frame0.FindVariable ("mine") + self.assertTrue (mine_value.IsValid(), "Got the SBValue for mine") + + mine_second_value = mine_value.GetChildMemberWithName ("second_val") + self.assertTrue (mine_second_value.IsValid(), "Got second_val from mine") + actual_value = mine_second_value.GetValueAsUnsigned (error, 0) + self.assertTrue (error.Success(), "Got an unsigned value for second_val") + self.assertTrue (actual_value == 5555) + + result = mine_second_value.SetValueFromCString ("98765") + self.assertTrue (result, "Success setting mine.second_value.") + actual_value = mine_second_value.GetValueAsSigned (error, 0); + self.assertTrue (error.Success(), "Got a changed value from mine.second_val") + self.assertTrue (actual_value == 98765, "Got the right changed value from mine.second_val") + + # Next do the same thing with the pointer version. + ptr_value = frame0.FindVariable ("ptr") + self.assertTrue (ptr_value.IsValid(), "Got the SBValue for ptr") + + ptr_second_value = ptr_value.GetChildMemberWithName ("second_val") + self.assertTrue (ptr_second_value.IsValid(), "Got second_val from ptr") + actual_value = ptr_second_value.GetValueAsUnsigned (error, 0) + self.assertTrue (error.Success(), "Got an unsigned value for ptr->second_val") + self.assertTrue (actual_value == 6666) + + result = ptr_second_value.SetValueFromCString ("98765") + self.assertTrue (result, "Success setting ptr->second_value.") + actual_value = ptr_second_value.GetValueAsSigned (error, 0); + self.assertTrue (error.Success(), "Got a changed value from ptr->second_val") + self.assertTrue (actual_value == 98765, "Got the right changed value from ptr->second_val") + + # gcc may set multiple locations for breakpoint + breakpoint.SetEnabled(False) + + # Now continue, grab the stdout and make sure we changed the real values as well... + process.Continue(); + + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + + expected_value = "Val - 12345 Mine - 55, 98765, 55555555. Ptr - 66, 98765, 66666666" + stdout = process.GetSTDOUT(1000) + self.assertTrue (expected_value in stdout, "STDOUT showed changed values.") + + # Finally, change the stack pointer to 0, and we should not make it to our end breakpoint. + frame0 = thread.GetFrameAtIndex(0) + self.assertTrue (frame0.IsValid(), "Second time: got a valid frame.") + sp_value = frame0.FindValue ("sp", lldb.eValueTypeRegister); + self.assertTrue (sp_value.IsValid(), "Got a stack pointer value") + result = sp_value.SetValueFromCString("1") + self.assertTrue (result, "Setting sp returned true.") + actual_value = sp_value.GetValueAsUnsigned (error, 0) + self.assertTrue (error.Success(), "Got a changed value for sp") + self.assertTrue (actual_value == 1, "Got the right changed value for sp.") + + # Boundary condition test the SBValue.CreateValueFromExpression() API. + # LLDB should not crash! + nosuchval = mine_value.CreateValueFromExpression(None, None) + + process.Continue() + + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread == None, "We should not have managed to hit our second breakpoint with sp == 1") + + process.Kill() diff --git a/packages/Python/lldbsuite/test/python_api/value/change_values/main.c b/packages/Python/lldbsuite/test/python_api/value/change_values/main.c new file mode 100644 index 0000000..01455c0 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value/change_values/main.c @@ -0,0 +1,29 @@ +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> + +struct foo +{ + uint8_t first_val; + uint32_t second_val; + uint64_t third_val; +}; + +int main () +{ + int val = 100; + struct foo mine = {55, 5555, 55555555}; + struct foo *ptr = (struct foo *) malloc (sizeof (struct foo)); + ptr->first_val = 66; + ptr->second_val = 6666; + ptr->third_val = 66666666; + + // Stop here and set values + printf ("Val - %d Mine - %d, %d, %llu. Ptr - %d, %d, %llu\n", val, + mine.first_val, mine.second_val, mine.third_val, + ptr->first_val, ptr->second_val, ptr->third_val); + + // Stop here and check values + printf ("This is just another call which we won't make it over %d.", val); + return 0; // Set a breakpoint here at the end +} diff --git a/packages/Python/lldbsuite/test/python_api/value/linked_list/Makefile b/packages/Python/lldbsuite/test/python_api/value/linked_list/Makefile new file mode 100644 index 0000000..314f1cb --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value/linked_list/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/value/linked_list/TestValueAPILinkedList.py b/packages/Python/lldbsuite/test/python_api/value/linked_list/TestValueAPILinkedList.py new file mode 100644 index 0000000..22d7e7e --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value/linked_list/TestValueAPILinkedList.py @@ -0,0 +1,133 @@ +""" +Test SBValue API linked_list_iter which treats the SBValue as a linked list and +supports iteration till the end of list is reached. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ValueAsLinkedListTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # We'll use the test method name as the exe_name. + self.exe_name = self.testMethodName + # Find the line number to break at. + self.line = line_number('main.cpp', '// Break at this line') + + @add_test_categories(['pyapi']) + def test(self): + """Exercise SBValue API linked_list_iter.""" + d = {'EXE': self.exe_name} + self.build(dictionary=d) + self.setTearDownCleanup(dictionary=d) + exe = os.path.join(os.getcwd(), self.exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint inside function 'main'. + breakpoint = target.BreakpointCreateByLocation('main.cpp', self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Get Frame #0. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + + # Get variable 'task_head'. + task_head = frame0.FindVariable('task_head') + self.assertTrue(task_head, VALID_VARIABLE) + self.DebugSBValue(task_head) + + # By design (see main.cpp), the visited id's are: [1, 2, 4, 5]. + visitedIDs = [1, 2, 4, 5] + list = [] + + cvf = lldbutil.ChildVisitingFormatter(indent_child=2) + for t in task_head.linked_list_iter('next'): + self.assertTrue(t, VALID_VARIABLE) + # Make sure that 'next' corresponds to an SBValue with pointer type. + self.assertTrue(t.TypeIsPointerType()) + if self.TraceOn(): + print(cvf.format(t)) + list.append(int(t.GetChildMemberWithName("id").GetValue())) + + # Sanity checks that the we visited all the items (no more, no less). + if self.TraceOn(): + print("visited IDs:", list) + self.assertTrue(visitedIDs == list) + + # Let's exercise the linked_list_iter() API again, this time supplying + # our end of list test function. + def eol(val): + """Test function to determine end of list.""" + # End of list is reached if either the value object is invalid + # or it corresponds to a null pointer. + if not val or int(val.GetValue(), 16) == 0: + return True + # Also check the "id" for correct semantics. If id <= 0, the item + # is corrupted, let's return True to signify end of list. + if int(val.GetChildMemberWithName("id").GetValue(), 0) <= 0: + return True + + # Otherwise, return False. + return False + + list = [] + for t in task_head.linked_list_iter('next', eol): + self.assertTrue(t, VALID_VARIABLE) + # Make sure that 'next' corresponds to an SBValue with pointer type. + self.assertTrue(t.TypeIsPointerType()) + if self.TraceOn(): + print(cvf.format(t)) + list.append(int(t.GetChildMemberWithName("id").GetValue())) + + # Sanity checks that the we visited all the items (no more, no less). + if self.TraceOn(): + print("visited IDs:", list) + self.assertTrue(visitedIDs == list) + + # Get variable 'empty_task_head'. + empty_task_head = frame0.FindVariable('empty_task_head') + self.assertTrue(empty_task_head, VALID_VARIABLE) + self.DebugSBValue(empty_task_head) + + list = [] + # There is no iterable item from empty_task_head.linked_list_iter(). + for t in empty_task_head.linked_list_iter('next', eol): + if self.TraceOn(): + print(cvf.format(t)) + list.append(int(t.GetChildMemberWithName("id").GetValue())) + + self.assertTrue(len(list) == 0) + + # Get variable 'task_evil'. + task_evil = frame0.FindVariable('task_evil') + self.assertTrue(task_evil, VALID_VARIABLE) + self.DebugSBValue(task_evil) + + list = [] + # There 3 iterable items from task_evil.linked_list_iter(). :-) + for t in task_evil.linked_list_iter('next'): + if self.TraceOn(): + print(cvf.format(t)) + list.append(int(t.GetChildMemberWithName("id").GetValue())) + + self.assertTrue(len(list) == 3) diff --git a/packages/Python/lldbsuite/test/python_api/value/linked_list/main.cpp b/packages/Python/lldbsuite/test/python_api/value/linked_list/main.cpp new file mode 100644 index 0000000..50517f4 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value/linked_list/main.cpp @@ -0,0 +1,56 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +class Task { +public: + int id; + Task *next; + Task(int i, Task *n): + id(i), + next(n) + {} +}; + + +int main (int argc, char const *argv[]) +{ + Task *task_head = NULL; + Task *task1 = new Task(1, NULL); + Task *task2 = new Task(2, NULL); + Task *task3 = new Task(3, NULL); // Orphaned. + Task *task4 = new Task(4, NULL); + Task *task5 = new Task(5, NULL); + + task_head = task1; + task1->next = task2; + task2->next = task4; + task4->next = task5; + + int total = 0; + Task *t = task_head; + while (t != NULL) { + if (t->id >= 0) + ++total; + t = t->next; + } + printf("We have a total number of %d tasks\n", total); + + // This corresponds to an empty task list. + Task *empty_task_head = NULL; + + Task *task_evil = new Task(1, NULL); + Task *task_2 = new Task(2, NULL); + Task *task_3 = new Task(3, NULL); + task_evil->next = task_2; + task_2->next = task_3; + task_3->next = task_evil; // In order to cause inifinite loop. :-) + + return 0; // Break at this line +} diff --git a/packages/Python/lldbsuite/test/python_api/value/main.c b/packages/Python/lldbsuite/test/python_api/value/main.c new file mode 100644 index 0000000..a007957 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value/main.c @@ -0,0 +1,52 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to test the lldb Python API SBValue.GetChildAtIndex(). + +int g_my_int = 100; + +const char *days_of_week[7] = { "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" }; + +const char *weekdays[5] = { "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday" }; + +const char **g_table[2] = { days_of_week, weekdays }; + +typedef int MyInt; + +struct MyStruct +{ + int a; + int b; +}; + +int main (int argc, char const *argv[]) +{ + int i; + MyInt a = 12345; + struct MyStruct s = { 11, 22 }; + int *my_int_ptr = &g_my_int; + printf("my_int_ptr points to location %p\n", my_int_ptr); + const char **str_ptr = days_of_week; + for (i = 0; i < 7; ++i) + printf("%s\n", str_ptr[i]); // Break at this line + // and do str_ptr_val.GetChildAtIndex(5, lldb.eNoDynamicValues, True). + + return 0; +} diff --git a/packages/Python/lldbsuite/test/python_api/value_var_update/Makefile b/packages/Python/lldbsuite/test/python_api/value_var_update/Makefile new file mode 100644 index 0000000..4b0e581 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value_var_update/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 +# See TestHelloWorld.py, which specifies the executable name with a dictionary. +EXE := hello_world + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/value_var_update/TestValueVarUpdate.py b/packages/Python/lldbsuite/test/python_api/value_var_update/TestValueVarUpdate.py new file mode 100644 index 0000000..251bbcf --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value_var_update/TestValueVarUpdate.py @@ -0,0 +1,59 @@ +"""Test SBValue::GetValueDidChange""" + +from __future__ import print_function + + + +import os, sys, time +import lldb +import time +from lldbsuite.test.lldbtest import * + +class HelloWorldTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Get the full path to our executable to be attached/debugged. + self.exe = os.path.join(os.getcwd(), self.testMethodName) + self.d = {'EXE': self.testMethodName} + + @add_test_categories(['pyapi']) + def test_with_process_launch_api(self): + """Test SBValue::GetValueDidChange""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + target = self.dbg.CreateTarget(self.exe) + + breakpoint = target.BreakpointCreateBySourceRegex("break here", lldb.SBFileSpec("main.c")) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + i = self.frame().FindVariable("i") + i_val = i.GetValueAsUnsigned(0) + c = self.frame().FindVariable("c") + + # Update any values from the SBValue objects so we can ask them if they changed after a continue + i.GetValueDidChange() + c.GetChildAtIndex(1).GetValueDidChange() + c.GetChildAtIndex(0).GetChildAtIndex(0).GetValueDidChange() + + if self.TraceOn(): self.runCmd("frame variable") + + self.runCmd("continue") + + if self.TraceOn(): self.runCmd("frame variable") + + self.assertTrue(i_val != i.GetValueAsUnsigned(0), "GetValue() is saying a lie") + self.assertTrue(i.GetValueDidChange(), "GetValueDidChange() is saying a lie") + + # Check complex type + self.assertTrue(c.GetChildAtIndex(0).GetChildAtIndex(0).GetValueDidChange() and + not c.GetChildAtIndex(1).GetValueDidChange(), "GetValueDidChange() is saying a lie") diff --git a/packages/Python/lldbsuite/test/python_api/value_var_update/main.c b/packages/Python/lldbsuite/test/python_api/value_var_update/main.c new file mode 100644 index 0000000..9ffca5c --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/value_var_update/main.c @@ -0,0 +1,15 @@ +struct complex_type { + struct { long l; } inner; + struct complex_type *complex_ptr; +}; + +int main() { + int i = 0; + struct complex_type c = { { 1L }, &c }; + for (int j = 3; j < 20; j++) + { + c.inner.l += (i += j); + i = i - 1; // break here + } + return i; +} diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/Makefile b/packages/Python/lldbsuite/test/python_api/watchpoint/Makefile new file mode 100644 index 0000000..0d70f25 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py b/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py new file mode 100644 index 0000000..264e212 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py @@ -0,0 +1,93 @@ +""" +Use lldb Python SBValue API to create a watchpoint for read_write of 'globl' var. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class SetWatchpointAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.c' + # Find the line number to break inside main(). + self.line = line_number(self.source, '// Set break point at this line.') + + @add_test_categories(['pyapi']) + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_watch_val(self): + """Exercise SBValue.Watch() API to set a watchpoint.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c. + breakpoint = target.BreakpointCreateByLocation(self.source, self.line) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + # We should be stopped due to the breakpoint. Get frame #0. + process = target.GetProcess() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + frame0 = thread.GetFrameAtIndex(0) + + # Watch 'global' for read and write. + value = frame0.FindValue('global', lldb.eValueTypeVariableGlobal) + error = lldb.SBError(); + watchpoint = value.Watch(True, True, True, error) + self.assertTrue(value and watchpoint, + "Successfully found the variable and set a watchpoint") + self.DebugSBValue(value) + + # Hide stdout if not running with '-t' option. + if not self.TraceOn(): + self.HideStdout() + + print(watchpoint) + + # Continue. Expect the program to stop due to the variable being written to. + process.Continue() + + if (self.TraceOn()): + lldbutil.print_stacktraces(process) + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) + self.assertTrue(thread, "The thread stopped due to watchpoint") + self.DebugSBValue(value) + + # Continue. Expect the program to stop due to the variable being read from. + process.Continue() + + if (self.TraceOn()): + lldbutil.print_stacktraces(process) + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) + self.assertTrue(thread, "The thread stopped due to watchpoint") + self.DebugSBValue(value) + + # Continue the process. We don't expect the program to be stopped again. + process.Continue() + + # At this point, the inferior process should have exited. + self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED) diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py b/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py new file mode 100644 index 0000000..a15e733 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py @@ -0,0 +1,89 @@ +""" +Use lldb Python SBWatchpoint API to set the ignore count. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class WatchpointIgnoreCountTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.c' + # Find the line number to break inside main(). + self.line = line_number(self.source, '// Set break point at this line.') + + @add_test_categories(['pyapi']) + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_set_watch_ignore_count(self): + """Test SBWatchpoint.SetIgnoreCount() API.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create a breakpoint on main.c in order to set our watchpoint later. + breakpoint = target.BreakpointCreateByLocation(self.source, self.line) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + # We should be stopped due to the breakpoint. Get frame #0. + process = target.GetProcess() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + frame0 = thread.GetFrameAtIndex(0) + + # Watch 'global' for read and write. + value = frame0.FindValue('global', lldb.eValueTypeVariableGlobal) + error = lldb.SBError(); + watchpoint = value.Watch(True, True, True, error) + self.assertTrue(value and watchpoint, + "Successfully found the variable and set a watchpoint") + self.DebugSBValue(value) + + # Hide stdout if not running with '-t' option. + if not self.TraceOn(): + self.HideStdout() + + # There should be only 1 watchpoint location under the target. + self.assertTrue(target.GetNumWatchpoints() == 1) + watchpoint = target.GetWatchpointAtIndex(0) + self.assertTrue(watchpoint.IsEnabled()) + self.assertTrue(watchpoint.GetIgnoreCount() == 0) + watch_id = watchpoint.GetID() + self.assertTrue(watch_id != 0) + print(watchpoint) + + # Now immediately set the ignore count to 2. When we continue, expect the + # inferior to run to its completion without stopping due to watchpoint. + watchpoint.SetIgnoreCount(2) + print(watchpoint) + process.Continue() + + # At this point, the inferior process should have exited. + self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED) + + # Verify some vital statistics. + self.assertTrue(watchpoint) + self.assertTrue(watchpoint.GetWatchSize() == 4) + self.assertTrue(watchpoint.GetHitCount() == 2) + print(watchpoint) diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py b/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py new file mode 100644 index 0000000..3154502 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py @@ -0,0 +1,115 @@ +""" +Use lldb Python SBTarget API to iterate on the watchpoint(s) for the target. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class WatchpointIteratorTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.c' + # Find the line number to break inside main(). + self.line = line_number(self.source, '// Set break point at this line.') + + @add_test_categories(['pyapi']) + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_watch_iter(self): + """Exercise SBTarget.watchpoint_iter() API to iterate on the available watchpoints.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create a breakpoint on main.c in order to set our watchpoint later. + breakpoint = target.BreakpointCreateByLocation(self.source, self.line) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + # We should be stopped due to the breakpoint. Get frame #0. + process = target.GetProcess() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + frame0 = thread.GetFrameAtIndex(0) + + # Watch 'global' for read and write. + value = frame0.FindValue('global', lldb.eValueTypeVariableGlobal) + error = lldb.SBError(); + watchpoint = value.Watch(True, True, True, error) + self.assertTrue(value and watchpoint, + "Successfully found the variable and set a watchpoint") + self.DebugSBValue(value) + + # Hide stdout if not running with '-t' option. + if not self.TraceOn(): + self.HideStdout() + + # There should be only 1 watchpoint location under the target. + self.assertTrue(target.GetNumWatchpoints() == 1) + self.assertTrue(watchpoint.IsEnabled()) + watch_id = watchpoint.GetID() + self.assertTrue(watch_id != 0) + + # Continue. Expect the program to stop due to the variable being written to. + process.Continue() + + # Hide stdout if not running with '-t' option. + if not self.TraceOn(): + self.HideStdout() + + # Print the stack traces. + lldbutil.print_stacktraces(process) + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) + self.assertTrue(thread, "The thread stopped due to watchpoint") + self.DebugSBValue(value) + + # We currently only support hardware watchpoint. Verify that we have a + # meaningful hardware index at this point. Exercise the printed repr of + # SBWatchpointLocation. + print(watchpoint) + self.assertTrue(watchpoint.GetHardwareIndex() != -1) + + # SBWatchpoint.GetDescription() takes a description level arg. + print(lldbutil.get_description(watchpoint, lldb.eDescriptionLevelFull)) + + # Now disable the 'rw' watchpoint. The program won't stop when it reads + # 'global' next. + watchpoint.SetEnabled(False) + self.assertTrue(watchpoint.GetHardwareIndex() == -1) + self.assertFalse(watchpoint.IsEnabled()) + + # Continue. The program does not stop again when the variable is being + # read from because the watchpoint location has been disabled. + process.Continue() + + # At this point, the inferior process should have exited. + self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED) + + # Verify some vital statistics and exercise the iterator API. + for watchpoint in target.watchpoint_iter(): + self.assertTrue(watchpoint) + self.assertTrue(watchpoint.GetWatchSize() == 4) + self.assertTrue(watchpoint.GetHitCount() == 1) + print(watchpoint) + diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/condition/Makefile b/packages/Python/lldbsuite/test/python_api/watchpoint/condition/Makefile new file mode 100644 index 0000000..314f1cb --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/condition/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/condition/TestWatchpointConditionAPI.py b/packages/Python/lldbsuite/test/python_api/watchpoint/condition/TestWatchpointConditionAPI.py new file mode 100644 index 0000000..f30bf85 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/condition/TestWatchpointConditionAPI.py @@ -0,0 +1,89 @@ +""" +Test watchpoint condition API. +""" + +from __future__ import print_function + + + +import os, time +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class WatchpointConditionAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.cpp' + # Find the line number to break inside main(). + self.line = line_number(self.source, '// Set break point at this line.') + # And the watchpoint variable declaration line number. + self.decl = line_number(self.source, '// Watchpoint variable declaration.') + # Build dictionary to have unique executable names for each test method. + self.exe_name = self.testMethodName + self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} + + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @skipIfWindows # Watchpoints not supported on Windows, and this test hangs + def test_watchpoint_cond_api(self): + """Test watchpoint condition API.""" + self.build(dictionary=self.d) + self.setTearDownCleanup(dictionary=self.d) + exe = os.path.join(os.getcwd(), self.exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c. + breakpoint = target.BreakpointCreateByLocation(self.source, self.line) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + # We should be stopped due to the breakpoint. Get frame #0. + process = target.GetProcess() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + frame0 = thread.GetFrameAtIndex(0) + + # Watch 'global' for write. + value = frame0.FindValue('global', lldb.eValueTypeVariableGlobal) + error = lldb.SBError(); + watchpoint = value.Watch(True, False, True, error) + self.assertTrue(value and watchpoint, + "Successfully found the variable and set a watchpoint") + self.DebugSBValue(value) + + # Now set the condition as "global==5". + watchpoint.SetCondition('global==5') + self.expect(watchpoint.GetCondition(), exe=False, + startstr = 'global==5') + + # Hide stdout if not running with '-t' option. + if not self.TraceOn(): + self.HideStdout() + + print(watchpoint) + + # Continue. Expect the program to stop due to the variable being written to. + process.Continue() + + if (self.TraceOn()): + lldbutil.print_stacktraces(process) + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) + self.assertTrue(thread, "The thread stopped due to watchpoint") + self.DebugSBValue(value) + + # Verify that the condition is met. + self.assertTrue(value.GetValueAsUnsigned() == 5) diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/condition/main.cpp b/packages/Python/lldbsuite/test/python_api/watchpoint/condition/main.cpp new file mode 100644 index 0000000..f4c3527 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/condition/main.cpp @@ -0,0 +1,28 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdint.h> + +int32_t global = 0; // Watchpoint variable declaration. + +static void modify(int32_t &var) { + ++var; +} + +int main(int argc, char** argv) { + int local = 0; + printf("&global=%p\n", &global); + printf("about to write to 'global'...\n"); // Set break point at this line. + // When stopped, watch 'global', + // for the condition "global == 5". + for (int i = 0; i < 10; ++i) + modify(global); + + printf("global=%d\n", global); +} diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/main.c b/packages/Python/lldbsuite/test/python_api/watchpoint/main.c new file mode 100644 index 0000000..4753edf --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/main.c @@ -0,0 +1,24 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdio.h> +#include <stdint.h> + +int32_t global = 10; // Watchpoint variable declaration. + +int main(int argc, char** argv) { + int local = 0; + printf("&global=%p\n", &global); + printf("about to write to 'global'...\n"); // Set break point at this line. + // When stopped, watch 'global' for read&write. + global = 20; + local += argc; + ++local; + printf("local: %d\n", local); + printf("global=%d\n", global); +} diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/Makefile b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/Makefile new file mode 100644 index 0000000..8817fff --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +ENABLE_THREADS := YES +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestSetWatchlocation.py b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestSetWatchlocation.py new file mode 100644 index 0000000..5a4a464 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestSetWatchlocation.py @@ -0,0 +1,90 @@ +""" +Use lldb Python SBValue.WatchPointee() API to create a watchpoint for write of '*g_char_ptr'. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class SetWatchlocationAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.cpp' + # Find the line number to break inside main(). + self.line = line_number(self.source, '// Set break point at this line.') + # This is for verifying that watch location works. + self.violating_func = "do_bad_thing_with_location"; + + @add_test_categories(['pyapi']) + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") # WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows + def test_watch_location(self): + """Exercise SBValue.WatchPointee() API to set a watchpoint.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c. + breakpoint = target.BreakpointCreateByLocation(self.source, self.line) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + # We should be stopped due to the breakpoint. Get frame #0. + process = target.GetProcess() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + frame0 = thread.GetFrameAtIndex(0) + + value = frame0.FindValue('g_char_ptr', + lldb.eValueTypeVariableGlobal) + pointee = value.CreateValueFromAddress("pointee", + value.GetValueAsUnsigned(0), + value.GetType().GetPointeeType()) + # Watch for write to *g_char_ptr. + error = lldb.SBError(); + watchpoint = value.WatchPointee(True, False, True, error) + self.assertTrue(value and watchpoint, + "Successfully found the pointer and set a watchpoint") + self.DebugSBValue(value) + self.DebugSBValue(pointee) + + # Hide stdout if not running with '-t' option. + if not self.TraceOn(): + self.HideStdout() + + print(watchpoint) + + # Continue. Expect the program to stop due to the variable being written to. + process.Continue() + + if (self.TraceOn()): + lldbutil.print_stacktraces(process) + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) + self.assertTrue(thread, "The thread stopped due to watchpoint") + self.DebugSBValue(value) + self.DebugSBValue(pointee) + + self.expect(lldbutil.print_stacktrace(thread, string_buffer=True), exe=False, + substrs = [self.violating_func]) + + # This finishes our test. diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py new file mode 100644 index 0000000..6facbaa --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py @@ -0,0 +1,130 @@ +""" +Use lldb Python SBtarget.WatchAddress() API to create a watchpoint for write of '*g_char_ptr'. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class TargetWatchAddressAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Our simple source filename. + self.source = 'main.cpp' + # Find the line number to break inside main(). + self.line = line_number(self.source, '// Set break point at this line.') + # This is for verifying that watch location works. + self.violating_func = "do_bad_thing_with_location"; + + @add_test_categories(['pyapi']) + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @expectedFailureWindows("llvm.org/pr24446") + def test_watch_address(self): + """Exercise SBTarget.WatchAddress() API to set a watchpoint.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c. + breakpoint = target.BreakpointCreateByLocation(self.source, self.line) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + # We should be stopped due to the breakpoint. Get frame #0. + process = target.GetProcess() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + frame0 = thread.GetFrameAtIndex(0) + + value = frame0.FindValue('g_char_ptr', + lldb.eValueTypeVariableGlobal) + pointee = value.CreateValueFromAddress("pointee", + value.GetValueAsUnsigned(0), + value.GetType().GetPointeeType()) + # Watch for write to *g_char_ptr. + error = lldb.SBError(); + watchpoint = target.WatchAddress(value.GetValueAsUnsigned(), 1, False, True, error) + self.assertTrue(value and watchpoint, + "Successfully found the pointer and set a watchpoint") + self.DebugSBValue(value) + self.DebugSBValue(pointee) + + # Hide stdout if not running with '-t' option. + if not self.TraceOn(): + self.HideStdout() + + print(watchpoint) + + # Continue. Expect the program to stop due to the variable being written to. + process.Continue() + + if (self.TraceOn()): + lldbutil.print_stacktraces(process) + + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonWatchpoint) + self.assertTrue(thread, "The thread stopped due to watchpoint") + self.DebugSBValue(value) + self.DebugSBValue(pointee) + + self.expect(lldbutil.print_stacktrace(thread, string_buffer=True), exe=False, + substrs = [self.violating_func]) + + # This finishes our test. + + @add_test_categories(['pyapi']) + @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported + @skipIf(archs=['mips', 'mipsel', 'mips64', 'mips64el']) # No size constraint on MIPS for watches + def test_watch_address_with_invalid_watch_size(self): + """Exercise SBTarget.WatchAddress() API but pass an invalid watch_size.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c. + breakpoint = target.BreakpointCreateByLocation(self.source, self.line) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple (None, None, self.get_process_working_directory()) + + # We should be stopped due to the breakpoint. Get frame #0. + process = target.GetProcess() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + frame0 = thread.GetFrameAtIndex(0) + + value = frame0.FindValue('g_char_ptr', + lldb.eValueTypeVariableGlobal) + pointee = value.CreateValueFromAddress("pointee", + value.GetValueAsUnsigned(0), + value.GetType().GetPointeeType()) + # Watch for write to *g_char_ptr. + error = lldb.SBError(); + watchpoint = target.WatchAddress(value.GetValueAsUnsigned(), 365, False, True, error) + self.assertFalse(watchpoint) + self.expect(error.GetCString(), exe=False, + substrs = ['watch size of %d is not supported' % 365]) diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/main.cpp b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/main.cpp new file mode 100644 index 0000000..a197a92 --- /dev/null +++ b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/main.cpp @@ -0,0 +1,104 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <chrono> +#include <condition_variable> +#include <cstdio> +#include <random> +#include <thread> + +std::default_random_engine g_random_engine{std::random_device{}()}; +std::uniform_int_distribution<> g_distribution{0, 3000000}; +std::condition_variable g_condition_variable; +std::mutex g_mutex; +int g_count; + +char *g_char_ptr = nullptr; + +void +barrier_wait() +{ + std::unique_lock<std::mutex> lock{g_mutex}; + if (--g_count > 0) + g_condition_variable.wait(lock); + else + g_condition_variable.notify_all(); +} + +void +do_bad_thing_with_location(char *char_ptr, char new_val) +{ + *char_ptr = new_val; +} + +uint32_t +access_pool (bool flag = false) +{ + static std::mutex g_access_mutex; + if (!flag) + g_access_mutex.lock(); + + char old_val = *g_char_ptr; + if (flag) + do_bad_thing_with_location(g_char_ptr, old_val + 1); + + if (!flag) + g_access_mutex.unlock(); + return *g_char_ptr; +} + +void +thread_func (uint32_t thread_index) +{ + printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); + + barrier_wait(); + + uint32_t count = 0; + uint32_t val; + while (count++ < 15) + { + // random micro second sleep from zero to 3 seconds + int usec = g_distribution(g_random_engine); + printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); + std::this_thread::sleep_for(std::chrono::microseconds{usec}); + + if (count < 7) + val = access_pool (); + else + val = access_pool (true); + + printf ("%s (thread = %u) after usleep access_pool returns %d (count=%d)...\n", __FUNCTION__, thread_index, val, count); + } + printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); +} + + +int main (int argc, char const *argv[]) +{ + g_count = 4; + std::thread threads[3]; + + g_char_ptr = new char{}; + + // Create 3 threads + for (auto &thread : threads) + thread = std::thread{thread_func, std::distance(threads, &thread)}; + + printf ("Before turning all three threads loose...\n"); // Set break point at this line. + barrier_wait(); + + // Join all of our threads + for (auto &thread : threads) + thread.join(); + + delete g_char_ptr; + + return 0; +} |