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:
#include <FunctionList.h> #include <FunctionId.h>
// 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); } }
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)) ); } }
// 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.