[lldb-dev] Not stopping on EXC_BAD_ACCESS

Heath Borders heath.borders at gmail.com
Wed Oct 23 22:08:55 PDT 2013


> Is lldb hanging, or is your program hanging?  If lldb is hanging, can you
file a bug with the backtrace of lldb (and a sample program if you can
easily whip one up...)

You're right, it wasn't lldb's fault. I attached lldb to the simulator from
the command-line, and everything worked as expected. The problem must lie
somewhere in the bowels of Xcode.

-Heath Borders
heath.borders at gmail.com
Twitter: heathborders
http://heath-tech.blogspot.com


On Mon, Oct 21, 2013 at 11:42 AM, <jingham at apple.com> wrote:

>
> On Oct 19, 2013, at 11:11 PM, Heath Borders <heath.borders at gmail.com>
> wrote:
>
> > (Sorry, I just discovered this list, and I don't know how to properly
> jump into a thread I didn't receive in email. I tried to replicate quoting
> one-level deep.)
> >
> >
> > I want to be notified when a __weak reference in one of my objects is
> about to be nil-ed. I accomplish this by allocating the object into a
> specific VM page and then marking the page as read-only. When ARC nils the
> __weak reference, I get an EXC_BAD_ACCESS, and I can mark the VM page as
> read-write, run my tear-down code while the object is still valid, and then
> return KERN_SUCCESS, which will allow ARC to continue on. However, as
> Richard described earlier, LLDB hangs when I set a breakpoint inside any
> code that isn't my exception handler when I use task_set_exception_ports.
>
> If you were watching all the exception types on the task exception port,
> then it would make sense to me that we would hang trying to continue, since
> lldb uses EXC_BREAKPOINT for its own purposes and if it is not seeing that,
> it won't be able to run its execution logic.  But if you are only watching
> for the EXC_BAD_ACCESS exception then lldb it shouldn't care about this
> (besides that lldb won't ever see real crashes.)
>
> Anyway, check that you really are only registering for the EXC_BAD_ACCESS
> exception when you do the {task,thread}_set_exception_ports.  Or, see
> below, maybe this is happening because you aren't replying to the exception
> message?
>
> >
> > You suggested using thread_set_exception_ports to fix this issue. I
> assume that thread_set_exception_ports only takes over exceptions that
> occur on the thread given to thread_set_exception_ports, and not for the
> whole task, like task_set_exception_ports does. Thus, I would need to call
> thread_set_exception_ports on every thread since I care about getting an
> EXC_BAD_ACCESS exception that occurs on any thread, right? My handler isn't
> called if I register for exceptions with a different thread.
> >
> > Is there a way to be notified when a thread is created so I can
> subscribe to its messages?
>
> Not that I am aware of.  There's no very good way to to watch for
> exceptions on threads you didn't create using the thread exception port, at
> least not one I know about.
>
> >
> > Also, I still see LLDB hanging when a use thread_set_exception_ports. Am
> I doing something wrong? My code is below:
>
> Is lldb hanging, or is your program hanging?  If lldb is hanging, can you
> file a bug with the backtrace of lldb (and a sample program if you can
> easily whip one up...)
>
> If it is your program that is hanging make sure you are sending on the
> reply message that you get when your catch_exception_raise returns
> KERN_SUCCESS.  Maybe that is what mach_msg_server does, I've never used
> that function so I don't know.  In lldb we call mach_exc_server to trigger
> the call to catch_exception_raise and that returns a reply right that you
> have to send on to the appropriate exception port for the process to
> continue.  If you don't do that your program won't make progress.  As I
> said, that may be already handled in mach_msg_server, I don't know, not
> having done it that way, but that's the only thing I can think of that
> might hang you up.  You can check out how lldb does this here:
>
>
> http://llvm.org/svn/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/MachException.cpp
>
> Jim
>
>
> >
> > kern_return_t catch_exception_raise(mach_port_t exception_port,
> >
> >                                     mach_port_t thread,
> >
> >                                     mach_port_t task,
> >                                     exception_type_t exception,
> >                                     exception_data_t code_vector,
> >                                     mach_msg_type_number_t code_count) {
> >
> >     x86_exception_state32_t x86_exception_state32;
> >
> >     mach_msg_type_number_t sc = x86_EXCEPTION_STATE32_COUNT;
> >
> >     thread_get_state(thread,
> >                              x86_EXCEPTION_STATE32,
> >                              (thread_state_t)&x86_exception_state32,
> >
> >                              &sc);
> >
> >
> >     // pull fault address from x86_exception_state32
> >     // check that it is an expected address
> >     // make the page read-write
> >     // do cleanup
> >
> >     return KERN_SUCCESS;
> > }
> >
> > void *exception_handler(void *arg) {
> >
> >     extern boolean_t exc_server();
> >     mach_port_t port = (mach_port_t) arg;
> >     mach_msg_server(exc_server, 2048, port, 0);
> >     abort(); // without this GCC complains (it doesn't know that
> mach_msg_server never returns)
> >
> > }
> >
> > // Does this need to be called on every thread?
> > // I assume exception_port can be reused. Is this true?
> > void setup_mach_exception_port() {
> >
> >     static mach_port_t exception_port = MACH_PORT_NULL;
> >     mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE,
> &exception_port);
> >     mach_port_insert_right(mach_task_self(), exception_port,
> exception_port, MACH_MSG_TYPE_MAKE_SEND);
> >
> >     // using task_set_exception_ports causes LLDB to hang...
> >     // ...whenever it hits breakpoint outside of catch_exception_raise
> >
> >     //
> > task_set_exception_ports(mach_task_self(), EXC_MASK_BAD_ACCESS,
> exception_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
> >      thread_set_exception_ports(mach_thread_self(), EXC_MASK_BAD_ACCESS,
> exception_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
> >     pthread_t returned_thread;
> >
> >     pthread_create(&returned_thread, NULL, exception_handler, (void*)
> exception_port);
> > }
> >
> > On Jul 8, 2013, at 12:41 PM, Greg Clayton <gclayton at apple.com> wrote:
> > Not many people actually take over their own mach exception ports, so
> this isn't something that hits a lot of people. It mainly hits the GC folks
> and the Runtime (Java) folks that need to intercept NULL derefs.
> > We do know about the issue and have plans to address this in the future.
> > The solution that works right now is to take over EXC_BAD_ACCESS on the
> _thread_ mach port. GDB and LLDB take over the task exception ports but we
> leave the thread exception ports alone. The thread mach ports will get the
> exception first, and if not handled, will pass it along to the task
> exception ports. Depending on your architecture, you might easily be able
> to do this, or it might be difficult.
> > Greg Clayton
> >
> >
> > -Heath Borders
> > heath.borders at gmail.com
> > Twitter: heathborders
> > http://heath-tech.blogspot.com
> > _______________________________________________
> > lldb-dev mailing list
> > lldb-dev at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20131023/791bf24a/attachment.html>


More information about the lldb-dev mailing list