These days the de facto debugger in macOS is LLDB. Apple’s old gdb fork doesn’t work anymore and the GNU gdb version is better these days but still quite meh (in the past it couldn’t deal with fat binary targets and I still think this holds true). So we are all essentially stuck with LLDB, warts and all. I also hate the lack of a gdbinit style output but Deroko started that project and I improved it with lldbinit.
Besides its horrible long command line syntax which is so unpopular that gdb-compatible commands were introduced, my biggest problem with it has been the lack of x86 hardware breakpoint support. While hardware breakpoints might not be needed to debug applications within Xcode, they are essential to any serious reverse engineer dealing with arbitrary untrusted targets such as malware, packers, obfuscators, and DRM. It has been a serious blocker for me against some targets and a source of immense frustration because it should be a basic debugger feature.
Last week I finally got fed up enough to dive into the LLDB C++ codebase and finally try to implement this feature. Instead of just posting a patch, this post is a journey into LLDB internals and how I implemented this feature. Hopefully it will help others exploring the LLDB codebase, which seems unfriendly because of the lack of really good documentation into its architecture. Maybe this could lead to further improvements and make LLDB more reverse engineer friendly.