Difference between revisions of "Studio:Accessing target data while processing a proxy call"

From STRIDE Wiki
Jump to: navigation, search
Line 56: Line 56:
  
  
[[Category:SCL]][[Category:Application Notes]]
+
[[Category:Application Notes]]

Revision as of 17:29, 4 February 2008

In some cases, void pointers are passed into proxy functions calls, or the passed structures are so complex that they cannot completely be described for STRIDE. In these cases, the proxy (e.g., a script) might have to access certain data on the target to be able to validate the functionality of the call. For example, this might be required with an interface that writes structured data to a file:

int write(const void *buffer, int element_size, int count)

STRIDE needs to know the data structure in order to correctly marshal the data across platforms. The element size itself is not enough information for STRIDE. The buffer pointer could be typecast to a byte pointer; however, in this case the number of elements would be based on element size and count. STRIDE supports sized pointers, as long as the size is a single field and not the combination of multiple fields.

How can an interface like this be easily dealt with in STRIDE if we plan on testing an application which uses this interface, but the library which implements the functionality is not yet available?

First of all, the assumption is the actual structure is of no interest. We simply want to test the ability to write to a stream and later read from it, and verify we get the same data back. In this case, we can leave the buffer pointer as a void pointer and just pass the void pointer to STRIDE. Once in the proxy function, we need a way to retrieve the actual data at this pointer address from the target; this can be done with a helper function which reads a number of bytes from a certain memory address and passes it back to STRIDE. A simple helper function in the .h file perform this function:

static void SCL_get_num_bytes(void *ptr, unsigned char* data, int num_bytes)
{
    memcpy(data, ptr, num_bytes);
}

An important note is that the data has to be valid when the helper function is called. In the case of a proxy call, the pointer should certainly be valid until the function returns. The proxy script is as follows:

   write.owner.register event = ascript.WaitForEvent(); 
   if (event = write)
   {
      /* Copy the buffer pointer from the proxy call */
      scl_get_num_bytes.ParameterList.num_bytes = write.ParameterList.element_size *write.ParameterList.count;    
     
      /* Call the helper function to retrieve the data */ 
      scl_get_num_bytes.Call();
     
      /* Process the data */ 
      get_num_bytes.User.OutPointers.data ...     ...     
      
      write.Return();  
      /* return from the proxy function call */
   }

The same can be done for the read function. Once the read proxy is called, a helper function can be called to copy the actual data in place. The read interface is as follows:

  int read(void *buffer, int element_size, int count);
  static void SCL_set_num_bytes(void *ptr, unsigned char* data, int num_bytes)
  {
    memcpy(ptr, data, num_bytes);
  }
  read.owner.register event = ascript.WaitForEvent();
  if (event = read)
  {
    /* set the data to be read */
    set_num_bytes.User.ParameterList.data = ...     ...   
     
    /* copy the buffer pointer from the proxy call */ 
    scl_set_num_bytes.ParameterList.ptr = read.ParameterList.buffer;
    
    /* calculate the number of bytes */     
    scl_set_num_bytes.ParameterList.num_bytes = read.ParameterList.element_size *read.ParameterList.count;  
    
    /* Call the helper function to retrieve the data */     
    scl_set_num_bytes.Call();     
    
    /* Process the data */     
    read.Return();  /* return from the proxy function call */
  }