Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lldb/include/lldb/Target/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,13 @@ class ProcessModID {
return m_resume_id == m_last_user_expression_resume;
}

bool IsRunningExpression() const {
// Don't return true if we are no longer running an expression:
if (m_running_user_expression || m_running_utility_function)
return true;
return false;
}

void SetRunningUserExpression(bool on) {
if (on)
m_running_user_expression++;
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Target/StopInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ class StopInfoBreakpoint : public StopInfo {

ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
Process *process = exe_ctx.GetProcessPtr();
if (process->GetModIDRef().IsLastResumeForUserExpression()) {
if (process->GetModIDRef().IsRunningExpression()) {
// If we are in the middle of evaluating an expression, don't run
// asynchronous breakpoint commands or expressions. That could
// lead to infinite recursion if the command or condition re-calls
Expand Down
4 changes: 4 additions & 0 deletions lldb/test/API/macosx/objc_exception_recognizer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
OBJC_SOURCES := main.m
LD_EXTRAS := -framework Foundation

include Makefile.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""
Test that the built in ObjC exception throw recognizer works
"""

import lldb
from lldbsuite.test.decorators import *
import lldbsuite.test.lldbutil as lldbutil
from lldbsuite.test.lldbtest import *

class TestObjCRecognizer(TestBase):

NO_DEBUG_INFO_TESTCASE = True

@skipUnlessDarwin
def test_exception_recognizer_sub_class(self):
"""There can be many tests in a test case - describe this test here."""
self.build()
self.main_source_file = lldb.SBFileSpec("main.m")
self.objc_recognizer_test(True)

@skipUnlessDarwin
def test_exception_recognizer_plain(self):
"""There can be many tests in a test case - describe this test here."""
self.build()
self.main_source_file = lldb.SBFileSpec("main.m")
self.objc_recognizer_test(False)

def objc_recognizer_test(self, sub_class):
"""Make sure we stop at the exception and get all the fields out of the recognizer.
If sub_class is True, we make a subclass of NSException and throw that."""
if sub_class:
bkpt_string = "Set a breakpoint here for MyException"
else:
bkpt_string = "Set a breakpoint here for plain exception"

(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
bkpt_string, self.main_source_file)

# Now turn on the ObjC Exception breakpoint and continue to hit it:
exception_bkpt = target.BreakpointCreateForException(lldb.eLanguageTypeObjC, False, True)
self.assertTrue(exception_bkpt.GetNumLocations() > 0, "Got some exception locations")

threads = lldbutil.continue_to_breakpoint(process, exception_bkpt)
self.assertEqual(len(threads), 1, "One thread hit exception breakpoint")
frame = threads[0].frame[0]

# This test relies on the dereference argument to ValueCheck, which isn't on
# this branch, so I'm skipping that portion of the test.
return

var_opts = lldb.SBVariablesOptions()
var_opts.SetIncludeRecognizedArguments(True)
var_opts.SetUseDynamic(True)
vars = frame.GetVariables(var_opts)
self.assertEqual(len(vars), 1, "Got the synthetic argument")
self.assertTrue(vars[0].IsValid(), "Got a valid Exception variable")

# This will be a pointer

ns_exception_children = [ValueCheck(type="NSObject"),
ValueCheck(name="name", summary='"NSException"'),
ValueCheck(name="reason", summary='"Simple Reason"'),
ValueCheck(name="userInfo"),
ValueCheck(name="reserved")]
ns_exception = ValueCheck(type="NSException", children=ns_exception_children)
if not sub_class:
simple_check = ValueCheck(name="exception", dereference=ns_exception)
simple_check.check_value(self, vars[0], "Simple exception is right")
else:
my_exception_children = [ns_exception, ValueCheck(name="extra_info", type="int", value="100")]
my_exception = ValueCheck(type="MyException", children=my_exception_children)
sub_check = ValueCheck(name="exception", type="MyException *", dereference=my_exception)
sub_check.check_value(self, vars[0], "Subclass exception is right")
37 changes: 37 additions & 0 deletions lldb/test/API/macosx/objc_exception_recognizer/main.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#import <Foundation/Foundation.h>

@interface MyException : NSException
{
int extra_info;
}
- (NSException *) initWithExtraInfo: (int) info;
@end

@implementation MyException
- (NSException *) initWithExtraInfo: (int) info
{
[super initWithName: @"NSException" reason: @"Simple Reason" userInfo: nil];
self->extra_info = info;
return self;
}
@end

int
main(int argc, char **argv)
{
// Set a breakpoint here for plain exception:
@try {
NSException *plain_exc = [[NSException alloc] initWithName: @"NSException" reason: @"Simple Reason" userInfo: nil];
[plain_exc raise];
}
@catch (id anException) {}

// Set a breakpoint here for MyException:
@try {
MyException *my_exc = [[MyException alloc] initWithExtraInfo: 100];
[my_exc raise];
}
@catch (id anException) {}

return 0;
}