1
2 #include "inc.h"
3
4 #include <stdarg.h>
5
6 /*
7 * The size of the formatting buffer, which in particular limits the maximum
8 * size of the output from the variadic functions. All printer functions which
9 * are dealing with potentially large or even unbounded output, should be able
10 * to generate their output in smaller chunks. In the end, nothing that is
11 * being printed as a unit should even come close to reaching this limit.
12 */
13 #define FORMAT_BUFSZ 4096
14
15 /*
16 * The buffer which is used for all intermediate copying and/or formatting.
17 * Care must be taken that only one function uses this buffer at any time.
18 */
19 static char formatbuf[FORMAT_BUFSZ];
20
21 /*
22 * Reset the line formatting for the given process.
23 */
24 void
format_reset(struct trace_proc * proc)25 format_reset(struct trace_proc * proc)
26 {
27
28 proc->next_sep = NULL;
29 proc->depth = -1;
30 }
31
32 /*
33 * Set the next separator for the given process. The given separator may be
34 * NULL.
35 */
36 void
format_set_sep(struct trace_proc * proc,const char * sep)37 format_set_sep(struct trace_proc * proc, const char * sep)
38 {
39
40 proc->next_sep = sep;
41 }
42
43 /*
44 * Print and clear the next separator for the process, if any.
45 */
46 void
format_push_sep(struct trace_proc * proc)47 format_push_sep(struct trace_proc * proc)
48 {
49
50 if (proc->next_sep != NULL) {
51 put_text(proc, proc->next_sep);
52
53 proc->next_sep = NULL;
54 }
55 }
56
57 /*
58 * Print a field, e.g. a parameter or a field from a structure, separated from
59 * other fields at the same nesting depth as appropriate. If the given field
60 * name is not NULL, it may or may not be printed. The given text is what will
61 * be printed for this field so far, but the caller is allowed to continue
62 * printing text for the same field with e.g. put_text(). As such, the given
63 * text may even be an empty string.
64 */
65 void
put_field(struct trace_proc * proc,const char * name,const char * text)66 put_field(struct trace_proc * proc, const char * name, const char * text)
67 {
68
69 /*
70 * At depth -1 (the basic line level), names are not used. A name
71 * should not be supplied by the caller in that case, but, it happens.
72 */
73 if (proc->depth < 0)
74 name = NULL;
75
76 format_push_sep(proc);
77
78 if (name != NULL && (proc->depths[proc->depth].name || allnames)) {
79 put_text(proc, name);
80 put_text(proc, "=");
81 }
82
83 put_text(proc, text);
84
85 format_set_sep(proc, proc->depths[proc->depth].sep);
86 }
87
88 /*
89 * Increase the nesting depth with a new block of fields, enclosed within
90 * parentheses, brackets, etcetera. The given name, which may be NULL, is the
91 * name of the entire nested block. In the flags field, PF_NONAME indicates
92 * that the fields within the block should have their names printed or not,
93 * although this may be overridden by setting the allnames variable. The given
94 * string is the block opening string (e.g., an opening parenthesis). The
95 * given separator is used to separate the fields within the nested block, and
96 * should generally be ", " to maintain output consistency.
97 */
98 void
put_open(struct trace_proc * proc,const char * name,int flags,const char * string,const char * sep)99 put_open(struct trace_proc * proc, const char * name, int flags,
100 const char * string, const char * sep)
101 {
102
103 put_field(proc, name, string);
104
105 proc->depth++;
106
107 assert(proc->depth < MAX_DEPTH);
108
109 proc->depths[proc->depth].sep = sep;
110 proc->depths[proc->depth].name = !(flags & PF_NONAME);
111
112 format_set_sep(proc, NULL);
113 }
114
115 /*
116 * Decrease the nesting depth by ending a nested block of fields. The given
117 * string is the closing parenthesis, bracket, etcetera.
118 */
119 void
put_close(struct trace_proc * proc,const char * string)120 put_close(struct trace_proc * proc, const char * string)
121 {
122
123 assert(proc->depth >= 0);
124
125 put_text(proc, string);
126
127 proc->depth--;
128
129 if (proc->depth >= 0)
130 format_set_sep(proc, proc->depths[proc->depth].sep);
131 else
132 format_set_sep(proc, NULL);
133 }
134
135 /*
136 * Version of put_text with variadic arguments. The given process may be NULL.
137 */
138 void
put_fmt(struct trace_proc * proc,const char * fmt,...)139 put_fmt(struct trace_proc * proc, const char * fmt, ...)
140 {
141 va_list ap;
142
143 va_start(ap, fmt);
144 (void)vsnprintf(formatbuf, sizeof(formatbuf), fmt, ap);
145 va_end(ap);
146
147 put_text(proc, formatbuf);
148 }
149
150 /*
151 * Version of put_field with variadic arguments.
152 */
153 void
put_value(struct trace_proc * proc,const char * name,const char * fmt,...)154 put_value(struct trace_proc * proc, const char * name, const char * fmt, ...)
155 {
156 va_list ap;
157
158 va_start(ap, fmt);
159 (void)vsnprintf(formatbuf, sizeof(formatbuf), fmt, ap);
160 va_end(ap);
161
162 put_field(proc, name, formatbuf);
163 }
164
165 /*
166 * Start printing a structure. In general, the function copies the contents of
167 * the structure of size 'size' from the traced process at 'addr' into the
168 * local 'ptr' structure, opens a nested block with name 'name' (which may
169 * be NULL) using an opening bracket, and returns TRUE to indicate that the
170 * caller should print fields from the structure. However, if 'flags' contains
171 * PF_FAILED, the structure will be printed as a pointer, no copy will be made,
172 * and the call will return FALSE. Similarly, if the remote copy fails, a
173 * pointer will be printed and the call will return FALSE. If PF_LOCADDR is
174 * given, 'addr' is a local address, and an intraprocess copy will be made.
175 */
176 int
put_open_struct(struct trace_proc * proc,const char * name,int flags,vir_bytes addr,void * ptr,size_t size)177 put_open_struct(struct trace_proc * proc, const char * name, int flags,
178 vir_bytes addr, void * ptr, size_t size)
179 {
180
181 if ((flags & PF_FAILED) || valuesonly > 1 || addr == 0) {
182 if (flags & PF_LOCADDR)
183 put_field(proc, name, "&..");
184 else
185 put_ptr(proc, name, addr);
186
187 return FALSE;
188 }
189
190 if (!(flags & PF_LOCADDR)) {
191 if (mem_get_data(proc->pid, addr, ptr, size) < 0) {
192 put_ptr(proc, name, addr);
193
194 return FALSE;
195 }
196 } else
197 memcpy(ptr, (void *) addr, size);
198
199 put_open(proc, name, flags, "{", ", ");
200
201 return TRUE;
202 }
203
204 /*
205 * End printing a structure. This must be called only to match a successful
206 * call to put_open_struct. The given 'all' flag indicates whether all fields
207 * of the structure have been printed; if not, a ".." continuation text is
208 * printed to show the user that some structure fields have not been printed.
209 */
210 void
put_close_struct(struct trace_proc * proc,int all)211 put_close_struct(struct trace_proc * proc, int all)
212 {
213
214 if (!all)
215 put_field(proc, NULL, "..");
216
217 put_close(proc, "}");
218 }
219
220 /*
221 * Print a pointer. NULL is treated as a special case.
222 */
223 void
put_ptr(struct trace_proc * proc,const char * name,vir_bytes addr)224 put_ptr(struct trace_proc * proc, const char * name, vir_bytes addr)
225 {
226
227 if (addr == 0 && !valuesonly)
228 put_field(proc, name, "NULL");
229 else
230 put_value(proc, name, "&0x%lx", addr);
231 }
232
233 /*
234 * Print the contents of a buffer, at remote address 'addr' and of 'bytes'
235 * size, as a field using name 'name' (which may be NULL). If the PF_FAILED
236 * flag is given, the buffer address is printed instead, since it is assumed
237 * that the actual buffer contains garbage. If the PF_LOCADDR flag is given,
238 * the given address is a local address and no intraprocess copies are
239 * performed. If the PF_STRING flag is given, the buffer is expected to
240 * contain a null terminator within its size, and the string will be printed
241 * only up to there. Normally, the string is cut off beyond a number of bytes
242 * which depends on the verbosity level; if the PF_FULL flag is given, the full
243 * string will be printed no matter its size (used mainly for path names, which
244 * typically become useless once cut off).
245 */
246 void
put_buf(struct trace_proc * proc,const char * name,int flags,vir_bytes addr,ssize_t size)247 put_buf(struct trace_proc * proc, const char * name, int flags, vir_bytes addr,
248 ssize_t size)
249 {
250 const char *escaped;
251 size_t len, off, max, chunk;
252 unsigned int i;
253 int cutoff;
254 char *p;
255
256 if ((flags & PF_FAILED) || valuesonly || addr == 0 || size < 0) {
257 if (flags & PF_LOCADDR)
258 put_field(proc, name, "&..");
259 else
260 put_ptr(proc, name, addr);
261
262 return;
263 }
264
265 if (size == 0) {
266 put_field(proc, name, "\"\"");
267
268 return;
269 }
270
271 /*
272 * TODO: the maximum says nothing about the size of the printed text.
273 * Escaped-character printing can make the output much longer. Does it
274 * make more sense to apply a limit after the escape transformation?
275 */
276 if (verbose == 0) max = 32;
277 else if (verbose == 1) max = 256;
278 else max = SIZE_MAX;
279
280 /*
281 * If the output is cut off, we put two dots after the closing quote.
282 * For non-string buffers, the output is cut off if the size exceeds
283 * our limit or we run into a copying error somewhere in the middle.
284 * For strings, the output is cut off unless we find a null terminator.
285 */
286 cutoff = !!(flags & PF_STRING);
287 len = (size_t)size;
288 if (!(flags & PF_FULL) && len > max) {
289 len = max;
290 cutoff = TRUE;
291 }
292
293 for (off = 0; off < len; off += chunk) {
294 chunk = len - off;
295 if (chunk > sizeof(formatbuf) - 1)
296 chunk = sizeof(formatbuf) - 1;
297
298 if (!(flags & PF_LOCADDR)) {
299 if (mem_get_data(proc->pid, addr + off, formatbuf,
300 chunk) < 0) {
301 if (off == 0) {
302 put_ptr(proc, name, addr);
303
304 return;
305 }
306
307 cutoff = TRUE;
308 break;
309 }
310 } else
311 memcpy(formatbuf, (void *)addr, chunk);
312
313 if (off == 0)
314 put_field(proc, name, "\"");
315
316 /* In strings, look for the terminating null character. */
317 if ((flags & PF_STRING) &&
318 (p = memchr(formatbuf, '\0', chunk)) != NULL) {
319 chunk = (size_t)(p - formatbuf);
320 cutoff = FALSE;
321 }
322
323 /* Print the buffer contents using escaped characters. */
324 for (i = 0; i < chunk; i++) {
325 escaped = get_escape(formatbuf[i]);
326
327 put_text(proc, escaped);
328 }
329
330 /* Stop if we found the end of the string. */
331 if ((flags & PF_STRING) && !cutoff)
332 break;
333 }
334
335 if (cutoff)
336 put_text(proc, "\"..");
337 else
338 put_text(proc, "\"");
339 }
340
341 /*
342 * Print a flags field, using known flag names. The name of the whole field is
343 * given as 'name' and may be NULL. The caller must supply an array of known
344 * flags as 'fp' (with 'num' entries). Each entry in the array has a mask, a
345 * value, and a name. If the given flags 'value', bitwise-ANDed with the mask
346 * of an entry, yields the value of that entry, then the name is printed. This
347 * means that certain zero bits may also be printed as actual flags, and that
348 * by supplying an all-bits-set mask can print a flag name for a zero value,
349 * for example F_OK for access(). See the FLAG macros and their usage for
350 * examples. All matching flag names are printed with a "|" separator, and if
351 * after evaluating all 'num' entries in 'fp' there are still bits in 'value'
352 * for which nothing has been printed, the remaining bits will be printed with
353 * the 'fmt' format string for an integer (generally "%d" should be used).
354 */
355 void
put_flags(struct trace_proc * proc,const char * name,const struct flags * fp,unsigned int num,const char * fmt,unsigned int value)356 put_flags(struct trace_proc * proc, const char * name, const struct flags * fp,
357 unsigned int num, const char * fmt, unsigned int value)
358 {
359 unsigned int left;
360 int first;
361
362 if (valuesonly) {
363 put_value(proc, name, fmt, value);
364
365 return;
366 }
367
368 put_field(proc, name, "");
369
370 for (first = TRUE, left = value; num > 0; fp++, num--) {
371 if ((value & fp->mask) == fp->value) {
372 if (first)
373 first = FALSE;
374 else
375 put_text(proc, "|");
376 put_text(proc, fp->name);
377
378 left -= fp->value;
379 }
380 }
381
382 if (left != 0) {
383 if (first)
384 first = FALSE;
385 else
386 put_text(proc, "|");
387
388 put_fmt(proc, fmt, left);
389 }
390
391 /*
392 * If nothing has been printed so far, simply print a zero. Ignoring
393 * the given format in this case is intentional: a simple 0 looks
394 * better than 0x0 or 00 etc.
395 */
396 if (first)
397 put_text(proc, "0");
398 }
399
400 /*
401 * Print a tail field at the end of an array. The given 'count' value is the
402 * total number of elements in the array, or 0 to indicate that an error
403 * occurred. The given 'printed' value is the number of fields printed so far.
404 * If some fields have been printed already, the number of fields not printed
405 * will be shown as "..(+N)". If no fields have been printed already, the
406 * (total) number of fields not printed will be shown as "..(N)". An error
407 * will print "..(?)".
408 *
409 * The rules for printing an array are as follows. In principle, arrays should
410 * be enclosed in "[]". However, if a copy error occurs immediately, a pointer
411 * to the array should be printed instead. An empty array should be printed as
412 * "[]" (not "[..(0)]"). If a copy error occurs in the middle of the array,
413 * put_tail should be used with count == 0. Only if not all fields in the
414 * array are printed, put_tail should be used with count > 0. The value of
415 * 'printed' is typically the result of an arbitrary limit set based on the
416 * verbosity level.
417 */
418 void
put_tail(struct trace_proc * proc,unsigned int count,unsigned int printed)419 put_tail(struct trace_proc * proc, unsigned int count, unsigned int printed)
420 {
421
422 if (count == 0)
423 put_field(proc, NULL, "..(?)");
424 else
425 put_value(proc, NULL, "..(%s%u)",
426 (printed > 0) ? "+" : "", count - printed);
427 }
428