Skip to content

[Support] [lldb] Fix thread jump #45326 #135778

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

Merged
merged 5 commits into from
May 28, 2025
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
5 changes: 4 additions & 1 deletion lldb/source/Commands/CommandObjectThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1649,11 +1649,14 @@ class CommandObjectThreadJump : public CommandObjectParsed {
return Status::FromErrorStringWithFormat("invalid line number: '%s'.",
option_arg.str().c_str());
break;
case 'b':
case 'b': {
option_arg.consume_front("+");
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be documented that an optional + can be specified?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is for _regexp-jump, as for the full thread jump command users are most like to just write the number without the plus.

Copy link
Contributor

Choose a reason for hiding this comment

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

I was just think that

Desc<"Jumps by a relative line offset from the current line.">;
doesn't mention that the leading + is supported or that the value can be negative. Also I can't tell, at least from the help text, if this includes whitespace or not.

Like if I had:

  int a = 3;
  a = 1;

  a = 2; //<pc=here> thread jump -b -1 does this go to the blank line?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added documentation clarifying it can be negative or positive.


if (option_arg.getAsInteger(0, m_line_offset))
return Status::FromErrorStringWithFormat("invalid line offset: '%s'.",
option_arg.str().c_str());
break;
}
case 'a':
m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
LLDB_INVALID_ADDRESS, &error);
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Commands/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1136,7 +1136,8 @@ let Command = "thread jump" in {
def thread_jump_line : Option<"line", "l">, Group<1>, Arg<"LineNum">,
Required, Desc<"Specifies the line number to jump to.">;
def thread_jump_by : Option<"by", "b">, Group<2>, Arg<"Offset">, Required,
Desc<"Jumps by a relative line offset from the current line.">;
Desc<"Jumps by a relative line offset from the current line,"
"can be a positive or negative offset">;
def thread_jump_address : Option<"address", "a">, Group<3>,
Arg<"AddressOrExpression">, Required, Desc<"Jumps to a specific address.">;
def thread_jump_force : Option<"force", "r">, Groups<[1,2,3]>,
Expand Down
70 changes: 69 additions & 1 deletion lldb/test/API/functionalities/thread/jump/TestThreadJump.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@


class ThreadJumpTestCase(TestBase):
def setUp(self):
TestBase.setUp(self)
self.build()

def test(self):
"""Test thread jump handling."""
self.build()
exe = self.getBuildArtifact("a.out")
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)

Expand Down Expand Up @@ -62,6 +65,71 @@ def test(self):
substrs=["error"],
)

def test_jump_offset(self):
"""Test Thread Jump by negative or positive offset"""
exe = self.getBuildArtifact("a.out")
file_name = "main.cpp"
self.runCmd(f"target create {exe}", CURRENT_EXECUTABLE_SET)

pos_jump = line_number(file_name, "// jump_offset 1")
neg_jump = line_number(file_name, "// jump_offset 2")
pos_breakpoint = line_number(file_name, "// breakpoint 1")
neg_breakpoint = line_number(file_name, "// breakpoint 2")
pos_jump_offset = pos_jump - pos_breakpoint
neg_jump_offset = neg_jump - neg_breakpoint

var_1, var_1_value = ("var_1", "10")
var_2, var_2_value = ("var_2", "40")
var_3, var_3_value = ("var_3", "10")

# create pos_breakpoint and neg_breakpoint
lldbutil.run_break_set_by_file_and_line(
self, file_name, pos_breakpoint, num_expected_locations=1
)
lldbutil.run_break_set_by_file_and_line(
self, file_name, neg_breakpoint, num_expected_locations=1
)

self.runCmd("run", RUN_SUCCEEDED)

# test positive jump
# The stop reason of the thread should be breakpoint 1.
self.expect(
"thread list",
STOPPED_DUE_TO_BREAKPOINT + " 1",
substrs=[
"stopped",
f"{file_name}:{pos_breakpoint}",
"stop reason = breakpoint 1",
],
)

self.runCmd(f"thread jump --by +{pos_jump_offset}")
self.expect("process status", substrs=[f"at {file_name}:{pos_jump}"])
self.expect(f"print {var_1}", substrs=[var_1_value])

self.runCmd("thread step-over")
self.expect(f"print {var_2}", substrs=[var_2_value])

self.runCmd("continue")

# test negative jump
# The stop reason of the thread should be breakpoint 1.
self.expect(
"thread list",
STOPPED_DUE_TO_BREAKPOINT + " 2",
substrs=[
"stopped",
f"{file_name}:{neg_breakpoint}",
"stop reason = breakpoint 2",
],
)

self.runCmd(f"thread jump --by {neg_jump_offset}")
self.expect("process status", substrs=[f"at {file_name}:{neg_jump}"])
self.runCmd("thread step-over")
self.expect(f"print {var_3}", substrs=[var_3_value])

def do_min_test(self, start, jump, var, value):
# jump to the start marker
self.runCmd("j %i" % start)
Expand Down
17 changes: 17 additions & 0 deletions lldb/test/API/functionalities/thread/jump/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ T min(T a, T b)
}
}

int jump_positive_offset() {
int var_1 = 10;
var_1 = 20; // breakpoint 1

int var_2 = 40; // jump_offset 1
return var_2;
}

int jump_negative_offset() {
int var_3 = 10; // jump_offset 2
var_3 = 99;

return var_3; // breakpoint 2
}

int main ()
{
int i;
Expand All @@ -22,5 +37,7 @@ int main ()
i = min(min_i_a, min_i_b); // 3rd marker
j = min(min_j_a, min_j_b); // 4th marker

jump_positive_offset();
jump_negative_offset();
return 0;
}
Loading