This is an archive of the discontinued LLVM Phabricator instance.

Allow scripted thread plans to modify the stop reason shown when the plan completes
AcceptedPublic

Authored by jingham on May 2 2023, 1:58 PM.

Details

Summary

We were just printing some fairly ugly boiler plate, for instance:

(lldb) thread step-scripted -C scripted_step.SimpleStep
Process 15467 stopped

  • thread #1, queue = 'com.apple.main-thread', stop reason = Python thread plan implemented by class scripted_step.SimpleStep.

This change allows the scripted ThreadPlan to implement:

def stop_description(self, stream):
    stream.Print("Simple step completed")

and then you will see:

(lldb) thread step-scripted -C scripted_step.SimpleStep
Process 15226 stopped

  • thread #1, queue = 'com.apple.main-thread', stop reason = Simple step completed

Diff Detail

Event Timeline

jingham created this revision.May 2 2023, 1:58 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 2 2023, 1:58 PM
jingham requested review of this revision.May 2 2023, 1:58 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 2 2023, 1:58 PM
mib added a comment.May 2 2023, 2:37 PM

This looks good to me, although I'm wondering whether instead of passing a string, we should pass a dictionary. This way the user could either fill the dictionary with a simple stop reason description or the MachException data What do you think Jim ?

lldb/bindings/python/python-wrapper.swig
390

If we passed a Status& instead of a bool& we would be able to get that error message in lldb.

lldb/examples/python/scripted_step.py
156

This is probably a typo

lldb/include/lldb/Interpreter/ScriptInterpreter.h
320

For Scripted Process, I pass a Status& argument which can hold an error message for better debugging. By doing so, you can also return Status.Success()

jingham updated this revision to Diff 518878.May 2 2023, 3:12 PM

Address review comments.

jingham marked an inline comment as done.May 2 2023, 3:12 PM
jingham added inline comments.
lldb/bindings/python/python-wrapper.swig
390

GetDescription doesn't end up returning a Status, just a bool saying whether anything got added. So even if I added a Status here, there would be no place for it to go.

lldb/include/lldb/Interpreter/ScriptInterpreter.h
320

There isn't any place to return an error along the GetStopDescription path above us. That API just returns a bool saying whether you added information to the stream. So returning just a bool at this layer mirrors its use better.

jingham added a comment.EditedMay 2 2023, 3:15 PM

This looks good to me, although I'm wondering whether instead of passing a string, we should pass a dictionary. This way the user could either fill the dictionary with a simple stop reason description or the MachException data What do you think Jim ?

ThreadPlan stop descriptions are only for display purposes, we don't ever reason based on them. We do put data in StopInfo's but this isn't constructing a StopInfo, it's just adding the string to StopInfoPlanComplete. So I can't see what use would be made of the more complex return.

You are probably thinking of providing scripted StopInfo subclasses that do have structured data. That will be better implemented if we add:

SBStructuredData SBThread::GetStructuredStopInfo()

and then breakpoint stops, mach exception stops, etc. can be more reasonably presented, and ScriptedThreads will have a much easier time producing their StopInfo as well.

But even in that case, the providers of StopInfo's will also have to provide a StopDescription as a string, since lldb wouldn't know how to summarize the elements in the StopInfo dictionary.

So this bit of work is orthogonal to providing structured stop infos, IMO.

mib accepted this revision.May 2 2023, 4:58 PM

Alright

This revision is now accepted and ready to land.May 2 2023, 4:58 PM

Committed as: c2be702104284cb3facf31124494b9a400296179.

I forgot to put the differential revision cookie in the commit message...

delcypher added inline comments.May 3 2023, 4:42 PM
lldb/examples/python/scripted_step.py
130

@jingham Thanks for implementing this. Is there a reason why the interface needs to act on a stream object? Wouldn't this be simpler

def stop_description(self) -> str:
   return "Simple step completed"