This is an archive of the discontinued LLVM Phabricator instance.

[LLDB][GUI] Add Breakpoints window
ClosedPublic

Authored by OmarEmaraDev on Aug 3 2021, 12:03 PM.

Details

Summary

This patch adds a breakpoints window that lists all breakpoints and
breakpoints locations. The window is implemented as a tree, where the
first level is the breakpoints and the second level is breakpoints
locations.

The tree delegate was hardcoded to only draw when there is a process,
which is not necessary for breakpoints, so the relevant logic was
abstracted in the TreeDelegateShouldDraw method.

Diff Detail

Event Timeline

OmarEmaraDev created this revision.Aug 3 2021, 12:03 PM
OmarEmaraDev requested review of this revision.Aug 3 2021, 12:03 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 3 2021, 12:03 PM

I faced a bit of difficulty in this patch, so it is not exactly complete. One issue is that breakpoint descriptions can be very long, I tried to implemented multiline items to workaround this, but that didn't work out and was a waste of time. For now, I just tried to keep descriptions as small as possible. One thing I want to try now is to simply add another tree level and add all necessary information there, similar to verbose breakpoint description.
This is also missing the breakpoint operators, like enabling and disabling breakpoints. Since the window doesn't delegate key handing to the items, this will have to be implemented first.

@clayborg What do you think? Should we add another tree level with more details or do something else?

By the way, it would be nice to have D107182 commited because it is needed by the search form.

clayborg added inline comments.Aug 5 2021, 4:46 PM
lldb/source/Core/IOHandlerCursesGUI.cpp
4352–4354

Remove {} for single statement if statements per LLVM guidelines

4468

I would show the address first, then the dump of the symbol context. You can ask the address from the location to dump itself as a load address and fallback to module + file address. Check out the Address::Dump function:

bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style, uint32_t addr_byte_size) const;

To get the raw address first in the string, you can first call the dump with:

// Emit the breakpoint location ID
stream.Format("{0} ", breakpoint_location->GetID())
// Emit the the address as a load address if the process is running, or fallback to <module>[<file-addr>] format if no process is running
address.Dump(&stream, process,  DumpStyleLoadAddress, DumpStyleModuleWithFileAddress, process->GetAddressByteSize());

Then you can add a space and then call this again with:

stream.PutChar(' ');
// Dump the resolved address description
address.Dump(&stream, process,  DumpStyleResolvedDescription, DumpStyleInvalid, process->GetAddressByteSize());

I believe that "DumpStyleResolvedDescription" will dump something verify similar to what you are dumping here with the "symbol_context.DumpStopContext(...)" call.

4474

Breakpoint locations have integer IDs. We should show these as the first item in the string.

Take a look at the output of "breakpoint list" or "breakpoint list --verbose" for ideas on how to format the string.

4477

We could allow locations to be expanded and then show the details of the resolved address like in the "breakpoint list --verbose" output:

(lldb) breakpoint list --verbose
Current breakpoints:
1: name = 'main'
    1.1: 
      module = /Users/gclayton/Documents/src/args/build/a.out
      compile unit = main.cpp
      function = main
      location = /Users/gclayton/Documents/src/args/main.cpp:5:3
      address = a.out[0x0000000100003f3a]
      resolved = false
      hardware = false
      hit count = 0

We could make a child for each of the lines in this output. I believe the about output is from calling Address::Dump(...) with a DumpStyle of "DumpStyleDetailedSymbolContext" (see above details on how to call Address::Dump(...)). You can dump this to a "StringStream" and then get the std::string back from it and split the string using newlines if you like that idea. I like the idea of getting full details on a breakpoint location by being able to expand it.

4501

Breakpoints have integer IDs. We should show these as the first item in the string. Not sure on the formatting of this number, maybe just the raw number followed by a space or possibly with square brackets and a space.

Take a look at the output of "breakpoint list" or "breakpoint list --verbose" for ideas on how to format the string.

6761

We would switch this one to 't' for backTrace and then let the breakpoint view take the 'b' key?

6772

switch to 'b' and mentioned above?

By the way, it would be nice to have D107182 commited because it is needed by the search form.

Just committed it!

@clayborg With you suggestions it currently looks like this. The concern I have is that lines are now 36 characters longer, and some important information are now truncated. The breakpoint and breakpoint locations IDs seems to be just the index of the objects in the tree, are they not? In this case, they seem redundant to me. Similarly, the address takes a lot of space and is included in the next level of details, so it might not be as important to include in this level either.

I am having some difficulties adding the last level of details. My initial approach was to add and compute a StringList containing all the details to the BreakpointLocationTreeDelegate. Then I added a StringTreeDelegate that have the string from the string list in its user data which it then simply draws. The problem, I realized, is that the BreakpointLocationTreeDelegate is shared between all Breakpoint Location items, so the list is overwritten by different elements. What I did was instance multiple BreakpointLocationTreeDelegate for each item, but that tuned more involved that I thought, so I am not sure what the best approach would be now. What do you think?

jingham added a subscriber: jingham.EditedAug 6 2021, 3:17 PM

@clayborg With you suggestions it currently looks like this. The concern I have is that lines are now 36 characters longer, and some important information are now truncated. The breakpoint and breakpoint locations IDs seems to be just the index of the objects in the tree, are they not? In this case, they seem redundant to me.

The breakpoint ID & loc ID are how you would refer to the breakpoint or location in any console commands, and also to go from the breakpoint ID displayed in a stop notification back to the entry in the breakpoints list. Those end up being fairly common operations.

You also can't just count nodes to figure out the breakpoint ID from the tree, since we don't fill in holes in the numbering when you delete a breakpoint.

The same is true of locations. For instance, if you set a breakpoint on "foo" and we find "foo" in library A, then we will add a location N to the breakpoint. Later, if A is unloaded, that location will be deleted, leaving a hole at N in the location numbering.

I don't have a strong opinion about the addresses, but I think you do need the breakpoint & location ID's in the UI somewhere.

Similarly, the address takes a lot of space and is included in the next level of details, so it might not be as important to include in this level either.

I am having some difficulties adding the last level of details. My initial approach was to add and compute a StringList containing all the details to the BreakpointLocationTreeDelegate. Then I added a StringTreeDelegate that have the string from the string list in its user data which it then simply draws. The problem, I realized, is that the BreakpointLocationTreeDelegate is shared between all Breakpoint Location items, so the list is overwritten by different elements. What I did was instance multiple BreakpointLocationTreeDelegate for each item, but that tuned more involved that I thought, so I am not sure what the best approach would be now. What do you think?

I like the new UI! I think you are right in that we don't need the address on the breakpoint location line if we can expand it and see it in the location children, so lets remove it from there. Other than that it looks good. The only other suggestion I would have is if we should display "1.1" and "1.2" for the breakpoint locations. This will match the output of "breakpoint list" a bit better.

  • Address review

@jingham I see. Thanks!

Here is how it looks now:

clayborg requested changes to this revision.Aug 9 2021, 9:52 AM

Just fix the possible crash when SetText gets a NULL string pointer, and this is good to go.

We also need to get the "is_pad(...)" fix in before this can be submitted right?

lldb/source/Core/IOHandlerCursesGUI.cpp
3967

This will crash if you pass in NULL. Test "text" before assignment and call m_text.clear() if it is NULL

This revision now requires changes to proceed.Aug 9 2021, 9:52 AM
  • Fix possible crash in SetText

@clayborg This is unrelated to D107761, so it should be safe to commit.

clayborg accepted this revision.Aug 9 2021, 10:54 AM
This revision is now accepted and ready to land.Aug 9 2021, 10:54 AM
This revision was landed with ongoing or failed builds.Aug 17 2021, 5:38 PM
This revision was automatically updated to reflect the committed changes.