|
This probe shows how to inject a heap memory fault in C++.
It also demonstrates the use of probe types and dynamic probes.
Test case: alloc.cpp
--------------------
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
// try standard new that raises an exception
on error
try
{
char* buf1 = new char[ 32 ];
cout << "buf1 is OK" << endl;
delete[] buf1;
}
catch( ... )
{
cout << "Caught ..." << endl;
}
// try old new that returns 0 on error
{
char* buf2 = new(nothrow) char[ 32 ];
if ( buf2 )
{
cout << "buf2 is OK" << endl;
}
else
{
cout << "buf2 is NULL" << endl;
}
delete[] buf2;
}
// try C calloc
{
char* buf3 = (char*)calloc( 32, 1 );
if ( buf3 )
{
puts( "buf3 is OK" );
}
else
{
puts( "buf3 is NULL" );
}
free( buf3 );
}
return 0;
}
The probe: alloc.apc
--------------------
probe program
{
ap_FunctionIdT fmalloc;
ap_FunctionIdT fcalloc;
on_entry
{
/* instrument malloc and calloc */
fmalloc =
ap_SymbolToFunction(
ap_SymbolNameToId( ap_ModuleNameToId(
"libc.so" ),
"malloc",
ap_NoName,
ap_FunctionSymbol
));
ap_InstrumentFunction( fmalloc );
fcalloc =
ap_SymbolToFunction(
ap_SymbolNameToId( ap_ModuleNameToId(
"libc.so" ),
"calloc",
ap_NoName,
ap_FunctionSymbol
));
ap_InstrumentFunction( fcalloc );
}
probe thread
{
probe extern:"main()"
{
/* declare the probe type */
typedef probe
{
on_entry ap_StubRoutine;
on_exit $return = 0;
} MemProbeT;
on_entry
{
new MemProbeT( fmalloc );
new MemProbeT( fcalloc );
}
}
}
}
The result:
----------
When running without the probe:
prompt> a.exe
buf1 is OK
buf2 is OK
buf3 is OK
When running with the probe:
prompt> aprobe -u alloc a.exe
Caught ...
buf2 is NULL
buf3 is NULL
---------------------------------------------------------------
Another example:
To force the return of an error code (-1) when
a caller tries to
make a tcp connection.
The probe: sock.apc
-------------------
#include <sys/types.h>
#include <sys/socket.h>
probe thread
{
probe extern:"socket()" in "libc.so"
{
int stub_flag = 0;
on_entry
{
int domain = $1;
int type = $2;
int proto = $3;
if ( domain == PF_INET && type ==
SOCK_STREAM && proto == 0 )
{
/* this is a TCP connection - stub it
*/
stub_flag = 1;
ap_StubRoutine;
}
}
on_exit
{
if ( stub_flag )
{
$return = -1;
stub_flag = 0;
}
}
}
}
The result:
----------
Here is how it works when applied to mozilla:
prompt> aprobe -u sock /usr/lib/mozilla-1.2.1/mozilla-bin
_X11TransSocketOpen: socket() failed for tcp
_X11TransSocketOpenCOTSClient: Unable to open
socket for tcp
_X11TransOpen: transport open failed for tcp/target1:0 |