Studio:Integrating the Intercept Module (IM): Difference between revisions

From STRIDE Wiki
Jump to navigation Jump to search
 
(20 intermediate revisions by 4 users not shown)
Line 6: Line 6:
== Activating the Intercept Module ==
== Activating the Intercept Module ==
=== Compiling the IM ===
=== Compiling the IM ===
To compile the IM, you must define the macro '''srIMON''' when you compile the IM.c file or any file that includes one of the headers.  This "turns on" the intercept feature. For example:
To compile the IM, you must define the '''STRIDE_ENABLED''' (or '''srIMON''' in 3.0.01xx or older releases) preprocessor directive when you compile the IM.c file or any file that includes one of the headers.  This "turns on" the intercept feature. For example:
   cc -c -IC:\STRIDE\inc -DsrIMON MyProjectIM.c
   cc -c -IC:\STRIDE\inc -DSTRIDE_ENABLED=1 MyProjectIM.c


Notice that the IM.c and IMEntry.h files reference header files in the STRIDE installation directory.  The build must include this directory when compiling either of these files.  The Delegate (IM.h) header file does not have any dependencies on this directory.
Notice that the IM.c and IMEntry.h files reference header files in the STRIDE installation directory.  The build must include this directory when compiling either of these files.  The public interface (IM.h) header file does not have any dependencies on this directory.


=== IM Resource Requirements ===
=== IM Resource Requirements ===
The Intercept Module is usually run as a separate task, and therefore has some
The Intercept Module is usually run as a separate task, and therefore has some
resource requirements that are in addition to those of the [[Target Integration#The STRIDE Runtime |Runtime]] and the [[Target Integration#The Platform Abstraction Layer (PAL)| PAL]]. One of these is the task resource itself.  Another is space for the task stack.
resource requirements that are in addition to those of the [[Runtime Integration|STRIDE Runtime]]. One of these is the task resource itself.  Another is space for the task stack.


The required task stack size if difficult to predict since it is dependent on the underlying system and on the data that is passed through function arguments.  A stack size between 2-4K would be a good starting point.
The required task stack size if difficult to predict since it is dependent on the underlying system and on the data that is passed through function arguments.  A stack size between 2-4K would be a good starting point.


=== Starting the srThread and IMStubRead threads ===
=== Starting the IMStubRead threads ===
The IM must be started ''after'' the Runtime and Transport have been initialized, but before any intercepted calls can be made.  Failure to do this before making an intercepted call can crash or hang the target.
The IM must be started ''after'' the Runtime and Transport have been initialized, but before any intercepted calls can be made.  Failure to do this before making an intercepted call can crash or hang the target.


This code snippet for Linux, based on using the POSIX call pthread_create() to start a task (your OS may use a different call), demonstrates how to initialize the PAL and the Runtime, start the IM, then becomes the Runtime message processing loop.  Note that this code assumes that it will become the Runtime thread's message processing loop (because srThread() will never return unless thread is stopped or killed).  The comments note that this could instead create a second task for the Runtime and return.
Look at any of the prepackaged [[:Category:SDKs|SDKs]] for examples of integrating your application.


=== Linux Implementation ===
[[Category:Studio:Installation]]
This code snippet for Linux also handles termination signals based on POSIX APIs in signal.h in order to cleanly shut down the target and clean up resources.  This is required if multi-process target is enabled in the Runtime, especially for Linux OS.
 
<source lang="c">
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
 
/* STRIDE runtime includes */
#include <sr.h>
/* The OS PAL configuration file */
#include <palcfg.h>
 
/* Intercept Module includes */
#include "MyProjectIMEntry.h"
 
extern palBOOL palInit();
extern palBOOL palUninit();
 
/* The IM message handler ("MyProject" is the IM name) */
extern void MyProjectIMStubThread();
 
/* Thread handling */
typedef void (*_ThreadFunc_t)( void );
 
void* _threadFunc(void* param)
{
    if (param)
    {
        _ThreadFunc_t proc = (_ThreadFunc_t)param;
        proc();
    }
 
    return NULL;
}
 
static pthread_t _threads[15] = {0};
 
/* Termination signals handling */
void _cleanup(void)
{
    int i = 0;
 
    fprintf(stdout, "TestAgent exiting.\n");
    for (i = sizeof(_threads)/sizeof(_threads[0]); i > 0; i--)
    {
        if (_threads[i-1] != 0)
        {
            palNotify(_threads[i-1], palSTOP_EVENT);
            pthread_join(_threads[i-1], NULL);
            pthread_detach(_threads[i-1]);
        }
    }
 
    srUninit();
    palUninit();
}
 
volatile sig_atomic_t termination_in_progress = 0;
 
void _terminate(int sig)
{
    /* Since this handler is established for more than one kind of signal,
      it might still get invoked recursively by delivery of some other kind
      of signal.  Use a static variable to keep track of that. */
    if (termination_in_progress)
        raise (sig);
    termination_in_progress = 1;
 
    /* cleanup */
    _cleanup();
 
    /* Now reraise the signal.  We reactivate the signal's
      default handling, which is to terminate the process.
      We could just call exit or abort,
      but reraising the signal sets the return status
      from the process correctly. */
    signal (sig, SIG_DFL);
    raise (sig);
}
 
 
/****************************************************************************
* Main entry point
***************************************************************************/
#ifdef __cplusplus
extern "C"
#endif
int main(int argc, char **argv)
{
    int i = 0;
    pthread_t *ioThread = NULL;
 
    // Set termination signals handling
    (void) signal(SIGABRT, _terminate);
    (void) signal(SIGTERM, _terminate);
    (void) signal(SIGINT, _terminate);
    (void) signal(SIGQUIT, _terminate);
 
    // Initialize PAL. It will return palFALSE if it fails
    if (palInit(&ioThread) == palFALSE)
    {
        palLog(palLOG_LEVEL_ERROR, "PAL Initialization failed.");
        palLog(palLOG_LEVEL_ERROR, "Quitting.");
        exit(1);
    }
 
    // Initialize Runtime
    if (srInit() != srOK)
    {
        palLog(palLOG_LEVEL_ERROR, "srInit failed.");
        palLog(palLOG_LEVEL_ERROR, "Quitting.");
        exit(1);
    }
 
    // Initialize GRS
    if (grsInit() != grsTRUE) {
        palLog(palLOG_LEVEL_ERROR, "grsInit FAILED");
        palLog(palLOG_LEVEL_ERROR, "Quitting.");
        exit(1);
    }
 
    // Start the Runtime thread first
    pthread_create(&_threads[i++], NULL, _threadFunc, (void*)srThread);
 
    // Start the IM stub read thread
    // The name of the stub read function is defined by the makefile
    pthread_create(&_threads[i++], NULL, _threadFunc, (void*)strideIMStubThread);
    // __STRIDE_FRAMEWORK_CUSTOM_INIT_BODY__
 
    int joinStatus = pthread_join(*ioThread, NULL);
 
    _cleanup();
 
    return 0;
}
</source>
 
=== Windows Implementation ===
This code snippet for Windows is based on using the Win32 API calls.
 
<source lang="c">
#include "stdafx.h"
#include <windows.h>
#include <commctrl.h>
 
#include <sr.h>
#include <palcfg.h>
#include "MyProjectIMEntry.h"
 
static bool bUseSerial = false;
 
struct ThreadInfo
{
    HANDLE handle;
    DWORD id;
};
 
typedef void (*_ThreadFunc_t)( void );
 
static DWORD WINAPI _threadFunc(LPVOID param)
{
    if (param)
    {
        _ThreadFunc_t proc = (_ThreadFunc_t)param;
        proc();
    }
 
    return 0;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    ThreadInfo threads[15] = {{NULL, 0}};
    int i = 0;
 
// Initialize the PAL
if (palOSInit() != palTRUE) {
palLog(palLOG_LEVEL_ERROR, "palOSInit FAILED.");
return -1;
}
 
pal_io_config_t cfg;
pal_prot_t protocol;
if (bUseSerial) {
protocol = PAL_PROT_SERIAL;
cfg.u.serial.BaudRate = PAL_SERIAL_BAUDRATE;
cfg.u.serial.ByteSize = PAL_SERIAL_BYTESIZE;
cfg.u.serial.ComPort = PAL_SERIAL_PORT;
cfg.u.serial.Parity = PAL_SERIAL_PARITY;
cfg.u.serial.StopBits = PAL_SERIAL_STOPBITS;
}
else {
protocol = PAL_PROT_TCP;
cfg.u.tcp.Port = PAL_DEFAULT_TCP_PORT;
}
 
// Initialize tcp transport
if (palIOInit(protocol, &cfg) != palTRUE) {
palLog(palLOG_LEVEL_ERROR, "palIOInit FAILED.");
return -1;
}
 
// Initialize Runtime
if (srInit() != srOK) {
palLog(palLOG_LEVEL_ERROR, "srInit FAILED.");
return -1;
}
 
    // Start the Runtime thread first
threads[i].handle = CreateThread(NULL, 0, _threadFunc, srThread, 0, &threads[i].id);
if (!threads[i++].handle) {
palLog(palLOG_LEVEL_ERROR, "CreateThread FAILED for Runtime Thread.");
return -1;
}
 
    // Start the IM stub read thread
threads[i].handle = CreateThread(NULL, 0, _threadFunc, MyProjectIMStubThread, 0, &threads[i].id);
if (!threads[i++].handle) {
palLog(palLOG_LEVEL_ERROR, "CreateThread FAILED for IM Thread.");
return -1;
}
 
    // Wait for Runtime thread
    WaitForSingleObject(threads[0].handle, INFINITE);
 
    fprintf (stdout, "TestAgent exiting.\n");
    for (i = sizeof(threads)/sizeof(threads[0]); i > 0; i--)
    {
        if (threads[i-1].handle != NULL)
        {
            palNotify(threads[i-1].id, palSTOP_EVENT);
            WaitForSingleObject(threads[i-1].handle, INFINITE);
            CloseHandle(threads[i-1].handle);
        }
    }
 
    srUninit();
    palOSUninit();
return 0;
}
</source>
 
 
[[Category: Installation]]

Latest revision as of 23:00, 19 May 2010

About Intercept Modules

Intercept Modules allow remote function calls across hardware (e.g., processor or machine) or software (operating system) platform boundaries. Intercept Modules are target-based components that are created as a step in the STRIDE build process. The Intercept Module, or IM, is created based on selected interfaces or test units that have been "captured", or identified through a subset of SCL pragmas that tag interfaces as candidates for remote function calls. Once created, the generated code is then compiled, linked and run along with the target application.


Activating the Intercept Module

Compiling the IM

To compile the IM, you must define the STRIDE_ENABLED (or srIMON in 3.0.01xx or older releases) preprocessor directive when you compile the IM.c file or any file that includes one of the headers. This "turns on" the intercept feature. For example:

 cc -c -IC:\STRIDE\inc -DSTRIDE_ENABLED=1 MyProjectIM.c

Notice that the IM.c and IMEntry.h files reference header files in the STRIDE installation directory. The build must include this directory when compiling either of these files. The public interface (IM.h) header file does not have any dependencies on this directory.

IM Resource Requirements

The Intercept Module is usually run as a separate task, and therefore has some resource requirements that are in addition to those of the STRIDE Runtime. One of these is the task resource itself. Another is space for the task stack.

The required task stack size if difficult to predict since it is dependent on the underlying system and on the data that is passed through function arguments. A stack size between 2-4K would be a good starting point.

Starting the IMStubRead threads

The IM must be started after the Runtime and Transport have been initialized, but before any intercepted calls can be made. Failure to do this before making an intercepted call can crash or hang the target.

Look at any of the prepackaged SDKs for examples of integrating your application.