1LIBTRACEEVENT(3)             libtraceevent Manual             LIBTRACEEVENT(3)
2
3
4

NAME

6       tep_plugin_kvm_get_func, tep_plugin_kvm_put_func - Add function name
7       for instruction pointer of kvm plugin
8

SYNOPSIS

10       #include <event-parse.h>
11
12       const char *tep_plugin_kvm_get_func(struct tep_event *event,
13                                           struct tep_record *record,
14                                           unsigned long long *paddr);
15       void tep_plugin_kvm_put_func(const char *func);
16

DESCRIPTION

18       The functions tep_plugin_kvm_get_func() and tep_plugin_kvm_put_func()
19       are not to be called by an application, but instead are to be defined
20       by an application.
21
22       Certain events (like kvm_exit and kvm_entry) have the instruction
23       pointer of where in the guest the context changed from guest to host.
24       As the host only knows the instruction pointer and does not have
25       information about what function in the guest that instruction pointer
26       belongs to, it can only print the address.
27
28       But the application may have more information about the guest, and know
29       where the guest was when the exit occurred, and also even know the
30       function name of that address.
31
32       The KVM plugin for libtraceevent is called on these events, and then
33       calls tep_plugin_kvm_get_func() to see if that function can resolve the
34       instruction pointer address to a real function name. If the return is
35       non NULL, it will print the function in the output for that event.
36
37       These functions are currently defined as weak functions within the
38       plugin, as to not require them to be defined elsewhere. For an
39       application to override the weak function, it will need to define the
40       function in a file that gets compiled with -rdynamic. That will tell
41       the dynamic linker to examine that object file and use function names
42       to resolve weak functions in other shared objects (in this case the KVM
43       plugin shared object).
44
45       If the application defines tep_plugin_kvm_get_func(), it must use the
46       above prototype. The event will hold the KVM event that has the
47       instruction pointer field. The record will be the instance of that
48       event. The application’s function does not need to use these
49       parameters, but they may be useful for finding the function name for
50       the address. The paddr is a pointer to a 64 bit value (where only 32
51       bits may be used on 32 bit machines). This value is the instruction
52       pointer to look up. If the application knows the start address of the
53       function as well, it can set paddr to that address, and the KVM plugin
54       will also append a "+offset" to the function name where the offset is
55       the original value in paddr minus the value in paddr when it is called.
56       Finally, the application should return the function name as a nul
57       terminated string if one is found.
58
59       If the returned string of tep_plugin_kvm_get_func() was allocated, the
60       KVM plugin will call tep_plugin_kvm_put_func() when it is through with
61       it, passing the value returned by tep_plugin_kvm_get_func() as func.
62       This allows the application to free it if necessary.
63

RETURN VALUE

65       The tep_plugin_kvm_get_func() is not to be called by the application
66       but instead is to be defined by the application. It should return a nul
67       terminated string representing the function for the given instruction
68       pointer passed to it by reference in paddr. It can then optionally
69       update the paddr to a value that holds the start of the function. The
70       string returned may be freed by the tep_plugin_kvm_put_func() that the
71       application should define to clean up the string.
72
73       The below example needs to be compiled with the -rdynamic flag so that
74       the dynamic linker can resolve the tep_plugin_kvm_get_func() and
75       tep_plugin_kvm_put_func() functions.
76
77       When run against a trace.dat file produced by trace-cmd(1) recording
78       the kvm_exit and kvm_entry events on a guest, and then the guest’s
79       /proc/kallsyms file is passed as the second parameter, the output
80       produced will look something like:
81
82           CPU 0/KVM-20407 83156.177626 [000] kvm_exit     reason APIC_ACCESS rip 0xffffffffb0056ee2 exit native_apic_mem_write+0x2 info 10b0 0
83           CPU 0/KVM-20407 83156.177632 [000] kvm_entry     vcpu 0 rip 0xffffffffb0056ee8 enter native_apic_mem_write+0x8
84
85       But without those callbacks, it would look like:
86
87           CPU 0/KVM-20407 83156.177626 [000] kvm_exit     reason APIC_ACCESS rip 0xffffffffb0056ee2 info 10b0 0
88           CPU 0/KVM-20407 83156.177632 [000] kvm_entry     vcpu 0 rip 0xffffffffb0056ee8
89

EXAMPLE

91           #include <stdio.h>
92           #include <stdlib.h>
93           #include <event-parse.h>
94           #include <trace-cmd.h>
95           #include <sys/stat.h>
96
97           static struct tep_handle *tep;
98
99           const char *tep_plugin_kvm_get_func(struct tep_event *event, struct tep_record *record,
100                                               unsigned long long *paddr)
101           {
102                   const char *func;
103                   char *event_func;
104                   char *ename;
105
106                   func = tep_find_function(tep, *paddr);
107                   if (!func)
108                           return NULL;
109
110                   if (strcmp(event->name, "kvm_exit") == 0)
111                           ename = "exit";
112                   else
113                           ename = "enter";
114
115                   /*
116                    * Normally, passing back func directly is sufficient and then
117                    * tep_plugin_kvm_put_func() would not be required. But this example
118                    * is showing how to handle allocation of the returned string.
119                    */
120                   event_func = malloc(strlen(ename) + strlen(func) + 2);
121                   if (!event_func)
122                           return NULL;
123                   sprintf(event_func, "%s %s", ename, func);
124
125                   *paddr = tep_find_function_address(tep, *paddr);
126
127                   return event_func;
128           }
129
130           void tep_plugin_kvm_put_func(const char *func)
131           {
132                   char *f = (char *)func;
133
134                   free(f);
135           }
136
137           static int show_event(struct tracecmd_input *handle, struct tep_event *event,
138                                 struct tep_record *record, int cpu, void *data)
139           {
140                   static struct trace_seq seq;
141                   tep = data;
142
143                   if (!seq.buffer)
144                           trace_seq_init(&seq);
145
146                   trace_seq_reset(&seq);
147                   tep_print_event(tracecmd_get_tep(handle), &seq, record,
148                                   "%s-%d\t%6.1000d [%03d] %s\t%s\n",
149                                   TEP_PRINT_COMM, TEP_PRINT_PID,
150                                   TEP_PRINT_TIME, TEP_PRINT_CPU,
151                                   TEP_PRINT_NAME, TEP_PRINT_INFO);
152                   trace_seq_terminate(&seq);
153                   trace_seq_do_printf(&seq);
154                   return 0;
155           }
156
157           int main(int argc, char **argv)
158           {
159                   struct tracecmd_input *handle;
160                   struct tep_handle *guest_tep;
161                   struct stat st;
162                   FILE *fp;
163                   char *buf;
164
165                   if (argc < 3) {
166                           printf("usage: trace.dat guest_kallsyms_file\n");
167                           exit(-1);
168                   }
169
170                   handle = tracecmd_open(argv[1], 0);
171                   if (!handle) {
172                           perror(argv[1]);
173                           exit(-1);
174                   }
175
176                   /* Just for kallsyms parsing */
177                   guest_tep = tep_alloc();
178                   if (!guest_tep)
179                           exit(-1);
180
181                   if (stat(argv[2], &st) < 0) {
182                           perror(argv[2]);
183                           exit(-1);
184                   }
185
186                   buf = malloc(st.st_size + 1);
187                   if (!buf)
188                           exit(-1);
189
190                   fp = fopen(argv[2], "r");
191                   if (!fp) {
192                           perror(argv[2]);
193                           exit(-1);
194                   }
195
196                   if (fread(buf, st.st_size, 1, fp) < 0) {
197                           perror(argv[2]);
198                           exit(-1);
199                   }
200
201                   buf[st.st_size] = '\0';
202
203                   if (tep_parse_kallsyms(guest_tep, buf) < 0) {
204                           printf("Failed to parse %s\n", argv[2]);
205                           exit(-1);
206                   }
207                   free(buf);
208
209                   tracecmd_follow_event(handle, "kvm", "kvm_exit", show_event, guest_tep);
210                   tracecmd_follow_event(handle, "kvm", "kvm_entry", show_event, guest_tep);
211
212                   tracecmd_iterate_events(handle, NULL, 0, NULL, NULL);
213
214                   tep_free(guest_tep);
215                   tracecmd_close(handle);
216           }
217

FILES

219           event-parse.h
220                   Header file to include in order to have access to the library APIs.
221           -ltraceevent
222                   Linker switch to add when building a program that uses the library.
223

SEE ALSO

225       libtraceevent(3), trace-cmd(1)
226

REPORTING BUGS

228       Report bugs to <linux-trace-devel@vger.kernel.org[1]>
229

LICENSE

231       libtraceevent is Free Software licensed under the GNU LGPL 2.1
232

RESOURCES

234       https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/
235

NOTES

237        1. linux-trace-devel@vger.kernel.org
238           mailto:linux-trace-devel@vger.kernel.org
239
240
241
242libtraceevent 1.7.2               04/05/2023                  LIBTRACEEVENT(3)
Impressum