Camden Weaver
Camden Weaver

Reputation: 324

How to develop a debugger

I am looking for a way to do things such as attach to a process, set breakpoints, view memory, and other things that gdb/lldb can do. I cannot, however, find a way to do these things.

This question is similar to this one, but for MacOS instead of Windows. Any help is appreciated!

Note: I want to make a debugger, not use one.

Another thing is that i dont want this debugger to be super complicated, all i need is just reading/writing memory, breakpoint handling, and viewing the GPR

Upvotes: 16

Views: 14231

Answers (6)

Zorg
Zorg

Reputation: 1018

If you want to write your own debugger, you'll need to obtain a task port to the process (task_for_pid), then you can read/write/iterate to virtual memory (mach_vm_read, mach_vm_write, mach_vm_region). To do breakpoints, you need to first set up an exception handler then you can manipulate the debug registers on threads (task_threads, thread_get_state, thread_set_state) and handle them in the exception handler.

Reference to some not all that correct debugger code I've written because breakpoints (especially instruction ones) are a bit involved.

MacDBG may be another lightweight reference but I haven't used it myself.

Upvotes: 3

Jim Ingham
Jim Ingham

Reputation: 27118

If you really want to make your own debugger, another way to start would be to figure out how to cons up and parse the gdb-remote protocol packets (e.g. https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html). That's the protocol gdb uses when remote debugging and lldb uses for everything but Windows debugging. On MacOS, lldb spawns a debugserver instance which does the actual debugging and controls it with gdb-remote protocol packets. On Linux, it uses the lldb-server tool that's part of the Linux lldb distribution for the same purpose.

The gdb-remote protocol has primitives for most of the operations you want to perform, launch a process, attach to a process, set breakpoints, read memory & registers and isolates you from a lot of the low-level details of controlling processes.

You can help yourself out by observing how lldb uses this protocol by running an lldb debug session with:

(lldb) log enable gdb-remote packets

But you might also have a look at the SB API's in lldb. The documentation is not as advanced as it should be but there are a bunch of examples in the examples/python directory of the lldb sources to get you started, and in general the API's are pretty straightforward and self-explanatory.

Upvotes: 3

TheDarkKnight
TheDarkKnight

Reputation: 27611

Whilst you could look at source code of another debugger, you may find it difficult to understand without the knowledge of the underlying concepts. Therefore, I recommend you start by obtaining a good grounding of the concepts with the following resources:

Mac OS X Sys Internals Rather outdated now, but the original bible for the internals of Mac

Mac OS X and iOS Internals Again, outdated but useful. This link is Jonathan Levin's (the author's) own site and he's now providing it for free, due to issues he had with the publisher. He's since purchased back the rights, making it available to all.

*OS Internals The current bible of Mac Internals, also by Jonathan Levin. Books III and I have been published, with book II to follow shortly!

Upvotes: 0

Konrad Rudolph
Konrad Rudolph

Reputation: 545628

LLDB has an API that can be consumed from C++ or Python. Maybe this is what you’re looking for.

Unfortunately the documentation is fairly threadbare, and there don’t seem to be usage examples. This will therefore entail some reading of the source and a lot of trial and error.

Upvotes: 3

Jesper Juhl
Jesper Juhl

Reputation: 31475

Use a debugger. Such as gdb or lldb for example. They have plenty of documentation to teach you the how bit, but for example gdb -p <pid of process> will attach gdb to a running process.

If you want to drive gdb for example from a C++ program, then launch it in a separate process (see fork and exec) with the aguments it needs (probably including the one to enable its machine parsable interface). Make sure you set up pipes to its stdin/stdout so you can read its output and send it commands.

If instead you want to write your own debugger from scratch then that is a huge undertaking. I suggest starting by reading the source of an existing open source debugger.

Upvotes: 1

rubenvb
rubenvb

Reputation: 76579

Well, if you want to write a debugger, take a look at the gdb/lldb source code. I'd suggest the latter, due to historical legacy in gdb that might cloud whatever is actually going on.

Upvotes: 2

Related Questions