blob: c639c88b52fb7213835d3a0b52b56097938e2044 [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"
Juan Cespedes5e01f651998-03-08 22:31:44 +01008
Juan Cespedesac3db291998-04-25 14:31:58 +02009static int display_char(int what);
Juan Cespedesa8909f72009-04-28 20:02:41 +020010static int display_string(enum tof type, Process *proc,
Steve Fink7bafff02006-08-07 04:50:42 +020011 void* addr, size_t maxlen);
Juan Cespedesa8909f72009-04-28 20:02:41 +020012static int display_value(enum tof type, Process *proc,
Steve Finke4b32632006-08-07 06:10:08 +020013 long value, arg_type_info *info,
14 void *st, arg_type_info* st_info);
Juan Cespedesa8909f72009-04-28 20:02:41 +020015static int display_unknown(enum tof type, Process *proc, long value);
16static int display_format(enum tof type, Process *proc, int arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010017
Zachary T Welchba6aca22010-12-08 18:55:09 -080018static size_t string_maxlength = INT_MAX;
19static size_t array_maxlength = INT_MAX;
Steve Fink6a48a6d2006-08-07 04:29:06 +020020
Juan Cespedesf1350522008-12-16 18:19:58 +010021static long
Juan Cespedesa8909f72009-04-28 20:02:41 +020022get_length(enum tof type, Process *proc, int len_spec,
Juan Cespedesf1350522008-12-16 18:19:58 +010023 void *st, arg_type_info* st_info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020024 long len;
25 arg_type_info info;
Steve Fink65b53df2006-09-25 02:27:08 +020026
Juan Cespedesa413e5b2007-09-04 17:34:53 +020027 if (len_spec > 0)
28 return len_spec;
29 if (type == LT_TOF_STRUCT) {
Luis Machado55c5feb2008-03-12 15:56:01 +010030 umovelong (proc, st + st_info->u.struct_info.offset[-len_spec-1],
31 &len, st_info->u.struct_info.fields[-len_spec-1]);
Juan Cespedesa413e5b2007-09-04 17:34:53 +020032 return len;
33 }
Steve Fink65b53df2006-09-25 02:27:08 +020034
Juan Cespedesa413e5b2007-09-04 17:34:53 +020035 info.type = ARGTYPE_INT;
36 return gimme_arg(type, proc, -len_spec-1, &info);
Steve Fink6a48a6d2006-08-07 04:29:06 +020037}
38
Juan Cespedesf1350522008-12-16 18:19:58 +010039static int
Juan Cespedesa8909f72009-04-28 20:02:41 +020040display_ptrto(enum tof type, Process *proc, long item,
Steve Finke4b32632006-08-07 06:10:08 +020041 arg_type_info * info,
Juan Cespedesf1350522008-12-16 18:19:58 +010042 void *st, arg_type_info* st_info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020043 arg_type_info temp;
44 temp.type = ARGTYPE_POINTER;
45 temp.u.ptr_info.info = info;
46 return display_value(type, proc, item, &temp, st, st_info);
Steve Fink1150bc42006-08-07 06:04:43 +020047}
48
49/*
50 * addr - A pointer to the first element of the array
51 *
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.
56 */
Juan Cespedesf1350522008-12-16 18:19:58 +010057static int
Juan Cespedesa8909f72009-04-28 20:02:41 +020058display_arrayptr(enum tof type, Process *proc,
Steve Finke4b32632006-08-07 06:10:08 +020059 void *addr, arg_type_info * info,
Juan Cespedesf1350522008-12-16 18:19:58 +010060 void *st, arg_type_info* st_info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020061 int len = 0;
Zachary T Welchba6aca22010-12-08 18:55:09 -080062 size_t i;
63 size_t array_len;
Steve Fink1150bc42006-08-07 06:04:43 +020064
Juan Cespedesa413e5b2007-09-04 17:34:53 +020065 if (addr == NULL)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010066 return fprintf(options.output, "NULL");
Steve Fink1150bc42006-08-07 06:04:43 +020067
Juan Cespedesa413e5b2007-09-04 17:34:53 +020068 array_len = get_length(type, proc, info->u.array_info.len_spec,
69 st, st_info);
Juan Cespedesb65bdc52008-12-16 19:50:16 +010070 len += fprintf(options.output, "[ ");
Juan Cespedesda9b9532009-04-07 15:33:50 +020071 for (i = 0; i < options.arraylen && i < array_maxlength && i < array_len; i++) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020072 arg_type_info *elt_type = info->u.array_info.elt_type;
73 size_t elt_size = info->u.array_info.elt_size;
74 if (i != 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010075 len += fprintf(options.output, ", ");
Juan Cespedesda9b9532009-04-07 15:33:50 +020076 if (options.debug)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010077 len += fprintf(options.output, "%p=", addr);
Juan Cespedesa413e5b2007-09-04 17:34:53 +020078 len +=
79 display_ptrto(type, proc, (long) addr, elt_type, st, st_info);
80 addr += elt_size;
81 }
82 if (i < array_len)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010083 len += fprintf(options.output, "...");
84 len += fprintf(options.output, " ]");
Juan Cespedesa413e5b2007-09-04 17:34:53 +020085 return len;
Steve Fink1150bc42006-08-07 06:04:43 +020086}
Juan Cespedesa413e5b2007-09-04 17:34:53 +020087
Steve Finke4b32632006-08-07 06:10:08 +020088/* addr - A pointer to the beginning of the memory region occupied by
89 * the struct (aka a pointer to the struct)
90 */
Juan Cespedesf1350522008-12-16 18:19:58 +010091static int
Juan Cespedesa8909f72009-04-28 20:02:41 +020092display_structptr(enum tof type, Process *proc,
Juan Cespedesf1350522008-12-16 18:19:58 +010093 void *addr, arg_type_info * info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020094 int i;
95 arg_type_info *field;
96 int len = 0;
Steve Finke4b32632006-08-07 06:10:08 +020097
Juan Cespedesa413e5b2007-09-04 17:34:53 +020098 if (addr == NULL)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010099 return fprintf(options.output, "NULL");
Steve Finke4b32632006-08-07 06:10:08 +0200100
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100101 len += fprintf(options.output, "{ ");
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200102 for (i = 0; (field = info->u.struct_info.fields[i]) != NULL; i++) {
103 if (i != 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100104 len += fprintf(options.output, ", ");
Juan Cespedesda9b9532009-04-07 15:33:50 +0200105 if (options.debug)
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200106 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100107 fprintf(options.output, "%p=",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200108 addr + info->u.struct_info.offset[i]);
109 len +=
110 display_ptrto(LT_TOF_STRUCT, proc,
111 (long) addr + info->u.struct_info.offset[i],
112 field, addr, info);
113 }
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100114 len += fprintf(options.output, " }");
Steve Finke4b32632006-08-07 06:10:08 +0200115
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200116 return len;
Steve Finke4b32632006-08-07 06:10:08 +0200117}
118
Juan Cespedesf1350522008-12-16 18:19:58 +0100119static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200120display_pointer(enum tof type, Process *proc, long value,
Steve Finke4b32632006-08-07 06:10:08 +0200121 arg_type_info * info,
Juan Cespedesf1350522008-12-16 18:19:58 +0100122 void *st, arg_type_info* st_info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200123 long pointed_to;
124 arg_type_info *inner = info->u.ptr_info.info;
Steve Fink7bafff02006-08-07 04:50:42 +0200125
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200126 if (inner->type == ARGTYPE_ARRAY) {
127 return display_arrayptr(type, proc, (void*) value, inner,
Steve Finke4b32632006-08-07 06:10:08 +0200128 st, st_info);
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200129 } else if (inner->type == ARGTYPE_STRUCT) {
130 return display_structptr(type, proc, (void *) value, inner);
131 } else {
132 if (value == 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100133 return fprintf(options.output, "NULL");
Luis Machado55c5feb2008-03-12 15:56:01 +0100134 else if (umovelong (proc, (void *) value, &pointed_to,
135 info->u.ptr_info.info) < 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100136 return fprintf(options.output, "?");
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200137 else
138 return display_value(type, proc, pointed_to, inner,
139 st, st_info);
140 }
Steve Fink7bafff02006-08-07 04:50:42 +0200141}
142
Juan Cespedesf1350522008-12-16 18:19:58 +0100143static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200144display_enum(enum tof type, Process *proc,
Juan Cespedesf1350522008-12-16 18:19:58 +0100145 arg_type_info* info, long value) {
Zachary T Welchba6aca22010-12-08 18:55:09 -0800146 size_t ii;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200147 for (ii = 0; ii < info->u.enum_info.entries; ++ii) {
148 if (info->u.enum_info.values[ii] == value)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100149 return fprintf(options.output, "%s", info->u.enum_info.keys[ii]);
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200150 }
Steve Fink6a3e24d2006-08-07 05:53:19 +0200151
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200152 return display_unknown(type, proc, value);
Steve Fink6a3e24d2006-08-07 05:53:19 +0200153}
154
Steve Fink7bafff02006-08-07 04:50:42 +0200155/* Args:
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
Steve Finke4b32632006-08-07 06:10:08 +0200160 st - if the current value is a struct member, the address of the struct
161 st_info - type of the above struct
162
163 Those last two parameters are used for structs containing arrays or
164 strings whose length is given by another structure element.
Steve Fink7bafff02006-08-07 04:50:42 +0200165*/
Juan Cespedesf1350522008-12-16 18:19:58 +0100166int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200167display_value(enum tof type, Process *proc,
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200168 long value, arg_type_info *info,
Juan Cespedesf1350522008-12-16 18:19:58 +0100169 void *st, arg_type_info* st_info) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100170 int tmp;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100171
Steve Fink6a48a6d2006-08-07 04:29:06 +0200172 switch (info->type) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100173 case ARGTYPE_VOID:
174 return 0;
175 case ARGTYPE_INT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100176 return fprintf(options.output, "%d", (int) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100177 case ARGTYPE_UINT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100178 return fprintf(options.output, "%u", (unsigned) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100179 case ARGTYPE_LONG:
180 if (proc->mask_32bit)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100181 return fprintf(options.output, "%d", (int) value);
Steve Fink7bafff02006-08-07 04:50:42 +0200182 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100183 return fprintf(options.output, "%ld", value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100184 case ARGTYPE_ULONG:
185 if (proc->mask_32bit)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100186 return fprintf(options.output, "%u", (unsigned) value);
Steve Fink7bafff02006-08-07 04:50:42 +0200187 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100188 return fprintf(options.output, "%lu", (unsigned long) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100189 case ARGTYPE_OCTAL:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100190 return fprintf(options.output, "0%o", (unsigned) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100191 case ARGTYPE_CHAR:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100192 tmp = fprintf(options.output, "'");
Steve Fink7bafff02006-08-07 04:50:42 +0200193 tmp += display_char(value == -1 ? value : (char) value);
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100194 tmp += fprintf(options.output, "'");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100195 return tmp;
Steve Fink6fa27c32006-08-07 05:56:56 +0200196 case ARGTYPE_SHORT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100197 return fprintf(options.output, "%hd", (short) value);
Steve Fink6fa27c32006-08-07 05:56:56 +0200198 case ARGTYPE_USHORT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100199 return fprintf(options.output, "%hu", (unsigned short) value);
Steve Fink6fa27c32006-08-07 05:56:56 +0200200 case ARGTYPE_FLOAT: {
Steve Fink65b53df2006-09-25 02:27:08 +0200201 union { long l; float f; double d; } cvt;
Steve Fink6fa27c32006-08-07 05:56:56 +0200202 cvt.l = value;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100203 return fprintf(options.output, "%f", cvt.f);
Steve Fink6fa27c32006-08-07 05:56:56 +0200204 }
Steve Fink65b53df2006-09-25 02:27:08 +0200205 case ARGTYPE_DOUBLE: {
206 union { long l; float f; double d; } cvt;
207 cvt.l = value;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100208 return fprintf(options.output, "%lf", cvt.d);
Steve Fink65b53df2006-09-25 02:27:08 +0200209 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100210 case ARGTYPE_ADDR:
Steve Fink7bafff02006-08-07 04:50:42 +0200211 if (!value)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100212 return fprintf(options.output, "NULL");
Steve Fink7bafff02006-08-07 04:50:42 +0200213 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100214 return fprintf(options.output, "0x%08lx", value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100215 case ARGTYPE_FORMAT:
Steve Fink7bafff02006-08-07 04:50:42 +0200216 fprintf(stderr, "Should never encounter a format anywhere but at the top level (for now?)\n");
217 exit(1);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100218 case ARGTYPE_STRING:
Steve Fink7bafff02006-08-07 04:50:42 +0200219 return display_string(type, proc, (void*) value,
Steve Fink6a48a6d2006-08-07 04:29:06 +0200220 string_maxlength);
221 case ARGTYPE_STRING_N:
Steve Fink7bafff02006-08-07 04:50:42 +0200222 return display_string(type, proc, (void*) value,
Steve Fink6a48a6d2006-08-07 04:29:06 +0200223 get_length(type, proc,
Steve Finke4b32632006-08-07 06:10:08 +0200224 info->u.string_n_info.size_spec, st, st_info));
Steve Fink1150bc42006-08-07 06:04:43 +0200225 case ARGTYPE_ARRAY:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100226 return fprintf(options.output, "<array without address>");
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200227 case ARGTYPE_ENUM:
Steve Fink6a3e24d2006-08-07 05:53:19 +0200228 return display_enum(type, proc, info, value);
Steve Finke4b32632006-08-07 06:10:08 +0200229 case ARGTYPE_STRUCT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100230 return fprintf(options.output, "<struct without address>");
Steve Fink7bafff02006-08-07 04:50:42 +0200231 case ARGTYPE_POINTER:
Steve Finke4b32632006-08-07 06:10:08 +0200232 return display_pointer(type, proc, value, info,
233 st, st_info);
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200234 case ARGTYPE_UNKNOWN:
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100235 default:
Steve Fink7bafff02006-08-07 04:50:42 +0200236 return display_unknown(type, proc, value);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100237 }
Steve Fink7bafff02006-08-07 04:50:42 +0200238}
239
Juan Cespedesf1350522008-12-16 18:19:58 +0100240int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200241display_arg(enum tof type, Process *proc, int arg_num, arg_type_info * info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200242 long arg;
Steve Fink7bafff02006-08-07 04:50:42 +0200243
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200244 if (info->type == ARGTYPE_VOID) {
245 return 0;
246 } else if (info->type == ARGTYPE_FORMAT) {
247 return display_format(type, proc, arg_num);
248 } else {
249 arg = gimme_arg(type, proc, arg_num, info);
250 return display_value(type, proc, arg, info, NULL, NULL);
251 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100252}
253
Juan Cespedesf1350522008-12-16 18:19:58 +0100254static int
255display_char(int what) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100256 switch (what) {
257 case -1:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100258 return fprintf(options.output, "EOF");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100259 case '\r':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100260 return fprintf(options.output, "\\r");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100261 case '\n':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100262 return fprintf(options.output, "\\n");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100263 case '\t':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100264 return fprintf(options.output, "\\t");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100265 case '\b':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100266 return fprintf(options.output, "\\b");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100267 case '\\':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100268 return fprintf(options.output, "\\\\");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100269 default:
Steve Fink7bafff02006-08-07 04:50:42 +0200270 if (isprint(what)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100271 return fprintf(options.output, "%c", what);
Steve Fink7bafff02006-08-07 04:50:42 +0200272 } else {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100273 return fprintf(options.output, "\\%03o", (unsigned char)what);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100274 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100275 }
276}
277
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100278#define MIN(a,b) (((a)<(b)) ? (a) : (b))
279
Juan Cespedesf1350522008-12-16 18:19:58 +0100280static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200281display_string(enum tof type, Process *proc, void *addr,
Juan Cespedesf1350522008-12-16 18:19:58 +0100282 size_t maxlength) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100283 unsigned char *str1;
Zachary T Welchba6aca22010-12-08 18:55:09 -0800284 size_t i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100285 int len = 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100286
Juan Cespedes5e01f651998-03-08 22:31:44 +0100287 if (!addr) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100288 return fprintf(options.output, "NULL");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100289 }
290
Juan Cespedescc813cd2009-04-07 15:45:53 +0200291 str1 = malloc(MIN(options.strlen, maxlength) + 3);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100292 if (!str1) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100293 return fprintf(options.output, "???");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100294 }
Juan Cespedescc813cd2009-04-07 15:45:53 +0200295 umovestr(proc, addr, MIN(options.strlen, maxlength) + 1, str1);
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100296 len = fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200297 for (i = 0; i < MIN(options.strlen, maxlength); i++) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100298 if (str1[i]) {
299 len += display_char(str1[i]);
300 } else {
301 break;
302 }
303 }
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100304 len += fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200305 if (str1[i] && (options.strlen <= maxlength)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100306 len += fprintf(options.output, "...");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100307 }
308 free(str1);
309 return len;
310}
311
Juan Cespedesf1350522008-12-16 18:19:58 +0100312static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200313display_unknown(enum tof type, Process *proc, long value) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100314 if (proc->mask_32bit) {
Steve Fink7bafff02006-08-07 04:50:42 +0200315 if ((int)value < 1000000 && (int)value > -1000000)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100316 return fprintf(options.output, "%d", (int)value);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100317 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100318 return fprintf(options.output, "%p", (void *)value);
Steve Fink7bafff02006-08-07 04:50:42 +0200319 } else if (value < 1000000 && value > -1000000) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100320 return fprintf(options.output, "%ld", value);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100321 } else {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100322 return fprintf(options.output, "%p", (void *)value);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100323 }
324}
Juan Cespedesac3db291998-04-25 14:31:58 +0200325
Juan Cespedesf1350522008-12-16 18:19:58 +0100326static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200327display_format(enum tof type, Process *proc, int arg_num) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100328 void *addr;
329 unsigned char *str1;
Juan Cespedesac3db291998-04-25 14:31:58 +0200330 int i;
Zachary T Welchba6aca22010-12-08 18:55:09 -0800331 size_t len = 0;
Steve Fink65b53df2006-09-25 02:27:08 +0200332 arg_type_info info;
Juan Cespedesac3db291998-04-25 14:31:58 +0200333
Steve Fink65b53df2006-09-25 02:27:08 +0200334 info.type = ARGTYPE_POINTER;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200335 addr = (void *)gimme_arg(type, proc, arg_num, &info);
Juan Cespedesac3db291998-04-25 14:31:58 +0200336 if (!addr) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100337 return fprintf(options.output, "NULL");
Juan Cespedesac3db291998-04-25 14:31:58 +0200338 }
339
Juan Cespedescc813cd2009-04-07 15:45:53 +0200340 str1 = malloc(MIN(options.strlen, string_maxlength) + 3);
Juan Cespedesac3db291998-04-25 14:31:58 +0200341 if (!str1) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100342 return fprintf(options.output, "???");
Juan Cespedesac3db291998-04-25 14:31:58 +0200343 }
Juan Cespedescc813cd2009-04-07 15:45:53 +0200344 umovestr(proc, addr, MIN(options.strlen, string_maxlength) + 1, str1);
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100345 len = fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200346 for (i = 0; len < MIN(options.strlen, string_maxlength) + 1; i++) {
Juan Cespedesac3db291998-04-25 14:31:58 +0200347 if (str1[i]) {
348 len += display_char(str1[i]);
349 } else {
350 break;
351 }
352 }
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100353 len += fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200354 if (str1[i] && (options.strlen <= string_maxlength)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100355 len += fprintf(options.output, "...");
Juan Cespedesac3db291998-04-25 14:31:58 +0200356 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100357 for (i = 0; str1[i]; i++) {
358 if (str1[i] == '%') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100359 int is_long = 0;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100360 while (1) {
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200361 unsigned char c = str1[++i];
Juan Cespedesac3db291998-04-25 14:31:58 +0200362 if (c == '%') {
363 break;
364 } else if (!c) {
365 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100366 } else if (strchr("lzZtj", c)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100367 is_long++;
368 if (c == 'j')
369 is_long++;
Ian Wienand3219f322006-02-16 06:00:00 +0100370 if (is_long > 1
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100371 && (sizeof(long) < sizeof(long long)
372 || proc->mask_32bit)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100373 len += fprintf(options.output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100374 str1[i + 1] = '\0';
Juan Cespedesd914a202004-11-10 00:15:33 +0100375 break;
376 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100377 } else if (c == 'd' || c == 'i') {
Steve Fink65b53df2006-09-25 02:27:08 +0200378 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100379 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100380 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100381 fprintf(options.output, ", %d",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200382 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100383 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100384 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100385 fprintf(options.output, ", %ld",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200386 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200387 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100388 } else if (c == 'u') {
Steve Fink65b53df2006-09-25 02:27:08 +0200389 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100390 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100391 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100392 fprintf(options.output, ", %u",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200393 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100394 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100395 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100396 fprintf(options.output, ", %lu",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200397 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200398 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100399 } else if (c == 'o') {
Steve Fink65b53df2006-09-25 02:27:08 +0200400 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100401 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100402 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100403 fprintf(options.output, ", 0%o",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200404 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100405 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100406 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100407 fprintf(options.output, ", 0%lo",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200408 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200409 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100410 } else if (c == 'x' || c == 'X') {
Steve Fink65b53df2006-09-25 02:27:08 +0200411 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100412 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100413 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100414 fprintf(options.output, ", %#x",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200415 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100416 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100417 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100418 fprintf(options.output, ", %#lx",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200419 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100420 break;
421 } else if (strchr("eEfFgGaACS", c)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100422 || (is_long
423 && (c == 'c' || c == 's'))) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100424 len += fprintf(options.output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100425 str1[i + 1] = '\0';
Juan Cespedesac3db291998-04-25 14:31:58 +0200426 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100427 } else if (c == 'c') {
Steve Fink65b53df2006-09-25 02:27:08 +0200428 info.type = ARGTYPE_LONG;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100429 len += fprintf(options.output, ", '");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100430 len +=
431 display_char((int)
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200432 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100433 len += fprintf(options.output, "'");
Juan Cespedesac3db291998-04-25 14:31:58 +0200434 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100435 } else if (c == 's') {
Steve Fink65b53df2006-09-25 02:27:08 +0200436 info.type = ARGTYPE_POINTER;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100437 len += fprintf(options.output, ", ");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100438 len +=
439 display_string(type, proc,
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200440 (void *)gimme_arg(type, proc, ++arg_num, &info),
Steve Fink6a48a6d2006-08-07 04:29:06 +0200441 string_maxlength);
Juan Cespedesac3db291998-04-25 14:31:58 +0200442 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100443 } else if (c == 'p' || c == 'n') {
Steve Fink65b53df2006-09-25 02:27:08 +0200444 info.type = ARGTYPE_POINTER;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100445 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100446 fprintf(options.output, ", %p",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200447 (void *)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200448 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100449 } else if (c == '*') {
Steve Fink65b53df2006-09-25 02:27:08 +0200450 info.type = ARGTYPE_LONG;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100451 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100452 fprintf(options.output, ", %d",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200453 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200454 }
455 }
456 }
457 }
458 free(str1);
459 return len;
460}