blob: 1c15f22022c8b9ae866cb677f2e2bdb85486384b [file] [log] [blame]
Juan Cespedesd44c6b81998-09-25 14:48:42 +02001#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
Juan Cespedes5e01f651998-03-08 22:31:44 +01005#include <stdio.h>
6#include <stdlib.h>
Juan Cespedesd914a202004-11-10 00:15:33 +01007#include <string.h>
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +01008#include <limits.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +01009
10#include "ltrace.h"
11#include "options.h"
12
Juan Cespedesac3db291998-04-25 14:31:58 +020013static int display_char(int what);
Steve Fink6a48a6d2006-08-07 04:29:06 +020014static int display_string(enum tof type, struct process *proc,
15 int arg_num, arg_type_info *info,
16 size_t maxlen);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010017static int display_unknown(enum tof type, struct process *proc, int arg_num);
18static int display_format(enum tof type, struct process *proc, int arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010019
Steve Fink6a48a6d2006-08-07 04:29:06 +020020static int string_maxlength = INT_MAX;
21
22static long get_length(enum tof type, struct process *proc, int len_spec)
23{
24 if (len_spec > 0)
25 return len_spec;
26 return gimme_arg(type, proc, -len_spec - 1);
27}
28
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010029int
Steve Fink6a48a6d2006-08-07 04:29:06 +020030display_arg(enum tof type, struct process *proc,
31 int arg_num, arg_type_info *info)
Ian Wienand2d45b1a2006-02-20 22:48:07 +010032{
Juan Cespedes5e01f651998-03-08 22:31:44 +010033 int tmp;
34 long arg;
35
Steve Fink6a48a6d2006-08-07 04:29:06 +020036 switch (info->type) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010037 case ARGTYPE_VOID:
38 return 0;
39 case ARGTYPE_INT:
40 return fprintf(output, "%d",
41 (int)gimme_arg(type, proc, arg_num));
42 case ARGTYPE_UINT:
43 return fprintf(output, "%u",
44 (unsigned)gimme_arg(type, proc, arg_num));
45 case ARGTYPE_LONG:
46 if (proc->mask_32bit)
47 return fprintf(output, "%d",
48 (int)gimme_arg(type, proc, arg_num));
49 return fprintf(output, "%ld", gimme_arg(type, proc, arg_num));
50 case ARGTYPE_ULONG:
51 if (proc->mask_32bit)
52 return fprintf(output, "%u",
53 (unsigned)gimme_arg(type, proc,
54 arg_num));
55 return fprintf(output, "%lu",
56 (unsigned long)gimme_arg(type, proc, arg_num));
57 case ARGTYPE_OCTAL:
58 return fprintf(output, "0%o",
59 (unsigned)gimme_arg(type, proc, arg_num));
60 case ARGTYPE_CHAR:
61 tmp = fprintf(output, "'");
62 tmp += display_char((int)gimme_arg(type, proc, arg_num));
63 tmp += fprintf(output, "'");
64 return tmp;
65 case ARGTYPE_ADDR:
66 arg = gimme_arg(type, proc, arg_num);
67 if (!arg) {
68 return fprintf(output, "NULL");
69 } else {
70 return fprintf(output, "%p", (void *)arg);
71 }
72 case ARGTYPE_FORMAT:
73 return display_format(type, proc, arg_num);
74 case ARGTYPE_STRING:
Steve Fink6a48a6d2006-08-07 04:29:06 +020075 return display_string(type, proc, arg_num, info,
76 string_maxlength);
77 case ARGTYPE_STRING_N:
78 return display_string(type, proc, arg_num, info,
79 get_length(type, proc,
80 info->u.string_n_info.size_spec));
Ian Wienand2d45b1a2006-02-20 22:48:07 +010081 case ARGTYPE_UNKNOWN:
82 default:
83 return display_unknown(type, proc, arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010084 }
85 return fprintf(output, "?");
86}
87
Ian Wienand2d45b1a2006-02-20 22:48:07 +010088static int display_char(int what)
89{
90 switch (what) {
91 case -1:
92 return fprintf(output, "EOF");
93 case '\r':
94 return fprintf(output, "\\r");
95 case '\n':
96 return fprintf(output, "\\n");
97 case '\t':
98 return fprintf(output, "\\t");
99 case '\b':
100 return fprintf(output, "\\b");
101 case '\\':
102 return fprintf(output, "\\\\");
103 default:
104 if ((what < 32) || (what > 126)) {
105 return fprintf(output, "\\%03o", (unsigned char)what);
106 } else {
107 return fprintf(output, "%c", what);
108 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100109 }
110}
111
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100112#define MIN(a,b) (((a)<(b)) ? (a) : (b))
113
Steve Fink6a48a6d2006-08-07 04:29:06 +0200114static int display_string(enum tof type, struct process *proc,
115 int arg_num, arg_type_info *info, size_t maxlength)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100116{
117 void *addr;
118 unsigned char *str1;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100119 int i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100120 int len = 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100121
122 addr = (void *)gimme_arg(type, proc, arg_num);
123 if (!addr) {
124 return fprintf(output, "NULL");
125 }
126
Steve Fink6a48a6d2006-08-07 04:29:06 +0200127 str1 = malloc(MIN(opt_s, maxlength) + 3);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100128 if (!str1) {
129 return fprintf(output, "???");
130 }
Steve Fink6a48a6d2006-08-07 04:29:06 +0200131 umovestr(proc, addr, MIN(opt_s, maxlength) + 1, str1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100132 len = fprintf(output, "\"");
Steve Fink6a48a6d2006-08-07 04:29:06 +0200133 for (i = 0; i < MIN(opt_s, maxlength); i++) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100134 if (str1[i]) {
135 len += display_char(str1[i]);
136 } else {
137 break;
138 }
139 }
140 len += fprintf(output, "\"");
Steve Fink6a48a6d2006-08-07 04:29:06 +0200141 if (str1[i] && (opt_s <= maxlength)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100142 len += fprintf(output, "...");
143 }
144 free(str1);
145 return len;
146}
147
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100148static int display_unknown(enum tof type, struct process *proc, int arg_num)
149{
Juan Cespedes5e01f651998-03-08 22:31:44 +0100150 long tmp;
151
152 tmp = gimme_arg(type, proc, arg_num);
153
Ian Wienand9a2ad352006-02-20 22:44:45 +0100154 if (proc->mask_32bit) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100155 if ((int)tmp < 1000000 && (int)tmp > -1000000)
Ian Wienand9a2ad352006-02-20 22:44:45 +0100156 return fprintf(output, "%d", (int)tmp);
157 else
158 return fprintf(output, "%p", (void *)tmp);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100159 } else if (tmp < 1000000 && tmp > -1000000) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100160 return fprintf(output, "%ld", tmp);
161 } else {
Juan Cespedesefe85f02004-04-04 01:31:38 +0200162 return fprintf(output, "%p", (void *)tmp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100163 }
164}
Juan Cespedesac3db291998-04-25 14:31:58 +0200165
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100166static int display_format(enum tof type, struct process *proc, int arg_num)
167{
168 void *addr;
169 unsigned char *str1;
Juan Cespedesac3db291998-04-25 14:31:58 +0200170 int i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100171 int len = 0;
Juan Cespedesac3db291998-04-25 14:31:58 +0200172
173 addr = (void *)gimme_arg(type, proc, arg_num);
174 if (!addr) {
175 return fprintf(output, "NULL");
176 }
177
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100178 str1 = malloc(MIN(opt_s, string_maxlength) + 3);
Juan Cespedesac3db291998-04-25 14:31:58 +0200179 if (!str1) {
180 return fprintf(output, "???");
181 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100182 umovestr(proc, addr, MIN(opt_s, string_maxlength) + 1, str1);
Juan Cespedesac3db291998-04-25 14:31:58 +0200183 len = fprintf(output, "\"");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100184 for (i = 0; len < MIN(opt_s, string_maxlength) + 1; i++) {
Juan Cespedesac3db291998-04-25 14:31:58 +0200185 if (str1[i]) {
186 len += display_char(str1[i]);
187 } else {
188 break;
189 }
190 }
191 len += fprintf(output, "\"");
192 if (str1[i] && (opt_s <= string_maxlength)) {
193 len += fprintf(output, "...");
194 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100195 for (i = 0; str1[i]; i++) {
196 if (str1[i] == '%') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100197 int is_long = 0;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100198 while (1) {
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200199 unsigned char c = str1[++i];
Juan Cespedesac3db291998-04-25 14:31:58 +0200200 if (c == '%') {
201 break;
202 } else if (!c) {
203 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100204 } else if (strchr("lzZtj", c)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100205 is_long++;
206 if (c == 'j')
207 is_long++;
Ian Wienand3219f322006-02-16 06:00:00 +0100208 if (is_long > 1
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100209 && (sizeof(long) < sizeof(long long)
210 || proc->mask_32bit)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100211 len += fprintf(output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100212 str1[i + 1] = '\0';
Juan Cespedesd914a202004-11-10 00:15:33 +0100213 break;
214 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100215 } else if (c == 'd' || c == 'i') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100216 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100217 len +=
218 fprintf(output, ", %d",
219 (int)gimme_arg(type,
220 proc,
221 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100222 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100223 len +=
224 fprintf(output, ", %ld",
225 gimme_arg(type,
226 proc,
227 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200228 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100229 } else if (c == 'u') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100230 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100231 len +=
232 fprintf(output, ", %u",
233 (int)gimme_arg(type,
234 proc,
235 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100236 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100237 len +=
238 fprintf(output, ", %lu",
239 gimme_arg(type,
240 proc,
241 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200242 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100243 } else if (c == 'o') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100244 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100245 len +=
246 fprintf(output, ", 0%o",
247 (int)gimme_arg(type,
248 proc,
249 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100250 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100251 len +=
252 fprintf(output, ", 0%lo",
253 gimme_arg(type,
254 proc,
255 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200256 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100257 } else if (c == 'x' || c == 'X') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100258 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100259 len +=
260 fprintf(output, ", %#x",
261 (int)gimme_arg(type,
262 proc,
263 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100264 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100265 len +=
266 fprintf(output, ", %#lx",
267 gimme_arg(type,
268 proc,
269 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100270 break;
271 } else if (strchr("eEfFgGaACS", c)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100272 || (is_long
273 && (c == 'c' || c == 's'))) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100274 len += fprintf(output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100275 str1[i + 1] = '\0';
Juan Cespedesac3db291998-04-25 14:31:58 +0200276 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100277 } else if (c == 'c') {
Juan Cespedesac3db291998-04-25 14:31:58 +0200278 len += fprintf(output, ", '");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100279 len +=
280 display_char((int)
281 gimme_arg(type, proc,
282 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200283 len += fprintf(output, "'");
284 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100285 } else if (c == 's') {
Steve Fink6a48a6d2006-08-07 04:29:06 +0200286 arg_type_info *info =
287 lookup_singleton(ARGTYPE_STRING);
Juan Cespedesac3db291998-04-25 14:31:58 +0200288 len += fprintf(output, ", ");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100289 len +=
290 display_string(type, proc,
Steve Fink6a48a6d2006-08-07 04:29:06 +0200291 ++arg_num, info,
292 string_maxlength);
Juan Cespedesac3db291998-04-25 14:31:58 +0200293 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100294 } else if (c == 'p' || c == 'n') {
295 len +=
296 fprintf(output, ", %p",
297 (void *)gimme_arg(type,
298 proc,
299 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200300 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100301 } else if (c == '*') {
302 len +=
303 fprintf(output, ", %d",
304 (int)gimme_arg(type, proc,
305 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200306 }
307 }
308 }
309 }
310 free(str1);
311 return len;
312}