[LLDB][MIPS] A small fix in GetBreakableLoadAddress() for MIPS

SUMMARY:
    Get the load address for the address given by symbol and function.
    Earlier, this was done for function only, this patch does it for symbol too.
    This patch also adds TestAvoidBreakpointInDelaySlot.py to test this change.
    
    Reviewers: clayborg
    Subscribers: labath, zturner, mohit.bhakkad, sagar, jaydeep, lldb-commits
    Differential Revision: http://reviews.llvm.org/D16049

llvm-svn: 258919
This commit is contained in:
Bhushan D. Attarde 2016-01-27 10:16:30 +00:00
parent 5e45630edf
commit df5f0b448c
8 changed files with 143 additions and 13 deletions

View File

@ -60,6 +60,9 @@ public:
bool bool
DoesBranch (); DoesBranch ();
bool
HasDelaySlot ();
void void
Print (FILE *out); Print (FILE *out);

View File

@ -0,0 +1,6 @@
LEVEL = ../../../make
C_SOURCES := main.c
include $(LEVEL)/Makefile.rules

View File

@ -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__)
@skipUnlessArch(archs=re.compile('mips*'))
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()

View File

@ -0,0 +1,21 @@
#include <stdio.h>
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;
}

View File

@ -636,6 +636,14 @@ def check_list_or_lambda(list_or_lambda, value):
else: else:
return list_or_lambda is None or value is None or list_or_lambda == value return list_or_lambda is None or value is None or list_or_lambda == value
def matchArchitectures(archs, actual_arch):
retype = type(re.compile('hello, world'))
list_passes = isinstance(archs, list) and actual_arch in archs
basestring_passes = isinstance(archs, basestring) and actual_arch == archs
regex_passes = isinstance(archs, retype) and re.match(archs, actual_arch)
return (list_passes or basestring_passes or regex_passes)
# provide a function to xfail on defined oslist, compiler version, and archs # provide a function to xfail on defined oslist, compiler version, and archs
# if none is specified for any argument, that argument won't be checked and thus means for all # if none is specified for any argument, that argument won't be checked and thus means for all
# for example, # for example,
@ -1029,7 +1037,7 @@ def skipUnlessHostPlatform(oslist):
return unittest2.skipUnless(getHostPlatform() in oslist, return unittest2.skipUnless(getHostPlatform() in oslist,
"requires on of %s" % (", ".join(oslist))) "requires on of %s" % (", ".join(oslist)))
def skipUnlessArch(archlist): def skipUnlessArch(archs):
"""Decorate the item to skip tests unless running on one of the listed architectures.""" """Decorate the item to skip tests unless running on one of the listed architectures."""
def myImpl(func): def myImpl(func):
if isinstance(func, type) and issubclass(func, unittest2.TestCase): if isinstance(func, type) and issubclass(func, unittest2.TestCase):
@ -1038,9 +1046,8 @@ def skipUnlessArch(archlist):
@wraps(func) @wraps(func)
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
self = args[0] self = args[0]
if self.getArchitecture() not in archlist: if not matchArchitectures(archs, self.getArchitecture()):
self.skipTest("skipping for architecture %s (requires one of %s)" % self.skipTest("skipping for architecture %s" % (self.getArchitecture()))
(self.getArchitecture(), ", ".join(archlist)))
else: else:
func(*args, **kwargs) func(*args, **kwargs)
return wrapper return wrapper

View File

@ -51,6 +51,9 @@ public:
bool bool
DoesBranch (); DoesBranch ();
bool
HasDelaySlot ();
void void
Print (FILE *out); Print (FILE *out);

View File

@ -160,6 +160,14 @@ SBInstruction::DoesBranch ()
return false; return false;
} }
bool
SBInstruction::HasDelaySlot ()
{
if (m_opaque_sp)
return m_opaque_sp->HasDelaySlot ();
return false;
}
void void
SBInstruction::SetOpaque (const lldb::InstructionSP &inst_sp) SBInstruction::SetOpaque (const lldb::InstructionSP &inst_sp)
{ {

View File

@ -2442,18 +2442,18 @@ Target::GetBreakableLoadAddress (lldb::addr_t addr)
SymbolContext sc; SymbolContext sc;
uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol; uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr, resolve_scope, sc); temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr, resolve_scope, sc);
Address sym_addr;
if (sc.function) if (sc.function)
{ sym_addr = sc.function->GetAddressRange().GetBaseAddress();
function_start = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(this);
if (function_start == LLDB_INVALID_ADDRESS)
function_start = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
}
else if (sc.symbol) else if (sc.symbol)
{ sym_addr = sc.symbol->GetAddress();
Address sym_addr = sc.symbol->GetAddress();
function_start = sym_addr.GetLoadAddress(this);
if (function_start == LLDB_INVALID_ADDRESS)
function_start = sym_addr.GetFileAddress(); function_start = sym_addr.GetFileAddress();
}
current_offset = addr - function_start; if (function_start)
current_offset = addr - function_start;
} }
// If breakpoint address is start of function then we dont have to do anything. // If breakpoint address is start of function then we dont have to do anything.