Dynamic Dynamic Loader logo

Dynamic Dynamic Loader (DDL) Project

NMSU

HOME

EVENT TOOL FRAMEWORK

DOCUMENTATION

DOWNLOAD

WRAPPER REDIRECTION

TABLE BASED REDIRECTION

REDIRECTION USING TCL

C++ REDIRECTION

FAQ

RESEARCH GROUP

PUBLICATIONS

FUTURE DIRECTIONS



Back to PLEASE Lab



Table Based Redirection

Table-based redirection allows you to use a "jump table" type of redirection. With Table-Based we can redirect all out target functions to a single wrapper function.


Example:
This is a sample for table based redirection. This code his following properties :

1. Tablesize = 4
The table can have maximum of 4 entries
2. Argument bytes = 16
The code argument bytes of all the target functions must be  less than or equal to 16.
3. Jump Index Variable = _jt_func_index
This variable is used to index the entries in jump table.
4. Jump Table Name = _jt_jumptable
All the target functions will be redirected to this location plus some offset.
5. Jump Function Name = _jt_jumppoint
This is the wrapper function for all target functions.
6. First entry is at _jt_jumptable + 3, each entry is 15 bytes
7. Entry address equation is (_jt_jumptable + 3 + i*15), i is index of entry (starting at 0)

Sample Source Code:

int _jt_func_index;

void _jt_jumptable()
{
     asm("\
    movl $0, _jt_func_index\n\
    jmp  _jt_jumppoint\n\
    movl $1, _jt_func_index\n\
    jmp  _jt_jumppoint\n\
    movl $2, _jt_func_index\n\
    jmp  _jt_jumppoint\n\
    movl $3, _jt_func_index\n\
    jmp  _jt_jumppoint\n\
    movl $4, _jt_func_index\n\
    jmp  _jt_jumppoint\n\
   ");
}

struct jt_args {

   int a0;
   int a1;
   int a2;
   int a3;
  };


// an array to store the symbol names
char* _jt_symboltable[4];

//array of function pointers to store original functions
int (*_jt_ptrtable[4])(struct jt_args args);

int _jt_nextstentry = 0;
int _jt_nextoffset = 0;

int _jt_get_tableoffset(char *funcname)
{
   if (_jt_nextstentry >= 4)
      return -1;
   _jt_symboltable[_jt_nextstentry] = strdup(funcname);
   _jt_ptrtable[_jt_nextstentry] = 0;
   _jt_nextoffset = 3 + 15 * _jt_nextstentry;
   _jt_nextstentry++;
   return _jt_nextoffset;
}


int _jt_jumppoint (struct jt_args args)
{
   int retval;
   do_redirect = 0;


  //
  // put my pre-call monitoring/logging/whatever code in here
  //
   
    if (!_jt_ptrtable[_jt_func_index])

    {
          _jt_ptrtable[_jt_func_index] = dlsym((void *)-1l, _jt_symboltable[_jt_func_index]);
              if (!_jt_ptrtable[_jt_func_index])
              {
                 fprintf(stderr,"Error: function %s cannot be found\n",_jt_symboltable[_jt_func_index]);
                 exit(1);
              }
    }
 
    retval =  (_jt_ptrtable[_jt_func_index])(args);


  //
  // put my post-call monitoring/logging/whatever code in here
  //

   do_redirect = 1;

   return retval;
}

Explanation of Sample Code:

void _jt_jumptable();
The symbol "_jt_jumptable" is the beginning of the jump table, and then you need to look at the object code to figure out the correct offsets. Each "mov" instruction begins a new table entry. The idea in the above code is to identify each function by an ID number, and then redirect them all to a single wrapper function. The wrapper function can then use the ID to know which function it is currently handling. Obviously, there is more programming to support all of this, but the foundational capability is already there.

struct jt_args;  The wrapper function can handle functions of different argument sizes but still we need to specify the maximum size of the arguments while writing the wrapper function. In this example we can wrap functions with argument size of 16 maximum. For this we are passing a structure of size 16 (4 integers) to our wrapper function.

int _jt_get_tableoffset(char *funcname)
This function is called by the redirection library to find the table offset of the functions which is being resolved. In this function we also store the function name in an array, store its address in function pointer array and calculate the offset for the next entry in jump table. The next offset is calculated by this statement;
_jt_nextoffset = 3 + 15 * _jt_nextstentry;

int _jt_jumppoint (struct jt_args args); This is the actual wrapper function. All the "wrapped" functions jump to this function from the jump table. This is the place where we add "pre-call" and "post-call" code  for all the "wrapped" function.