blob: 872b1c9ad1bfda4c2de1088e275afba3741ff559 [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"
Petr Machata000e3112012-01-03 17:03:39 +01009#include "type.h"
Juan Cespedes5e01f651998-03-08 22:31:44 +010010
Juan Cespedesac3db291998-04-25 14:31:58 +020011static int display_char(int what);
Juan Cespedesa8909f72009-04-28 20:02:41 +020012static int display_string(enum tof type, Process *proc,
Steve Fink7bafff02006-08-07 04:50:42 +020013 void* addr, size_t maxlen);
Juan Cespedesa8909f72009-04-28 20:02:41 +020014static int display_value(enum tof type, Process *proc,
Petr Machata000e3112012-01-03 17:03:39 +010015 long value, struct arg_type_info *info,
16 void *st, struct arg_type_info *st_info);
Juan Cespedesa8909f72009-04-28 20:02:41 +020017static int display_unknown(enum tof type, Process *proc, long value);
18static int display_format(enum tof type, Process *proc, int arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010019
Zachary T Welchba6aca22010-12-08 18:55:09 -080020static size_t string_maxlength = INT_MAX;
21static size_t array_maxlength = INT_MAX;
Steve Fink6a48a6d2006-08-07 04:29:06 +020022
Juan Cespedesf1350522008-12-16 18:19:58 +010023static long
Juan Cespedesa8909f72009-04-28 20:02:41 +020024get_length(enum tof type, Process *proc, int len_spec,
Petr Machata000e3112012-01-03 17:03:39 +010025 void *st, struct arg_type_info *st_info)
26{
Juan Cespedesa413e5b2007-09-04 17:34:53 +020027 long len;
Petr Machata000e3112012-01-03 17:03:39 +010028 struct arg_type_info info;
Steve Fink65b53df2006-09-25 02:27:08 +020029
Juan Cespedesa413e5b2007-09-04 17:34:53 +020030 if (len_spec > 0)
31 return len_spec;
32 if (type == LT_TOF_STRUCT) {
Petr Machata000e3112012-01-03 17:03:39 +010033 umovelong(proc, st + st_info->u.struct_info.offset[-len_spec-1],
34 &len, st_info->u.struct_info.fields[-len_spec-1]);
Juan Cespedesa413e5b2007-09-04 17:34:53 +020035 return len;
36 }
Steve Fink65b53df2006-09-25 02:27:08 +020037
Juan Cespedesa413e5b2007-09-04 17:34:53 +020038 info.type = ARGTYPE_INT;
39 return gimme_arg(type, proc, -len_spec-1, &info);
Steve Fink6a48a6d2006-08-07 04:29:06 +020040}
41
Juan Cespedesf1350522008-12-16 18:19:58 +010042static int
Juan Cespedesa8909f72009-04-28 20:02:41 +020043display_ptrto(enum tof type, Process *proc, long item,
Petr Machata000e3112012-01-03 17:03:39 +010044 struct arg_type_info * info,
45 void *st, struct arg_type_info *st_info) {
46 struct arg_type_info temp;
Juan Cespedesa413e5b2007-09-04 17:34:53 +020047 temp.type = ARGTYPE_POINTER;
48 temp.u.ptr_info.info = info;
49 return display_value(type, proc, item, &temp, st, st_info);
Steve Fink1150bc42006-08-07 06:04:43 +020050}
51
52/*
53 * addr - A pointer to the first element of the array
54 *
55 * The function name is used to indicate that we're not actually
56 * looking at an 'array', which is a contiguous region of memory
57 * containing a sequence of elements of some type; instead, we have a
58 * pointer to that region of memory.
59 */
Juan Cespedesf1350522008-12-16 18:19:58 +010060static int
Juan Cespedesa8909f72009-04-28 20:02:41 +020061display_arrayptr(enum tof type, Process *proc,
Petr Machata000e3112012-01-03 17:03:39 +010062 void *addr, struct arg_type_info * info,
63 void *st, struct arg_type_info *st_info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020064 int len = 0;
Zachary T Welchba6aca22010-12-08 18:55:09 -080065 size_t i;
66 size_t array_len;
Steve Fink1150bc42006-08-07 06:04:43 +020067
Juan Cespedesa413e5b2007-09-04 17:34:53 +020068 if (addr == NULL)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010069 return fprintf(options.output, "NULL");
Steve Fink1150bc42006-08-07 06:04:43 +020070
Juan Cespedesa413e5b2007-09-04 17:34:53 +020071 array_len = get_length(type, proc, info->u.array_info.len_spec,
72 st, st_info);
Juan Cespedesb65bdc52008-12-16 19:50:16 +010073 len += fprintf(options.output, "[ ");
Juan Cespedesda9b9532009-04-07 15:33:50 +020074 for (i = 0; i < options.arraylen && i < array_maxlength && i < array_len; i++) {
Petr Machata000e3112012-01-03 17:03:39 +010075 struct arg_type_info *elt_type = info->u.array_info.elt_type;
Juan Cespedesa413e5b2007-09-04 17:34:53 +020076 size_t elt_size = info->u.array_info.elt_size;
77 if (i != 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010078 len += fprintf(options.output, ", ");
Juan Cespedesda9b9532009-04-07 15:33:50 +020079 if (options.debug)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010080 len += fprintf(options.output, "%p=", addr);
Juan Cespedesa413e5b2007-09-04 17:34:53 +020081 len +=
82 display_ptrto(type, proc, (long) addr, elt_type, st, st_info);
83 addr += elt_size;
84 }
85 if (i < array_len)
Juan Cespedesb65bdc52008-12-16 19:50:16 +010086 len += fprintf(options.output, "...");
87 len += fprintf(options.output, " ]");
Juan Cespedesa413e5b2007-09-04 17:34:53 +020088 return len;
Steve Fink1150bc42006-08-07 06:04:43 +020089}
Juan Cespedesa413e5b2007-09-04 17:34:53 +020090
Steve Finke4b32632006-08-07 06:10:08 +020091/* addr - A pointer to the beginning of the memory region occupied by
92 * the struct (aka a pointer to the struct)
93 */
Juan Cespedesf1350522008-12-16 18:19:58 +010094static int
Juan Cespedesa8909f72009-04-28 20:02:41 +020095display_structptr(enum tof type, Process *proc,
Petr Machata000e3112012-01-03 17:03:39 +010096 void *addr, struct arg_type_info * info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +020097 int i;
Petr Machata000e3112012-01-03 17:03:39 +010098 struct arg_type_info *field;
Juan Cespedesa413e5b2007-09-04 17:34:53 +020099 int len = 0;
Steve Finke4b32632006-08-07 06:10:08 +0200100
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200101 if (addr == NULL)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100102 return fprintf(options.output, "NULL");
Steve Finke4b32632006-08-07 06:10:08 +0200103
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100104 len += fprintf(options.output, "{ ");
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200105 for (i = 0; (field = info->u.struct_info.fields[i]) != NULL; i++) {
106 if (i != 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100107 len += fprintf(options.output, ", ");
Juan Cespedesda9b9532009-04-07 15:33:50 +0200108 if (options.debug)
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200109 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100110 fprintf(options.output, "%p=",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200111 addr + info->u.struct_info.offset[i]);
112 len +=
113 display_ptrto(LT_TOF_STRUCT, proc,
114 (long) addr + info->u.struct_info.offset[i],
115 field, addr, info);
116 }
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100117 len += fprintf(options.output, " }");
Steve Finke4b32632006-08-07 06:10:08 +0200118
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200119 return len;
Steve Finke4b32632006-08-07 06:10:08 +0200120}
121
Juan Cespedesf1350522008-12-16 18:19:58 +0100122static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200123display_pointer(enum tof type, Process *proc, long value,
Petr Machata000e3112012-01-03 17:03:39 +0100124 struct arg_type_info * info,
125 void *st, struct arg_type_info *st_info) {
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200126 long pointed_to;
Petr Machata000e3112012-01-03 17:03:39 +0100127 struct arg_type_info *inner = info->u.ptr_info.info;
Steve Fink7bafff02006-08-07 04:50:42 +0200128
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200129 if (inner->type == ARGTYPE_ARRAY) {
130 return display_arrayptr(type, proc, (void*) value, inner,
Steve Finke4b32632006-08-07 06:10:08 +0200131 st, st_info);
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200132 } else if (inner->type == ARGTYPE_STRUCT) {
133 return display_structptr(type, proc, (void *) value, inner);
134 } else {
135 if (value == 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100136 return fprintf(options.output, "NULL");
Luis Machado55c5feb2008-03-12 15:56:01 +0100137 else if (umovelong (proc, (void *) value, &pointed_to,
138 info->u.ptr_info.info) < 0)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100139 return fprintf(options.output, "?");
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200140 else
141 return display_value(type, proc, pointed_to, inner,
142 st, st_info);
143 }
Steve Fink7bafff02006-08-07 04:50:42 +0200144}
145
Juan Cespedesf1350522008-12-16 18:19:58 +0100146static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200147display_enum(enum tof type, Process *proc,
Petr Machata000e3112012-01-03 17:03:39 +0100148 struct arg_type_info *info, long value) {
Zachary T Welchba6aca22010-12-08 18:55:09 -0800149 size_t ii;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200150 for (ii = 0; ii < info->u.enum_info.entries; ++ii) {
151 if (info->u.enum_info.values[ii] == value)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100152 return fprintf(options.output, "%s", info->u.enum_info.keys[ii]);
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200153 }
Steve Fink6a3e24d2006-08-07 05:53:19 +0200154
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200155 return display_unknown(type, proc, value);
Steve Fink6a3e24d2006-08-07 05:53:19 +0200156}
157
Steve Fink7bafff02006-08-07 04:50:42 +0200158/* Args:
159 type - syscall or shared library function or memory
160 proc - information about the traced process
161 value - the value to display
162 info - the description of the type to display
Steve Finke4b32632006-08-07 06:10:08 +0200163 st - if the current value is a struct member, the address of the struct
164 st_info - type of the above struct
165
166 Those last two parameters are used for structs containing arrays or
167 strings whose length is given by another structure element.
Steve Fink7bafff02006-08-07 04:50:42 +0200168*/
Juan Cespedesf1350522008-12-16 18:19:58 +0100169int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200170display_value(enum tof type, Process *proc,
Petr Machata000e3112012-01-03 17:03:39 +0100171 long value, struct arg_type_info *info,
172 void *st, struct arg_type_info *st_info) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100173 int tmp;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100174
Steve Fink6a48a6d2006-08-07 04:29:06 +0200175 switch (info->type) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100176 case ARGTYPE_VOID:
177 return 0;
178 case ARGTYPE_INT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100179 return fprintf(options.output, "%d", (int) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100180 case ARGTYPE_UINT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100181 return fprintf(options.output, "%u", (unsigned) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100182 case ARGTYPE_LONG:
183 if (proc->mask_32bit)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100184 return fprintf(options.output, "%d", (int) value);
Steve Fink7bafff02006-08-07 04:50:42 +0200185 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100186 return fprintf(options.output, "%ld", value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100187 case ARGTYPE_ULONG:
188 if (proc->mask_32bit)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100189 return fprintf(options.output, "%u", (unsigned) value);
Steve Fink7bafff02006-08-07 04:50:42 +0200190 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100191 return fprintf(options.output, "%lu", (unsigned long) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100192 case ARGTYPE_OCTAL:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100193 return fprintf(options.output, "0%o", (unsigned) value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100194 case ARGTYPE_CHAR:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100195 tmp = fprintf(options.output, "'");
Steve Fink7bafff02006-08-07 04:50:42 +0200196 tmp += display_char(value == -1 ? value : (char) value);
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100197 tmp += fprintf(options.output, "'");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100198 return tmp;
Steve Fink6fa27c32006-08-07 05:56:56 +0200199 case ARGTYPE_SHORT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100200 return fprintf(options.output, "%hd", (short) value);
Steve Fink6fa27c32006-08-07 05:56:56 +0200201 case ARGTYPE_USHORT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100202 return fprintf(options.output, "%hu", (unsigned short) value);
Steve Fink6fa27c32006-08-07 05:56:56 +0200203 case ARGTYPE_FLOAT: {
Steve Fink65b53df2006-09-25 02:27:08 +0200204 union { long l; float f; double d; } cvt;
Steve Fink6fa27c32006-08-07 05:56:56 +0200205 cvt.l = value;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100206 return fprintf(options.output, "%f", cvt.f);
Steve Fink6fa27c32006-08-07 05:56:56 +0200207 }
Steve Fink65b53df2006-09-25 02:27:08 +0200208 case ARGTYPE_DOUBLE: {
209 union { long l; float f; double d; } cvt;
210 cvt.l = value;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100211 return fprintf(options.output, "%lf", cvt.d);
Steve Fink65b53df2006-09-25 02:27:08 +0200212 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100213 case ARGTYPE_ADDR:
Steve Fink7bafff02006-08-07 04:50:42 +0200214 if (!value)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100215 return fprintf(options.output, "NULL");
Steve Fink7bafff02006-08-07 04:50:42 +0200216 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100217 return fprintf(options.output, "0x%08lx", value);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100218 case ARGTYPE_FORMAT:
Steve Fink7bafff02006-08-07 04:50:42 +0200219 fprintf(stderr, "Should never encounter a format anywhere but at the top level (for now?)\n");
220 exit(1);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100221 case ARGTYPE_STRING:
Steve Fink7bafff02006-08-07 04:50:42 +0200222 return display_string(type, proc, (void*) value,
Steve Fink6a48a6d2006-08-07 04:29:06 +0200223 string_maxlength);
224 case ARGTYPE_STRING_N:
Steve Fink7bafff02006-08-07 04:50:42 +0200225 return display_string(type, proc, (void*) value,
Steve Fink6a48a6d2006-08-07 04:29:06 +0200226 get_length(type, proc,
Steve Finke4b32632006-08-07 06:10:08 +0200227 info->u.string_n_info.size_spec, st, st_info));
Steve Fink1150bc42006-08-07 06:04:43 +0200228 case ARGTYPE_ARRAY:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100229 return fprintf(options.output, "<array without address>");
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200230 case ARGTYPE_ENUM:
Steve Fink6a3e24d2006-08-07 05:53:19 +0200231 return display_enum(type, proc, info, value);
Steve Finke4b32632006-08-07 06:10:08 +0200232 case ARGTYPE_STRUCT:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100233 return fprintf(options.output, "<struct without address>");
Steve Fink7bafff02006-08-07 04:50:42 +0200234 case ARGTYPE_POINTER:
Steve Finke4b32632006-08-07 06:10:08 +0200235 return display_pointer(type, proc, value, info,
236 st, st_info);
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200237 case ARGTYPE_UNKNOWN:
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100238 default:
Steve Fink7bafff02006-08-07 04:50:42 +0200239 return display_unknown(type, proc, value);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100240 }
Steve Fink7bafff02006-08-07 04:50:42 +0200241}
242
Juan Cespedesf1350522008-12-16 18:19:58 +0100243int
Petr Machata000e3112012-01-03 17:03:39 +0100244display_arg(enum tof type, Process *proc, int arg_num,
245 struct arg_type_info * info)
246{
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200247 long arg;
Steve Fink7bafff02006-08-07 04:50:42 +0200248
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200249 if (info->type == ARGTYPE_VOID) {
250 return 0;
251 } else if (info->type == ARGTYPE_FORMAT) {
252 return display_format(type, proc, arg_num);
253 } else {
254 arg = gimme_arg(type, proc, arg_num, info);
255 return display_value(type, proc, arg, info, NULL, NULL);
256 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100257}
258
Juan Cespedesf1350522008-12-16 18:19:58 +0100259static int
260display_char(int what) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100261 switch (what) {
262 case -1:
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100263 return fprintf(options.output, "EOF");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100264 case '\r':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100265 return fprintf(options.output, "\\r");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100266 case '\n':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100267 return fprintf(options.output, "\\n");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100268 case '\t':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100269 return fprintf(options.output, "\\t");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100270 case '\b':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100271 return fprintf(options.output, "\\b");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100272 case '\\':
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100273 return fprintf(options.output, "\\\\");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100274 default:
Steve Fink7bafff02006-08-07 04:50:42 +0200275 if (isprint(what)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100276 return fprintf(options.output, "%c", what);
Steve Fink7bafff02006-08-07 04:50:42 +0200277 } else {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100278 return fprintf(options.output, "\\%03o", (unsigned char)what);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100279 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100280 }
281}
282
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100283#define MIN(a,b) (((a)<(b)) ? (a) : (b))
284
Juan Cespedesf1350522008-12-16 18:19:58 +0100285static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200286display_string(enum tof type, Process *proc, void *addr,
Juan Cespedesf1350522008-12-16 18:19:58 +0100287 size_t maxlength) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100288 unsigned char *str1;
Zachary T Welchba6aca22010-12-08 18:55:09 -0800289 size_t i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100290 int len = 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100291
Juan Cespedes5e01f651998-03-08 22:31:44 +0100292 if (!addr) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100293 return fprintf(options.output, "NULL");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100294 }
295
Juan Cespedescc813cd2009-04-07 15:45:53 +0200296 str1 = malloc(MIN(options.strlen, maxlength) + 3);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100297 if (!str1) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100298 return fprintf(options.output, "???");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100299 }
Juan Cespedescc813cd2009-04-07 15:45:53 +0200300 umovestr(proc, addr, MIN(options.strlen, maxlength) + 1, str1);
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100301 len = fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200302 for (i = 0; i < MIN(options.strlen, maxlength); i++) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100303 if (str1[i]) {
304 len += display_char(str1[i]);
305 } else {
306 break;
307 }
308 }
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100309 len += fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200310 if (str1[i] && (options.strlen <= maxlength)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100311 len += fprintf(options.output, "...");
Juan Cespedes5e01f651998-03-08 22:31:44 +0100312 }
313 free(str1);
314 return len;
315}
316
Juan Cespedesf1350522008-12-16 18:19:58 +0100317static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200318display_unknown(enum tof type, Process *proc, long value) {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100319 if (proc->mask_32bit) {
Steve Fink7bafff02006-08-07 04:50:42 +0200320 if ((int)value < 1000000 && (int)value > -1000000)
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100321 return fprintf(options.output, "%d", (int)value);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100322 else
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100323 return fprintf(options.output, "%p", (void *)value);
Steve Fink7bafff02006-08-07 04:50:42 +0200324 } else if (value < 1000000 && value > -1000000) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100325 return fprintf(options.output, "%ld", value);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100326 } else {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100327 return fprintf(options.output, "%p", (void *)value);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100328 }
329}
Juan Cespedesac3db291998-04-25 14:31:58 +0200330
Juan Cespedesf1350522008-12-16 18:19:58 +0100331static int
Juan Cespedesa8909f72009-04-28 20:02:41 +0200332display_format(enum tof type, Process *proc, int arg_num) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100333 void *addr;
334 unsigned char *str1;
Juan Cespedesac3db291998-04-25 14:31:58 +0200335 int i;
Zachary T Welchba6aca22010-12-08 18:55:09 -0800336 size_t len = 0;
Petr Machata000e3112012-01-03 17:03:39 +0100337 struct arg_type_info info;
Juan Cespedesac3db291998-04-25 14:31:58 +0200338
Steve Fink65b53df2006-09-25 02:27:08 +0200339 info.type = ARGTYPE_POINTER;
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200340 addr = (void *)gimme_arg(type, proc, arg_num, &info);
Juan Cespedesac3db291998-04-25 14:31:58 +0200341 if (!addr) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100342 return fprintf(options.output, "NULL");
Juan Cespedesac3db291998-04-25 14:31:58 +0200343 }
344
Juan Cespedescc813cd2009-04-07 15:45:53 +0200345 str1 = malloc(MIN(options.strlen, string_maxlength) + 3);
Juan Cespedesac3db291998-04-25 14:31:58 +0200346 if (!str1) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100347 return fprintf(options.output, "???");
Juan Cespedesac3db291998-04-25 14:31:58 +0200348 }
Juan Cespedescc813cd2009-04-07 15:45:53 +0200349 umovestr(proc, addr, MIN(options.strlen, string_maxlength) + 1, str1);
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100350 len = fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200351 for (i = 0; len < MIN(options.strlen, string_maxlength) + 1; i++) {
Juan Cespedesac3db291998-04-25 14:31:58 +0200352 if (str1[i]) {
353 len += display_char(str1[i]);
354 } else {
355 break;
356 }
357 }
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100358 len += fprintf(options.output, "\"");
Juan Cespedescc813cd2009-04-07 15:45:53 +0200359 if (str1[i] && (options.strlen <= string_maxlength)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100360 len += fprintf(options.output, "...");
Juan Cespedesac3db291998-04-25 14:31:58 +0200361 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100362 for (i = 0; str1[i]; i++) {
363 if (str1[i] == '%') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100364 int is_long = 0;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100365 while (1) {
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200366 unsigned char c = str1[++i];
Juan Cespedesac3db291998-04-25 14:31:58 +0200367 if (c == '%') {
368 break;
369 } else if (!c) {
370 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100371 } else if (strchr("lzZtj", c)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100372 is_long++;
373 if (c == 'j')
374 is_long++;
Ian Wienand3219f322006-02-16 06:00:00 +0100375 if (is_long > 1
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100376 && (sizeof(long) < sizeof(long long)
377 || proc->mask_32bit)) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100378 len += fprintf(options.output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100379 str1[i + 1] = '\0';
Juan Cespedesd914a202004-11-10 00:15:33 +0100380 break;
381 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100382 } else if (c == 'd' || c == 'i') {
Steve Fink65b53df2006-09-25 02:27:08 +0200383 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100384 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100385 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100386 fprintf(options.output, ", %d",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200387 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100388 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100389 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100390 fprintf(options.output, ", %ld",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200391 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200392 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100393 } else if (c == 'u') {
Steve Fink65b53df2006-09-25 02:27:08 +0200394 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100395 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100396 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100397 fprintf(options.output, ", %u",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200398 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100399 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100400 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100401 fprintf(options.output, ", %lu",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200402 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200403 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100404 } else if (c == 'o') {
Steve Fink65b53df2006-09-25 02:27:08 +0200405 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100406 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100407 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100408 fprintf(options.output, ", 0%o",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200409 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100410 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100411 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100412 fprintf(options.output, ", 0%lo",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200413 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200414 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100415 } else if (c == 'x' || c == 'X') {
Steve Fink65b53df2006-09-25 02:27:08 +0200416 info.type = ARGTYPE_LONG;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100417 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100418 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100419 fprintf(options.output, ", %#x",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200420 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100421 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100422 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100423 fprintf(options.output, ", %#lx",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200424 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesd914a202004-11-10 00:15:33 +0100425 break;
426 } else if (strchr("eEfFgGaACS", c)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100427 || (is_long
428 && (c == 'c' || c == 's'))) {
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100429 len += fprintf(options.output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100430 str1[i + 1] = '\0';
Juan Cespedesac3db291998-04-25 14:31:58 +0200431 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100432 } else if (c == 'c') {
Steve Fink65b53df2006-09-25 02:27:08 +0200433 info.type = ARGTYPE_LONG;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100434 len += fprintf(options.output, ", '");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100435 len +=
436 display_char((int)
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200437 gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100438 len += fprintf(options.output, "'");
Juan Cespedesac3db291998-04-25 14:31:58 +0200439 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100440 } else if (c == 's') {
Steve Fink65b53df2006-09-25 02:27:08 +0200441 info.type = ARGTYPE_POINTER;
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100442 len += fprintf(options.output, ", ");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100443 len +=
444 display_string(type, proc,
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200445 (void *)gimme_arg(type, proc, ++arg_num, &info),
Steve Fink6a48a6d2006-08-07 04:29:06 +0200446 string_maxlength);
Juan Cespedesac3db291998-04-25 14:31:58 +0200447 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100448 } else if (c == 'p' || c == 'n') {
Steve Fink65b53df2006-09-25 02:27:08 +0200449 info.type = ARGTYPE_POINTER;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100450 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100451 fprintf(options.output, ", %p",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200452 (void *)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200453 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100454 } else if (c == '*') {
Steve Fink65b53df2006-09-25 02:27:08 +0200455 info.type = ARGTYPE_LONG;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100456 len +=
Juan Cespedesb65bdc52008-12-16 19:50:16 +0100457 fprintf(options.output, ", %d",
Juan Cespedesa413e5b2007-09-04 17:34:53 +0200458 (int)gimme_arg(type, proc, ++arg_num, &info));
Juan Cespedesac3db291998-04-25 14:31:58 +0200459 }
460 }
461 }
462 }
463 free(str1);
464 return len;
465}