1LIBTRACEEVENT(3) libtraceevent Manual LIBTRACEEVENT(3)
2
3
4
6 tep_plugin_kvm_get_func, tep_plugin_kvm_put_func - Add function name
7 for instruction pointer of kvm plugin
8
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
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
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
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
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
225 libtraceevent(3), trace-cmd(1)
226
228 Report bugs to <linux-trace-devel@vger.kernel.org[1]>
229
231 libtraceevent is Free Software licensed under the GNU LGPL 2.1
232
234 https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/
235
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)