Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[lldb] add stop-at-user-entry option to process launch #67019

Merged
merged 1 commit into from
Oct 9, 2023

Conversation

junior-jl
Copy link
Contributor

@junior-jl junior-jl commented Sep 21, 2023

Description

This pull request adds a new stop-at-user-entry option to LLDB process launch command, allowing users to launch a process and pause execution at the entry point of the program (for C-based languages, main function).

Motivation

This option provides a convenient way to begin debugging a program by launching it and breaking at the desired entry point.

Changes Made

  • Added stop-at-user-entry option to Options.td and the corresponding case in CommandOptionsProcessLaunch.cpp (short option is 'm')
  • Implemented GetUserEntryPointName method in the Language plugins available at the moment.
  • Declared the CreateBreakpointAtUserEntry method in the Target API.
  • Create Shell test for the command command-process-launch-user-entry.test.

Usage

process launch --stop-at-user-entry or process launch -m launches the process and pauses execution at the entry point of the program.

@llvmbot llvmbot added the lldb label Sep 21, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Sep 21, 2023

@llvm/pr-subscribers-lldb

Changes

Description

This pull request adds a new start command to LLDB, allowing users to launch a process and pause execution at either the main function or the first instruction.

Motivation

The start command provides a convenient way to begin debugging a program by launching it and breaking at the desired entry point.

Changes Made

  • Added CommandObjectStart class to implement the start command.
  • The start command accepts an optional argument to specify whether to pause at the main function or the first instruction.
  • Registered the command in the CMakeLists.txt file and in the CommandInterpreter.

Usage

start runs the program and pauses execution at main function
start first runs the program and pauses execution at the first instruction.


Full diff: https://github.com/llvm/llvm-project/pull/67019.diff

4 Files Affected:

  • (modified) lldb/source/Commands/CMakeLists.txt (+1)
  • (added) lldb/source/Commands/CommandObjectStart.cpp (+102)
  • (added) lldb/source/Commands/CommandObjectStart.h (+32)
  • (modified) lldb/source/Interpreter/CommandInterpreter.cpp (+2)
diff --git a/lldb/source/Commands/CMakeLists.txt b/lldb/source/Commands/CMakeLists.txt
index 6a36c5376d5c574..54c62e0f5284beb 100644
--- a/lldb/source/Commands/CMakeLists.txt
+++ b/lldb/source/Commands/CMakeLists.txt
@@ -30,6 +30,7 @@ add_lldb_library(lldbCommands NO_PLUGIN_DEPENDENCIES
   CommandObjectSession.cpp
   CommandObjectSettings.cpp
   CommandObjectSource.cpp
+  CommandObjectStart.cpp
   CommandObjectStats.cpp
   CommandObjectTarget.cpp
   CommandObjectThread.cpp
diff --git a/lldb/source/Commands/CommandObjectStart.cpp b/lldb/source/Commands/CommandObjectStart.cpp
new file mode 100644
index 000000000000000..7406143c50fec1b
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectStart.cpp
@@ -0,0 +1,102 @@
+//===-- CommandObjectStart.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectStart.h"
+#include "lldb/Interpreter/CommandObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// Constructor for CommandObjectStart
+CommandObjectStart::CommandObjectStart(CommandInterpreter &interpreter)
+    : CommandObjectParsed(
+          interpreter, "start",
+          "Launches the process and pauses execution at main function",
+          "start args [optional args]") {
+  // Define command arguments
+  CommandArgumentData pause_location{eArgTypeName, eArgRepeatPlain};
+  m_arguments.push_back({pause_location});
+}
+
+CommandObjectStart::~CommandObjectStart() = default;
+
+// Execute the 'start' command
+bool CommandObjectStart::DoExecute(Args &command, CommandReturnObject &result) {
+  // Check if the 'first' subcommand is specified
+  bool pause_at_first_instruction = false;
+
+  if (command.GetArgumentCount() == 1 &&
+      strcmp(command.GetArgumentAtIndex(0), "first") == 0) {
+    pause_at_first_instruction = true;
+  }
+
+  // Get the current selected target
+  TargetSP target_sp = GetDebugger().GetSelectedTarget();
+  if (!target_sp) {
+    result.AppendError("No target selected.\n");
+    return false;
+  }
+
+  // Create the breakpoint at main or the first instruction
+  BreakpointSP bp_sp;
+  if (pause_at_first_instruction) {
+    ModuleSP exe_module_sp = target_sp->GetExecutableModule();
+    ObjectFile *object = exe_module_sp->GetObjectFile();
+    Address address = object->GetEntryPointAddress();
+
+    if (!address.IsValid()) {
+      result.AppendError("Failed to get the entry point address");
+      result.SetStatus(eReturnStatusFailed);
+      return false;
+    }
+
+    bp_sp = target_sp->CreateBreakpoint(address, false, false);
+
+  } else {
+    // Create a breakpoint at the main function
+    bp_sp = target_sp->CreateBreakpoint(
+        nullptr, nullptr, "main", eFunctionNameTypeAuto, eLanguageTypeUnknown,
+        0, eLazyBoolNo, false, false);
+  }
+
+  if (!bp_sp) {
+    result.AppendError("Breakpoint creation failed.\n");
+    result.SetStatus(eReturnStatusFailed);
+    return false;
+  } else {
+    result.GetOutputStream().Printf("Breakpoint created%s.\n",
+                                    pause_at_first_instruction
+                                        ? " at first instruction"
+                                        : " in main function");
+    result.SetStatus(eReturnStatusSuccessFinishResult);
+  }
+
+  // Construct the process launch info
+  ProcessLaunchInfo launch_info;
+  launch_info.SetShell(HostInfo::GetDefaultShell());
+  ModuleSP exe_module_sp = target_sp->GetExecutableModule();
+  if (!exe_module_sp) {
+    result.AppendError("No executable module found.\n");
+    return false;
+  }
+
+  launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), true);
+  // Launch the process
+  StreamString stream;
+  Status error = target_sp->Launch(launch_info, &stream);
+
+  if (error.Success()) {
+    result.SetStatus(eReturnStatusSuccessFinishResult);
+    result.GetOutputStream().Printf("Process launched successfully.\n");
+  } else {
+    result.AppendErrorWithFormat("Process launch failed: %s\n",
+                                 error.AsCString());
+    return false;
+  }
+  return result.Succeeded();
+}
diff --git a/lldb/source/Commands/CommandObjectStart.h b/lldb/source/Commands/CommandObjectStart.h
new file mode 100644
index 000000000000000..8475a17c347f7be
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectStart.h
@@ -0,0 +1,32 @@
+//===-- CommandObjectStart.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_COMMANDS_COMMANDOBJECTStart_H
+#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTStart_H
+
+#include "lldb/Core/Module.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/ProcessLaunchInfo.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/SymbolContext.h"
+
+namespace lldb_private {
+class CommandObjectStart : public CommandObjectParsed {
+public:
+  CommandObjectStart(CommandInterpreter &interpreter);
+  ~CommandObjectStart() override;
+
+protected:
+  bool DoExecute(Args &args, CommandReturnObject &result) override;
+};
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTStart_H
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index dcff53ff843f328..5d6ad7f0dbb1e8e 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -36,6 +36,7 @@
 #include "Commands/CommandObjectSession.h"
 #include "Commands/CommandObjectSettings.h"
 #include "Commands/CommandObjectSource.h"
+#include "Commands/CommandObjectStart.h"
 #include "Commands/CommandObjectStats.h"
 #include "Commands/CommandObjectTarget.h"
 #include "Commands/CommandObjectThread.h"
@@ -559,6 +560,7 @@ void CommandInterpreter::LoadCommandDictionary() {
   REGISTER_COMMAND_OBJECT("settings", CommandObjectMultiwordSettings);
   REGISTER_COMMAND_OBJECT("session", CommandObjectSession);
   REGISTER_COMMAND_OBJECT("source", CommandObjectMultiwordSource);
+  REGISTER_COMMAND_OBJECT("start", CommandObjectStart);
   REGISTER_COMMAND_OBJECT("statistics", CommandObjectStats);
   REGISTER_COMMAND_OBJECT("target", CommandObjectMultiwordTarget);
   REGISTER_COMMAND_OBJECT("thread", CommandObjectMultiwordThread);

@DavidSpickett DavidSpickett requested a review from a team September 21, 2023 15:17
Copy link
Collaborator

@jimingham jimingham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Half of this command is just process launch --stop-at-entry. If you wanted to can the "break at main" part, then add a --stop-at-main to process launch. And if you want a "start" command, the lldb way to do that would be to make a regex command that either does process launch --stop-at-entry or the new process launch --stop-at-main.

We don't add real top level commands that are just aliases to extant behavior.

@jimingham
Copy link
Collaborator

Even if this were enough behavior to warrant a new command, it would live under the process launch node, not as a top level command. We try not to make lots of top level commands so as to leave plenty of namespace in the easy access commands for user customization.

@junior-jl
Copy link
Contributor Author

Thank you for the explanation here and in Discourse. I added the option stop-at-main to process launch.

Copy link
Collaborator

@jimingham jimingham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason that gdb has a "start" command is that not all languages and their runtimes use the same name for the the entry point function. So start does "figure out what the start function in the main executable is and set a breakpoint there". Or maybe it just knows the start points of all the languages and breaks symbolically on each one, I can't remember how gdb does this...
In our case, the languages we currently support all use "main" for the entry point function, but since we're going to the trouble of making an canned bit of functionality for this, it might be nice to add that abstraction.

@jimingham
Copy link
Collaborator

I can't tell how to read the "Files Changed" part of the GitHub PR change. It looks like the --stop-at-main is additive, but to be clear, the second of these two commits looks okay to me, but the first commit is still not something we want to do.

@walter-erquinigo
Copy link
Member

Btw, I'm building support for the mojo language, and very likely the main method will not have the symbol main, so building an abstraction around this, for every language, would be very convenient.

@jimingham
Copy link
Collaborator

The other improvement I'd suggest here is that the breakpoints you set to implement the "stop at main" behavior need to be be "one-shot" breakpoints. Otherwise, if you do:

(lldb) process launch --stop-at-main
... the process exits

and then:

(lldb) process launch

you're still going to stop at main, which is surprising.

@junior-jl
Copy link
Contributor Author

This might be a dumb question, but I committed the implementation as an option as the second commit thinking you would/could discard my first commit. Is that possible? What would be the best way to correct this?

@walter-erquinigo
Copy link
Member

That's file. You can have multiple commits in the same PR, because when it gets approved and merged, github will squash all your commits into a single one.

@bulbazord
Copy link
Member

Concretely, you can revert the first commit and push that so that your branch has your first commit, second commit, and a revert commit for the first one. As Walter said, it should squash down and resolve correctly.

@bulbazord
Copy link
Member

You also may want to change the title of your PR to reflect the actual change you'll be making as well. When you squash and merge, you'll have an opportunity to rewrite the commit message to more accurately reflect what your change does as well.

lldb/source/Commands/CMakeLists.txt Outdated Show resolved Hide resolved
lldb/source/Commands/CommandObjectStart.cpp Outdated Show resolved Hide resolved
lldb/source/Commands/CommandObjectStart.h Outdated Show resolved Hide resolved
lldb/source/Commands/CommandOptionsProcessLaunch.cpp Outdated Show resolved Hide resolved
lldb/source/Commands/CommandOptionsProcessLaunch.cpp Outdated Show resolved Hide resolved
lldb/source/Interpreter/CommandInterpreter.cpp Outdated Show resolved Hide resolved
lldb/source/Interpreter/CommandInterpreter.cpp Outdated Show resolved Hide resolved
@junior-jl
Copy link
Contributor Author

Thank you @bulbazord & @clayborg for the step-by-step, it was really helpful. I reverted the first commit, removed the shell modification you mentioned and the created breakpoint is now one-shot, @jimingham.

@junior-jl junior-jl changed the title [lldb] add command start [lldb] add stop-at-main option to process launch Sep 25, 2023
Copy link
Collaborator

@clayborg clayborg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my inline comments. I am wondering if we want to get the platform involved here so they can do the right thing for any platform and it might involve renaming the option away from containing "main" since that might not be the user entry point into a program for all platforms.

lldb/source/Commands/CommandOptionsProcessLaunch.cpp Outdated Show resolved Hide resolved
lldb/source/Commands/CommandOptionsProcessLaunch.cpp Outdated Show resolved Hide resolved
lldb/source/Commands/CommandOptionsProcessLaunch.cpp Outdated Show resolved Hide resolved
lldb/source/Commands/Options.td Outdated Show resolved Hide resolved
Copy link
Collaborator

@clayborg clayborg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After Jim's recent comments sounds like the Platform is not the right place to set the breakpoint. So please ignore my comments suggesting to use the Platform layer.

@jimingham
Copy link
Collaborator

jimingham commented Sep 26, 2023 via email

@jimingham
Copy link
Collaborator

jimingham commented Sep 26, 2023 via email

@jimingham
Copy link
Collaborator

jimingham commented Sep 26, 2023 via email

@junior-jl
Copy link
Contributor Author

This is the case in the current commit. I was trying to implement this with SmallSet and const char* to use the overload you mentioned, Jim, but I was having trouble with it, specially because I needed to hard code a 'max number of languages'. So I used the overload that takes a std::vectorstd::string. Let me know if that's not good.

case 'm': // Stop at user entry point
  {
    TargetSP target_sp =
        execution_context ? execution_context->GetTargetSP() : TargetSP();
    ModuleSP main_module_sp = target_sp->GetExecutableModule();
    FileSpecList shared_lib_filter;
    shared_lib_filter.Append(main_module_sp->GetFileSpec());
    std::vector<std::string> entryPointNames;
    for (LanguageType lang_type : Language::GetSupportedLanguages()) {
      Language *lang = Language::FindPlugin(lang_type);
      if (lang) {
        std::string entryPointName = lang->GetUserEntryPointName();
        if (!entryPointName.empty()) {
          entryPointNames.push_back(entryPointName);
        }
      }
    }
    BreakpointSP bp_sp = target_sp->CreateBreakpoint(
        /*containingModules=*/&shared_lib_filter,
        /*containingSourceFiles=*/nullptr, 
        /*func_names=*/entryPointNames,
        /*func_name_type_mask=*/eFunctionNameTypeFull,
        /*language=*/eLanguageTypeUnknown,
        /*offset=*/0, /*skip_prologue=*/eLazyBoolNo, /*internal=*/false,
        /*hardware=*/false);
    if (!bp_sp)
      error.SetErrorString("Breakpoint creation failed.\n");
    bp_sp->SetOneShot(true);
    break;
  }

@junior-jl
Copy link
Contributor Author

Also, I just noticed that clang-format did some minor changes to Language.h. Please, let me know if I need to revert those.

@github-actions
Copy link

github-actions bot commented Sep 26, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@junior-jl junior-jl changed the title [lldb] add stop-at-main option to process launch [lldb] add stop-at-user-entry option to process launch Sep 26, 2023
lldb/source/Commands/CommandOptionsProcessLaunch.cpp Outdated Show resolved Hide resolved
lldb/source/Commands/CommandOptionsProcessLaunch.cpp Outdated Show resolved Hide resolved
lldb/source/Commands/Options.td Outdated Show resolved Hide resolved
@junior-jl
Copy link
Contributor Author

What are your thoughts on creating an alias for process launch --stop-at-user-entry such as the intended start (or begin, or even run -m).

Also, if I wanted to do that, the only change would be an AddAlias in CommandInterpreter.cpp? Or there's something else?

@jimingham
Copy link
Collaborator

jimingham commented Sep 27, 2023 via email

@junior-jl
Copy link
Contributor Author

I understand, thank you, Jim.

Is there anything else I should change in this PR?

@medismailben
Copy link
Member

I think you're good for the implementing however it would be nice to add a shell test to make sure it works well and it doesn't break in the future.

@medismailben
Copy link
Member

You can use lldb/test/Shell/Commands/command-thread-select.test as an example to write your own test.

@junior-jl
Copy link
Contributor Author

You can use lldb/test/Shell/Commands/command-thread-select.test as an example to write your own test.

Using this file as a template, I wrote command-process-launch-user-entry.test as shown below:

# RUN: %clang_host -g %S/Inputs/main.c -o %t
# RUN: %lldb %t -s %s -o exit | FileCheck %s

process launch -m
# CHECK-LABEL: process launch -m
# CHECK: Process {{.*}} stopped
# CHECK: stop reason = one-shot breakpoint 1
# CHECK:   frame #0: {{.*}}`main at main.c

But I wanted to add the check line # CHECK: Process {{.*}} launched: '{{.*}}' {{.*}}, but this fails because the following is happening:

  1. When the command is executed from the (lldb) prompt, it correctly shows that the process is launched then stopped.
$ ./bin/lldb ~/main.out
(lldb) target create "/home/jose/main.out"
Current executable set to '/home/jose/main.out' (x86_64).
(lldb) process launch -m
Process 63632 launched: '/home/jose/main.out' (x86_64)
Process 63632 stopped
* thread #1, name = 'main.out', stop reason = one-shot breakpoint 1
    frame #0: 0x0000555555555140 main.out`main at main.c:2
   1   	int foo() { return 0; }
-> 2   	int main() { return foo(); }
   3   	
(lldb) 
  1. When I run like shown below, the Process launched message is shown after the stop.
$ ./bin/lldb ~/main.out -o 'process launch -m'
(lldb) target create "/home/jose/main.out"
Current executable set to '/home/jose/main.out' (x86_64).
(lldb) process launch -m
Process 63846 stopped
* thread #1, name = 'main.out', stop reason = one-shot breakpoint 1
    frame #0: 0x0000555555555140 main.out`main at main.c:2
   1   	int foo() { return 0; }
-> 2   	int main() { return foo(); }
   3
Process 63846 launched: '/home/jose/main.out' (x86_64)
(lldb) 

Is this behaviour expected?

@medismailben
Copy link
Member

medismailben commented Oct 2, 2023

You can use lldb/test/Shell/Commands/command-thread-select.test as an example to write your own test.

Using this file as a template, I wrote command-process-launch-user-entry.test as shown below:

# RUN: %clang_host -g %S/Inputs/main.c -o %t
# RUN: %lldb %t -s %s -o exit | FileCheck %s

process launch -m
# CHECK-LABEL: process launch -m
# CHECK: Process {{.*}} stopped
# CHECK: stop reason = one-shot breakpoint 1
# CHECK:   frame #0: {{.*}}`main at main.c

But I wanted to add the check line # CHECK: Process {{.*}} launched: '{{.*}}' {{.*}}, but this fails because the following is happening:

  1. When the command is executed from the (lldb) prompt, it correctly shows that the process is launched then stopped.
$ ./bin/lldb ~/main.out
(lldb) target create "/home/jose/main.out"
Current executable set to '/home/jose/main.out' (x86_64).
(lldb) process launch -m
Process 63632 launched: '/home/jose/main.out' (x86_64)
Process 63632 stopped
* thread #1, name = 'main.out', stop reason = one-shot breakpoint 1
    frame #0: 0x0000555555555140 main.out`main at main.c:2
   1   	int foo() { return 0; }
-> 2   	int main() { return foo(); }
   3   	
(lldb) 
  1. When I run like shown below, the Process launched message is shown after the stop.
$ ./bin/lldb ~/main.out -o 'process launch -m'
(lldb) target create "/home/jose/main.out"
Current executable set to '/home/jose/main.out' (x86_64).
(lldb) process launch -m
Process 63846 stopped
* thread #1, name = 'main.out', stop reason = one-shot breakpoint 1
    frame #0: 0x0000555555555140 main.out`main at main.c:2
   1   	int foo() { return 0; }
-> 2   	int main() { return foo(); }
   3
Process 63846 launched: '/home/jose/main.out' (x86_64)
(lldb) 

Is this behaviour expected?

I can reproduce it:

$ ./bin/lldb /tmp/main -o "b main" -o "r"
(lldb) target create "/tmp/main"
Current executable set to '/tmp/main' (arm64).
(lldb) b main
Breakpoint 1: where = main`main + 12 at main.cpp:2:3, address = 0x0000000100003fa0
(lldb) r
Process 53764 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100003fa0 main`main at main.cpp:2:3
   1   	int main() {
-> 2   	  return 0;
   3   	}
Process 53764 launched: '/tmp/main' (arm64)

By default the debugger runs in asynchronous mode so the stop events can be handled in a nondetermistic way. However, I think this is confusing and we should do something about it (in a separate PR). Could you file a new issue describing this behavior and pasting the link here.

Your test looks fine to me, so we can move on with it to merge your PR. I'll update it after we fix that other bug.

@junior-jl
Copy link
Contributor Author

Could you file a new issue describing this behavior and pasting the link here.

Done! #68035

Your test looks fine to me, so we can move on with it to merge your PR. I'll update it after we fix that other bug.

Great. Added the test in the latest commit.

@medismailben
Copy link
Member

@clayborg what do you think ? Can we merge this ?

lldb/include/lldb/Target/Language.h Outdated Show resolved Hide resolved
lldb/source/Target/Target.cpp Show resolved Hide resolved
lldb/source/Commands/CommandOptionsProcessLaunch.cpp Outdated Show resolved Hide resolved
Copy link
Collaborator

@clayborg clayborg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just remove the includes that are no longer needed and this is good to go!

lldb/source/Commands/CommandOptionsProcessLaunch.cpp Outdated Show resolved Hide resolved
@medismailben
Copy link
Member

@junior-jl I think everyone approved the PR so you just need to address the formatting issues so we can merge it. Would you mind squashing your 3 commits into a single one and running git clang-format HEAD~ and git commit --amend --no-edit and pushing your branch again ? Thanks!

lldb/include/lldb/Target/Language.h Outdated Show resolved Hide resolved
lldb/source/Target/Target.cpp Outdated Show resolved Hide resolved
[lldb] add stop-at-user-entry option to process launch

refactor CreateBreakpointAtUserEntry method

remove unecessary includes
@junior-jl
Copy link
Contributor Author

Addressed @JDevlieghere comments regarding formatting and inlined comments.

Copy link
Member

@JDevlieghere JDevlieghere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@medismailben medismailben merged commit ac0dda8 into llvm:main Oct 9, 2023
3 checks passed
@clayborg
Copy link
Collaborator

very nice! Thanks for doing all of our suggested improvements, great patch. I would love to see a new API in SBTarget that exposes this feature:

lldb::SBBreakpoint lldb::SBTarget::CreateBreakpointAtUserEntry();

@DavidSpickett
Copy link
Collaborator

Thanks for working on this! It's going to save me a lot of "b main" in the future.

@junior-jl junior-jl deleted the start branch November 28, 2023 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.