This is an archive of the discontinued LLVM Phabricator instance.

Make a more convenient way to allow Darwin users to ignore certain Mach Exceptions
ClosedPublic

Authored by jingham on May 11 2022, 4:58 PM.

Details

Summary

For relatively uninteresting reasons, it is not possible when running under the debugger to invoke the mechanism that converts a Mach Exception into its BSD signal equivalent. The Mach Exceptions contain more information than the signal does, so we prefer to stop at the mach exception raise for most purposes. But if your application relies on a SIGBUS, SIGSEGV, etc. handler, then your application won't run properly in the debugger, it will just get stuck on the exception.

A workaround for this was added a while back - by passing -U to debugserver, EXC_BAD_ACCESS, EXC_BAD_INSTRUCTION and EXC_ARITHMETIC are masked out. But this isn't terribly convenient, because you have to invoke debugserver specially so you have to do this every time you debug, you can't use the feature when you don't control how debugserver is launched, and you can't control which exception you want to mask out.

I made this more convenient by adding a QSetIgnoredExceptions packet to debugserver which will set the exceptions not to include, so we can direct this from lldb.

Then I added a way for Platform to provide "extra startup commands" to the remote startup sequence - there was already a way for the user to supply extra startup commands, and I could have had users set the QSetIgnoredExceptions in the "target.extra-startup-commands", but that would be pretty undiscoverable. Instead, I added a "platform.plugin.darwin.ignored-exceptions" property that users can set with just the exception mask. Then PlatformDarwin gathers the results of this setting, and conses up the appropriate packet and returns that from PlatformDarwin::ExtraStartupCommands.

I also wanted to add a validator for the property. Since I don't control the property creation (that all happens through processing the .td file) I couldn't put my validator in the OptionValueString made for the setting on construction, so I added an API to set it after the fact.

Diff Detail

Event Timeline

jingham created this revision.May 11 2022, 4:58 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 11 2022, 4:58 PM
jingham requested review of this revision.May 11 2022, 4:58 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 11 2022, 4:58 PM
jingham edited the summary of this revision. (Show Details)May 11 2022, 5:24 PM

I hope that those minor edits help at least a little!

lldb/source/Plugins/Platform/MacOSX/PlatformMacOSXProperties.td
14
15
jasonmolenda accepted this revision.May 12 2022, 3:06 PM

This is a nice piece of work, and a good cleanup, LGTM.

This revision is now accepted and ready to land.May 12 2022, 3:06 PM
JDevlieghere added inline comments.May 13 2022, 12:08 PM
lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
80–111

What's the point of having this? Isn't PlatformDarwin an abstract class anyway?

166

PlatformDarwin is the name of the class, but I don't think we ever present it that way to the user.

176–177

Unless you expect this string to contain a null byte you could turn this into a StringRef and check ::empty() instead.

lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
959–964

You can use a range-based for loop here.

967–970

nit: LLVM likes to do this but I personally don't care.

lldb/tools/debugserver/source/MacOSX/MachException.cpp
527–558

Why not make it a string and use it's equals method? All these strcmps make the whole this unnecessary verbose imho.

if (name == "BAD_ACCESS")

Addressed review comments.

lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
80–111

As it currently stands, you can't create a plugin setting if the plugin doesn't have a CreateInstance. I wanted settings set platform.plugin.darwin.ignored-exceptions, rather than repeating the setting on all the concrete instances of PlatformDarwin, since this is a Darwin feature, so I had to add that.

176–177

This won't contain nulls, so that part's okay. Using a StringRef simplifies the check here, but in order to make up the packet I have to call ignored_exceptions_as_StringRef.str() in order to have something to pass to packet.append. This isn't performance critical, so I don't mind the copy, but since we're going to end up making a std string anyway, I used std::string rather than StringRef.

jingham updated this revision to Diff 430435.May 18 2022, 10:13 AM

Address review comments

jingham marked 2 inline comments as done.May 18 2022, 10:15 AM
This revision was landed with ongoing or failed builds.May 18 2022, 10:16 AM
This revision was automatically updated to reflect the committed changes.