The macro expander emits lots of different kinds of events that allow the macro stepper to reconstruct the context and steps of expansion. In the expander, the interface with the macro stepper is mainly in log.rkt. Look for calls to log-expand etc in expr.rkt and other files in that directory.
For example, in the expansion of a lambda expression, the expander would emit a visit event ("I'm about to start expanding this expression"), then a prim-lambda event ("After inspecting the expression and resolving the head identifier, looks like Racket's lambda syntax"), then a lambda-renames event ("Here are the formal parameters with the new lexical scope applied"), then events for its body, then various events to indicate that it's exiting the context of the lambda expression. (I've skipped a few for simplicity.)
The macro stepper parses that sequence of events into a tree --- yes, parses, using Racket's LALR(1) parser generator --- and then it uses that tree to generate reduction steps. The tree structure is used to determine the context of each expansion step, so macro steps within the lambda expression's body show the surrounding lambda expression, show arrows between lambda-bound variables and apparent references, etc.
The macro-debugger/emit API doesn't provide a way to set the context of a remark or artificial step, but that could probably be added, at least in a limited form.