Intercept Module: Difference between revisions

From STRIDE Wiki
Jump to navigation Jump to search
No edit summary
 
(17 intermediate revisions by 5 users not shown)
Line 1: Line 1:
== About Intercept Modules<br> ==
__NOTOC__
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 (see the [[Build Tools|Build Tools]] page). The Intercept Module, or IM, is created based on selected interfaces or test units that have been "captured", or identified through a subset of STRIDE 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.<br>  


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 (see the [[Build Tools|Build Tools]] page). 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.<br>
The [[s2sinstrument]] executable generates the code for an intercept module for selected functions or test units. Generation can be tailored to include different instrumentation details for each function.  
 
<br>
 
The [[s2sinstrument]] program, or alternatively, the Intercept Module Wizard in Studio generate the code for an intercept module for selected functions or test units. Generation can be tailored to include different instrumentation details for each function.  


<br> Three files are created, each prepended with the name of the Intercept Module that you gave it when it was created:  
<br> Three files are created, each prepended with the name of the Intercept Module that you gave it when it was created:  


*The Intercept Module source file (''imname'''''IM.c''' or ''imname'''''IM.cpp''')<br>This file contains the code that allows the ''remoting'' of functions so that they can be accessed by the Target and Host.  
*The Intercept Module source file (''imname'''''IM.c''' or ''imname'''''IM.cpp''')<br>This file contains the code that allows the ''remoting'' of functions so that they can be accessed by the Target and Host.  
*The Delegate Mangling header file (''imname'''''IM.h''')<br>This file must be included in all of your C files that are using Delegates (Dynamic or Tracing). It contains macros that will mangle the appropriate function names so that they can be intercepted and routed through the IM. When used, it must be the last file <tt>#include</tt>'d in the source. Also, it is only required if the C file uses Delegates. Stubs and Proxy functions do not require this file  
*The Name Mangling header file (''imname'''''IM.h''')<br>This file must be included in all of your C files that are using ''Interceptors'' (formal ''Delegates'') - ''Remote'' (aka ''Dynamic'') or ''Trace''. It contains macros that will mangle the appropriate function names so that they can be intercepted and routed through the IM. When used, it must be the last file <tt>#include</tt>'d in the source. ''Stub'' and ''Proxy'' functions do not require this file  
*The IM Entry point header file (''imname'''''IMEntry.h''')<br>This file contains the prototypes for the external entry points into the IM. It is needed only by the function that starts the IM Stub Read Thread.
*The IM Entry point header file (''imname'''''IMEntry.h''')<br>This file contains the prototypes for the external entry points into the IM. It is needed only by the function that starts the IM Stub Read Thread.
<br>


The following examples describe integration and testing situations that would require generation of one or more intercept modules:  
The following examples describe integration and testing situations that would require generation of one or more intercept modules:  


*To call a function on the target platform from the host, you must generate an intercept module containing a stub and include it in the target build.  
*To call a function on the target platform from the host, you must generate an intercept module containing a '''stub''' and include it in the target build.  
*To call a function on the host platform from a function on the target, you must generate an intercept module containing a proxy and include it in the target build.  
*To call a function on the host platform from a function on the target, you must generate an intercept module containing a '''proxy''' and include it in the target build.  
*To trace on that function resides wholly on the target (e.g., both the called and the calling functions are co-located on the target platform), you must generate an intercept module containing a tracing delegate and include it in the target build.  
*To trace on a function that completely resides on the target (e.g., both the called and the calling functions are co-located on the target platform), you must generate an intercept module containing a '''trace interceptor''' (formal '''trace delegate''') and include it in the target build.  
*To be able to dynamically "move" a function back and forth between host and target platforms during integration and testing without rebuilding the target application, you must generate an intercept module containing a dynamic delegate and include it in the target build.<br>
*To be able to dynamically "move" a function back and forth between host and target platforms during integration and testing without rebuilding the target application, you must generate an intercept module containing a '''remote interceptor''' (formal '''dynamic delegate''') and include it in the target build.<br>
 
<br>
 
== Stubs, Proxies, and Delegates<br>  ==
 
Target instrumentation is handled via stubs, proxies, and delegates, each of which provide distinct functionality.<br>  


<br>  
Target instrumentation is handled via stubs, proxies, and interceptors, each of which provide distinct functionality.<br>  


[[Image:PROXYSTUB.gif|center]]  
[[Image:PROXYSTUB.gif|center]]  


<br>


=== Stub<br>  ===
= Stub =


A stub is required in order to call a function, f(), on the target from the host.  
A stub is required in order to call a function, f(), on the target from the host.  
Line 45: Line 33:
When a proxy and a stub exist for a given function, the stub is never on the same platform as the proxy.  
When a proxy and a stub exist for a given function, the stub is never on the same platform as the proxy.  


<br>
= Proxy =
 
=== Proxy<br>  ===


A proxy is required in order to transparently intercept a target call to a function, f(), and remote the call to a host implementation of f().  
A proxy is required in order to transparently intercept a target call to a function, f(), and remote the call to a host implementation of f().  
Line 60: Line 46:
<br> '''Note:''' A stub and a proxy cannot simultaneously coexist for the same function. Only one can be used for any given test configuration.  
<br> '''Note:''' A stub and a proxy cannot simultaneously coexist for the same function. Only one can be used for any given test configuration.  


=== <br>  ===
= Interceptor =
 
=== Delegate<br>  ===
 
A delegate is a specialized type of proxy. A delegate can perform the following tasks:
 
*Transparently trace all calls to a method, f(), whose implementation resides on the target. All calls and parameter data can be captured and recorded. This type of delegate is called a '''Tracing Delegate'''.
*Transparently route calls to either a target- or host-based implementation of f(). This routing is dynamic and controlled by the host. This type of delegate is called a '''Dynamic Delegate'''.


A Tracing Delegate intercepts calls to f() and records tracing information such as time, input parameters, etc. before passing control to the local implementation of f(). Upon the return from f(), the delegate again records tracing information before passing control back to the caller. The delegate inserts itself between the caller and the callee in order to capture tracing information.
An interceptor is a specialized type of proxy. It can perform the following tasks:


A Dynamic Delegate inserts itself between the caller and the callee in the same way as a Tracing Delegate, but its logic is different. In addition to recording tracing information, it contains logic to check certain state information to determine whether to route the call to a host implementation (and override the owner) of f(), or to allow the call to proceed to the local implementation (owner) of f().  
*Transparently trace all calls to a method, f(), whose implementation resides on the target. All calls and parameter data can be captured and recorded. This type of interceptor is called a '''Trace Interceptor''' (formally known as '''Trace Delegate''').  


'''Note:''' A Dynamic Delegate is always a Tracing Delegate, but depending upon instructions you give the Intercept Module Wizard, a Tracing Delegate may or may not be a Dynamic Delegate.<br><br>
*Transparently route calls to either a target- or host-based implementation of f(). This routing is dynamic and controlled by the host. This type of interceptor is called a '''Remote Interceptor''' (formally known as '''Dynamic Delegate''').


==== Delegate Options<br>  ====
A Trace Interceptor intercepts calls to f(), by inserts itself between the caller and the callee, and records tracing information such as time, input parameters, etc. before passing control to the local implementation of f(). Upon the return from f(), the interceptor again records tracing information before passing control back to the caller.


==== ''Owner/User''<br>  ====
A Remote Interceptor inserts itself between the caller and the callee in the same way as a Trace Interceptor, but its logic is different. It checks certain state information to determine whether to route the call to a host implementation (and override the owner) of f(), or to allow the call to proceed to the local implementation (owner) of f().


To insert a delegate between a user (calling) function and owner (called) function, you must choose how function [[Name Mangling|name mangling]] will be handled. Name mangling describes the automatic source transformation required for a delegate to insert itself between caller and callee. There are two options for handling name mangling, one of which must be chosen when using delegates:<br>
== Interceptor Options ==


#A call to a function f() is transformed to "__imf()” to allow the delegate to intercept the call. This is referred to as '''user mangling'''.
=== ''Definition/Reference'' ===
#The implemention of f() can be transformed to "__imf()”. This is referred to as '''owner mangling'''.<br>


See the [[Name Mangling|Understanding Name Mangling]] page for a detailed explanation of name mangling and how it is used.<br>
To insert an interceptor between a ''reference'' function and ''definition'' function, you must choose how function ''name mangling'' will be handled. Name mangling describes the automatic source transformation required for an interceptor to insert itself between caller and callee. There are two options for handling name mangling, one of which must be chosen:


==== ''Implicit/Explicit''<br>  ====
*A call to a function f() is transformed to "__im_f()” to allow interception of the call. This is referred to as '''reference mangling'''.


A delegate may have either implicit or explicit mangling incorporated into it. By default, implicit mangling is used; this means that selected routines will be mangled using a [[#Group_ID|Group ID]]. If explicit mangling is used, you must explicitly mangle selected routines using the explicit macro "'''imDELEGATE('''''&lt;function_name&gt;''''')'''". For detailed information about implicit and explicit mangling, including examples, click [[Name Mangling|here]].  
*The implemention of f() can be transformed to "__im_f()”. This is referred to as '''definition mangling'''.


==== ''Group ID''<br>  ====
See the [[Name Mangling]] page for a detailed explanation of name mangling and how it is used.


A Group ID assigns a special symbolic constant, declared in the Intercept Module delegate mangling header file (xxxIM.h), that can be used by the preprocessor to mangle a subset of routines; successful use of Group ID(s) assumes that each source file (e.g., FuncA.c and FuncB.c) has its own header file (e.g., FuncA.h and FuncB.h). A Group ID can be defined within the source file or defined as a compiler input parameter. The default Group ID(s) used by the [[s2sinstrument]] executable or the Intercept Module Wizard in Studio can be overridden with your own Group ID(s). Name mangling conflicts can be resolved using the Group ID(s).<br>
=== ''Implicit/Explicit'' ===


<br>'''See also'''  
An interceptor may have either implicit or explicit name mangling incorporated into it. By default, implicit mangling is used; this means that selected routines will be mangled using a '''Group_ID'''. If explicit mangling is used, you must explicitly mangle selected routines using the explicit macro "'''srTEST_INTERCEPT('''''&lt;function_name&gt;''''')'''". For detailed information about implicit and explicit name mangling, including examples, see the [[Name Mangling]] page.


*[[Name Mangling|Understanding Name Mangling]]
=== ''Group ID'' ===
*'''[[Integrating the Intercept Module (IM)|Integrating the Intercept Module (IM)]]''' for directions on how to generate an IM and add it to your target build
*[[S2sinstrument|Using s2sinstrument.exe to generate an Intercept Module]]


[[Category:Reference]]
A Group ID assigns a special symbolic constant, declared in the Intercept Module name mangling header file (xxxIM.h), that can be used by the preprocessor to mangle a subset of routines. A Group ID can be defined within the source file or defined as a compiler input parameter (preprocessor directive). Name mangling conflicts can be resolved using the Group ID(s).

Latest revision as of 15:54, 4 July 2015

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 (see the Build Tools page). The Intercept Module, or IM, is created based on selected interfaces or test units that have been "captured", or identified through a subset of STRIDE 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.

The s2sinstrument executable generates the code for an intercept module for selected functions or test units. Generation can be tailored to include different instrumentation details for each function.


Three files are created, each prepended with the name of the Intercept Module that you gave it when it was created:

  • The Intercept Module source file (imnameIM.c or imnameIM.cpp)
    This file contains the code that allows the remoting of functions so that they can be accessed by the Target and Host.
  • The Name Mangling header file (imnameIM.h)
    This file must be included in all of your C files that are using Interceptors (formal Delegates) - Remote (aka Dynamic) or Trace. It contains macros that will mangle the appropriate function names so that they can be intercepted and routed through the IM. When used, it must be the last file #include'd in the source. Stub and Proxy functions do not require this file
  • The IM Entry point header file (imnameIMEntry.h)
    This file contains the prototypes for the external entry points into the IM. It is needed only by the function that starts the IM Stub Read Thread.

The following examples describe integration and testing situations that would require generation of one or more intercept modules:

  • To call a function on the target platform from the host, you must generate an intercept module containing a stub and include it in the target build.
  • To call a function on the host platform from a function on the target, you must generate an intercept module containing a proxy and include it in the target build.
  • To trace on a function that completely resides on the target (e.g., both the called and the calling functions are co-located on the target platform), you must generate an intercept module containing a trace interceptor (formal trace delegate) and include it in the target build.
  • To be able to dynamically "move" a function back and forth between host and target platforms during integration and testing without rebuilding the target application, you must generate an intercept module containing a remote interceptor (formal dynamic delegate) and include it in the target build.

Target instrumentation is handled via stubs, proxies, and interceptors, each of which provide distinct functionality.

PROXYSTUB.gif


Stub

A stub is required in order to call a function, f(), on the target from the host.

The stub performs two main tasks:

  • Provides a handler for incoming host invocations and transparently converts them into local calls to f().
  • Captures the return and output values of the local call and transmits them back to the host.

When a proxy and a stub exist for a given function, the stub is never on the same platform as the proxy.

Proxy

A proxy is required in order to transparently intercept a target call to a function, f(), and remote the call to a host implementation of f().

The proxy performs two main tasks:

  • Intercepts local calls to f() and transfers the call, along with parameter data, to the host implementation.
  • Captures the host response containing return values and output data, and transparently returns the information to the local caller.

When a proxy and a stub exist for a given function, the stub is never on the same platform as a proxy. When more than one proxy exists for a given function, each proxy must be located on a different platform.


Note: A stub and a proxy cannot simultaneously coexist for the same function. Only one can be used for any given test configuration.

Interceptor

An interceptor is a specialized type of proxy. It can perform the following tasks:

  • Transparently trace all calls to a method, f(), whose implementation resides on the target. All calls and parameter data can be captured and recorded. This type of interceptor is called a Trace Interceptor (formally known as Trace Delegate).
  • Transparently route calls to either a target- or host-based implementation of f(). This routing is dynamic and controlled by the host. This type of interceptor is called a Remote Interceptor (formally known as Dynamic Delegate).

A Trace Interceptor intercepts calls to f(), by inserts itself between the caller and the callee, and records tracing information such as time, input parameters, etc. before passing control to the local implementation of f(). Upon the return from f(), the interceptor again records tracing information before passing control back to the caller.

A Remote Interceptor inserts itself between the caller and the callee in the same way as a Trace Interceptor, but its logic is different. It checks certain state information to determine whether to route the call to a host implementation (and override the owner) of f(), or to allow the call to proceed to the local implementation (owner) of f().

Interceptor Options

Definition/Reference

To insert an interceptor between a reference function and definition function, you must choose how function name mangling will be handled. Name mangling describes the automatic source transformation required for an interceptor to insert itself between caller and callee. There are two options for handling name mangling, one of which must be chosen:

  • A call to a function f() is transformed to "__im_f()” to allow interception of the call. This is referred to as reference mangling.
  • The implemention of f() can be transformed to "__im_f()”. This is referred to as definition mangling.

See the Name Mangling page for a detailed explanation of name mangling and how it is used.

Implicit/Explicit

An interceptor may have either implicit or explicit name mangling incorporated into it. By default, implicit mangling is used; this means that selected routines will be mangled using a Group_ID. If explicit mangling is used, you must explicitly mangle selected routines using the explicit macro "srTEST_INTERCEPT(<function_name>)". For detailed information about implicit and explicit name mangling, including examples, see the Name Mangling page.

Group ID

A Group ID assigns a special symbolic constant, declared in the Intercept Module name mangling header file (xxxIM.h), that can be used by the preprocessor to mangle a subset of routines. A Group ID can be defined within the source file or defined as a compiler input parameter (preprocessor directive). Name mangling conflicts can be resolved using the Group ID(s).