Index: include/lldb/API/SBInstruction.h =================================================================== --- include/lldb/API/SBInstruction.h +++ include/lldb/API/SBInstruction.h @@ -60,6 +60,9 @@ bool DoesBranch (); + bool + HasDelaySlot (); + void Print (FILE *out); Index: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/Makefile =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules Index: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/TestAvoidBreakpointInDelaySlot.py @@ -0,0 +1,82 @@ +""" +Test specific to MIPS +""" + +import os, time +import re +import unittest2 +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class AvoidBreakpointInDelaySlotAPITestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessMips + def test(self): + self.build() + exe = os.path.join(os.getcwd(), "a.out") + self.expect("file " + exe, + patterns = [ "Current executable set to .*a.out.*" ]) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + breakpoint = target.BreakpointCreateByName('main', 'a.out') + 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) + + list = target.FindFunctions('foo', lldb.eFunctionNameTypeAuto) + self.assertTrue(list.GetSize() == 1) + sc = list.GetContextAtIndex(0) + self.assertTrue(sc.GetSymbol().GetName() == "foo") + function = sc.GetFunction() + self.assertTrue(function) + self.function(function, target) + + def function (self, function, target): + """Iterate over instructions in function and place a breakpoint on delay slot instruction""" + # Get the list of all instructions in the function + insts = function.GetInstructions(target) + print insts + i = 0 + for inst in insts: + if (inst.HasDelaySlot()): + # Remember the address of branch instruction. + branchinstaddress = inst.GetAddress().GetLoadAddress(target) + + # Get next instruction i.e delay slot instruction. + delayinst = insts.GetInstructionAtIndex(i+1) + delayinstaddr = delayinst.GetAddress().GetLoadAddress(target) + + # Set breakpoint on delay slot instruction + breakpoint = target.BreakpointCreateByAddress(delayinstaddr) + + # Verify the breakpoint. + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + # Get the location from breakpoint + location = breakpoint.GetLocationAtIndex(0) + + # Get the address where breakpoint is actually set. + bpaddr = location.GetLoadAddress() + + # Breakpoint address should be adjusted to the address of branch instruction. + self.assertTrue(branchinstaddress == bpaddr) + i += 1 + else: + i += 1 + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Index: packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/main.c =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_in_delayslot/main.c @@ -0,0 +1,21 @@ +#include + +foo (int a, int b) +{ + int c; + if (a<=b) + c=b-a; + else + c=b+a; + return c; +} + +int main() +{ + int a=7, b=8, c; + + c = foo(a, b); + +return 0; +} + Index: packages/Python/lldbsuite/test/lldbtest.py =================================================================== --- packages/Python/lldbsuite/test/lldbtest.py +++ packages/Python/lldbsuite/test/lldbtest.py @@ -1218,6 +1218,21 @@ func(*args, **kwargs) return wrapper +def skipUnlessMips(func): + """Decorate the item to skip tests that should be skipped only if not building for any of the mips targets.""" + if isinstance(func, type) and issubclass(func, unittest2.TestCase): + raise Exception("@skipIfNotMips can only be used to decorate a test method") + @wraps(func) + def wrapper(*args, **kwargs): + from unittest2 import case + self = args[0] + arch = self.getArchitecture() + if not re.match('mips', arch): + self.skipTest("skipping because this is a mips specific test") + else: + func(*args, **kwargs) + return wrapper + class _PlatformContext(object): """Value object class which contains platform-specific options.""" Index: scripts/interface/SBInstruction.i =================================================================== --- scripts/interface/SBInstruction.i +++ scripts/interface/SBInstruction.i @@ -51,6 +51,9 @@ bool DoesBranch (); + bool + HasDelaySlot (); + void Print (FILE *out); Index: source/API/SBInstruction.cpp =================================================================== --- source/API/SBInstruction.cpp +++ source/API/SBInstruction.cpp @@ -160,6 +160,14 @@ return false; } +bool +SBInstruction::HasDelaySlot () +{ + if (m_opaque_sp) + return m_opaque_sp->HasDelaySlot (); + return false; +} + void SBInstruction::SetOpaque (const lldb::InstructionSP &inst_sp) {