Dynamic Probe Class Library

Dynamic Probe Class Library Programming Guide


Chapter 15. Searching for, and listing, functions in the target application

When installing and activating point probes (as described in Chapter 9, Executing probes in target application processes), the analysis tool must navigate the application source structure to get a reference to the instrumentation point where the point probe will be installed. For reusable, general-purpose, analysis tools, it is helpful to provide the end user with some way of searching the target application for the functions that match a user-supplied search string in order to determine where the user would like to install point probes. This frees the end user from the burden of having to know the exact name of the function.

Fortunately, the SourceObj class contains two functions (bget_function_list and get_function_list) that return a list of functions in a target application process that match a regular expression search pattern that you supply. This list of functions is returned as a FunctionList object which contains FunctionId objects that represent the individual functions that match the supplied regular expression. To determine the number of FunctionId objects in a FunctionList object, the analysis tool can call the FunctionList::get_count function. To get a reference to a particular FunctionId object in the FunctionList, the analysis tool can use the FunctionList::get_entry function. Once the analysis tool has a reference to a FunctionId object, it can use the FunctionId::get_demangled_name, FunctionId::get_mangled_name, and FunctionId::get_module_name functions to get specific information about the particular function.

The listmod sample application installed as part of DPCL provides a good example of how an analysis tool can use the FunctionList and FunctionId classes to search for and list functions in the target application. This sample application was copied to the directory /usr/lpp/ppe.dpcl/samples/listmod when you installed DPCL, and, by default, displays all instrumentation points in the target application. Using the optional -f flag, however, the end user can supply a regular expression search pattern. If the -f flag is used, the listmod application will list instrumentation points only for functions that match the supplied search pattern. For the complete code, refer to the /usr/lpp/ppe.dpcl/samples/listmod directory. Here are some highlights related to our current discussion:

  1. The analysis tool includes the appropriate header files:
    #include <FunctionList.h>
    
    #include <FunctionId.h>
    
    
  2. If a regular expression was supplied, the analysis tool gets the function list using the SourceObj::bget_function_list function.
     // check for function regular expression flag
    
      if ( strcmp(argv[3],"-f")==0)
    
      {
    
        if ( argc < 5 )
    
        {
    
          printf("Usage: host /path../code [-f func_reg_expr] \n");
    
          exit(1);
    
        }
    
        minus_f = true;
    
        strcpy(func_expr, argv[4]);
    
        printf(" Searching for functions like: \"%s\"\n",func_expr);
    
      }
    
     
    
      argvp[0] = path;
    
      argvp[1] = NULL;
    
     
    
      sts=P.bcreate(host, path, argvp, envp, stdout_cb, NULL, stderr_cb, NULL);
    
      if ( (int)sts != 0)
    
      {
    
        printf("bcreate %s\n", sts.status_name());
    
        exit(1);
    
      }
    
     
    
      SourceObj myprog = P.get_program_object();
    
     
    
      // If there was a regular expression specified, get the function list
    
      FunctionList *func_listp;
    
      if ( minus_f == true ) 
    
      {
    
        AisStatus *stsp = new AisStatus(ASC_success);
    
        func_listp = myprog.bget_function_list(P, func_expr, stsp);
    
        if ( (int)*stsp != 0) 
    
        {
    
          printf("bget_function_list %s\n", sts.status_name());
    
          exit(1);
    
        }
    
      }
    
    
  3. The analysis tool uses the program function show_function_list to list the entries in the function list. To do this, the show_function_list program function uses the FunctionList::get_count, FunctionList::get_entry, FunctionId::get_module_name, FunctionId::get_demangled_name, and FunctionId::get_mangled_name functions.
      show_function_list(func_listp);
    
     
    
    .
    
    .
    
    .
    
     
    
    ///////////////////////////////////////////////////////////////////////
    
    //
    
    // show the entries in the passed in function list
    
    //
    
    ///////////////////////////////////////////////////////////////////////
    
    void show_function_list(FunctionList *flp)
    
    {
    
      char mod_buf[MAXPATHLEN];
    
      char func_buf[MAXPATHLEN];
    
      char mang_buf[MAXPATHLEN];
    
     
    
      printf("FunctionList has %d elements\n", flp->get_count());
    
     
    
      for (int i = 0; i < flp->get_count(); i++) 
    
      {
    
        FunctionId id = flp->get_entry(i);
    
        printf("%s, %s, %s\n", id.get_module_name(mod_buf, sizeof(mod_buf)),
    
                               id.get_demangled_name(func_buf, sizeof(func_buf)),
    
                               id.get_mangled_name(mang_buf, sizeof(mang_buf)) );
    
     
    
      }
    
    }
    
    
  4. When listing the available instrumentation points, the analysis tool uses the program functions module_match and function_match to ensure that only instrumentation points for the pertinent modules/functions are listed. The program functions module_match and function_match use the FunctionList::get_count, FunctionList::get_entry, FunctionId::get_module_name, and FunctionId::get_mangled_name to accomplish their tasks.
        // only report on modules that have functions with a match
    
        if (!module_match(mymod.module_name(bufmname, bufSize), func_listp))
    
          continue;
    
        sts = mymod.bexpand(P);
    
        if ( (int)sts != 0)
    
          printf("%s\n", sts.status_name());
    
     
    
        modcount = mymod.child_count();
    
        printf("%2d.    %3d functions in file "
    
               "%s\n", c, modcount, mymod.module_name(bufmname,  bufSize));
    
     
    
        for ( x = 0; x < modcount; x++)
    
        { /* functions */
    
          myfun = mymod.child(x);
    
     
    
          // only report on functions that match the regular expression
    
          if (!function_match(myfun.get_mangled_name(bufmname, bufSize), func_listp))
    
            continue;
    
          count=myfun.exclusive_point_count();
    
          printf("%2d.%03d %3d IPT in function %s"
    
                 "\n", c, x, count, myfun.get_demangled_name(bufmname,  bufSize));
    
     
    
          for (int z=0; z<count; z++)
    
          {
    
            ip=myfun.exclusive_point(z);
    
            switch ( ip.get_type() )  {
    
              case IPT_function_call :
    
                printf("           %3d call  at lineno %d @ 0x%llx %s"
    
                       "\n", z, ip.get_line(), ip.get_address(),
    
                        ip.get_demangled_name(bufmname, bufSize));
    
                break;
    
     
    
              case IPT_function_entry :
    
                printf("           %3d entry at lineno %d @ 0x%llx %s"
    
                       "\n", z, ip.get_line(), ip.get_address(),
    
                       myfun.get_demangled_name(bufmname, bufSize));
    
                break;
    
     
    
              case IPT_function_exit :
    
                printf("           %3d exit  at lineno %d @ 0x%llx %s"
    
                       "\n", z, ip.get_line(), ip.get_address(),
    
                       myfun.get_demangled_name(bufmname, bufSize));
    
                break;
    
     
    
              default:
    
                printf("           %3d type   %d lineno %d @ 0x%llx %s"
    
                      "\n", z, ip.get_type(), ip.get_line(), ip.get_address(),
    
                      ip.get_demangled_name(bufmname, bufSize));
    
                break;
    
            }
    
     
    
          }
    
        }
    
      }
    
     
    
    .
    
    .
    
    .
    
     
    
    ///////////////////////////////////////////////////////////////////////
    
    //
    
    // check if string passed in is a module name in the function list
    
    //
    
    ///////////////////////////////////////////////////////////////////////
    
    bool
    
    module_match(char *in_str, FunctionList *flp)
    
    {
    
      char mod_buf[MAXPATHLEN];
    
     
    
      // If no regular expression specified, don't bother to look
    
      //  for a match
    
      if ( minus_f == false )
    
        return true;
    
     
    
      // look through the list for a matching module
    
      // return true if a match is found
    
      for (int i = 0; i < flp->get_count(); i++)
    
      {
    
        FunctionId id = flp->get_entry(i);
    
        if (!strcmp(in_str, id.get_module_name(mod_buf, sizeof(mod_buf))))
    
        {
    
          return true;
    
        }
    
      }
    
     
    
      // no match was found
    
      return false;
    
    }
    
     
    
     
    
    ///////////////////////////////////////////////////////////////////////
    
    //
    
    // check if string passed in is a function name in the function list
    
    //
    
    ///////////////////////////////////////////////////////////////////////
    
    bool function_match(char *in_str, FunctionList *flp)
    
    {
    
      char mang_buf[MAXPATHLEN];
    
     
    
      // If no regular expression specified, don't bother to look
    
      //  for a match
    
      if ( minus_f == false )
    
        return true;
    
     
    
      // look through the list for a matching function
    
      // return true if a match is found
    
      for (int i = 0; i < flp->get_count(); i++)
    
      {
    
        FunctionId id = flp->get_entry(i);
    
        if (!strcmp(in_str, id.get_mangled_name(mang_buf, sizeof(mang_buf))))
    
        {
    
          return true;
    
        }
    
      }
    
     
    
      // no match was found
    
      return false;
    
    }
    
    

For more information about the DPCL functions used in the previous example, refer to their UNIX man pages or their entries in the DPCL Class Reference.


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]