As mentioned above, you can use TraceEvent() to manage the instrumented kernel's buffers, but it's probably easier to run tracelogger in daemon mode and let it look after the buffers. Nevertheless, here's a summary of how to do it with TraceEvent():
TraceEvent(_NTO_TRACE_ALLOCBUFFER, uint bufnum, void** paddr);
Allocated trace buffers can store 1024 simple trace events.
Once you've allocated the buffers, you can use mmap() to map the buffers into your process's address space and get their virtual address. For example:
paddr_t paddr; tracebuf_t *kbufs; ret = TraceEvent(_NTO_TRACE_ALLOCBUFFER, num_buffers, &paddr); if( ret == -1 ) { // Handle the error. } kbufs = mmap( 0, num_buffers * sizeof(tracebuf_t), PROT_READ | PROT_WRITE, MAP_PHYS | MAP_SHARED, NOFD, paddr ); if( kbufs == MAP_FAILED ) { // Handle the error. }
Then you can use InterruptHookTrace() to register a handler for the _NTO_HOOK_TRACE synthetic interrupt that the instrumented kernel raises as each buffer becomes full.
TraceEvent(_NTO_TRACE_DEALLOCBUFFER);
All events stored in the trace buffers are lost.
TraceEvent(_NTO_TRACE_FLUSHBUFFER);
num_events = TraceEvent(_NTO_TRACE_QUERYEVENTS);
For examples of some of these commands, see Data-capture program in the Sample Programs appendix.