Thursday, December 06, 2018

Switching to lldb for OS X

I have had extensive problems getting gdb to run properly on OS X, but I have generally been successful.  Recently I installed Mojave in a VM and ran into an issue that I didn't resolve.  Running gdb now requires modifying SIP (System Integrity Protection) which can only be done by booting into Recovery Mode.  I have yet to boot this VM into Recovery Mode, so gdb doesn't work.

It is ridiculous to tell people trying to learn assembly language the number of steps required to change SIP, create a certificate and codesign gdb in order to run ebe, so I have decided to bite the bullet and configure ebe to use either gdb or lldb.

Step 1 is to create a Debugger class which is a pure virtual class which allows me to have both GDB and LLDB subclasses and from the other parts of ebe use a single pointer to Debugger to refer to whichever debugger I am using.  After a little relearning it turned out to be pretty easy to create a superclass for GDB and start working on the LLDB class.

I think I have had the same start-up trials with gdb and lldb: they won't simply accept a stream of text as input.  You have to have a little time between commands.  This is my best assessment.  The truth might be a bit different.  Anyway to conquer getting all the output from a command I always follow an lldb command with "script print '<LLDB>\n'" which will print "LLDB" on a line by itself.  For some strange reasons I have to not simply read the output from a command; I have to use a Qt function to wait for outout to be ready.  The docs claim that it will wait up to the specified number of milliseconds, but I think it waits that amount of time.  Maybe I'm wrong on that.  Anyway after a certain amount of time of waiting, I go ahead and send the script command to lldb.  Unfortunately occasionally the command seems to disappear.  My solution is to wait up to about 4 seconds and then issue the script command a second time.

I don't like solutions like this, but sometimes it seems to be the best I can do.  I expect that perhaps a slower computer (or maybe faster) will exhibit different patterns of failing to execute my script command, so I have attempted to put in a little cushion in my times for waiting.

There is another issue with lldb.  If you set breakpoints by address and then run the program, the breakpoints are unresolved and don't work.  They do work if you do that process again.  So, in ebe, you would have to click on the alien icon once to "prime the pump" and click again to start debugging.  I have tried this and it is quick.   There is another way to start a program using "process launch --stop-at-entry" which will start it and stop at an entry point before main.  This takes about 3 seconds, but after that breakpoints can be set and a "continue" command will get the debugging started.  In ebe, you just click on the alien icon once and after a small delay it just works.  I prefer the "just works" with a small delay.  I don't wish to explain to people that you have to click twice.  If only I knew why lldb requires 3 seconds longer to find an entry point and set a breakpoint there and run the program...  A computer could do a lot in 3 seconds.  It makes no sense to me.

Anyway I have debugging working with the next line highlighted, registers, floating point registers, back trace, assembly data, and stack displayed.  Left to do is a collection of data for C/C++ in the data window.  Assembly debugging seems pretty solid.  I would prefer rock solid, but I don't know how to fix my issues with lldb.  I think the same issues have always existed with gdb, but my gdb kludge has been pretty successful if not rock solid.

No comments: