blob: 5df34cae3d94fc2f247960cee5545f9334895df9 [file] [log] [blame]
Steve Fink7bafff02006-08-07 04:50:42 +02001#include <ctype.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +01002#include <stdio.h>
3#include <stdlib.h>
Juan Cespedesd914a202004-11-10 00:15:33 +01004#include <string.h>
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +01005#include <limits.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +01006
Juan Cespedesf7281232009-06-25 16:11:21 +02007#include "common.h"
Petr Machata366c2f42012-02-09 19:34:36 +01008#include "proc.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +01009
Juan Cespedesac3db291998-04-25 14:31:58 +020010static int display_char(int what);
Juan Cespedesa8909f72009-04-28 20:02:41 +020011static int display_string(enum tof type, Process *proc,
Steve Fink7bafff02006-08-07 04:50:42 +020012 void* addr, size_t maxlen);
Juan Cespedesa8909f72009-04-28 20:02:41 +020013static int display_value(enum tof type, Process *proc,
Steve Finke4b32632006-08-07 06:10:08 +020014 long value, arg_type_info *info,
15 void *st, arg_type_info* st_info);
Juan Cespedesa8909f72009-04-28 20:02:41 +020016static int display_unknown(enum tof type, Process *proc, long value);
17static int display_format(enum tof type, Process *proc, int arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010018
Zachary T Welchba6aca22010-12-08 18:55:09 -080019static size_t string_maxlength = INT_MAX;
20static size_t array_maxlength = INT_MAX;
Steve Fink6a48a6d2006-08-07 04:29:06 +020021
Juan Cespedesf1350522008-12-16 18:19:58 +010022static long
Juan Cespedesa8909f72009-04-28 20:02:41 +020023get_length(enum tof type, Process *proc, int len_spec,
Juan Cespedesf1350522008-12-16 18:19:58 +010024 void *st, arg_type_info* st_info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020025 long len;
26 arg_type_info info;
Steve Fink65b53df2006-09-25 02:27:08 +020027
Juan Cespedesa413e5b2007-09-04 17:34:53 +020028 if (len_spec > 0)
29 return len_spec;
30 if (type == LT_TOF_STRUCT) {
Luis Machado55c5feb2008-03-12 15:56:01 +010031 umovelong (proc, st + st_info->u.struct_info.offset[-len_spec-1],
32 &len, st_info->u.struct_info.fields[-len_spec-1]);
Juan Cespedesa413e5b2007-09-04 17:34:53 +020033 return len;
34 }
Steve Fink65b53df2006-09-25 02:27:08 +020035
Juan Cespedesa413e5b2007-09-04 17:34:53 +020036 info.type = ARGTYPE_INT;
37 return gimme_arg(type, proc, -len_spec-1, &info);
Steve Fink6a48a6d2006-08-07 04:29:06 +020038}
39
Juan Cespedesf1350522008-12-16 18:19:58 +010040static int
Juan Cespedesa8909f72009-04-28 20:02:41 +020041display_ptrto(enum tof type, Process *proc, long item,
Steve Finke4b32632006-08-07 06:10:08 +020042 arg_type_info * info,
Juan Cespedesf1350522008-12-16 18:19:58 +010043 void *st, arg_type_info* st_info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020044 arg_type_info temp;
45 temp.type = ARGTYPE_POINTER;
46 temp.u.ptr_info.info = info;
47 return display_value(type, proc, item, &temp, st, st_info);
Steve Fink1150bc42006-08-07 06:04:43 +020048}
49
50/*
51 * addr - A pointer to the first element of the array
52 *
53 * The function name is used to indicate that we're not actually
54 * looking at an 'array', which is a contiguous region of memory
55 * containing a sequence of elements of some type; instead, we have a
56 * pointer to that region of memory.
57 */
Juan Cespedesf1350522008-12-16 18:19:58 +010058static int
Juan Cespedesa8909f72009-04-28 20:02:41 +020059display_arrayptr(enum tof type, Process *proc,
Steve Finke4b32632006-08-07 06:10:08 +020060 void *addr, arg_type_info * info,
Juan Cespedesf1350522008-12-16 18:19:58 +010061 void *st, arg_type_info* st_info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020062 int len = 0;
Zachary T Welchba6aca22010-12-08 18:55:09 -080063 size_t i;
64 size_t array_len;
Steve Fink1150bc42006-08-07 06:04:43 +020065
Juan Cespedesa413e5b2007-09-04 17:34:53 +020066 if (addr == NULL)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010067 return fprintf(options.output, "NULL");
Steve Fink1150bc42006-08-07 06:04:43 +020068
Juan Cespedesa413e5b2007-09-04 17:34:53 +020069 array_len = get_length(type, proc, info->u.array_info.len_spec,
70 st, st_info);
Juan Cespedesb65bdc52008-12-16 19:50:16 +010071 len += fprintf(options.output, "[ ");
Juan Cespedesda9b9532009-04-07 15:33:50 +020072 for (i = 0; i < options.arraylen && i < array_maxlength && i < array_len; i++) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020073 arg_type_info *elt_type = info->u.array_info.elt_type;
74 size_t elt_size = info->u.array_info.elt_size;
75 if (i != 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010076 len += fprintf(options.output, ", ");
Juan Cespedesda9b9532009-04-07 15:33:50 +020077 if (options.debug)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010078 len += fprintf(options.output, "%p=", addr);
Juan Cespedesa413e5b2007-09-04 17:34:53 +020079 len +=
80 display_ptrto(type, proc, (long) addr, elt_type, st, st_info);
81 addr += elt_size;
82 }
83 if (i < array_len)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010084 len += fprintf(options.output, "...");
85 len += fprintf(options.output, " ]");
Juan Cespedesa413e5b2007-09-04 17:34:53 +020086 return len;
Steve Fink1150bc42006-08-07 06:04:43 +020087}
Juan Cespedesa413e5b2007-09-04 17:34:53 +020088
Steve Finke4b32632006-08-07 06:10:08 +020089/* addr - A pointer to the beginning of the memory region occupied by
90 * the struct (aka a pointer to the struct)
91 */
Juan Cespedesf1350522008-12-16 18:19:58 +010092static int
Juan Cespedesa8909f72009-04-28 20:02:41 +020093display_structptr(enum tof type, Process *proc,
Juan Cespedesf1350522008-12-16 18:19:58 +010094 void *addr, arg_type_info * info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020095 int i;
96 arg_type_info *field;
97 int len = 0;
Steve Finke4b32632006-08-07 06:10:08 +020098
Juan Cespedesa413e5b2007-09-04 17:34:53 +020099 if (addr == NULL)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100100 return fprintf(options.output, "NULL");
Steve Finke4b32632006-08-07 06:10:08 +0200101
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100102 len += fprintf(options.output, "{ ");
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200103 for (i = 0; (field = info->u.struct_info.fields[i]) != NULL; i++) {
104 if (i != 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100105 len += fprintf(options.output, ", ");
Juan Cespedesda9b9532009-04-07 15:33:50 +0200106 if (options.debug)
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200107 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100108 fprintf(options.output, "%p=",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200109 addr + info->u.struct_info.offset[i]);
110 len +=
111 display_ptrto(LT_TOF_STRUCT, proc,
112 (long) addr + info->u.struct_info.offset[i],
113 field, addr, info);
114 }
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100115 len += fprintf(options.output, " }");
Steve Finke4b32632006-08-07 06:10:08 +0200116
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200117 return len;
Steve Finke4b32632006-08-07 06:10:08 +0200118}
119
Juan Cespedesf1350522008-12-16 18:19:58 +0100120static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200121display_pointer(enum tof type, Process *proc, long value,
Steve Finke4b32632006-08-07 06:10:08 +0200122 arg_type_info * info,
Juan Cespedesf1350522008-12-16 18:19:58 +0100123 void *st, arg_type_info* st_info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200124 long pointed_to;
125 arg_type_info *inner = info->u.ptr_info.info;
Steve Fink7bafff02006-08-07 04:50:42 +0200126
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200127 if (inner->type == ARGTYPE_ARRAY) {
128 return display_arrayptr(type, proc, (void*) value, inner,
Steve Finke4b32632006-08-07 06:10:08 +0200129 st, st_info);
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200130 } else if (inner->type == ARGTYPE_STRUCT) {
131 return display_structptr(type, proc, (void *) value, inner);
132 } else {
133 if (value == 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100134 return fprintf(options.output, "NULL");
Luis Machado55c5feb2008-03-12 15:56:01 +0100135 else if (umovelong (proc, (void *) value, &pointed_to,
136 info->u.ptr_info.info) < 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100137 return fprintf(options.output, "?");
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200138 else
139 return display_value(type, proc, pointed_to, inner,
140 st, st_info);
141 }
Steve Fink7bafff02006-08-07 04:50:42 +0200142}
143
Juan Cespedesf1350522008-12-16 18:19:58 +0100144static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200145display_enum(enum tof type, Process *proc,
Juan Cespedesf1350522008-12-16 18:19:58 +0100146 arg_type_info* info, long value) {
Zachary T Welchba6aca22010-12-08 18:55:09 -0800147 size_t ii;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200148 for (ii = 0; ii < info->u.enum_info.entries; ++ii) {
149 if (info->u.enum_info.values[ii] == value)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100150 return fprintf(options.output, "%s", info->u.enum_info.keys[ii]);
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200151 }
Steve Fink6a3e24d2006-08-07 05:53:19 +0200152
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200153 return display_unknown(type, proc, value);
Steve Fink6a3e24d2006-08-07 05:53:19 +0200154}
155
Steve Fink7bafff02006-08-07 04:50:42 +0200156/* Args:
157 type - syscall or shared library function or memory
158 proc - information about the traced process
159 value - the value to display
160 info - the description of the type to display
Steve Finke4b32632006-08-07 06:10:08 +0200161 st - if the current value is a struct member, the address of the struct
162 st_info - type of the above struct
163
164 Those last two parameters are used for structs containing arrays or
165 strings whose length is given by another structure element.
Steve Fink7bafff02006-08-07 04:50:42 +0200166*/
Juan Cespedesf1350522008-12-16 18:19:58 +0100167int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200168display_value(enum tof type, Process *proc,
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200169 long value, arg_type_info *info,
Juan Cespedesf1350522008-12-16 18:19:58 +0100170 void *st, arg_type_info* st_info) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100171 int tmp;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100172
Steve Fink6a48a6d2006-08-07 04:29:06 +0200173 switch (info->type) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100174 case ARGTYPE_VOID:
175 return 0;
176 case ARGTYPE_INT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100177 return fprintf(options.output, "%d", (int) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100178 case ARGTYPE_UINT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100179 return fprintf(options.output, "%u", (unsigned) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100180 case ARGTYPE_LONG:
181 if (proc->mask_32bit)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100182 return fprintf(options.output, "%d", (int) value);
Steve Fink7bafff02006-08-07 04:50:42 +0200183 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100184 return fprintf(options.output, "%ld", value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100185 case ARGTYPE_ULONG:
186 if (proc->mask_32bit)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100187 return fprintf(options.output, "%u", (unsigned) value);
Steve Fink7bafff02006-08-07 04:50:42 +0200188 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100189 return fprintf(options.output, "%lu", (unsigned long) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100190 case ARGTYPE_OCTAL:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100191 return fprintf(options.output, "0%o", (unsigned) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100192 case ARGTYPE_CHAR:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100193 tmp = fprintf(options.output, "'");
Steve Fink7bafff02006-08-07 04:50:42 +0200194 tmp += display_char(value == -1 ? value : (char) value);
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100195 tmp += fprintf(options.output, "'");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100196 return tmp;
Steve Fink6fa27c32006-08-07 05:56:56 +0200197 case ARGTYPE_SHORT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100198 return fprintf(options.output, "%hd", (short) value);
Steve Fink6fa27c32006-08-07 05:56:56 +0200199 case ARGTYPE_USHORT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100200 return fprintf(options.output, "%hu", (unsigned short) value);
Steve Fink6fa27c32006-08-07 05:56:56 +0200201 case ARGTYPE_FLOAT: {
Steve Fink65b53df2006-09-25 02:27:08 +0200202 union { long l; float f; double d; } cvt;
Steve Fink6fa27c32006-08-07 05:56:56 +0200203 cvt.l = value;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100204 return fprintf(options.output, "%f", cvt.f);
Steve Fink6fa27c32006-08-07 05:56:56 +0200205 }
Steve Fink65b53df2006-09-25 02:27:08 +0200206 case ARGTYPE_DOUBLE: {
207 union { long l; float f; double d; } cvt;
208 cvt.l = value;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100209 return fprintf(options.output, "%lf", cvt.d);
Steve Fink65b53df2006-09-25 02:27:08 +0200210 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100211 case ARGTYPE_ADDR:
Steve Fink7bafff02006-08-07 04:50:42 +0200212 if (!value)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100213 return fprintf(options.output, "NULL");
Steve Fink7bafff02006-08-07 04:50:42 +0200214 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100215 return fprintf(options.output, "0x%08lx", value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100216 case ARGTYPE_FORMAT:
Steve Fink7bafff02006-08-07 04:50:42 +0200217 fprintf(stderr, "Should never encounter a format anywhere but at the top level (for now?)\n");
218 exit(1);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100219 case ARGTYPE_STRING:
Steve Fink7bafff02006-08-07 04:50:42 +0200220 return display_string(type, proc, (void*) value,
Steve Fink6a48a6d2006-08-07 04:29:06 +0200221 string_maxlength);
222 case ARGTYPE_STRING_N:
Steve Fink7bafff02006-08-07 04:50:42 +0200223 return display_string(type, proc, (void*) value,
Steve Fink6a48a6d2006-08-07 04:29:06 +0200224 get_length(type, proc,
Steve Finke4b32632006-08-07 06:10:08 +0200225 info->u.string_n_info.size_spec, st, st_info));
Steve Fink1150bc42006-08-07 06:04:43 +0200226 case ARGTYPE_ARRAY:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100227 return fprintf(options.output, "<array without address>");
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200228 case ARGTYPE_ENUM:
Steve Fink6a3e24d2006-08-07 05:53:19 +0200229 return display_enum(type, proc, info, value);
Steve Finke4b32632006-08-07 06:10:08 +0200230 case ARGTYPE_STRUCT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100231 return fprintf(options.output, "<struct without address>");
Steve Fink7bafff02006-08-07 04:50:42 +0200232 case ARGTYPE_POINTER:
Steve Finke4b32632006-08-07 06:10:08 +0200233 return display_pointer(type, proc, value, info,
234 st, st_info);
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200235 case ARGTYPE_UNKNOWN:
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100236 default:
Steve Fink7bafff02006-08-07 04:50:42 +0200237 return display_unknown(type, proc, value);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100238 }
Steve Fink7bafff02006-08-07 04:50:42 +0200239}
240
Juan Cespedesf1350522008-12-16 18:19:58 +0100241int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200242display_arg(enum tof type, Process *proc, int arg_num, arg_type_info * info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200243 long arg;
Steve Fink7bafff02006-08-07 04:50:42 +0200244
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200245 if (info->type == ARGTYPE_VOID) {
246 return 0;
247 } else if (info->type == ARGTYPE_FORMAT) {
248 return display_format(type, proc, arg_num);
249 } else {
250 arg = gimme_arg(type, proc, arg_num, info);
251 return display_value(type, proc, arg, info, NULL, NULL);
252 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100253}
254
Juan Cespedesf1350522008-12-16 18:19:58 +0100255static int
256display_char(int what) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100257 switch (what) {
258 case -1:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100259 return fprintf(options.output, "EOF");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100260 case '\r':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100261 return fprintf(options.output, "\\r");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100262 case '\n':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100263 return fprintf(options.output, "\\n");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100264 case '\t':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100265 return fprintf(options.output, "\\t");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100266 case '\b':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100267 return fprintf(options.output, "\\b");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100268 case '\\':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100269 return fprintf(options.output, "\\\\");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100270 default:
Steve Fink7bafff02006-08-07 04:50:42 +0200271 if (isprint(what)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100272 return fprintf(options.output, "%c", what);
Steve Fink7bafff02006-08-07 04:50:42 +0200273 } else {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100274 return fprintf(options.output, "\\%03o", (unsigned char)what);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100275 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100276 }
277}
278
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100279#define MIN(a,b) (((a)<(b)) ? (a) : (b))
280
Juan Cespedesf1350522008-12-16 18:19:58 +0100281static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200282display_string(enum tof type, Process *proc, void *addr,
Juan Cespedesf1350522008-12-16 18:19:58 +0100283 size_t maxlength) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100284 unsigned char *str1;
Zachary T Welchba6aca22010-12-08 18:55:09 -0800285 size_t i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100286 int len = 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100287
Juan Cespedes5e01f651998-03-08 22:31:44 +0100288 if (!addr) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100289 return fprintf(options.output, "NULL");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100290 }
291
Juan Cespedescc813cd2009-04-07 15:45:53 +0200292 str1 = malloc(MIN(options.strlen, maxlength) + 3);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100293 if (!str1) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100294 return fprintf(options.output, "???");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100295 }
Juan Cespedescc813cd2009-04-07 15:45:53 +0200296 umovestr(proc, addr, MIN(options.strlen, maxlength) + 1, str1);
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100297 len = fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200298 for (i = 0; i < MIN(options.strlen, maxlength); i++) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100299 if (str1[i]) {
300 len += display_char(str1[i]);
301 } else {
302 break;
303 }
304 }
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100305 len += fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200306 if (str1[i] && (options.strlen <= maxlength)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100307 len += fprintf(options.output, "...");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100308 }
309 free(str1);
310 return len;
311}
312
Juan Cespedesf1350522008-12-16 18:19:58 +0100313static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200314display_unknown(enum tof type, Process *proc, long value) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100315 if (proc->mask_32bit) {
Steve Fink7bafff02006-08-07 04:50:42 +0200316 if ((int)value < 1000000 && (int)value > -1000000)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100317 return fprintf(options.output, "%d", (int)value);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100318 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100319 return fprintf(options.output, "%p", (void *)value);
Steve Fink7bafff02006-08-07 04:50:42 +0200320 } else if (value < 1000000 && value > -1000000) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100321 return fprintf(options.output, "%ld", value);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100322 } else {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100323 return fprintf(options.output, "%p", (void *)value);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100324 }
325}
Juan Cespedesac3db291998-04-25 14:31:58 +0200326
Juan Cespedesf1350522008-12-16 18:19:58 +0100327static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200328display_format(enum tof type, Process *proc, int arg_num) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100329 void *addr;
330 unsigned char *str1;
Juan Cespedesac3db291998-04-25 14:31:58 +0200331 int i;
Zachary T Welchba6aca22010-12-08 18:55:09 -0800332 size_t len = 0;
Steve Fink65b53df2006-09-25 02:27:08 +0200333 arg_type_info info;
Juan Cespedesac3db291998-04-25 14:31:58 +0200334
Steve Fink65b53df2006-09-25 02:27:08 +0200335 info.type = ARGTYPE_POINTER;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200336 addr = (void *)gimme_arg(type, proc, arg_num, &info);
Juan Cespedesac3db291998-04-25 14:31:58 +0200337 if (!addr) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100338 return fprintf(options.output, "NULL");
Juan Cespedesac3db291998-04-25 14:31:58 +0200339 }
340
Juan Cespedescc813cd2009-04-07 15:45:53 +0200341 str1 = malloc(MIN(options.strlen, string_maxlength) + 3);
Juan Cespedesac3db291998-04-25 14:31:58 +0200342 if (!str1) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100343 return fprintf(options.output, "???");
Juan Cespedesac3db291998-04-25 14:31:58 +0200344 }
Juan Cespedescc813cd2009-04-07 15:45:53 +0200345 umovestr(proc, addr, MIN(options.strlen, string_maxlength) + 1, str1);
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100346 len = fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200347 for (i = 0; len < MIN(options.strlen, string_maxlength) + 1; i++) {
Juan Cespedesac3db291998-04-25 14:31:58 +0200348 if (str1[i]) {
349 len += display_char(str1[i]);
350 } else {
351 break;
352 }
353 }
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100354 len += fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200355 if (str1[i] && (options.strlen <= string_maxlength)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100356 len += fprintf(options.output, "...");
Juan Cespedesac3db291998-04-25 14:31:58 +0200357 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100358 for (i = 0; str1[i]; i++) {
359 if (str1[i] == '%') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100360 int is_long = 0;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100361 while (1) {
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200362 unsigned char c = str1[++i];
Juan Cespedesac3db291998-04-25 14:31:58 +0200363 if (c == '%') {
364 break;
365 } else if (!c) {
366 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100367 } else if (strchr("lzZtj", c)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100368 is_long++;
369 if (c == 'j')
370 is_long++;
Ian Wienand3219f322006-02-16 06:00:00 +0100371 if (is_long > 1
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100372 && (sizeof(long) < sizeof(long long)
373 || proc->mask_32bit)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100374 len += fprintf(options.output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100375 str1[i + 1] = '\0';
Juan Cespedesd914a202004-11-10 00:15:33 +0100376 break;
377 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100378 } else if (c == 'd' || c == 'i') {
Steve Fink65b53df2006-09-25 02:27:08 +0200379 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100380 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100381 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100382 fprintf(options.output, ", %d",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200383 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100384 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100385 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100386 fprintf(options.output, ", %ld",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200387 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200388 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100389 } else if (c == 'u') {
Steve Fink65b53df2006-09-25 02:27:08 +0200390 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100391 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100392 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100393 fprintf(options.output, ", %u",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200394 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100395 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100396 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100397 fprintf(options.output, ", %lu",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200398 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200399 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100400 } else if (c == 'o') {
Steve Fink65b53df2006-09-25 02:27:08 +0200401 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100402 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100403 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100404 fprintf(options.output, ", 0%o",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200405 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100406 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100407 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100408 fprintf(options.output, ", 0%lo",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200409 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200410 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100411 } else if (c == 'x' || c == 'X') {
Steve Fink65b53df2006-09-25 02:27:08 +0200412 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100413 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100414 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100415 fprintf(options.output, ", %#x",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200416 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100417 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100418 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100419 fprintf(options.output, ", %#lx",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200420 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100421 break;
422 } else if (strchr("eEfFgGaACS", c)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100423 || (is_long
424 && (c == 'c' || c == 's'))) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100425 len += fprintf(options.output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100426 str1[i + 1] = '\0';
Juan Cespedesac3db291998-04-25 14:31:58 +0200427 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100428 } else if (c == 'c') {
Steve Fink65b53df2006-09-25 02:27:08 +0200429 info.type = ARGTYPE_LONG;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100430 len += fprintf(options.output, ", '");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100431 len +=
432 display_char((int)
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200433 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100434 len += fprintf(options.output, "'");
Juan Cespedesac3db291998-04-25 14:31:58 +0200435 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100436 } else if (c == 's') {
Steve Fink65b53df2006-09-25 02:27:08 +0200437 info.type = ARGTYPE_POINTER;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100438 len += fprintf(options.output, ", ");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100439 len +=
440 display_string(type, proc,
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200441 (void *)gimme_arg(type, proc, ++arg_num, &info),
Steve Fink6a48a6d2006-08-07 04:29:06 +0200442 string_maxlength);
Juan Cespedesac3db291998-04-25 14:31:58 +0200443 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100444 } else if (c == 'p' || c == 'n') {
Steve Fink65b53df2006-09-25 02:27:08 +0200445 info.type = ARGTYPE_POINTER;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100446 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100447 fprintf(options.output, ", %p",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200448 (void *)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200449 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100450 } else if (c == '*') {
Steve Fink65b53df2006-09-25 02:27:08 +0200451 info.type = ARGTYPE_LONG;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100452 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100453 fprintf(options.output, ", %d",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200454 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200455 }
456 }
457 }
458 }
459 free(str1);
460 return len;
461}