1libtraceevent(3) 2================ 3 4NAME 5---- 6tep_plugin_kvm_get_func, tep_plugin_kvm_put_func - Add function name for instruction pointer of kvm plugin 7 8SYNOPSIS 9-------- 10[verse] 11-- 12*#include <event-parse.h>* 13 14const char pass:[*]*tep_plugin_kvm_get_func*(struct tep_event pass:[*]event, 15 struct tep_record pass:[*]record, 16 unsigned long long pass:[*]paddr); 17void *tep_plugin_kvm_put_func*(const char pass:[*]func); 18-- 19 20DESCRIPTION 21----------- 22The functions *tep_plugin_kvm_get_func()* and *tep_plugin_kvm_put_func()* 23are not to be called by an application, but instead are to be defined by 24an application. 25 26Certain events (like kvm_exit and kvm_entry) have the instruction pointer 27of where in the guest the context changed from guest to host. As the host 28only knows the instruction pointer and does not have information about what 29function in the guest that instruction pointer belongs to, it can only print 30the address. 31 32But the application may have more information about the guest, and know where 33the guest was when the exit occurred, and also even know the function name 34of that address. 35 36The KVM plugin for libtraceevent is called on these events, and then calls 37*tep_plugin_kvm_get_func()* to see if that function can resolve the instruction 38pointer address to a real function name. If the return is non NULL, it will 39print the function in the output for that event. 40 41These functions are currently defined as weak functions within the plugin, as 42to not require them to be defined elsewhere. For an application to override 43the weak function, it will need to define the function in a file that gets 44compiled with *-rdynamic*. That will tell the dynamic linker to examine that 45object file and use function names to resolve weak functions in other shared 46objects (in this case the KVM plugin shared object). 47 48If the application defines *tep_plugin_kvm_get_func()*, it must use the above 49prototype. The _event_ will hold the KVM event that has the instruction pointer 50field. The _record_ will be the instance of that event. The application's function 51does not need to use these parameters, but they may be useful for finding the 52function name for the address. The _paddr_ is a pointer to a 64 bit value (where 53only 32 bits may be used on 32 bit machines). This value is the instruction 54pointer to look up. If the application knows the start address of the function 55as well, it can set _paddr_ to that address, and the KVM plugin will also 56append a "+offset" to the function name where the offset is the original 57value in _paddr_ minus the value in _paddr_ when it is called. Finally, 58the application should return the function name as a nul terminated string 59if one is found. 60 61If the returned string of *tep_plugin_kvm_get_func()* was allocated, the KVM plugin 62will call *tep_plugin_kvm_put_func()* when it is through with it, passing the 63value returned by *tep_plugin_kvm_get_func()* as _func_. This allows the application 64to free it if necessary. 65 66RETURN VALUE 67------------ 68The *tep_plugin_kvm_get_func()* is not to be called by the application but instead 69is to be defined by the application. It should return a nul terminated string representing 70the function for the given instruction pointer passed to it by reference in _paddr_. It 71can then optionally update the _paddr_ to a value that holds the start of the function. 72The string returned may be freed by the *tep_plugin_kvm_put_func()* that the application 73should define to clean up the string. 74 75The below example needs to be compiled with the *-rdynamic* flag so that the dynamic 76linker can resolve the *tep_plugin_kvm_get_func()* and *tep_plugin_kvm_put_func()* functions. 77 78When run against a trace.dat file produced by *trace-cmd(1)* recording the kvm_exit and 79kvm_entry events on a guest, and then the guest's /proc/kallsyms file is passed as the 80second parameter, the output produced will look something like: 81 82[source,c] 83-- 84CPU 0/KVM-20407 83156.177626 [000] kvm_exit reason APIC_ACCESS rip 0xffffffffb0056ee2 exit native_apic_mem_write+0x2 info 10b0 0 85CPU 0/KVM-20407 83156.177632 [000] kvm_entry vcpu 0 rip 0xffffffffb0056ee8 enter native_apic_mem_write+0x8 86-- 87 88But without those callbacks, it would look like: 89 90[source,c] 91-- 92CPU 0/KVM-20407 83156.177626 [000] kvm_exit reason APIC_ACCESS rip 0xffffffffb0056ee2 info 10b0 0 93CPU 0/KVM-20407 83156.177632 [000] kvm_entry vcpu 0 rip 0xffffffffb0056ee8 94-- 95 96EXAMPLE 97------- 98[source,c] 99-- 100#include <stdio.h> 101#include <stdlib.h> 102#include <event-parse.h> 103#include <trace-cmd.h> 104#include <sys/stat.h> 105 106static struct tep_handle *tep; 107 108const char *tep_plugin_kvm_get_func(struct tep_event *event, struct tep_record *record, 109 unsigned long long *paddr) 110{ 111 const char *func; 112 char *event_func; 113 char *ename; 114 115 func = tep_find_function(tep, *paddr); 116 if (!func) 117 return NULL; 118 119 if (strcmp(event->name, "kvm_exit") == 0) 120 ename = "exit"; 121 else 122 ename = "enter"; 123 124 /* 125 * Normally, passing back func directly is sufficient and then 126 * tep_plugin_kvm_put_func() would not be required. But this example 127 * is showing how to handle allocation of the returned string. 128 */ 129 event_func = malloc(strlen(ename) + strlen(func) + 2); 130 if (!event_func) 131 return NULL; 132 sprintf(event_func, "%s %s", ename, func); 133 134 *paddr = tep_find_function_address(tep, *paddr); 135 136 return event_func; 137} 138 139void tep_plugin_kvm_put_func(const char *func) 140{ 141 char *f = (char *)func; 142 143 free(f); 144} 145 146static int show_event(struct tracecmd_input *handle, struct tep_event *event, 147 struct tep_record *record, int cpu, void *data) 148{ 149 static struct trace_seq seq; 150 tep = data; 151 152 if (!seq.buffer) 153 trace_seq_init(&seq); 154 155 trace_seq_reset(&seq); 156 tep_print_event(tracecmd_get_tep(handle), &seq, record, 157 "%s-%d\t%6.1000d [%03d] %s\t%s\n", 158 TEP_PRINT_COMM, TEP_PRINT_PID, 159 TEP_PRINT_TIME, TEP_PRINT_CPU, 160 TEP_PRINT_NAME, TEP_PRINT_INFO); 161 trace_seq_terminate(&seq); 162 trace_seq_do_printf(&seq); 163 return 0; 164} 165 166int main(int argc, char **argv) 167{ 168 struct tracecmd_input *handle; 169 struct tep_handle *guest_tep; 170 struct stat st; 171 FILE *fp; 172 char *buf; 173 174 if (argc < 3) { 175 printf("usage: trace.dat guest_kallsyms_file\n"); 176 exit(-1); 177 } 178 179 handle = tracecmd_open(argv[1], 0); 180 if (!handle) { 181 perror(argv[1]); 182 exit(-1); 183 } 184 185 /* Just for kallsyms parsing */ 186 guest_tep = tep_alloc(); 187 if (!guest_tep) 188 exit(-1); 189 190 if (stat(argv[2], &st) < 0) { 191 perror(argv[2]); 192 exit(-1); 193 } 194 195 buf = malloc(st.st_size + 1); 196 if (!buf) 197 exit(-1); 198 199 fp = fopen(argv[2], "r"); 200 if (!fp) { 201 perror(argv[2]); 202 exit(-1); 203 } 204 205 if (fread(buf, st.st_size, 1, fp) < 0) { 206 perror(argv[2]); 207 exit(-1); 208 } 209 210 buf[st.st_size] = '\0'; 211 212 if (tep_parse_kallsyms(guest_tep, buf) < 0) { 213 printf("Failed to parse %s\n", argv[2]); 214 exit(-1); 215 } 216 free(buf); 217 218 tracecmd_follow_event(handle, "kvm", "kvm_exit", show_event, guest_tep); 219 tracecmd_follow_event(handle, "kvm", "kvm_entry", show_event, guest_tep); 220 221 tracecmd_iterate_events(handle, NULL, 0, NULL, NULL); 222 223 tep_free(guest_tep); 224 tracecmd_close(handle); 225} 226-- 227 228FILES 229----- 230[verse] 231-- 232*event-parse.h* 233 Header file to include in order to have access to the library APIs. 234*-ltraceevent* 235 Linker switch to add when building a program that uses the library. 236-- 237 238SEE ALSO 239-------- 240*libtraceevent*(3), *trace-cmd*(1) 241 242REPORTING BUGS 243-------------- 244Report bugs to <[email protected]> 245 246LICENSE 247------- 248libtraceevent is Free Software licensed under the GNU LGPL 2.1 249 250RESOURCES 251--------- 252https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ 253