-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[lldb] Fix "in function" detection in "thread until" #123622
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
Changes from 5 commits
0a80b7a
dbecc09
e8d4455
97320a5
41e1ff7
2596148
9f0c2aa
8c04565
6e1f15d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -959,7 +959,6 @@ class CommandObjectThreadUntil : public CommandObjectParsed { | |
| } | ||
|
|
||
| LineEntry function_start; | ||
| uint32_t index_ptr = 0, end_ptr = UINT32_MAX; | ||
| std::vector<addr_t> address_list; | ||
|
|
||
| // Find the beginning & end index of the function, but first make | ||
|
|
@@ -970,19 +969,26 @@ class CommandObjectThreadUntil : public CommandObjectParsed { | |
| return; | ||
| } | ||
|
|
||
| AddressRange fun_addr_range = sc.function->GetAddressRange(); | ||
| Address fun_start_addr = fun_addr_range.GetBaseAddress(); | ||
| line_table->FindLineEntryByAddress(fun_start_addr, function_start, | ||
| &index_ptr); | ||
|
|
||
| Address fun_end_addr(fun_start_addr.GetSection(), | ||
| fun_start_addr.GetOffset() + | ||
| fun_addr_range.GetByteSize()); | ||
|
|
||
| bool all_in_function = true; | ||
| uint32_t lowest_func_idx = UINT32_MAX; | ||
| uint32_t highest_func_idx = 0; | ||
| for (AddressRange range : sc.function->GetAddressRanges()) { | ||
| uint32_t idx; | ||
| LineEntry unused; | ||
| Address addr = range.GetBaseAddress(); | ||
| if (line_table->FindLineEntryByAddress(addr, unused, &idx)) | ||
| lowest_func_idx = std::min(lowest_func_idx, idx); | ||
|
|
||
| addr.Slide(range.GetByteSize()); | ||
| if (line_table->FindLineEntryByAddress(addr, unused, &idx)) { | ||
| highest_func_idx = std::max(highest_func_idx, idx); | ||
| } else { | ||
| // No line entry after the current function. The function is the | ||
| // last in the file, so we can just search until the end. | ||
| highest_func_idx = UINT32_MAX; | ||
| } | ||
| } | ||
|
|
||
| line_table->FindLineEntryByAddress(fun_end_addr, function_start, | ||
| &end_ptr); | ||
| bool found_something = false; | ||
|
|
||
| // Since not all source lines will contribute code, check if we are | ||
| // setting the breakpoint on the exact line number or the nearest | ||
|
|
@@ -991,14 +997,15 @@ class CommandObjectThreadUntil : public CommandObjectParsed { | |
| for (uint32_t line_number : line_numbers) { | ||
| LineEntry line_entry; | ||
| bool exact = false; | ||
| uint32_t start_idx_ptr = index_ptr; | ||
| start_idx_ptr = sc.comp_unit->FindLineEntry( | ||
| index_ptr, line_number, nullptr, exact, &line_entry); | ||
| if (start_idx_ptr != UINT32_MAX) | ||
| line_number = line_entry.line; | ||
| if (sc.comp_unit->FindLineEntry(0, line_number, nullptr, exact, | ||
| &line_entry) == UINT32_MAX) | ||
| continue; | ||
|
|
||
| found_something = true; | ||
| line_number = line_entry.line; | ||
| exact = true; | ||
| start_idx_ptr = index_ptr; | ||
| while (start_idx_ptr <= end_ptr) { | ||
| uint32_t start_idx_ptr = lowest_func_idx; | ||
| while (start_idx_ptr <= highest_func_idx) { | ||
| start_idx_ptr = sc.comp_unit->FindLineEntry( | ||
| start_idx_ptr, line_number, nullptr, exact, &line_entry); | ||
| if (start_idx_ptr == UINT32_MAX) | ||
|
|
@@ -1007,29 +1014,29 @@ class CommandObjectThreadUntil : public CommandObjectParsed { | |
| addr_t address = | ||
| line_entry.range.GetBaseAddress().GetLoadAddress(target); | ||
| if (address != LLDB_INVALID_ADDRESS) { | ||
| if (fun_addr_range.ContainsLoadAddress(address, target)) | ||
| AddressRange unused; | ||
| if (sc.function->GetRangeContainingLoadAddress(address, *target, | ||
| unused)) | ||
| address_list.push_back(address); | ||
| else | ||
| all_in_function = false; | ||
| } | ||
| start_idx_ptr++; | ||
| } | ||
| } | ||
|
|
||
| for (lldb::addr_t address : m_options.m_until_addrs) { | ||
| if (fun_addr_range.ContainsLoadAddress(address, target)) | ||
| AddressRange unused; | ||
| if (sc.function->GetRangeContainingLoadAddress(address, *target, | ||
| unused)) | ||
| address_list.push_back(address); | ||
| else | ||
| all_in_function = false; | ||
| } | ||
|
|
||
| if (address_list.empty()) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you only care here about
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so. address_list being empty is the "error" case. In case of success, the full list of addresses is used for stepping (line 1040) |
||
| if (all_in_function) | ||
| if (found_something) | ||
| result.AppendErrorWithFormat( | ||
| "No line entries matching until target.\n"); | ||
| "Until target outside of the current function.\n"); | ||
| else | ||
| result.AppendErrorWithFormat( | ||
| "Until target outside of the current function.\n"); | ||
| "No line entries matching until target.\n"); | ||
|
|
||
| return; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this be useful anywhere else? It's asking a Function what its highest and lowest indexes are in the linetable from its CU.