Index: include/lldb/API/SBModule.h =================================================================== --- include/lldb/API/SBModule.h +++ include/lldb/API/SBModule.h @@ -309,6 +309,7 @@ lldb::SBFileSpec GetSymbolFileSpec() const; lldb::SBAddress GetObjectFileHeaderAddress() const; + lldb::SBAddress GetObjectFileEntryPointAddress() const; private: friend class SBAddress; Index: packages/Python/lldbsuite/test/functionalities/expr-entry-bp/Makefile =================================================================== --- packages/Python/lldbsuite/test/functionalities/expr-entry-bp/Makefile +++ packages/Python/lldbsuite/test/functionalities/expr-entry-bp/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules Index: packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py +++ packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py @@ -0,0 +1,34 @@ +""" +Tests expressions evaluation when the breakpoint on module's entry is set. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ExprEntryBPTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_expr_entry_bp(self): + """Tests expressions evaluation when the breakpoint on module's entry is set.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file) + + self.assertEqual(1, bkpt.GetNumLocations()) + entry = bkpt.GetLocationAtIndex(0).GetAddress().GetModule().GetObjectFileEntryPointAddress() + self.assertTrue(entry.IsValid(), "Can't get a module entry point") + + entry_bp = target.BreakpointCreateBySBAddress(entry) + self.assertTrue(entry_bp.IsValid(), "Can't set a breakpoint on the module entry point") + + result = target.EvaluateExpression("sum(7, 1)") + self.assertTrue(result.IsValid(), "Can't evaluate expression") + self.assertEqual(8, result.GetValueAsSigned()) + + def setUp(self): + TestBase.setUp(self) Index: packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c =================================================================== --- packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c +++ packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c @@ -0,0 +1,10 @@ +#include + +int sum(int x, int y) { + return x + y; +} + +int main() { + printf("Set a breakpoint here.\n"); + return sum(-1, 1); +} Index: scripts/interface/SBModule.i =================================================================== --- scripts/interface/SBModule.i +++ scripts/interface/SBModule.i @@ -332,6 +332,9 @@ lldb::SBAddress GetObjectFileHeaderAddress() const; + lldb::SBAddress + GetObjectFileEntryPointAddress() const; + bool operator == (const lldb::SBModule &rhs) const; Index: source/API/SBModule.cpp =================================================================== --- source/API/SBModule.cpp +++ source/API/SBModule.cpp @@ -591,3 +591,14 @@ } return sb_addr; } + +lldb::SBAddress SBModule::GetObjectFileEntryPointAddress() const { + lldb::SBAddress sb_addr; + ModuleSP module_sp(GetSP()); + if (module_sp) { + ObjectFile *objfile_ptr = module_sp->GetObjectFile(); + if (objfile_ptr) + sb_addr.ref() = objfile_ptr->GetEntryPointAddress(); + } + return sb_addr; +} Index: source/Target/StopInfo.cpp =================================================================== --- source/Target/StopInfo.cpp +++ source/Target/StopInfo.cpp @@ -329,6 +329,19 @@ // commands when we see the same breakpoint hit a second time. m_should_stop_is_valid = true; + + // It is possible that the user has a breakpoint at the same site + // as the completed plan had (e.g. user has a breakpoint + // on a module entry point, and `ThreadPlanCallFunction` ends + // also there). We can't find an internal breakpoint in the loop + // later because it was already removed on the plan completion. + // So check if the plan was completed, and stop if so. + if (thread_sp->CompletedPlanOverridesBreakpoint()) { + m_should_stop = true; + thread_sp->ResetStopInfo(); + return; + } + if (log) log->Printf("StopInfoBreakpoint::PerformAction - Hit a " "breakpoint while running an expression,"