Managing trace buffers
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():
- To allocate the buffers, use the _NTO_TRACE_ALLOCBUFFER
command, specifying the number of buffers and a pointer to a location
where TraceEvent() can store the physical address of
the beginning of the ring of allocated trace buffers:
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.
- To free the buffers, use the _NTO_TRACE_DEALLOCBUFFER command.
It doesn't take any additional arguments:
TraceEvent(_NTO_TRACE_DEALLOCBUFFER);All events stored in the trace buffers are lost.
- To flush the buffer, regardless of the number of trace events it
contains, use the _NTO_TRACE_FLUSHBUFFER command:
TraceEvent(_NTO_TRACE_FLUSHBUFFER); - To get the number of simple trace events that are currently stored in
the trace buffer, use the _NTO_TRACE_QUERYEVENTS command:
num_events = TraceEvent(_NTO_TRACE_QUERYEVENTS);
For examples of some of these commands, see
Data-capture program
in the
Sample Programs
appendix.
