9 static int display_char(int what);
10 static int display_string(enum tof type, Process *proc,
11 void* addr, size_t maxlen);
12 static int display_value(enum tof type, Process *proc,
13 long value, arg_type_info *info,
14 void *st, arg_type_info* st_info);
15 static int display_unknown(enum tof type, Process *proc, long value);
16 static int display_format(enum tof type, Process *proc, int arg_num);
18 static int string_maxlength = INT_MAX;
19 static int array_maxlength = INT_MAX;
22 get_length(enum tof type, Process *proc, int len_spec,
23 void *st, arg_type_info* st_info) {
29 if (type == LT_TOF_STRUCT) {
30 umovelong (proc, st + st_info->u.struct_info.offset[-len_spec-1],
31 &len, st_info->u.struct_info.fields[-len_spec-1]);
35 info.type = ARGTYPE_INT;
36 return gimme_arg(type, proc, -len_spec-1, &info);
40 display_ptrto(enum tof type, Process *proc, long item,
42 void *st, arg_type_info* st_info) {
44 temp.type = ARGTYPE_POINTER;
45 temp.u.ptr_info.info = info;
46 return display_value(type, proc, item, &temp, st, st_info);
50 * addr - A pointer to the first element of the array
52 * The function name is used to indicate that we're not actually
53 * looking at an 'array', which is a contiguous region of memory
54 * containing a sequence of elements of some type; instead, we have a
55 * pointer to that region of memory.
58 display_arrayptr(enum tof type, Process *proc,
59 void *addr, arg_type_info * info,
60 void *st, arg_type_info* st_info) {
66 return fprintf(options.output, "NULL");
68 array_len = get_length(type, proc, info->u.array_info.len_spec,
70 len += fprintf(options.output, "[ ");
71 for (i = 0; i < options.arraylen && i < array_maxlength && i < array_len; i++) {
72 arg_type_info *elt_type = info->u.array_info.elt_type;
73 size_t elt_size = info->u.array_info.elt_size;
75 len += fprintf(options.output, ", ");
77 len += fprintf(options.output, "%p=", addr);
79 display_ptrto(type, proc, (long) addr, elt_type, st, st_info);
83 len += fprintf(options.output, "...");
84 len += fprintf(options.output, " ]");
88 /* addr - A pointer to the beginning of the memory region occupied by
89 * the struct (aka a pointer to the struct)
92 display_structptr(enum tof type, Process *proc,
93 void *addr, arg_type_info * info) {
99 return fprintf(options.output, "NULL");
101 len += fprintf(options.output, "{ ");
102 for (i = 0; (field = info->u.struct_info.fields[i]) != NULL; i++) {
104 len += fprintf(options.output, ", ");
107 fprintf(options.output, "%p=",
108 addr + info->u.struct_info.offset[i]);
110 display_ptrto(LT_TOF_STRUCT, proc,
111 (long) addr + info->u.struct_info.offset[i],
114 len += fprintf(options.output, " }");
120 display_pointer(enum tof type, Process *proc, long value,
121 arg_type_info * info,
122 void *st, arg_type_info* st_info) {
124 arg_type_info *inner = info->u.ptr_info.info;
126 if (inner->type == ARGTYPE_ARRAY) {
127 return display_arrayptr(type, proc, (void*) value, inner,
129 } else if (inner->type == ARGTYPE_STRUCT) {
130 return display_structptr(type, proc, (void *) value, inner);
133 return fprintf(options.output, "NULL");
134 else if (umovelong (proc, (void *) value, &pointed_to,
135 info->u.ptr_info.info) < 0)
136 return fprintf(options.output, "?");
138 return display_value(type, proc, pointed_to, inner,
144 display_enum(enum tof type, Process *proc,
145 arg_type_info* info, long value) {
147 for (ii = 0; ii < info->u.enum_info.entries; ++ii) {
148 if (info->u.enum_info.values[ii] == value)
149 return fprintf(options.output, "%s", info->u.enum_info.keys[ii]);
152 return display_unknown(type, proc, value);
156 type - syscall or shared library function or memory
157 proc - information about the traced process
158 value - the value to display
159 info - the description of the type to display
160 st - if the current value is a struct member, the address of the struct
161 st_info - type of the above struct
163 Those last two parameters are used for structs containing arrays or
164 strings whose length is given by another structure element.
167 display_value(enum tof type, Process *proc,
168 long value, arg_type_info *info,
169 void *st, arg_type_info* st_info) {
172 switch (info->type) {
176 return fprintf(options.output, "%d", (int) value);
178 return fprintf(options.output, "%u", (unsigned) value);
180 if (proc->mask_32bit)
181 return fprintf(options.output, "%d", (int) value);
183 return fprintf(options.output, "%ld", value);
185 if (proc->mask_32bit)
186 return fprintf(options.output, "%u", (unsigned) value);
188 return fprintf(options.output, "%lu", (unsigned long) value);
190 return fprintf(options.output, "0%o", (unsigned) value);
192 tmp = fprintf(options.output, "'");
193 tmp += display_char(value == -1 ? value : (char) value);
194 tmp += fprintf(options.output, "'");
197 return fprintf(options.output, "%hd", (short) value);
199 return fprintf(options.output, "%hu", (unsigned short) value);
200 case ARGTYPE_FLOAT: {
201 union { long l; float f; double d; } cvt;
203 return fprintf(options.output, "%f", cvt.f);
205 case ARGTYPE_DOUBLE: {
206 union { long l; float f; double d; } cvt;
208 return fprintf(options.output, "%lf", cvt.d);
212 return fprintf(options.output, "NULL");
214 return fprintf(options.output, "0x%08lx", value);
216 fprintf(stderr, "Should never encounter a format anywhere but at the top level (for now?)\n");
219 return display_string(type, proc, (void*) value,
221 case ARGTYPE_STRING_N:
222 return display_string(type, proc, (void*) value,
223 get_length(type, proc,
224 info->u.string_n_info.size_spec, st, st_info));
226 return fprintf(options.output, "<array without address>");
228 return display_enum(type, proc, info, value);
230 return fprintf(options.output, "<struct without address>");
231 case ARGTYPE_POINTER:
232 return display_pointer(type, proc, value, info,
234 case ARGTYPE_UNKNOWN:
236 return display_unknown(type, proc, value);
241 display_arg(enum tof type, Process *proc, int arg_num, arg_type_info * info) {
244 if (info->type == ARGTYPE_VOID) {
246 } else if (info->type == ARGTYPE_FORMAT) {
247 return display_format(type, proc, arg_num);
249 arg = gimme_arg(type, proc, arg_num, info);
250 return display_value(type, proc, arg, info, NULL, NULL);
255 display_char(int what) {
258 return fprintf(options.output, "EOF");
260 return fprintf(options.output, "\\r");
262 return fprintf(options.output, "\\n");
264 return fprintf(options.output, "\\t");
266 return fprintf(options.output, "\\b");
268 return fprintf(options.output, "\\\\");
271 return fprintf(options.output, "%c", what);
273 return fprintf(options.output, "\\%03o", (unsigned char)what);
278 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
281 display_string(enum tof type, Process *proc, void *addr,
288 return fprintf(options.output, "NULL");
291 str1 = malloc(MIN(options.strlen, maxlength) + 3);
293 return fprintf(options.output, "???");
295 umovestr(proc, addr, MIN(options.strlen, maxlength) + 1, str1);
296 len = fprintf(options.output, "\"");
297 for (i = 0; i < MIN(options.strlen, maxlength); i++) {
299 len += display_char(str1[i]);
304 len += fprintf(options.output, "\"");
305 if (str1[i] && (options.strlen <= maxlength)) {
306 len += fprintf(options.output, "...");
313 display_unknown(enum tof type, Process *proc, long value) {
314 if (proc->mask_32bit) {
315 if ((int)value < 1000000 && (int)value > -1000000)
316 return fprintf(options.output, "%d", (int)value);
318 return fprintf(options.output, "%p", (void *)value);
319 } else if (value < 1000000 && value > -1000000) {
320 return fprintf(options.output, "%ld", value);
322 return fprintf(options.output, "%p", (void *)value);
327 display_format(enum tof type, Process *proc, int arg_num) {
334 info.type = ARGTYPE_POINTER;
335 addr = (void *)gimme_arg(type, proc, arg_num, &info);
337 return fprintf(options.output, "NULL");
340 str1 = malloc(MIN(options.strlen, string_maxlength) + 3);
342 return fprintf(options.output, "???");
344 umovestr(proc, addr, MIN(options.strlen, string_maxlength) + 1, str1);
345 len = fprintf(options.output, "\"");
346 for (i = 0; len < MIN(options.strlen, string_maxlength) + 1; i++) {
348 len += display_char(str1[i]);
353 len += fprintf(options.output, "\"");
354 if (str1[i] && (options.strlen <= string_maxlength)) {
355 len += fprintf(options.output, "...");
357 for (i = 0; str1[i]; i++) {
358 if (str1[i] == '%') {
361 unsigned char c = str1[++i];
366 } else if (strchr("lzZtj", c)) {
371 && (sizeof(long) < sizeof(long long)
372 || proc->mask_32bit)) {
373 len += fprintf(options.output, ", ...");
377 } else if (c == 'd' || c == 'i') {
378 info.type = ARGTYPE_LONG;
379 if (!is_long || proc->mask_32bit)
381 fprintf(options.output, ", %d",
382 (int)gimme_arg(type, proc, ++arg_num, &info));
385 fprintf(options.output, ", %ld",
386 gimme_arg(type, proc, ++arg_num, &info));
388 } else if (c == 'u') {
389 info.type = ARGTYPE_LONG;
390 if (!is_long || proc->mask_32bit)
392 fprintf(options.output, ", %u",
393 (int)gimme_arg(type, proc, ++arg_num, &info));
396 fprintf(options.output, ", %lu",
397 gimme_arg(type, proc, ++arg_num, &info));
399 } else if (c == 'o') {
400 info.type = ARGTYPE_LONG;
401 if (!is_long || proc->mask_32bit)
403 fprintf(options.output, ", 0%o",
404 (int)gimme_arg(type, proc, ++arg_num, &info));
407 fprintf(options.output, ", 0%lo",
408 gimme_arg(type, proc, ++arg_num, &info));
410 } else if (c == 'x' || c == 'X') {
411 info.type = ARGTYPE_LONG;
412 if (!is_long || proc->mask_32bit)
414 fprintf(options.output, ", %#x",
415 (int)gimme_arg(type, proc, ++arg_num, &info));
418 fprintf(options.output, ", %#lx",
419 gimme_arg(type, proc, ++arg_num, &info));
421 } else if (strchr("eEfFgGaACS", c)
423 && (c == 'c' || c == 's'))) {
424 len += fprintf(options.output, ", ...");
427 } else if (c == 'c') {
428 info.type = ARGTYPE_LONG;
429 len += fprintf(options.output, ", '");
432 gimme_arg(type, proc, ++arg_num, &info));
433 len += fprintf(options.output, "'");
435 } else if (c == 's') {
436 info.type = ARGTYPE_POINTER;
437 len += fprintf(options.output, ", ");
439 display_string(type, proc,
440 (void *)gimme_arg(type, proc, ++arg_num, &info),
443 } else if (c == 'p' || c == 'n') {
444 info.type = ARGTYPE_POINTER;
446 fprintf(options.output, ", %p",
447 (void *)gimme_arg(type, proc, ++arg_num, &info));
449 } else if (c == '*') {
450 info.type = ARGTYPE_LONG;
452 fprintf(options.output, ", %d",
453 (int)gimme_arg(type, proc, ++arg_num, &info));