Solution (source code)

= Solution

Add profiling to the timer-<interrupt> handler. When the target <operating-system process> is interrupted while running, record its saved <instruction pointer>, map that address to a code region in the executable, and increment an address histogram. Addresses with many samples identify regions consuming a large fraction of execution time. The executable's code can then be disassembled around these addresses even when source and symbolic names are absent.

This is <statistical program profiling>: uniform samples of running time estimate time spent in code, not exact execution counts. Restrict samples to the desired process and distinguish application execution from unrelated kernel work. A sufficiently fine address histogram and many samples reveal hot loops; varying the sample interval reduces synchronization bias. If exact visit counts rather than time hotspots are needed, arrange breakpoint or single-step traps, or rewrite the binary to add counters, accepting their much larger overhead. \b[Source code is not required to associate sampled execution with instruction addresses.]