gdb.info: Tracing on Symmetrix

Go forward to Rationale
Go backward to Varying Target Capabilities
Go up to Agent Expressions
Go to the top op gdb

Tracing on Symmetrix

This section documents the API used by the GDB agent to collect data on
Symmetrix systems.
   Cygnus originally implemented these tracing features to help EMC
Corporation debug their Symmetrix high-availability disk drives.  The
Symmetrix application code already includes substantial tracing
facilities; the GDB agent for the Symmetrix system uses those facilities
for its own data collection, via the API described here.
 - Function: DTC_RESPONSE adbg_find_memory_in_frame (FRAME_DEF *FRAME,
          char *ADDRESS, char **BUFFER, unsigned int *SIZE)
     Search the trace frame FRAME for memory saved from ADDRESS.  If
     the memory is available, provide the address of the buffer holding
     it; otherwise, provide the address of the next saved area.
        * If the memory at ADDRESS was saved in FRAME, set `*BUFFER' to
          point to the buffer in which that memory was saved, set
          `*SIZE' to the number of bytes from ADDRESS that are saved at
          `*BUFFER', and return `OK_TARGET_RESPONSE'.  (Clearly, in
          this case, the function will always set `*SIZE' to a value
          greater than zero.)
        * If FRAME does not record any memory at ADDRESS, set `*SIZE'
          to the distance from ADDRESS to the start of the saved region
          with the lowest address higher than ADDRESS.  If there is no
          memory saved from any higher address, set `*SIZE' to zero.
          Return `NOT_FOUND_TARGET_RESPONSE'.
     These two possibilities allow the caller to either retrieve the
     data, or walk the address space to the next saved area.
   This function allows the GDB agent to map the regions of memory
saved in a particular frame, and retrieve their contents efficiently.
   This function also provides a clean interface between the GDB agent
and the Symmetrix tracing structures, making it easier to adapt the GDB
agent to future versions of the Symmetrix system, and vice versa.  This
function searches all data saved in FRAME, whether the data is there at
the request of a bytecode expression, or because it falls in one of the
format's memory ranges, or because it was saved from the top of the
stack.  EMC can arbitrarily change and enhance the tracing mechanism,
but as long as this function works properly, all collected memory is
visible to GDB.
   The function itself is straightforward to implement.  A single pass
over the trace frame's stack area, memory ranges, and expression blocks
can yield the address of the buffer (if the requested address was
saved), and also note the address of the next higher range of memory,
to be returned when the search fails.
   As an example, suppose the trace frame `f' has saved sixteen bytes
from address `0x8000' in a buffer at `0x1000', and thirty-two bytes
from address `0xc000' in a buffer at `0x1010'.  Here are some sample
calls, and the effect each would have:
`adbg_find_memory_in_frame (f, (char*) 0x8000, &buffer, &size)'
     This would set `buffer' to `0x1000', set `size' to sixteen, and
     return `OK_TARGET_RESPONSE', since `f' saves sixteen bytes from
     `0x8000' at `0x1000'.
`adbg_find_memory_in_frame (f, (char *) 0x8004, &buffer, &size)'
     This would set `buffer' to `0x1004', set `size' to twelve, and
     return `OK_TARGET_RESPONSE', since `f' saves the twelve bytes from
     `0x8004' starting four bytes into the buffer at `0x1000'.  This
     shows that request addresses may fall in the middle of saved
     areas; the function should return the address and size of the
     remainder of the buffer.
`adbg_find_memory_in_frame (f, (char *) 0x8100, &buffer, &size)'
     This would set `size' to `0x3f00' and return
     `NOT_FOUND_TARGET_RESPONSE', since there is no memory saved in `f'
     from the address `0x8100', and the next memory available is at
     `0x8100 + 0x3f00', or `0xc000'.  This shows that request addresses
     may fall outside of all saved memory ranges; the function should
     indicate the next saved area, if any.
`adbg_find_memory_in_frame (f, (char *) 0x7000, &buffer, &size)'
     This would set `size' to `0x1000' and return
     `NOT_FOUND_TARGET_RESPONSE', since the next saved memory is at
     `0x7000 + 0x1000', or `0x8000'.
`adbg_find_memory_in_frame (f, (char *) 0xf000, &buffer, &size)'
     This would set `size' to zero, and return
     `NOT_FOUND_TARGET_RESPONSE'.  This shows how the function tells the
     caller that no further memory ranges have been saved.
   As another example, here is a function which will print out the
addresses of all memory saved in the trace frame `frame' on the
Symmetrix INLINES console:
     void
     print_frame_addresses (FRAME_DEF *frame)
     {
       char *addr;
       char *buffer;
       unsigned long size;
       addr = 0;
       for (;;)
         {
           /* Either find out how much memory we have here, or discover
              where the next saved region is.  */
           if (adbg_find_memory_in_frame (frame, addr, &buffer, &size)
               == OK_TARGET_RESPONSE)
             printp ("saved %x to %x\n", addr, addr + size);
           if (size == 0)
             break;
           addr += size;
         }
     }
   Note that there is not necessarily any connection between the order
in which the data is saved in the trace frame, and the order in which
`adbg_find_memory_in_frame' will return those memory ranges.  The code
above will always print the saved memory regions in order of increasing
address, while the underlying frame structure might store the data in a
random order.
   [[This section should cover the rest of the Symmetrix functions the
stub relies upon, too.]]